流式返回中的非文本事件
Q:流式返回时,如何插入非文本事件(工具调用标记、思考过程、错误提示、分段标识),且不影响前端渲染?
来源:牛客Agent面经汇总(含答题思路)
新手答:“把工具调用信息也当文本发回去就行了。”
高手答:
核心思路是结构化事件流——不是所有内容都是文本,SSE 的 event 字段天然支持事件分类。
协议设计:
text
event: text
data: {"content": "让我帮你查一下..."}
event: tool_call
data: {"tool": "search", "params": {"query": "xxx"}, "status": "start"}
event: thinking
data: {"content": "用户想要对比两个方案..."}
event: tool_result
data: {"tool": "search", "status": "done", "summary": "找到3条结果"}
event: text
data: {"content": "根据搜索结果,..."}
event: error
data: {"code": "TOOL_TIMEOUT", "message": "搜索服务超时,已使用缓存结果"}前端渲染策略:
| 事件类型 | 渲染方式 |
|---|---|
text | 追加到主回答区,支持 Markdown 流式渲染 |
thinking | 折叠区域,默认收起,用户可展开 |
tool_call | 状态卡片(加载动画 → 完成打勾) |
error | 内联 toast 或黄色提示条,不打断主流 |
separator | 分段线,标记逻辑段落边界 |
工程细节:
- 每个事件带序号(
id字段):断线重连时从上次 ID 续传 - 工具调用用 start/done 配对:前端据此展示“正在调用 XX”的 loading 态
- 文本和非文本事件交错:前端维护一个渲染队列,按序号严格顺序渲染
- 错误事件分级:warning 级不中断流,error 级中断当前段落
差距在哪:面试官考的是“你做过面向用户的 Agent 产品吗”。只会拼接文本字符串说明你没处理过工具调用的中间态展示。能设计出分层事件协议 + 前端分类渲染,说明你理解 Agent 和纯 ChatBot 在交互设计上的本质区别。