AI 回复
用户和 AI 机器人单聊时,机器人的回复是一条 type 为 ai 的消息,内容边生成边推送过来。im.ai 负责接收这些实时内容:按顺序拼接、断线后续传、重新上线时补发,回复结束后以消息正文为准;你只需要显示。机器人和回复由你的服务端创建,见 AI 对话。
版本
AI 回复从 SDK 2.0.1 起提供,下载见 Demo 运行指南与下载。
机器人
机器人在客户端就是一个普通用户:用户资料的 kind 为 bot,可以加好友、出现在会话列表中,用户像平常一样给它发文字消息即可。机器人不能被拉进群,在群里邀请机器人会失败(permission_denied,details.reason 为 bot_account)。
AI 消息
MessageView.type 为 ai 时,用 im.ai.bodyOf(message) 读取正文:
val body = im.ai.bodyOf(message) ?: return // 不是 ai 消息时为 null
println(body.status) // streaming、completed、stopped、failed
println(body.parts) // 结束后的完整内容;生成中为空| 字段 | 说明 |
|---|---|
streamId | 这条回复的流 ID,读取实时内容、停止生成时使用 |
status | streaming 生成中,completed 已完成,stopped 已停止,failed 生成中断 |
parts | 片段(AIPart):type 为 text 的正文(Markdown),reasoning 思考过程,image、file 附件,tool 工具调用的进度(state 为 running、done、failed) |
text | 正文去掉 Markdown 后的纯文本,最多 2000 个字符,复制、预览时使用 |
finishReason、error | 结束原因;生成中断时 error.message 是要显示给用户的说明 |
片段的完整说明见 AI 消息。会话列表的预览(summarize 已支持 AI 消息:生成中、已停止、生成中断各有文案)、未读数、搜索与普通消息相同。
显示生成中的内容
生成中的消息 parts 为空,实时内容在 im.ai.state(streamId) 中,每次更新发出 DREvent.AIStreamUpdated:
fun partsOf(message: MessageView): List<AIPart> {
val body = im.ai.bodyOf(message) ?: return emptyList()
return if (body.status == "streaming") im.ai.state(body.streamId)?.parts.orEmpty() else body.parts
}
lifecycleScope.launch {
im.events.collect { event ->
when (event) {
// state.parts 是当前完整内容(不是增量),按它整体重画这条消息
is DREvent.AIStreamUpdated -> redrawByStream(event.state.streamId)
is DREvent.AIStreamStarted -> redrawByStream(event.state.streamId)
// 回复结束:消息随后(或已经)以 MessagesChanged 更新为最终内容
is DREvent.AIStreamEnded -> redrawByStream(event.streamId)
else -> {}
}
}
}| 事件 | 时机 |
|---|---|
AIStreamStarted | 收到一条生成中的 AI 消息 |
AIStreamUpdated | 内容更新:收到新的内容,或断线续传、重新上线后补齐;state.parts 为当前完整内容 |
AIStreamEnded | 回复结束(status 为 completed、stopped、failed);最终内容在消息正文中 |
- 推送合并为每 50 毫秒或 2 KB 一次。生成中只重画这一条消息,不要每次更新都重建整个消息列表。
- 断线、切到后台再回来、重新启动 App 时,SDK 自动补齐正在生成的内容,不需要处理。
im.ai.state()在回复结束后返回null,之后读取消息正文。
停止生成
val stream = im.ai.stop(body.streamId)
// stream.status 为 stopped;已结束的回复返回当前状态,不报错只有接收回复的用户可以停止。停止后回复立即结束,已生成的内容保留,机器人的服务端会收到停止通知。需要从服务端读取一条回复的当前内容时用 im.ai.get(streamId);结束超过 10 分钟的以 not_found 失败,改为读取消息。
Java 中通过 im.ai() 使用同样的方法:stop、get 提供回调和 ...Async() 入口,见 Java 接入。
重新生成
平台没有单独的“重新生成”接口:再发一次被回复的问题,机器人的服务端会开始一条新的回复。AI 消息的 replyTo 指向它回答的那条消息。
示例 App
示例 App 的聊天页已显示 AI 回复(AIBubble.kt),可以作为参考:
- 正文按 Markdown 显示(标题、粗体、行内代码、列表、引用、代码块、表格),生成中末尾显示光标;
- 思考过程、工具调用的进度(进行中、完成、失败、已取消)、文件附件;
- 生成中显示“停止生成”,结束后提供“复制”;已停止、生成中断(带原因)的提示。
AI 回复的内容可能很长,气泡宜使用固定宽度(例如内容区的最大宽度)。宽度由外层 wrap_content 与 match_parent 协商时,长文本可能按一种宽度测量高度、按另一种宽度排版,造成末尾几行被截掉。
