#

SUD

大模型游戏互动接入(iOS)

在支持AI互动的游戏当中,用户可以通过语音或者文字与大模型AI玩家进行互动
互动的前提是游戏中至少得有一个真人,再通过相应接口先加入大模型AI玩家,后续通过ISudAiAgent相关接口和大模型AI玩家进行互动

ISudAiAgent接口

接口定义:


@protocol ISudAiAgent;

/// AI Agent
@protocol ISudAiAgent <NSObject>

/// 设置房间消息监听
/// @param roomMsgListener roomMsgListener description
- (void)setOnRoomChatMessageListener:(void(^)(NSString *json))roomMsgListener;

/// 传入的音频切片是从RTC获取的PCM数据
/// PCM数据格式必须是:采样率:16000, 采样位数:16, 声道数: MONO
/// PCM数据长度可以根据效果调整,长度大: 精确度好但延时长  长度小:延时短但牺牲精确度
/// @param data pcm数据
- (void)pushAudio:(NSData *_Nonnull)data;


/// 暂停push语音数据,会将前面推送的语音数据进行句子结束返回
- (void)pauseAudio;


/// 不再进行推送语音数据时调用,用于释放当前处理语音相关上下文
- (void)stopAudio;

/// 发送文本内容
- (void)sendText:(NSString *_Nonnull)text;
@end

一、获取ISudAiAgent

加载游戏后通过ISudFSTAPP接口方法getAiAgent获取ISudAiAgent
获取ISudAiAgent接口后,可通过该接口和大模型AI玩家进行语音、文字的互动,并可设置监听来接收大模型AI玩家的回复消息。 通过ISudFSTAPP游戏实例获取ISudAiAgent实例接口:


@protocol ISudFSTAPP <NSObject>
/// 创建一个ai agent操作实例
- (id<ISudAiAgent>)getAiAgent;

@end

参考样例:


// AI代理人
@property(nonatomic, strong) id<ISudAiAgent> aiAgent;

/// 游戏开始
- (void)onGameStarted {
    DDLogDebug(@"onGameStarted");
    [self.vc handleGameStared];
    /// 创建AI大模型互动
    [self createAiAgent: self.sudFSTAPPDecorator.iSudFSTAPP];
}


- (void)createAiAgent:(id <ISudFSTAPP> )iSudFSTAPP {
    // 振魂石 和 飞行棋
    if (self.loadConfigModel.gameId == 1890346721291059202L || self.loadConfigModel.gameId == 1468180338417074177L) {
        self.aiAgent = [iSudFSTAPP getAiAgent];
        WeakSelf

        /// 监听AI大模型互动信息
        [self.aiAgent setOnRoomChatMessageListener:^(NSString * _Nonnull json) {

            [weakSelf handleAiRoomChatMsg:json];
        }];

    }
}

二、添加大模型AI玩家

接口定义文档:通用状态 notifyStateChange

52. 设置游戏中的大模型AI玩家
app_common_game_add_big_scale_model_ai_players

在游戏位当中至少有一个真人时,客户端可通过该接口定义的协议格式向游戏发送消息来添加大模型AI玩家

对应的可以通过使用SudGIPWrapper模块提供交互接口将AI大模型机器人加入到游戏中,接口如下:


/// 设置游戏中的大模型AI玩家 APP_COMMON_GAME_ADD_BIG_SCALE_MODEL_AI_PLAYERS
/// @param appCommonGameAddAiPlayersModel  配置信息
- (void)notifyAppCommonGameAddBigScaleModelAPlayers:(AppCommonGameAddBigScaleModelAiPlayersModel *)appCommonGameAddAiPlayersModel;

参考样例:

// 添加大模型AI
NSMutableArray *aiPlayers = [[NSMutableArray alloc] init];
BigScaleModelAiPlayerInfoModel *aiPlayerInfoModel = [BigScaleModelAiPlayerInfoModel alloc];
aiPlayerInfoModel.userId = [NSString stringWithFormat:@"%@", @(robotInfoModel.userId)];
aiPlayerInfoModel.name = robotInfoModel.name;
aiPlayerInfoModel.avatar = robotInfoModel.avatar;
aiPlayerInfoModel.gender = robotInfoModel.gender;
aiPlayerInfoModel.aiIdStr = @"1";
[aiPlayers addObject:aiPlayerInfoModel];

AppCommonGameAddBigScaleModelAiPlayersModel *appCommonGameAddAiPlayersModel = [[AppCommonGameAddBigScaleModelAiPlayersModel alloc] init];
appCommonGameAddAiPlayersModel.aiPlayers = aiPlayers;
appCommonGameAddAiPlayersModel.isReady = YES;
[weakSelf.gameEventHandler.sudFSTAPPDecorator notifyAppCommonGameAddBigScaleModelAPlayers:appCommonGameAddAiPlayersModel];

三、文本对话

APP可选择向游戏发送文本消息与大模型AI玩家对话
通过ISudAiAgent接口方法sendText来向游戏发送文本内容

接口:


/// 发送文本内容
- (void)sendText:(NSString *_Nonnull)text;

参考样例:


- (void)sendTextToAiAgent:(NSString *)text {
    if (self.aiAgent) {
        [self.aiAgent sendText:text];
    }
}

四、语音对话

APP可选择向游戏发送语音消息与大模型AI玩家对话
通过ISudAiAgent接口方法pushAudio来向游戏发送语音消息
pauseAudio用于暂停语音对话,stopAudio用于关闭语音对话

接口:


/// 传入的音频切片是从RTC获取的PCM数据
/// PCM数据格式必须是:采样率:16000, 采样位数:16, 声道数: MONO
/// PCM数据长度可以根据效果调整,长度大: 精确度好但延时长  长度小:延时短但牺牲精确度
/// @param data pcm数据
- (void)pushAudio:(NSData *_Nonnull)data;


/// 暂停push语音数据,会将前面推送的语音数据进行句子结束返回
- (void)pauseAudio;


/// 不再进行推送语音数据时调用,用于释放当前处理语音相关上下文
- (void)stopAudio;

参考样例:


/// 推送语音数据
- (void)pushAudioToAiAgent:(NSData *)pcmData {
    if (self.aiAgent) {
        [self.aiAgent pushAudio:pcmData];
    }
}

/// 暂停推送语音数据
- (void)pauseAudioToAiAgent {
    if (!self.aiAgent) {
        return;
    }
    [self.aiAgent pauseAudio];
}

五、接收大模型AI玩家的消息

当APP通过语音或者文字向大模型AI玩家发送消息之后,大模型AI玩家会进行回复一条或多条消息给房间里的玩家
通过ISudAiAgent接口方法setOnRoomChatMessageListener设置监听器用于监听大模型AI玩家的回复消息

回调接口:


/// 设置房间消息监听
/// @param roomMsgListener roomMsgListener description
- (void)setOnRoomChatMessageListener:(void(^)(NSString *json))roomMsgListener;

回调消息格式样例:

{
"uid": "123456",
"audioData": "UklGRhQAAABXQVZFZm10IBAAAAA",
"content": "你好"
}

参考样例:


/// 大模型互动回调JSON数据结构
@interface AiRoomChatMsgModel : NSObject
/// 发送者id
@property(nonatomic, strong)NSString *uid;
/// base64语音数据(mp3)
@property(nonatomic, strong)NSString *audioData;
/// 文本内容
@property(nonatomic, strong)NSString *content;
@end



/// 处理大模型回调信息
/// - Parameter json: json字符串数据
- (void)handleAiRoomChatMsg:(NSString *)json {

    WeakSelf
    AiRoomChatMsgModel *aiRoomChatMsgModel = [AiRoomChatMsgModel mj_objectWithKeyValues:json];
    NSString *audioDataBase64 = aiRoomChatMsgModel.audioData;// infoDic[@"audioData"];
    NSString *playerId = aiRoomChatMsgModel.uid;// infoDic[@"userId"];
    if (audioDataBase64) {
        NSData *audioData = [[NSData alloc]initWithBase64EncodedString:audioDataBase64 options:0];
        BOOL isPlyeByRtc = YES;
        if (isPlyeByRtc) {

            id audioEngine = AudioEngineFactory.shared.audioEngine;
            // rtc 如果支持本地播放,则选用
            if ([audioEngine respondsToSelector:@selector(playLocalAudio:)]) {

                SudRtcAudioItem *audioItem = [[SudRtcAudioItem alloc]init];
                audioItem.audioData = audioData;
                audioItem.extra = playerId;
                audioItem.playStateChangedBlock = ^(SudRtcAudioItem *item, SudRtcAudioItemPlayerState playerState) {
                    [weakSelf handleUserPlayerAudioState:item.extra state:playerState];
                };
                [audioEngine playLocalAudio:audioItem];
                return;
            }
        }
        // 自行创建播放器播放
        SudAudioItem *audioItem = [[SudAudioItem alloc]init];
        audioItem.audioData = audioData;
        audioItem.extra = playerId;
        audioItem.playStateChangedBlock = ^(SudAudioItem *item, SudAudioItemPlayerState playerState) {
            [weakSelf handleUserPlayerAudioState:item.extra state:playerState];
        };
        [SudAudioPlayer.shared playeAudioMulti:audioItem];
    }
}

当收到onRoomChatMessage回调时,大型型AI玩家的说话内容,APP根据自身产品需求来选择展示文本消息或者是播放语音消息

六、声浪控制

当APP收到下面的游戏消息时,表示APP可选择控制游戏展示对应玩家的声浪效果
接口定义文档:通用状态-游戏

69. 通知app可以开始推送麦克说话状态
mg_common_game_player_mic_state

对应SudGIPWrapper回调接口:


/// 通知APP 玩家麦克风状态准备OK MG_COMMON_GAME_PLAYER_MIC_STATE
- (void)onGameMgCommonGamePlayerMicState:(nonnull id <ISudFSMStateHandle>)handle model:(MgCommonGamePlayerMicState *)model;

收到指令之后可通过如下接口进行控制
接口定义文档:通用状态 notifyStateChange

51. app向游戏下发玩家mic状态
app_common_game_player_mic_state

对应SudGIPWrapper调用接口:


/// app通知游戏更新麦克风状态 APP_COMMON_GAME_PLAYER_MIC_STATE
- (void)notifyAppCommonGamePlayerMicState:(AppCommonGamePlayerMicState *)model;

用于控制游戏当中是否显示指定玩家的声浪,是一个开关性质的指令,开启或关闭的时候发送一次即可

参考样例:


- (void)onGameMgCommonGamePlayerMicState:(id<ISudFSMStateHandle>)handle model:(MgCommonGamePlayerMicState *)model {
    self.isGamePlayerMicStateOk = YES;
    for (NSString *key in self.userAudioPlayStateMap.allKeys) {
        NSInteger state = [self.userAudioPlayStateMap[key] integerValue];
        [self sendGamePlayerAudioState:key state:state];
    }
}

/// 发送给游戏播放状态
- (void)sendGamePlayerAudioState:(NSString *)userId state:(NSInteger)state {
    // 没有开启AI或者游戏没有通知玩家麦克风准备好了, 别发
    if (!self.isOpenAiAgent || !self.isGamePlayerMicStateOk) {
        return;
    }
    AppCommonGamePlayerMicState *stateModel = AppCommonGamePlayerMicState.new;
    stateModel.state = SudAudioItemPlayerStatePlaying == state ? 1 : 0;
    stateModel.uid = userId;
    [self.sudFSTAPPDecorator notifyAppCommonGamePlayerMicState:stateModel];
}

results matching ""

    No results matching ""