更新时间:2025-08-12 02:05:38下载pdf
在接入 AI 基座通道前,请先阅读 App SDK 接入文档并完成接入:智能生活 App SDK > 准备工作。
完成接入后,在 Podfile
中引入 AI 基座通道:
target 'xxxxx' do
# 注意,ThingSmartHomeKit 需 >= 6.7.0
# ....
# 引入 AI 基座通道 SDK
pod 'ThingSmartBusinessExtensionKitAIStreamExtra'
end
为了确保智能体在您的 App 中可用,需要完成以下流程:
创建智能体:详细操作流程,请参考文档 智能体开发平台。
发布并投放智能体到指定 App:配置完成后,单击页面顶部的 上架。
请记录智能体的 Agent ID,用于后续 SDK 中 创建 session 使用。
在 智能体投放 页面,单击 投放 App 将智能体投放到指定 App,确认后,单击 确认投放信息并上架。请记录 小程序 ID 用于后续 SDK 中 创建 session 使用。
由于当前版本处于开发者预览状态,您需要将记录的 Agent ID 和 小程序 ID 提供给涂鸦开发者团队,以便在您的应用中启用正确的配置。
通道连接目前有两种连接类型,即:App、代理设备。
会话是建立在通道之上,一个通道内可以有多个会话 Session,数据流传输需要 Session。
当使用不同智能体、不同配置时,需要使用这些信息请求获取 Agent Token 并创建会话。
在数据流传输之前,请先确保已经创建了会话 Session。
下面为您介绍以下概念:
Event
)DataChannel
)ReuseDataChannel
)StreamFlag
)Event
)Event
可以是 App 向服务端发送,也可以是服务端投递给 App。
发送时,主要包含以下事件:
事件 | 说明 |
---|---|
EventStart |
标记事件开始,在传递数据流之前,需要先发送该事件。需要传递一个 EventId ,直到发送 EventEnd 、ChatBreak 之前,都需要使用相同的 EventId |
EventPayloadEnd |
标记 Event 内某一个数据传递完成,需要传递 DataChannel 数据 |
EventEnd |
标记事件结束。在所有数据流传递完成后,发送该事件。服务端接受到该事件后会将所有数据投递给智能体进行处理 |
ChatBreak |
打断事件。既可以在发送数据流时打断,也可以在接受数据流时打断 |
接收时,主要包含以下事件:
事件 | 说明 |
---|---|
EventStart |
标记事件开始,表示云端即将开始向 App 投递数据,其携带 EventId 与 App 发送时对应 |
EventPayloadEnd |
标记 Event 内某一个数据传递完成 |
EventEnd |
标记事件结束。在所有数据流投递完成后,投递该事件 |
ChatBreak |
打断事件。表示云端打断 App,App 不再需在这个 EventId 上发送或接收数据(需配置开启) |
ServerVAD |
云端 VAD,即:云端识别到 App 发送的音频片段结束。接收到该事件后,App 无需再继续向该 EventId 投递音频数据(即使投递云端也不再处理);需要配置开启 |
通道支持多模态,可以在一次 Event 周期内投递多种类型数据流。具体的支持数据类型,详见智能体的配置。
DataChannel
)在创建会话阶段获取 AgentToken
时中除了返回 Token 以外,还会返回 bizConfig
信息,它包含了 sendData
、revData
两个属性,用于表明传递数据类型。
SDK 会根据 bizConfig.sendData
和 bizConfig.revData
生成数据通道 sendDataChannels
和recvDataChannels
。
sendAudioData
、sendVideoData
等),可以不用关心。
dataChannel
值,目前暂无该场景。
sendEventPayloadsEnd
方法时,必须传递 dataChannel
。
ReuseDataChannel
)在创建会话接口中有 reuseDataChannel
参数,通常情况下是传递 false
,即:不启用复用。
用途主要针对实时流数据(比如:实时音频流、实时视频流)场景,当有两个或以上的会话需要对同一份实时数据做不同的处理的时候,就需要用到数据复用,对数据时效性以及传输开销友好。
StreamFlag
)数据包传递的标记,用于标记某种数据流的传输起止,有以下四种类型:
OnlyOne(0)
:仅一包,通常发文本、小尺寸图片时可以使用。StreamStart(1)
:数据流开始,表示开始发送或开始接收。通常第一包数据需要携带数据的额外属性(如:音频流数据需要携带采样率、位深、格式等),此状态数据可以为空。Streaming(2)
:数据传输中。StreamEnd(3)
:数据传输结束,此状态数据可以为空。#import <ThingSmartStreamChannelKit/ThingSmartStreamChannelKit.h>
// 使用设备身份
self.client = [ThingSmartStreamClient clientForAgentDevice:@"device_id"];
// 使用 App 身份
self.client = [ThingSmartStreamClient clientForApp];
@interface ThingSmartStreamClient : NSObject
/// Adds an Stream client delegate.
/// - Parameter delegate: Delegate
- (void)addDelegate:(id<ThingSmartStreamClientDelegate>)delegate;
/// Removes an Stream client delegate.
/// - Parameter delegate: Delegate
- (void)removeDelegate:(id<ThingSmartStreamClientDelegate>)delegate;
@end
使用示例:
在连接之前、接收数据之前,需要先设置监听才能收到相关消息。
- (void)addListner {
// self.client = [ThingSmartStreamClient clientForApp];
// self.client = [ThingSmartStreamClient clientForAgentDevice:@"xxx"];
[self.client addDelegate:self];
}
@protocol ThingSmartStreamClientDelegate <NSObject>
@optional
/// Connection connect state changed
/// - Parameters:
/// - client: stream client object
/// - connectState: connect state
/// - error: error info. when `connectState` == `ThingSmartStreamConnectStateClosedByServer`
- (void)streamClient:(ThingSmartStreamClient *)client
connectState:(ThingSmartStreamConnectState)connectState
error:(nullable NSError *)error;
/// Session state changed.
/// - Parameters:
/// - sessionID: session id
/// - sessionState: session state
/// - error: error info. when `connectState` != `ThingSmartStreamSessionStateCreateSuccess`
- (void)streamClientSessionId:(NSString *)sessionID
changedSessionState:(ThingSmartStreamSessionState)sessionState
error:(nullable NSError *)error;
@end
@protocol ThingSmartStreamClientDelegate <NSObject>
@optional
- (void)streamClientDidReceiveEvent:(ThingStreamEventPacketModel *)packet;
- (void)streamClientDidReceiveVideo:(ThingStreamVideoPacketModel *)packet;
- (void)streamClientDidReceiveAudio:(ThingStreamAudioPacketModel *)packet;
- (void)streamClientDidReceiveImage:(ThingStreamImagePacketModel *)packet;
- (void)streamClientDidReceiveFile:(ThingStreamFilePacketModel *)packet;
- (void)streamClientDidReceiveText:(ThingStreamTextPacketModel *)packet;
@end
调用流程如下:
@interface ThingSmartStreamClient : NSObject
@property (nonatomic, assign, readonly) ThingSmartStreamClientType clientType;
/// The stream client for AgentDevice.
/// - Parameter devId: Device ID.
+ (nullable instancetype)clientForAgentDevice:(NSString *)devId;
/// The stream client for App
+ (instancetype)clientForApp;
@end
@interface ThingSmartStreamClient : NSObject
/// Connect to stream server.
- (void)connect;
/// - Parameter success: calllback `connection id` when connection established.
- (void)connect:(ThingSuccessString)success;
@end
对于设备代理方式 (clientType == ThingSmartStreamClientTypeDevice
),建议在退出设备操作页面后销毁通道。
@interface ThingSmartStreamClient : NSObject
/// Disconnect from stream server.
- (void)disconnect;
/// Destory the stream client. ( Only for AgentDevice client. )
- (void)destory;
@end
typedef NS_ENUM(NSUInteger, ThingSmartStreamConnectState) {
ThingSmartStreamConnectStateIdle = 0,
ThingSmartStreamConnectStateConnecting = 1,
ThingSmartStreamConnectStateAuthing = 2,
ThingSmartStreamConnectStateConnected = 3,
ThingSmartStreamConnectStateClosedByServer = 4,
ThingSmartStreamConnectStateClosed = 5
};
@interface ThingSmartStreamClient : NSObject
@property (atomic, assign, readonly) ThingSmartStreamConnectState state;
/// Check the connection is connected;
- (BOOL)isConnected;
@end
一个 连接(Connection)
下最大可同时保持的 Session
数量为 20,请合理创建/关闭会话。
创建会话有两种方式:
方式一:常规用法:先获取 Agent Token Info
,再用其创建 Session 会话。
由于获取 Agent Token Info
是有一定耗时的,通过该方法可以前置获取,通常情况下有效期是 24 小时。
@interface ThingSmartStreamClient : NSObject
#pragma mark - Session Establish & Close
/// Query AI agent token.
/// - Parameters:
/// - params: Query params obj.
/// - success: Success handler.
/// - failure: Fail handler.
- (void)queryAgentToken:(ThingStreamQueryAgentTokenParams *)params
success:(void(^)(ThingStreamAgentTokenInfo *tokenResponse))success
failure:(ThingFailureError)failure;
/// Creat a new session.
/// - Parameters:
/// - tokenInfo: Agent token info. (use `-queryAgentToken:success:failure:` to get token info)
/// - bizTag: Biz tag.
/// - reuseDataChannel: Reuse data channel. (Default is NO)
/// - sessionId: Session ID. If `sessionId` is nil, a new session will be created.
/// - cacheBasePath: Cache receive data path.
/// - userDatas: User data list.
/// - completion: Completion.
- (void)createSessionWithToken:(ThingStreamAgentTokenInfo *)token
bizTag:(uint64_t)bizTag
reuseDataChannel:(BOOL)reuseDataChannel
sessionId:(nullable NSString *)sessionId
cacheBasePath:(nullable NSString *)cacheBasePath
userDatas:(nullable NSArray<ThingStreamAttribute *> *)userDatas
completion:(nullable ThingSmartStreamSessionCompletion)completion;
@end
方式二:简化用法:获取 Agent Token Info
并自动创建 Session 会话。
@interface ThingSmartStreamClient : NSObject
/// Query AI agent token and creat a new session.
/// - Parameters:
/// - params: Query params obj.
/// - reuseDataChannel: reuse data channel. (Default is NO)
/// - cacheBasePath: Cache receive data path. If `cacheBasePath` is nil, won't cache datas.
/// - userDatas: User data list.
/// - completion: Completion.
- (void)createSessionWithQueryParams:(ThingStreamQueryAgentTokenParams *)params
reuseDataChannel:(BOOL)reuseDataChannel
cacheBasePath:(nullable NSString *)cacheBasePath
userDatas:(nullable NSArray<ThingStreamAttribute *> *)userDatas
completion:(nullable ThingSmartStreamSessionCompletion)completion;
@end
一个 Connection
下最大可同时保持的 Session
数量为 20,请在合适的时候关闭掉不必要的会话。
@interface ThingSmartStreamClient : NSObject
/// Close a session
/// - Parameters:
/// - sessionID: session id.
/// - code: close reason.
/// - completion: Completion.
- (void)closeSession:(NSString *)sessionID
withCode:(ThingStreamAttributeConnectionSessionCode)code
completion:(nullable ThingSmartStreamCompletion)completion;
@end
Session 创建需要传 API 和相关参数,以下是调用示例和参数说明:
- (void)createSession {
// First, select an identity and ensure that the channel is connected
// self.clent = [ThingSmartStreamClient clientForAgentDevice:@"your_device_id"];
// self.client = [ThingSmartStreamClient clientForApp];
ThingStreamQueryAgentTokenParams *params = [ThingStreamQueryAgentTokenParams new];
params.solutionCode = @"your_agent_id"; // agent id
params.ownerId = @"your_home_id"; // home id
params.api = @"m.life.ai.token.get";
params.apiVerion = @"1.0";
params.extParams = @{
@"miniProgramId": @"your_mini_app_id",
@"onlyAsr": @NO, // only ASR or not
@"needTts": @NO // need TTS or not
};
WEAKSELF_ThingSDK
// Normal: Request the agent token first and then create the session.
[self.client queryAgentToken:params success:^(ThingStreamAgentTokenInfo * _Nonnull tokenResponse) {
[weakSelf_ThingSDK.client createSessionWithToken:tokenResponse bizTag:0 reuseDataChannel:NO sessionId:nil cacheBasePath:nil userDatas:nil completion:^(ThingStreamSessionInfo * _Nullable result, NSError * _Nullable error) {
if (result) {
NSLog(@"Creat success: %@", result.sessionID);
} else {
NSLog(@"Create fail: %@", error);
}
}];
} failure:^(NSError *error) {
NSLog(@"Query token fail: %@", error);
}];
// // Convenient: Request the agent token to create a session in one function
// [self.client createSessionWithQueryParams:params reuseDataChannel:NO cacheBasePath:nil userDatas:nil completion:^(ThingStreamSessionInfo * _Nullable result, NSError * _Nullable error) {
// if (result) {
// NSLog(@"Creat success: %@", result.sessionID);
// } else {
// NSLog(@"Create fail: %@", error);
// }
// }];
}
可发送的 Event 分为:
EventStart
:一轮对话开始的标志,可以指定 EventId
、也可以由 SDK 自动生成 EventId
。EventPayloadEnd
:告知云端这次对话中某一个数据流传输完成。EventEnd
:一轮对话结束,发送后 AI 会处理所有传输的数据,并进行回复。ChatBreak
:打断某个对话。可以在发送时,也可以在接收时打断。@interface ThingSmartStreamClient : NSObject
#pragma mark - Send Event Packet
/// Send event start.
/// - Parameters:
/// - sessionId: Session id.
/// - attributes: Attributes of Event Packet.
/// - Optional attributes:
/// - UserData
/// - successHandler: Success handler.
/// - failure: Failure handler.
- (void)sendEventStart:(NSString *)sessionId
userDatas:(nullable NSArray<ThingStreamAttribute *> *)userDatas
success:(nullable void(^)(NSString *eventId))successHandler
failure:(nullable ThingFailureError)failure;
/// Send event start.
/// - Parameters:
/// - sessionId: Session id.
/// - eventId: Event id.
/// - attributes: Attributes of Event Packet.
/// - Optional attributes:
/// - UserData
/// - successHandler: Success handler.
/// - failure: Failure handler.
- (void)sendEventStart:(NSString *)sessionId
eventId:(nullable NSString *)eventId
userDatas:(nullable NSArray<ThingStreamAttribute *> *)userDatas
success:(nullable void(^)(NSString *eventId))successHandler
failure:(nullable ThingFailureError)failure;
/// Send event payloads end.
/// - Parameters:
/// - eventId: Event ID. Same as the value passed in to `-startEventStart:sessionId:attributes:completion:`
/// - sessionId: Session id.
/// - dataChannel: The `dataChannel` used in`Video/Audio/Image/File/Text Packet` that transmission payload end.
/// - attributes: Attributes of Event Packet.
/// - Optional attributes:
/// - UserData
/// - completion: Completion.
- (void)sendEventPayloadsEnd:(NSString *)eventId
sessionId:(NSString *)sessionId
dataChannel:(NSString *)dataChannel
userDatas:(nullable NSArray<ThingStreamAttribute *> *)userDatas
completion:(nullable ThingSmartStreamCompletion)completion;
/// Send event end.
/// - Parameters:
/// - eventId: Event ID. Same as the value passed in to `-startEventStart:sessionId:attributes:completion:`
/// - sessionId: Session id.
/// - attributes: Attributes of Event Packet.
/// - Optional attributes:
/// - UserData
/// - EventTimestamp
/// - completion: Completion.
- (void)sendEventEnd:(NSString *)eventId
sessionId:(NSString *)sessionId
userDatas:(nullable NSArray<ThingStreamAttribute *> *)userDatas
completion:(nullable ThingSmartStreamCompletion)completion ;
/// Send event chat break.
/// - Parameters:
/// - eventId: Event ID. Same as the value passed in to `-startEventStart:sessionId:attributes:completion:`
/// - sessionId: Session id.
/// - completion: Completion.
- (void)sendEventChatBreak:(NSString *)eventId
sessionId:(NSString *)sessionId
completion:(nullable ThingSmartStreamCompletion)completion;
@end
@interface ThingSmartStreamClient : NSObject
#pragma mark - Packet
#pragma mark Send Video/Audio/Image/Text/File Packet
/// Send video packet.
/// - Parameters:
/// - videoModel: Video packet model.
/// - completion: completion.
- (void)sendVideoData:(ThingStreamVideoPacketModel *)packet completion:(nullable ThingSmartStreamCompletion)completion;
/// Send audio packet.
/// - Parameters:
/// - audioModel: Audio packet model.
/// - completion: completion.
- (void)sendAudioData:(ThingStreamAudioPacketModel *)packet completion:(nullable ThingSmartStreamCompletion)completion;
/// Send text packet.
/// - Parameters:
/// - textModel: text packet model.
/// - completion: completion.
- (void)sendTextData:(ThingStreamTextPacketModel *)packet completion:(nullable ThingSmartStreamCompletion)completion;
/// Send image packet.
/// - Parameters:
/// - imageModel: image packet model.
/// - completion: completion.
- (void)sendImageData:(ThingStreamImagePacketModel *)packet
progress:(nullable void(^)(int progress))progress
completion:(nullable ThingSmartStreamCompletion)completion;
/// Send file packet. (目前服务端模型尚未支持)
/// - Parameters:
/// - fileModel: file packet model.
/// - completion: completion.
- (void)sendFileData:(ThingStreamFilePacketModel *)packet
progress:(nullable void(^)(int progress))progress
completion:(nullable ThingSmartStreamCompletion)completion;
@end
对于 实时录制音频、播放接收音频文件提供了 ThingStreamRecorder.h
、ThingStreamPlayer.h
两个工具类,可通过引入 #import <ThingSmartStreamBizKit/ThingSmartStreamBizKit.h>
使用。
您可以访问如下地址获取 Demo:tuya-home-ios-sdk-sample-swift
使用说明:
StreamChatController.swift
文件。func createSession()
中:
solutionCode
为前置准备中记录的 Agent ID
。miniProgramId
为前置准备中记录的 小程序 ID
。func createSession()
中,选择一个会话创建方法 Normal
/Convenient
,并取消相关注释代码。code | msg | 含义 | 备注 |
---|---|---|---|
39001 | / | 通用错误 | 用于一些杂项错误 |
39002 |
|
参数不合法 |
|
39003 | 云端错误文案 | http 请求失败 | Agent token 获取失败:请求 agent token 云端接口返回失败 |
39004 | not connect | Connection 未连接 | 创建/关闭 Session、发送 Data、Event 时 |
39005 | session is invalid | SessionId 不存在 | 关闭 Session、发送 Data、Event 时 |
39006 | eventId is invalid | EventId 为空 | 发送 Event 时 |
39007 | dataChannel is invalid | DataChannel 不合法 | 发送 Data、PayloadEnd 时 |
39008 | packet is invalid | 数据包不合法 | 发 Data 时,比如:首包/仅一包数据时需要固定的参数,文本内容为空 |
39009 |
|
文件数据读取异常 | 发送 Data 时,如:图片、文件文件不存在,或读取过程中出现异常TTT:播放音频所需文件不存在(startPlayAudio ) |
39010 |
|
发送数据失败 | Socket 发送数据失败,内含 Socket 错误信息 |
39012 |
|
Connection 被远端关闭 | 详细错误对应云端错误码:200、400、401、404、408、500、504、601、602、603、604、605对 TTT 来说没有 39012,是通过 onConnectStateChanged 报的详细错误码 200、400… |
本文档详细说明了 AI 聊天组件中处理的各种 JSON 格式及其处理逻辑。
当用户发送语音输入后,系统会返回 ASR(语音识别)结果,格式如下:
{
"bizId": "asr-1754380053514",
"bizType": "ASR",
"eof": 0,
"data": {
"text": "what's the weather today?"
}
}
字段 | 字段含义 | 字段类型 | 示例值 |
---|---|---|---|
bizId | 业务 ID,用于标识一次交互 | string | asr-1754380053514 |
bizType | 业务类型,ASR 表示语音识别结果 | string | ASR |
eof | 结束标志,0 表示未结束,1 表示已结束 |
int | 0 或 1 |
data | 返回的 ASR 结果对象 | object | |
text | 识别出的文本内容 | string | what’s the weather today? |
处理逻辑:
eof
= 0
时,保存临时结果,显示中间识别结果。eof
= 1
时,显示最终识别结果并添加到聊天列表中。AI 模型响应用户查询后,返回的数据格式:
{
"bizId": "nlg-1754380053514",
"bizType": "NLG",
"eof": 0,
"data": {
"appendMode": "append",
"reasoningContent": "思考过程内容",
"content": "模型回复的文本内容",
"images": [
{
"url": "https://www.tuya.com/image1.jpg"
}
]
}
}
字段 | 字段含义 | 字段类型 | 示例值 |
---|---|---|---|
bizId | 业务 ID,用于关联同一次交互的消息 | string | nlg-1754380053514 |
bizType | 业务类型,NLG 表示自然语言生成 | string | NLG |
eof | 结束标志,0 表示流式输出中,1 表示结束 |
int | 0 或 1 |
data | 返回的数据对象 | object | |
appendMode | 文本追加模式 | string | append(追加)或其他 |
reasoningContent | 大模型思考过程(思维链) | string | 思考过程内容 |
content | 大模型生成的实际响应内容 | string | 模型回复的文本内容 |
images | 大模型返回的图片数据数组 | array | |
url | 图片的网址 | string | https://www.tuya.com/image1.jpg |
处理逻辑:
appendMode
为 append
时,将新内容追加到已有消息,否则创建新消息。eof
= 1
时,标记该 NLG 流结束。AI 可调用各种技能,如表情展示等功能。
这里仅举例说明表情类型的技能,其他技能根据智能体的定义 data
有所不同。
{
"bizId": "skill-1754380053514",
"bizType": "SKILL",
"eof": 0,
"data": {
"code": "llm_emo",
"skillContent": {
"text": "😀",
"startTime": 1000,
"endTime": 2000,
"sequence": 1
}
}
}
字段 | 字段含义 | 字段类型 | 示例值 |
---|---|---|---|
bizId | 业务 ID | string | skill-1754380053514 |
bizType | 业务类型,SKILL 表示技能调用 |
string | SKILL |
eof | 结束标志 | int | 0 或 1 |
data | 返回数据 | object | |
code | 技能代码 | string | llm_emo |
skillContent | 技能内容 | object | |
text | 表情符号 | string | 😀 |
startTime | 表情显示开始时间(毫秒) | long | 1000 |
endTime | 表情显示结束时间(毫秒) | long | 2000 |
sequence | 序列号,1 表示序列开始 |
int | 1 |
处理逻辑:
sequence
= 1
时,清空现有表情步骤列表。eof
= 1
时,开始按时间顺序展示表情。系统支持以下表情类型:
情绪类型 | Unicode 表情 | 显示效果 |
---|---|---|
SAD | \uD83D\uDE22 | 😢 |
ANGRY | \uD83D\uDE20 | 😠 |
NEUTRAL | \uD83D\uDE10 | 😐 |
FEARFUL | \uD83D\uDE28 | 😨 |
SURPRISE | \uD83D\uDE32 | 😲 |
CONFUSED | \uD83D\uDE15 | 😕 |
DISAPPOINTED | \uD83D\uDE1E | 😞 |
ANNOYED | \uD83D\uDE21 | 😡 |
THINKING | \uD83E\uDD14 | 🤔 |
HAPPY | \uD83D\uDE00 | 😀 |
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈