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 協商時,長文字可能按一種寬度測量高度、按另一種寬度排版,造成末尾幾行被截掉。
