# New Chat 接口流式返回格式说明 ## 接口概览 - **路径**:`POST /new_chat` - **传输协议**:Server-Sent Events (SSE) - **Content-Type**:`text/event-stream` - **协议基础**:Vercel AI SDK Data Stream Protocol --- ## 请求格式 ```json { "chat_id": 123, "search_space_id": 456, "user_query": "用户问题", "pic_query": [{"image_url": "/tmp/xxx.png"}], "model_name": "gpt-4o", "enable_citations": true, } ``` | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `chat_id` | int | ✅ | 会话 ID,同时作为 LangGraph 的 thread_id | | `search_space_id` | int | ✅ | 搜索空间 ID | | `user_query` | string | ✅ | 用户问题 | | `pic_query` | list\|null | ❌ | 图片路径列表,格式 `[{"image_url": "..."}]` | | `model_name` | string\|null | ❌ | 指定模型名称(插件场景使用) | | `enable_citations` | bool | ❌ | 是否启用引用(默认 true) | | `messages` | list\|null | ❌ | 历史消息列表 | | `attachments` | list\|null | ❌ | 上传附件(已解析为 Markdown) | | `mentioned_document_ids` | list\|null | ❌ | 前端 @ 引用的文档 ID 列表 | --- ## 响应 Headers ``` Content-Type: text/event-stream Cache-Control: no-cache Connection: keep-alive X-Accel-Buffering: no ``` --- ## SSE 数据帧格式 每条消息均为标准 SSE 格式: ``` data: {JSON 对象}\n\n ``` 流结束时发送: ``` data: [DONE]\n\n ``` --- ## 事件类型详解 ### 1. 消息生命周期 #### `start` — 消息开始 ```json {"type": "start", "messageId": "msg_abc123"} ``` | 字段 | 说明 | |------|------| | `messageId` | 本次消息的唯一 ID | --- #### `finish` — 消息结束 ```json {"type": "finish"} ``` --- #### `[DONE]` — 流终止标记 ``` data: [DONE] ``` > 这是流中最后一帧,为纯字符串,不是 JSON。 --- ### 2. 步骤控制(多轮工具调用) #### `start-step` — 步骤开始 ```json {"type": "start-step"} ``` #### `finish-step` — 步骤结束 ```json {"type": "finish-step"} ``` > 每次 LLM 调用算一个 step。工具调用期间会有多个 step 交替出现。 --- ### 3. 文本块(start / delta / end 模式) #### `text-start` — 文本块开始 ```json {"type": "text-start", "id": "text_abc123"} ``` #### `text-delta` — 文本增量内容 ```json {"type": "text-delta", "id": "text_abc123", "delta": "Hello, "} ``` #### `text-end` — 文本块结束 ```json {"type": "text-end", "id": "text_abc123"} ``` --- ### 4. 推理块(Reasoning,适用于 DeepSeek R1 等思维链模型) #### `reasoning-start` — 推理块开始 ```json {"type": "reasoning-start", "id": "reasoning_abc123"} ``` #### `reasoning-delta` — 推理增量内容 ```json {"type": "reasoning-delta", "id": "reasoning_abc123", "delta": "让我先思考..."} ``` #### `reasoning-end` — 推理块结束 ```json {"type": "reasoning-end", "id": "reasoning_abc123"} ``` > 触发时机: > - 模型返回 `additional_kwargs.reasoning_content`(DeepSeek R1 原生) > - 模型输出中包含 `...` 标签(自动剥离) --- ### 5. 工具调用 #### `tool-input-start` — 工具调用开始 ```json {"type": "tool-input-start", "toolCallId": "call_abc123", "toolName": "search_knowledge_base"} ``` #### `tool-input-delta` — 工具输入流式内容(增量) ```json {"type": "tool-input-delta", "toolCallId": "call_abc123", "inputTextDelta": "San Fra"} ``` #### `tool-input-available` — 工具输入完整参数 ```json { "type": "tool-input-available", "toolCallId": "call_abc123", "toolName": "search_knowledge_base", "input": {"query": "机器学习入门"} } ``` #### `tool-output-available` — 工具执行结果 ```json { "type": "tool-output-available", "toolCallId": "call_abc123", "output": {"status": "completed", "result_length": 1234} } ``` > 注意:`search_knowledge_base` 只返回摘要(不含全文),`write_todos`、`link_preview`、`display_image`、`scrape_webpage`、`generate_podcast` 会返回完整 output 供前端渲染组件。 --- ### 6. 来源引用 #### `source-url` — URL 来源 ```json { "type": "source-url", "sourceId": "https://example.com", "url": "https://example.com", "title": "示例页面" } ``` #### `source-document` — 文档来源 ```json { "type": "source-document", "sourceId": "doc_123", "mediaType": "file", "title": "报告.pdf", "description": "第三季度报告" } ``` --- ### 7. 文件 ```json {"type": "file", "url": "https://example.com/image.png", "mediaType": "image/png"} ``` --- ### 8. 自定义数据(`data-*` 类型) #### `data-terminal-info` — 终端信息提示 ```json { "type": "data-terminal-info", "data": { "text": "知识库搜索已完成", "type": "success" } } ``` `type` 枚举值:`info` | `error` | `success` | `warning` --- #### `data-further-questions` — 推荐追问问题 ```json { "type": "data-further-questions", "data": { "questions": ["问题1", "问题2", "问题3"] } } ``` --- #### `data-thinking-step` — 思考步骤(思维链 UI 展示) ```json { "type": "data-thinking-step", "data": { "id": "thinking-1", "title": "正在搜索知识库", "status": "in_progress", "items": ["Query: 机器学习入门"] } } ``` | 字段 | 说明 | |------|------| | `id` | 步骤唯一 ID(格式 `thinking-N`) | | `title` | 步骤标题 | | `status` | `pending` \| `in_progress` \| `completed` | | `items` | 步骤详情列表(可选) | > 同一个 `id` 的步骤事件会被重复发送以更新状态(先 `in_progress` 后 `completed`)。 **常见步骤标题对照:** | 工具 / 场景 | 标题 | |------------|------| | 初始分析 | 正在理解您的请求 / 正在分析您的内容 | | `search_knowledge_base` | 查询个人知识库中 | | `search_web` | 网查搜索中 | | `link_preview` | 正在获取链接预览 | | `display_image` | 正在分析图片 | | `scrape_webpage` | 正在抓取网页 | | `write_todos`(首次) | 正在创建计划 | | `write_todos`(更新) | 正在更新进度 | | `generate_podcast` | 正在生成播客 | --- ### 9. 错误 ```json { "type": "error", "errorText": "API rate limit exceeded", "errorType": "llm", "errorCode": "rate_limit" } ``` | 字段 | 说明 | |------|------| | `errorText` | 错误描述文本 | | `errorType` | 错误类型(见下表) | | `errorCode` | 具体错误代码(可选) | **errorType 枚举:** | 值 | 含义 | |----|------| | `llm` | LLM / API 错误(模型不存在、限流、密钥错误等) | | `network` | 网络连通性错误 | | `timeout` | 请求超时 | | `authentication` | 鉴权 / 权限错误 | | `rate_limit` | 速率限制 | | `validation` | 输入验证错误 | | `internal` | 内部服务器错误 | | `unknown` | 未知错误 | --- ### 10. 中断(Human-in-the-loop) ```json { "type": "interrupt", "messageId": "msg_abc123", "interrupt": { "action_requests": [...], "review_configs": [...] }, "payload": {"expertAgentId": 42} } ``` --- ## 完整流示例(普通问答) ``` data: {"type":"start","messageId":"msg_abc123"} data: {"type":"start-step"} data: {"type":"data-thinking-step","data":{"id":"thinking-1","title":"正在理解您的请求","status":"in_progress","items":["Processing: 什么是向量数据库?"]}} data: {"type":"data-thinking-step","data":{"id":"thinking-1","title":"正在理解您的请求","status":"completed","items":["Processing: 什么是向量数据库?"]}} data: {"type":"text-start","id":"text_xyz789"} data: {"type":"text-delta","id":"text_xyz789","delta":"向量数据库是"} data: {"type":"text-delta","id":"text_xyz789","delta":"一种专为存储和检索"} data: {"type":"text-delta","id":"text_xyz789","delta":"高维向量而设计的数据库..."} data: {"type":"text-end","id":"text_xyz789"} data: {"type":"finish-step"} data: {"type":"finish"} data: [DONE] ``` --- ## 完整流示例(含工具调用) ``` data: {"type":"start","messageId":"msg_abc123"} data: {"type":"start-step"} data: {"type":"data-thinking-step","data":{"id":"thinking-1","title":"正在理解您的请求","status":"in_progress","items":["Processing: 搜索最新 AI 论文"]}} data: {"type":"data-thinking-step","data":{"id":"thinking-1","title":"正在理解您的请求","status":"completed","items":["Processing: 搜索最新 AI 论文"]}} data: {"type":"data-thinking-step","data":{"id":"thinking-2","title":"查询个人知识库中","status":"in_progress","items":["Query: 最新 AI 论文"]}} data: {"type":"tool-input-start","toolCallId":"call_xxx","toolName":"search_knowledge_base"} data: {"type":"tool-input-available","toolCallId":"call_xxx","toolName":"search_knowledge_base","input":{"query":"最新 AI 论文"}} data: {"type":"data-thinking-step","data":{"id":"thinking-2","title":"Searching knowledge base","status":"completed","items":["Query: 最新 AI 论文","Found relevant information (2048 chars)"]}} data: {"type":"tool-output-available","toolCallId":"call_xxx","output":{"status":"completed","result_length":2048}} data: {"type":"data-terminal-info","data":{"text":"知识库搜索已完成","type":"success"}} data: {"type":"text-start","id":"text_xyz789"} data: {"type":"text-delta","id":"text_xyz789","delta":"根据知识库中的内容..."} data: {"type":"text-end","id":"text_xyz789"} data: {"type":"finish-step"} data: {"type":"finish"} data: [DONE] ``` --- ## 完整流示例(含推理过程) ``` data: {"type":"start","messageId":"msg_abc123"} data: {"type":"start-step"} data: {"type":"reasoning-start","id":"reasoning_r01"} data: {"type":"reasoning-delta","id":"reasoning_r01","delta":"让我先分析这个问题..."} data: {"type":"reasoning-delta","id":"reasoning_r01","delta":"需要考虑以下几个方面..."} data: {"type":"reasoning-end","id":"reasoning_r01"} data: {"type":"text-start","id":"text_xyz789"} data: {"type":"text-delta","id":"text_xyz789","delta":"综合分析后,结论是..."} data: {"type":"text-end","id":"text_xyz789"} data: {"type":"finish-step"} data: {"type":"finish"} data: [DONE] ``` --- ## 标准消息流顺序 ``` start └─ start-step ├─ [data-thinking-step × N] 思考步骤(可多次) ├─ [reasoning-start/delta/end] 推理过程(可选) ├─ [tool-input-start] 工具调用开始(可多次) ├─ [tool-input-available] 工具参数确认 ├─ [tool-output-available] 工具结果 ├─ [data-terminal-info] 终端提示(可多次) ├─ [source-url / source-document] 来源引用(可选) ├─ text-start │ └─ text-delta × N 流式文本 └─ text-end finish-step finish [DONE] ```