From da5ae863213811e3ccb025cb9401f90a0b81bf89 Mon Sep 17 00:00:00 2001 From: Hongyu Shi Date: Wed, 6 Aug 2025 18:39:38 +0800 Subject: [PATCH] docs: add openHermes backend docs Signed-off-by: Hongyu Shi --- ...44\344\272\222\345\275\242\345\274\217.md" | 708 +++ ...0\347\275\262\345\275\242\346\200\201.png" | Bin 0 -> 30791 bytes .../server-side/openHermes.openapi.json | 5219 +++++++++++++++++ 3 files changed, 5927 insertions(+) create mode 100644 "docs/development/server-side/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222\345\275\242\345\274\217.md" create mode 100644 "docs/development/server-side/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222/openEuler_Inteligence_\351\203\250\347\275\262\345\275\242\346\200\201.png" create mode 100644 docs/development/server-side/openHermes.openapi.json diff --git "a/docs/development/server-side/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222\345\275\242\345\274\217.md" "b/docs/development/server-side/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222\345\275\242\345\274\217.md" new file mode 100644 index 0000000..a8df352 --- /dev/null +++ "b/docs/development/server-side/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222\345\275\242\345\274\217.md" @@ -0,0 +1,708 @@ +# openEuler Intelligence 框架交互 + +## 部署形态 + +在本地环境下 openEuler Intelligence 的部署形态如下图所示: + +![openEuler Inteligence 部署形态](.\openEuler_Inteligence_部署形态.png) + +首先,当前有一套(基于rpm的)一键部署的脚本来用于 openEuler Intelligence 的部署,如上图所示,运行 openEuelr Intelligence 的最小单位是框架 + MongoDB,并且在部署之前可以在框架指定的目录下存放对应的 mcp config 并且在一键部署的脚本中填写 Agent 的配置,那么会在框架服务启动的时候将 mcp 服务进行注册和构建默认的 Agent。 + +其次,为了轻量化部署,降低本地运行消耗,在这套部署体系下 Web 和知识库是可选的(PS:Web 为了便携用户后续 MCP 注册和 Agent 的构建,知识库则是提供了文档治理和知识检索的能力,可以让框架在基本问答模式下更好的运作)。 + +接着,用户要使用 openEuler Intelligence 服务,需要和安装服务的人在同一个组;在本地环境下 openEuler Intelligence 不需要鉴权即可访问,通过识别当前操作系统用户名称作为当前用户的 user_sub,后续只要使用同一个用户进行登入那么即可访问用户使用的一些列历史记录。 + +最后,openEuler 提供了几个 API 用于对外提供 Agent 的能力,具体如下,在后文对其中的 chat 接口返回的信息中会更详细的讲解: + +```text +GET /api/conversation (获取用户当前所有对话记录) + +POST /api/conversation(创建新对话) + +GET /api/record/{conversation_id}(获取会话下的所有用户和智能体的交互历史) + +GET /api/chat(在会话中通过流式的形式与智能体会话) + +GET /api/app(获取当前用户可用的智能体) +``` + +接口的输入&输出及详情可以通过加入下面团队进行访问 + + + +## openEuler Intelligence 框架交互逻辑 + +### 用户整体的使用逻辑如下图所示 + +```mermaid +flowchart TB + user[用户] + state1[激活mcp] + state2[构建Agent应用] + state3[使用Agent应用] + state4[确认执行工具] + state5[工具执行] + state7[用户手动填参] + state8[执行结束] + user-->state1 + state1-->state2 + state2-->state3 + state3-->conda1{用户是否开启自动执行} + conda1-->|yes|state5 + conda1-->|no|state4 + state4-->conda2{是否执行} + conda2-->|yes|state5 + conda2-->|no|state8 + state5-->conda4{是否达到最后一步} + conda4-->|yes|state8 + conda4-->|no|conda3{工具执行是否报错} + conda3-->|yes|state7 + conda3-->|no|conda1 + state7-->state5 +``` + +### MCP 注册 + +```mermaid +flowchart TB + user[用户] + web[openEuler intelligence前端] + process[进程管理] + framework[框架] + os[操作系统] + user--[1]注册mcp-->web + web--[9]可视化展示mcp安装状态-->user + web--[2]传输mcp config+mcp env-->framework + framework--[3]存储 mcp config-->os + os--[4]存储成功/失败-->framework + framework--[5]创建进程安装mcp相关的依赖-->process + process--[6]返回mcp相关的依赖安装结果-->framework + web--[7]轮询mcp安装状态-->framework + framework--[8]返回mcp安装状态-->web +``` + +### Agent 构建 + +```mermaid +flowchart TB + user[用户] + web[openEuler intelligence前端] + framework[框架] + mongodb[数据库] + user--[1]创建基于mcp的Agent应用-->web + web--[2]发送用户选择的mcp的列表和Agent应用的基本参数-->framwork + framwork--[3]存储Agent信息-->mongodb + mongodb--[4]存储成功/失败-->framework + framework--[5]返回Agent创建结果-->web + web--[6]可视化Agent创建结果-->user +``` + +### 交互 + +这里的交互是指用户与Agent的交互,下面两个主要的交互示意图,一个主要是描述用户行为一个主要描述后端行为 + +#### 用户交互示意图 + +```mermaid +flowchart TB + user[用户] + state1[流程(重)规划] + state2[询问用户是否执行工具] + state3[用户补充参数] + state4[执行工具前的描述] + state8[(重)生成参数] + state5[执行工具] + state6[总结] + state7[流结束执行] + user--使用Agent应用-->state1 + state1-->state2 + state2-->conda1{yes/no} + conda1-->|yes|state4 + state4-->state8 + state8-->state5 + conda1-->|no|state7 + state6-->state7 + state5-->conda2{执行成功或者失败} + conda2-->|成功|conda5{流程是否执行完毕} + conda5-->|是|state6 + conda5-->|否|state2 + conda2-->|失败|conda3{当前计划是否可以修复} + conda3-->|是|conda4{是否是因为当前步骤缺失参数引起的执行错误} + conda3-->|否|state7 + conda4-->|是|state3 + conda4-->|否|conda6{是否需要重新规划} + conda6-->|是|state1 + conda6-->|否|state8 + state3-->state8 +``` + +在使用chat接口与后端交互的时候会接收到流式返回的信息,单条流式消息内容模板如下(后续将与Agent的交互流程称为流): + +```json +{ + "event": "heartbeat", + "id": "550e8400-e29b-41d4-a716-446655440000", + "groupId": "550e8400-e29b-41d4-a716-446655440001", + "conversationId": "550e8400-e29b-41d4-a716-446655440002", + "taskId": "550e8400-e29b-41d4-a716-446655440003", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "stepId": "23641ffd-a8db-403a-9cf8-5ca305db3a0d", + "stepName": "大模型", + "stepStatus": "running" + } + "content": { + "text": "这是一条心跳消息内容", + "type": "heartbeat_info" + }, + "metadata": { + "inputTokens": 0, + "outputTokens": 0, + "timeCost": 0.05, + "feature": null, + "footNoteMetadataList": [] + } +} +``` + +event 代表这条流式消息的类型 + +groupId 代表这条流式消息关联的消息组 id + +id 代表这条流式消息关联的消息记录的 id + +conversationId 代表这条流式消息关联的对话的 id + +taskId 代表这条流式消息关联的任务的 id + +flow 代表这条流式消息关联的执行流的信息(内部含有当前执行的流来自的应用以及流的状态和基本等信息) + +context 存放了前端真实要渲染的内容步骤的出参、入参和回显的文字等 + +节下面的事件类型和上面的模板下面有几种衍生信息 + +## 一、流状态转换关系 + +**初始化(init)→ 运行(running)** +触发条件:流初始化完成后开始工作 +对应消息:init 消息后触发 flow.start 消息 +**运行(running)→ 暂停(stop)** +触发条件:步骤需要用户确认执行(step.waiting_for_start)或等待补充参数(step.waiting_for_param) +对应消息:flow.stop 消息随步骤等待消息一同发送 +**暂停(stop)→ 运行(running)** +触发条件:用户确认执行步骤或补充参数后,流恢复执行 +对应消息:无单独流启动消息,通过步骤状态变更(step.input)体现流恢复运行 +**运行(running)→ 失败(error)** +触发条件:单个步骤多次执行失败或其他异常 +对应消息:flow.failed 消息,包含失败步骤信息 +**运行 / 暂停(running/stop)→ 取消(cancel)** +触发条件:用户主动暂停对话或取消步骤执行 +对应消息:flow.cancel 消息,同步更新流和步骤状态 +**运行(running)→ 成功(success)** +触发条件:所有步骤执行完成且无异常 +对应消息:flow.success 消息,标识流执行结束 +**成功 / 失败(success/error)→ 通道关闭** +触发条件:流执行完成(无论成功或失败) +对应消息:成功时输出 [DONE],失败时输出 [ERROR] + +## 二、步骤状态转换关系 + +**初始化(init)→ 等待确认(waiting_for_start)** +触发条件:步骤初始化后,需用户确认是否执行(非自动执行模式) +对应消息:step.waiting_for_start 消息,包含风险提示 +**初始化(init)→ 运行中(running)** +触发条件:步骤初始化后,无需用户确认(自动执行模式) +对应消息:无单独步骤运行消息,通过 step.input 消息体现 +**等待确认(waiting_for_start)→ 运行中(running)** +触发条件:用户确认执行步骤 +对应消息:step.input 消息,输出步骤入参 +**等待确认(waiting_for_start)→ 取消(cancel)** +触发条件:用户拒绝执行步骤 +对应消息:step.cancel 消息,同步终止流和步骤 +**运行中(running)→ 成功(success)** +触发条件:步骤执行完成且无错误 +对应消息:step.output 消息,输出步骤出参 +**运行中(running)→ 等待参数(waiting_for_param)** +触发条件:步骤执行时发现参数缺失,需用户确认(非自动执行模式) +对应消息:step.waiting_for_param 消息,提示需补充的参数 +**等待参数(waiting_for_param)→ 运行中(running)** +触发条件:用户补充参数后,步骤重新执行 +对应消息:step.input 消息,使用补充后的参数执行 +**运行中 / 等待确认 / 等待参数(running/waiting_for_start/waiting_for_param)→ 失败(error)** +触发条件:步骤执行报错且重试后仍失败 +对应消息:无单独步骤失败消息,通过 flow.failed 消息体现 +三、辅助状态转换关系 +心跳状态(heartbeat):无转换关系,在流运行期间定期发送,不影响其他状态 +文本 / 文档输出状态(text.add/document.add):仅在流和步骤处于 running 状态时触发,不改变主状态 +步骤成功(success)→ 下步骤初始化(init):当前步骤成功后,自动触发下一步骤初始化,对应 step.init 消息 + +```python +class EventType(str, Enum): + """事件类型""" + + HEARTBEAT = "heartbeat" + INIT = "init", + TEXT_ADD = "text.add" + GRAPH = "graph" + DOCUMENT_ADD = "document.add" + STEP_WAITING_FOR_START = "step.waiting_for_start" + STEP_WAITING_FOR_PARAM = "step.waiting_for_param" + FLOW_START = "flow.start" + STEP_INIT = "step.init" + STEP_INPUT = "step.input" + STEP_OUTPUT = "step.output" + STEP_CANCEL = "step.cancel" + STEP_ERROR = "step.error" + FLOW_STOP = "flow.stop" + FLOW_FAILED = "flow.failed" + FLOW_SUCCESS = "flow.success" + FLOW_CANCEL = "flow.cancel" + DONE = "done" +``` + +**流初始化信息**:代表当前流初始化完成要开始工作了 + +```json +data: { + "event": "init", + "id": "99473b7c-e158-49c6-b075-8232ad68d7a2", + "groupId": "154054b1-5237-4cb4-adbe-148d1f395ec5", + "conversationId": "b5c690b9-4232-4fb8-b0da-15ead469589c", + "taskId": "31e66cf6-9d60-445c-9bad-191c0f16c29f", + "content": { + "feature": { + "maxTokens": 8192, + "contextNum": 3, + "enableFeedback": false, + "enableRegenerate": false + }, + "createdAt": 1753621532.719 + }, + "metadata": { + "inputTokens": 0, + "outputTokens": 0, + "timeCost": 0.011, + "footNoteMetadataList": [] + } +} +``` + +**流开始信息**:代表流(重新)开始工作 + +```json +data: { + "event": "flow.start", + "id": "99473b7c-e158-49c6-b075-8232ad68d7a2", + "groupId": "154054b1-5237-4cb4-adbe-148d1f395ec5", + "conversationId": "b5c690b9-4232-4fb8-b0da-15ead469589c", + "taskId": "31e66cf6-9d60-445c-9bad-191c0f16c29f", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "running", + "stepId": "", + "stepName": "", + "stepStatus": "unkown" + }, + "content": {}, + "metadata": { + "inputTokens": 0, + "outputTokens": 0, + "timeCost": 0.942, + "footNoteMetadataList": [] + } +} +``` + +**流运行失败的消息**:单个步骤多次执行失败或其他异常清空流进入失败状态 + +```json +data: { + "event": "flow.failed", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "error", + "stepId": "722f636a-4a66-4feb-80dd-7b2ea50ab494", + "stepName": "shell工具执行", + "stepStatus": "error", + }, + "content": {}, + "metadata": { + "inputTokens": 1004, + "outputTokens": 62, + "timeCost": 7.069, + "footNoteMetadataList": [] + } +} +``` + +**流成功暂停运行的消息**:在步骤等待确认执行和待用户手填参数的时候会推出这个消息 + +```json +data: { + "event": "flow.stop", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "stop", + "stepId": "722f636a-4a66-4feb-80dd-7b2ea50ab494", + "stepName": "shell工具执行", + "stepStatus": "waiting" + }, + "content": {}, + "metadata": { + "inputTokens": 1004, + "outputTokens": 62, + "timeCost": 7.069, + "footNoteMetadataList": [] + } +} +``` + +**流取消运行的消息**:用户暂停对话或者取消某个步骤的执行 + +```json +data: { + "event": "flow.cancel", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "cancel", + "stepId": "722f636a-4a66-4feb-80dd-7b2ea50ab494", + "stepName": "记忆存储", + "stepStatus": "cancel" + }, + "content": {}, + "metadata": { + "inputTokens": 1004, + "outputTokens": 62, + "timeCost": 7.069, + "footNoteMetadataList": [] + } +} +``` + +**流成功运行的消息**:流执行成功的消息 + +```json +data: { + "event": "flow.success", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "success", + "stepId": "722f636a-4a66-4feb-80dd-7b2ea50ab494", + "stepName": "记忆存储", + "stepStatus": "success" + }, + "content": {}, + "metadata": { + "inputTokens": 1004, + "outputTokens": 62, + "timeCost": 7.069, + "footNoteMetadataList": [] + } +} +``` + +**MCP tool 初始化消息:** + +```json +data: { + "event": "step.init", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "running", + "stepId": "b61aae5a-ed17-40ba-9b2c-6a96a0f0878a", + "stepName": "知识库", + "stepStatus": "init" + }, + "content": { + }, + "metadata": { + "inputTokens": 195, + "outputTokens": 15, + "timeCost": 0.002, + "footNoteMetadataList": [] + } +} +``` + +**MCP tool等待用户确认执行的信息**: + +```json +data: { + "event": "step.waiting_for_start", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "stop", + "stepId": "b61aae5a-ed17-40ba-9b2c-6a96a0f0878a", + "stepName": "知识库", + "stepStatus": "waiting" + }, + "content": { + "risk": "low", +​ "reason": "知识库查询可能会造成时延!" +​ }, +​ "metadata": { +​ "inputTokens": 195, +​ "outputTokens": 15, +​ "timeCost": 0.002, +​ "footNoteMetadataList": [] +​ } +} +``` + +**MCP tool等待用户补充参数:** + +```json +data: { + "event": "step.waiting_for_param", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "stop", + "stepId": "b61aae5a-ed17-40ba-9b2c-6a96a0f0878a", + "stepName": "高德地图", + "stepStatus": "param" + }, + "content": { + "message": "当运行产生如下报错:\n缺少access key" , + "params": params_with_null + }, + "metadata": { + "inputTokens": 195, + "outputTokens": 15, + "timeCost": 0.002, + "footNoteMetadataList": [] + } +} +``` + +**MCP tool 取消执行:** + +```json +data: { + "event": "step.cancal", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowName": "test", + "flowStatus": "cancel", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "stepId": "b61aae5a-ed17-40ba-9b2c-6a96a0f0878a", + "stepName": "高德地图", + "stepStatus": "cancel" + }, + "content": { + }, + "metadata": { + "inputTokens": 195, + "outputTokens": 15, + "timeCost": 0.002, + "footNoteMetadataList": [] + } +} +``` + +**MCP tool执行的入参信息**:content中是入参的真实内容 + +```json +data: { + "event": "step.input", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "running", + "stepId": "b61aae5a-ed17-40ba-9b2c-6a96a0f0878a", + "stepName": "end", + "stepStatus": "running" + }, + "content": { + "session_id": "fcdbca3513c8e61de58eeeef88c8ada6", + "kbIds": [], + "topK": 5, + "query": "231", + "searchMethod": "keyword_and_vector", + "isRelatedSurrounding": true, + "isClassifyByDoc": false, + "isRerank": false, + "isCompress": false, + "tokensLimit": 8192 + }, + "metadata": { + "inputTokens": 195, + "outputTokens": 15, + "timeCost": 0.002, + "footNoteMetadataList": [] + } +} + + +``` + +**Mcp tool执行的出参信息**:content中是入参的真实内容 + +```json +data: { + "event": "step.output", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "running", + "stepId": "b61aae5a-ed17-40ba-9b2c-6a96a0f0878a", + "stepName": "知识库", + "stepStatus": "success" + }, + "content": { + "question": "231", + "corpus": [] + }, + "metadata": { + "inputTokens": 590, + "outputTokens": 26, + "timeCost": 1.855, + "footNoteMetadataList": [] + } +} +``` + +**Agent运行过程中输出文本消息**:交互过程中大模型的总结 + +```json +data: { + "event": "text.add", + "id": "d6f49ddf-0599-4950-89bf-cffec4bddc72", + "groupId": "68bcb0aa-a1db-4be0-bef7-a70a8ba2360e", + "conversationId": "5cdc5c08-5118-468d-80b4-27f906961266", + "taskId": "0c0ff56f-8352-4835-a278-cf39ea943b15", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "running", + "stepId": "23641ffd-a8db-403a-9cf8-5ca305db3a0d", + "stepName": "总结", + "stepStatus": "running" + }, + "content": { + "text": "你好" + }, + "metadata": { + "inputTokens": 590, + "outputTokens": 26, + "timeCost": 1.351, + "footNoteMetadataList": [] + } +} +``` + +**Agent运行过程中输出文档消息**:当前文档来自于rag,后续如果有来自于网上或者实时生成可以考虑在content加入documentSource字段来动态获取文档本体 + +```json +data: { + "event": "document.add", + "id": "d9582240-b7e4-4e7c-8443-02385f9ef178", + "groupId": "a619941d-12f6-49d3-a8c0-95e089932539", + "conversationId": "ba3c4e4f-1ae3-42cd-878f-d3261618cf29", + "taskId": "db458861-9e1c-4de0-aab2-48c2c285cc96", + "flow": { + "appId": "3514eec9-699c-4ebd-85cc-e92caa24e141", + "flowId": "0b7b5949-01f4-4e41-871e-d78fe01ec455", + "flowName": "test", + "flowStatus": "running", + "stepId": "23641ffd-a8db-403a-9cf8-5ca305db3a0d", + "stepName": "文档生成", + "stepStatus": "running" + }, + "content": { + "documentId": "3760ae3e-b55a-4c30-8785-58f5e4a4e0dd", + "documentOrder": 1, + "documentAuthor": "42497", + "documentName": "openEuler 24.03 LTS SP1 技术白皮书-1-13.pdf", + "documentAbstract": "openEuler 技术白皮书\nopenEuler 24.03 LTS SP1 技术白皮书\n1.概述\nOpenAtom openEuler(简称“openEuler”) 社区是一个面向数字基础设施操作系统的开源社区。由开\n放原子开源基金会(以下简称“基金会", + "documentType": "pdf", + "documentSize": 778615.0, + "createdAt": 1753623806.708 + }, + "metadata": { + "inputTokens": 8306, + "outputTokens": 0, + "timeCost": 2.191, + "footNoteMetadataList": [] + } +} +``` + +**流运行成功消息通道关闭的特殊消息**:意味着前端循环可以break了 + +```text +data: [DONE] +``` + +**流运行失败消息通道关闭的特殊消息**:意味着前端循环可以break了 + +```text +data: [ERROR] +``` + +**心跳消息**:保活 + +```json +data: {"event": "heartbeat"} +``` + +状态转换关系描述 diff --git "a/docs/development/server-side/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222/openEuler_Inteligence_\351\203\250\347\275\262\345\275\242\346\200\201.png" "b/docs/development/server-side/openEuler Intelligence \346\241\206\346\236\266\344\272\244\344\272\222/openEuler_Inteligence_\351\203\250\347\275\262\345\275\242\346\200\201.png" new file mode 100644 index 0000000000000000000000000000000000000000..b7f58d0f3ae980ea7bd6ec33c6d6fc7e69c9e437 GIT binary patch literal 30791 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�=p?eRGmUbckPq% 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 Dam