mirror of
https://github.com/kuaifan/dootask.git
synced 2026-07-31 10:25:59 +00:00
75 lines
2.3 KiB
Markdown
75 lines
2.3 KiB
Markdown
---
|
||
id: ai-assistant.streaming.concept
|
||
title: AI 助手流式输出
|
||
type: concept
|
||
feature: ai-assistant
|
||
scope: end-user
|
||
locale: zh
|
||
aliases:
|
||
- AI 流式回答
|
||
- 边写边出
|
||
- AI 一边打字一边显示
|
||
- SSE 流
|
||
- AI 实时输出
|
||
related_tools: []
|
||
related_pages: []
|
||
prerequisites: []
|
||
negative:
|
||
- 不支持 WebSocket 推送,固定走 SSE
|
||
- 不支持手动重试单条;流断后该 message 标记 error,需重新发送
|
||
- 同会话并发流会被前一个的发送动作清掉
|
||
last_verified: v1.7.90
|
||
---
|
||
|
||
# AI 助手流式输出
|
||
|
||
## 定义
|
||
AI 助手通过 **SSE(Server-Sent Events)** 接收上游 LLM 的逐 token 输出,每收到一个 chunk 就追加到当前 message 的 `rawOutput`,呈现 ChatGPT 般「边写边出」的效果。
|
||
|
||
## 数据流
|
||
1. `POST api/assistant/auth` → 拿 stream_key
|
||
2. `EventSource ai/invoke/stream/{stream_key}`
|
||
3. 监听三类事件:
|
||
- `append` → 追加(`entry.rawOutput += chunk`)
|
||
- `replace` → 整段替换(`entry.rawOutput = chunk`)
|
||
- `done` → 流结束(`entry.status = 'completed'`)
|
||
4. 断流 / 异常 → `handleStreamFailed`
|
||
|
||
## 事件类型
|
||
|
||
| 事件 | 用途 |
|
||
|---|---|
|
||
| `append` | 普通增量 token(最常见) |
|
||
| `replace` | 整段替换(工具结果回填、思考链重写) |
|
||
| `done` | 流结束,payload 含 `error` 字段表示上游报错 |
|
||
|
||
## 状态机
|
||
每条 AI message 4 个状态:
|
||
- `waiting` → 已发出但首个 chunk 未到
|
||
- `streaming` → 正在接收 chunk
|
||
- `completed` → `done` 正常收到
|
||
- `error` → 上游错误、连接失败、用户中断
|
||
|
||
## 并发与归属
|
||
- 每个流绑定 `owner = {sessionKey, sessionId, localId}`
|
||
- 用户切到其他会话后,原流仍后台跑,结束时写回原会话存储
|
||
- 发新问题前会清掉同会话的所有活跃流,防止两段对话错位
|
||
|
||
## 中断恢复保护
|
||
- 关浮窗 / 页面崩溃后,下次加载会话发现 message 仍是 `streaming/waiting` 则归一为 `error`
|
||
- 避免「永远转圈」(`sanitizeResponsesForPersist`)
|
||
|
||
## 滚动行为
|
||
- 视图在最底部时新 chunk 自动 `scrollToBottom`
|
||
- 用户向上翻历史时(距底 > 20px)不强制下拉
|
||
|
||
## 不支持
|
||
- 不支持 WebSocket
|
||
- 不支持 chunk 级别撤销
|
||
- 不支持自动重试断流
|
||
|
||
## 相关
|
||
- [[ai-assistant.stop.howto]]
|
||
- [[ai-assistant.modal.concept]]
|
||
- [[ai-assistant.session-save.howto]]
|