5.9 KiB
5.9 KiB
事件流说明(轮询返回 events)
GET /api/v1/tasks/{task_id} 返回的 events 字段,是一个按时间顺序(idx 递增)的事件流。
本项目的目标是:与网页端 WebSocket 事件保持同一粒度。因此你会看到:
- token 级别的
text_chunk/thinking_chunk - 工具调用生命周期事件(准备/意图/开始/状态更新)
- 工具执行结果的状态更新与系统消息
提示:客户端应只依赖
type字符串与data字段,并对未知事件类型保持兼容(忽略或记录)。
1. 事件统一包裹格式(envelope)
每个事件的结构:
{
"idx": 12,
"type": "text_chunk",
"data": { "content": "你好", "index": 5, "elapsed": 0.003 },
"ts": 1769182968.154797
}
字段含义:
idx:事件序号(从 0 开始递增),用于轮询 offset 与去重type:事件类型(字符串)data:事件载荷(不同 type 不同结构)ts:服务端记录的 UNIX 时间戳(秒,float)
2. offset 与去重
轮询接口支持 from 参数:
GET /api/v1/tasks/{task_id}?from=0:从头拉取GET /api/v1/tasks/{task_id}?from=next_offset:增量拉取 (路径里的{task_id}为任务 id)
正确做法:
- 客户端本地保存
offset(初始 0) - 轮询请求带上
from=offset - 处理返回
events - 将
offset更新为返回的next_offset
3. 常见事件类型与载荷
以下为常见事件类型(实际可能随版本增加更多 type)。
3.1 AI 消息生命周期
ai_message_start
AI 新一轮回复开始(一次用户消息可能触发多次迭代,但 UI 通常以此作为“助手消息开始”的信号)。
{ "type": "ai_message_start", "data": {} }
3.2 思考(reasoning)
thinking_start
{ "type": "thinking_start", "data": {} }
thinking_chunk
逐段思考内容(细粒度流式)。
{ "type": "thinking_chunk", "data": { "content": "..." } }
thinking_end
思考结束(带完整思考文本)。
{ "type": "thinking_end", "data": { "full_content": "..." } }
建议客户端处理方式:
- 若你想还原“实时思考流”,就持续 append
thinking_chunk.data.content; - 若你只想最终值,可忽略 chunk,只在
thinking_end读取full_content。
3.3 正文输出(token 级)
text_start
{ "type": "text_start", "data": {} }
text_chunk
逐 token/子串输出。字段:
content:本次增量内容index:从 1 开始的 chunk 序号(仅用于调试/对齐)elapsed:与上一 chunk 的时间间隔(秒)
{
"type": "text_chunk",
"data": { "content": "你好", "index": 5, "elapsed": 0.003 }
}
text_end
正文结束,包含 full_content(完整文本)。
{ "type": "text_end", "data": { "full_content": "..." } }
建议客户端处理方式:
- 实时显示:append
text_chunk.data.content - 最终落盘:以
text_end.data.full_content为准(如果你做了实时 append,最终可用 full_content 校验/纠偏)
注意:若模型在工具调用后没有再次输出总结文本,则可能出现“最后一轮事件是工具相关,没有 text_end”的情况;这属于模型行为/迭代次数限制导致,并不代表任务异常。
3.4 工具调用(tool)相关
工具链路通常会出现如下事件:
tool_preparing(模型开始输出 tool_calls 时)tool_intent(从增量 arguments 中抽取 intent 字段)tool_start(真正执行工具时)update_action(执行进度与结果状态更新)
tool_preparing
{
"type": "tool_preparing",
"data": {
"id": "web_search:0",
"name": "web_search",
"message": "准备调用 web_search...",
"intent": "搜索明日方舟终末地游戏信息",
"conversation_id": "conv_..."
}
}
tool_intent
{
"type": "tool_intent",
"data": {
"id": "web_search:0",
"name": "web_search",
"intent": "搜索明日方舟终末地游戏信息",
"conversation_id": "conv_..."
}
}
tool_start
{
"type": "tool_start",
"data": {
"id": "tool_0_web_search_...",
"name": "web_search",
"arguments": { "...": "..." },
"preparing_id": "web_search:0",
"monitor_snapshot": null,
"conversation_id": "conv_..."
}
}
说明:
preparing_id用于把“模型输出的 tool_call”与“真实执行的工具卡片”关联起来arguments为工具参数(通常是 JSON 对象)
update_action
该事件用于更新工具卡片(或其他 action)的状态。字段随工具不同可能略有差异,但通常包含:
id:与tool_start.data.id对应status:running/completed/failed/...message:可读描述- 可能还带
result/summary/monitor_snapshot/...
客户端建议:
- 把
update_action当作通用的“状态更新”事件处理; - 对未知字段保持兼容(直接展示或忽略)。
3.5 系统消息与错误
system_message
{ "type": "system_message", "data": { "content": "..." } }
error
任务内错误(不同于 HTTP 层错误)。出现后通常任务会进入 failed。
{ "type": "error", "data": { "message": "..." } }
3.6 任务结束
task_complete
{
"type": "task_complete",
"data": {
"total_iterations": 2,
"total_tool_calls": 1,
"auto_fix_attempts": 0
}
}
结束条件以轮询返回的
status != running为准;task_complete是一个“完成事件”,但客户端仍应读取status。
4. 事件缓冲与性能建议
- 服务端每个任务保存最近 1000 条事件(队列会丢弃更早的数据)
- 建议轮询间隔
0.5s ~ 2s - 长任务建议客户端把
text_chunk与关键工具事件持久化到本地,避免错过