# Agent 对话与 RAG 接口 **本文引用的文件** - [AgentChatController.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentChatController.java) - [AgentModelController.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentModelController.java) - [AgentExpertController.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentExpertController.java) - [AgentToolPackController.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentToolPackController.java) - [AgentCapabilityController.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentCapabilityController.java) - [AgentArtifactController.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentArtifactController.java) - [AgentPythonFileController.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentPythonFileController.java) - [InsightController.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/insight/controller/InsightController.java) - [ChatRequestDTO.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/dto/ChatRequestDTO.java) - [AgentChatServiceImpl.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java) - [LlmService.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/llm/LlmService.java) - [RagSchemaService.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/rag/RagSchemaService.java) - [PythonExecutor.java](file://ai-server/src/main/java/com/zsjz/ai/module/agent/python/PythonExecutor.java) - [Result.java](file://ai-server/src/main/java/com/zsjz/ai/common/config/Result.java) - [GlobalExceptionHandler.java](file://ai-server/src/main/java/com/zsjz/ai/common/exception/GlobalExceptionHandler.java) - [AuthController.java](file://ai-server/src/main/java/com/zsjz/ai/module/plat/controller/AuthController.java) ## 目录 1. [引言](#引言) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [接口规范](#接口规范) 6. [SSE 对话流程详解](#sse-对话流程详解) 7. [依赖关系分析](#依赖关系分析) 8. [性能与限流特性](#性能与限流特性) 9. [故障排查指南](#故障排查指南) 10. [结论](#结论) ## 引言 本文档面向调用方和前端开发者,系统化说明后端 Agent 对话、RAG、模型管理、专家目录、工具包、能力清单、Artifacts、Python 文件服务以及 Insight 研判相关接口的 URL、方法、参数、响应格式、错误语义与排查方法。重点覆盖 `/chat/stream` SSE 接口:连接建立方式、`x-token` 认证、请求体字段、事件类型、增量数据、结束帧、心跳保活、中断重连策略,并给出 curl 与前端 `fetch`/SSE 示例。 ## 项目结构 后端主要 API 集中在 `ai-server` 模块的 `com.zsjz.ai.module.agent` 包下,按控制器分层: ```mermaid graph TB subgraph "Agent 控制器" Chat["AgentChatController
/chat"] Model["AgentModelController
/models"] Expert["AgentExpertController
/agents"] ToolPack["AgentToolPackController
/tool-packs"] Capability["AgentCapabilityController
/capability"] Artifact["AgentArtifactController
/agent/artifact"] PyFiles["AgentPythonFileController
/py/files"] InsightCtrl["InsightController
/insight"] end subgraph "核心服务" ChatSvc["AgentChatServiceImpl"] Llm["LlmService"] Rag["RagSchemaService"] Python["PythonExecutor"] end Chat --> ChatSvc InsightCtrl --> ChatSvc ChatSvc --> Llm ChatSvc --> Rag ChatSvc --> Python ``` **图示来源** - [AgentChatController.java:24-170](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentChatController.java#L24-L170) - [InsightController.java:42-127](file://ai-server/src/main/java/com/zsjz/ai/module/agent/insight/controller/InsightController.java#L42-L127) - [AgentChatServiceImpl.java:345-600](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L345-L600) **章节来源** - [AgentChatController.java:24-170](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentChatController.java#L24-L170) - [InsightController.java:42-127](file://ai-server/src/main/java/com/zsjz/ai/module/agent/insight/controller/InsightController.java#L42-L127) ## 核心组件 - **Agent 对话控制器**:负责会话 CRUD、消息管理、附件上传、图谱复原、SSE 流式对话和索引重建。 - **模型控制器**:提供模型厂商列表、模型列表、模型增删改、默认模型设置、连通性测试。 - **专家控制器**:管理内置与自建专家,受登录用户隔离。 - **工具包控制器**:管理用户自定义工具组合,删除时自动清理方案绑定并驱逐实例池。 - **能力控制器**:暴露工具清单、技能列表、技能详情、技能安装/卸载/启停。 - **Artifacts 控制器**:预览与下载 Agent 产出的 CSV。 - **Python 文件控制器**:安全读取 Python 沙箱产出的图片。 - **Insight 控制器**:对象关系研判场景的会话、历史、分页消息、执行明细与线索聚合。 - **LLM 服务**:直连大模型的轻量文本调用层,不经过 Agent。 - **RAG Schema 服务**:统一表结构向量索引查询门面。 - **Python 执行器**:子进程沙箱执行 Python,生成快照数据库与图片输出。 **章节来源** - [AgentChatController.java:24-170](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentChatController.java#L24-L170) - [AgentModelController.java:18-91](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentModelController.java#L18-L91) - [AgentExpertController.java:31-72](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentExpertController.java#L31-L72) - [AgentToolPackController.java:33-73](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentToolPackController.java#L33-L73) - [AgentCapabilityController.java:33-135](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentCapabilityController.java#L33-L135) - [AgentArtifactController.java:26-76](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentArtifactController.java#L26-L76) - [AgentPythonFileController.java:27-112](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentPythonFileController.java#L27-L112) - [InsightController.java:42-127](file://ai-server/src/main/java/com/zsjz/ai/module/agent/insight/controller/InsightController.java#L42-L127) - [LlmService.java:23-200](file://ai-server/src/main/java/com/zsjz/ai/module/agent/llm/LlmService.java#L23-L200) - [RagSchemaService.java:26-181](file://ai-server/src/main/java/com/zsjz/ai/module/agent/rag/RagSchemaService.java#L26-L181) - [PythonExecutor.java:26-200](file://ai-server/src/main/java/com/zsjz/ai/module/agent/python/PythonExecutor.java#L26-L200) ## 架构总览 Agent 对话链路以 AgentScope 的 `HarnessAgent` 为核心,结合工具、意图识别、Followup 中间件、RAG 与 Python 执行器完成多轮 ReAct 推理;LLM 服务则用于无需 Agent 链路的纯文本任务。 ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "AgentChatController" participant Service as "AgentChatServiceImpl" participant Agent as "HarnessAgent" participant Tools as "工具集合" participant LLM as "LLM Provider" participant DB as "持久层" Client->>Controller: POST /chat/stream Controller->>Service: stream(ChatRequestDTO) Service->>Service: 校验 sessionKey/案件/附件 Service->>Agent: streamEvents([USER], RuntimeContext) Agent->>Tools: 工具调用 Tools->>DB: 查库/SQL/图谱/RAG Tools-->>Agent: 工具结果 Agent->>LLM: 生成回复 LLM-->>Agent: token/思考/工具指令 Agent-->>Service: event 流 Service-->>Client: SSE: tool_call/token/thinking/done/error Service->>DB: 异步落库 assistant 消息 ``` **图示来源** - [AgentChatController.java:145-170](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentChatController.java#L145-L170) - [AgentChatServiceImpl.java:345-600](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L345-L600) - [LlmService.java:23-200](file://ai-server/src/main/java/com/zsjz/ai/module/agent/llm/LlmService.java#L23-L200) ## 接口规范 ### 通用响应约定 - 多数业务接口返回 `Result`,包含 `code`、`message`、`data`。 - `/chat/**` 与 `/insight/**` 采用裸响应(不走 `Result`),便于前端复用原始流或对象。 - 全局异常处理器将未处理异常统一封装为 `Result`,并映射 HTTP 状态码。 **章节来源** - [Result.java:1-114](file://ai-server/src/main/java/com/zsjz/ai/common/config/Result.java#L1-L114) - [GlobalExceptionHandler.java:1-222](file://ai-server/src/main/java/com/zsjz/ai/common/exception/GlobalExceptionHandler.java#L1-L222) - [InsightController.java:53-65](file://ai-server/src/main/java/com/zsjz/ai/module/agent/insight/controller/InsightController.java#L53-L65) ### 认证与 Token - 登录接口位于 `/auth/login`,返回包含 token 的 `LoginVO`。 - 鉴权通过 sa-token 拦截器实现,除白名单外均要求登录。 - Token 通过请求头 `x-token` 传递。 - 未登录、Token 失效、被顶下线时,全局异常处理器返回 HTTP 200 + `body.code=401`,由前端触发重新登录逻辑。 | 接口 | 方法 | 说明 | |---|---|---| | `/auth/login` | `POST` | 用户名+密码登录,返回 token | | `/auth/logout` | `POST` | 登出并释放数据源 | | `/auth/info` | `GET` | 当前用户信息 | | `/auth/changePwd` | `POST` | 修改密码 | | `/auth/verifyPwd` | `POST` | 验证密码 | **章节来源** - [AuthController.java:19-82](file://ai-server/src/main/java/com/zsjz/ai/module/plat/controller/AuthController.java#L19-L82) - [GlobalExceptionHandler.java:44-75](file://ai-server/src/main/java/com/zsjz/ai/common/exception/GlobalExceptionHandler.java#L44-L75) ### 模型管理 `/models` | 接口 | 方法 | 参数 | 响应 | 说明 | |---|---|---|---|---| | `/models/providers` | `GET` | 无 | `Result>` | 模型厂商列表 | | `/models` | `GET` | 无 | `Result>` | 启用模型列表 | | `/models` | `POST` | `CreateModelDTO` | `Result` | 创建模型 | | `/models/{id}` | `PUT` | path:`id`, body:`UpdateModelDTO` | `Result` | 更新模型 | | `/models/{id}` | `GET` | path:`id` | `Result` | 删除模型 | | `/models/{id}/default` | `GET` | path:`id` | `Result` | 设置默认模型 | | `/models/{id}/test` | `GET` | path:`id` | `Result` | 连通性测试,失败也返回 200 + `success=false` | **章节来源** - [AgentModelController.java:18-91](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentModelController.java#L18-L91) ### 专家目录 `/agents` | 接口 | 方法 | 参数 | 响应 | 说明 | |---|---|---|---|---| | `/agents` | `GET` | 无 | `Result>` | 内置 + 当前用户自建专家 | | `/agents` | `POST` | `SaveExpertDTO` | `Result` | 新建自建专家 | | `/agents/{id}` | `PUT` | path:`id`, body:`SaveExpertDTO` | `Result` | 编辑专家(内置拒绝) | | `/agents/{id}` | `DELETE` | path:`id` | `Result` | 删除专家(内置拒绝) | **章节来源** - [AgentExpertController.java:31-72](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentExpertController.java#L31-L72) ### 工具包 `/tool-packs` | 接口 | 方法 | 参数 | 响应 | 说明 | |---|---|---|---|---| | `/tool-packs` | `GET` | 无 | `Result>` | 当前用户工具包列表 | | `/tool-packs` | `POST` | `SaveToolPackDTO` | `Result` | 新建工具包 | | `/tool-packs/{id}` | `PUT` | path:`id`, body:`SaveToolPackDTO` | `Result` | 编辑工具包 | | `/tool-packs/{id}` | `DELETE` | path:`id` | `Result` | 删除工具包,并移除方案绑定 | **章节来源** - [AgentToolPackController.java:33-73](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentToolPackController.java#L33-L73) ### 能力与技能 `/capability` | 接口 | 方法 | 参数 | 响应 | 说明 | |---|---|---|---|---| | `/capability/tools` | `GET` | 无 | `Result>` | 运行时工具清单 | | `/capability/skills` | `GET` | 可选 `caseId` | `Result>` | 技能清单 | | `/capability/skills/{name}` | `GET` | path:`name`, 可选 `caseId` | `Result` | 技能详情 | | `/capability/skills/{name}/file` | `GET` | path:`name`, query:`path`, 可选 `caseId` | `Result` | 技能内单个文件内容 | | `/capability/skills` | `POST` | `SaveSkillDTO` | `Result` | 新建技能 | | `/capability/skills/{name}` | `PUT` | path:`name`, body:`SaveSkillDTO` | `Result` | 修改技能 | | `/capability/skills/install` | `POST` | file:`file`, query:`overwrite` | `Result` | 上传 zip 安装技能 | | `/capability/skills/{name}/delete` | `GET` | path:`name` | `Result` | 卸载技能 | | `/capability/skills/{name}/toggle` | `GET` | path:`name`, query:`enabled` | `Result` | 启停技能 | **章节来源** - [AgentCapabilityController.java:33-135](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentCapabilityController.java#L33-L135) ### Artifacts 产物 `/agent/artifact` | 接口 | 方法 | 参数 | 响应 | 说明 | |---|---|---|---|---| | `/agent/artifact/preview` | `GET` | query:`id`, 可选 `limit` | 裸对象 `{columns, rows}` | 预览 CSV 前 N 行 | | `/agent/artifact/download` | `GET` | query:`id` | 二进制 CSV 流 | 下载完整产物 | 注意事项: - 鉴权使用请求头 `x-token`,不进入 sa-token 白名单。 - 路径归属由 `CaseContextHolder` 保证,跨案件访问返回 404/400。 - 前端必须用 `fetch` 携带 `x-token` 后保存 blob,不能直接用 ``。 **章节来源** - [AgentArtifactController.java:26-76](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentArtifactController.java#L26-L76) ### Python 文件 `/py/files` | 接口 | 方法 | 参数 | 响应 | 说明 | |---|---|---|---|---| | `/py/files/{workspaceId}/{execId}/{filename}` | `GET` | path:`workspaceId`,`execId`,`filename` | 图片二进制流 | 读取 Python 沙箱产出图片 | 约束: - 仅允许 png、jpg、jpeg、gif、webp、svg、bmp。 - `workspaceId` 必须等于当前打开案件 ID,否则返回 403。 - 路径归一化后必须落在 `workspace/{workspaceId}/py-out/`,否则返回 400。 - 响应带 1 小时公共缓存控制。 **章节来源** - [AgentPythonFileController.java:27-112](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentPythonFileController.java#L27-L112) ### Insight 研判 `/insight` | 接口 | 方法 | 参数 | 响应 | 说明 | |---|---|---|---|---| | `/insight/sessions` | `POST` | `InsightCreateDTO` | `InsightSessionVO` | 创建研判会话 | | `/insight/stream` | `POST` | `InsightStreamDTO` | SSE 流 | 流式分析 | | `/insight/sessions` | `GET` | query:`caseId`, 可选 `scope` | `List` | 历史会话 | | `/insight/sessions/{id}` | `GET` | path:`id`, query:`caseId` | `InsightSessionVO` | 会话详情 | | `/insight/sessions/{id}/messages` | `GET` | path:`id`, query:`caseId`, 分页参数 | `IPage` | 分页消息 | | `/insight/messages/{messageId}/trace` | `GET` | path:`messageId`, query:`caseId` | `InsightMessageTraceVO` | 单条消息执行明细 | | `/insight/sessions/{id}/delete` | `GET` | path:`id`, query:`caseId` | 裸空响应 | 删除会话 | | `/insight/clues` | `GET` | query:`caseId`, 可选 `level`,`limit` | `List` | 线索聚合 | 注意: - 所有读接口强制 `caseId` 双条件校验。 - 响应为裸对象,不走 `Result`。 **章节来源** - [InsightController.java:42-127](file://ai-server/src/main/java/com/zsjz/ai/module/agent/insight/controller/InsightController.java#L42-L127) ## SSE 对话流程详解 ### 端点与连接建立 - 端点:`POST /chat/stream` - Content-Type:`application/json` - Accept:`text/event-stream` - 认证:请求头 `x-token` - 返回:Reactor `Flux>`,每个事件为一个 `event:` + `data:` JSON 帧 curl 示例: ```bash curl -N -X POST http://host/chat/stream \ -H "Content-Type: application/json" \ -H "x-token: YOUR_TOKEN" \ -d '{"message":"分析本案件资金流向","sessionKey":"SESSION_ID"}' ``` 前端 `fetch` + `ReadableStream` 示例: ```javascript const res = await fetch("/chat/stream", { method: "POST", headers: { "Content-Type": "application/json", "x-token": token, }, body: JSON.stringify({ message, sessionKey }), }); const reader = res.body.getReader(); const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; const text = decoder.decode(value, { stream: true }); // 按行解析 data: 和 event: 字段 } ``` **章节来源** - [AgentChatController.java:145-170](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentChatController.java#L145-L170) ### 请求体 ChatRequestDTO | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `message` | `String` | 是 | 用户提问文本 | | `sessionKey` | `String` | 是 | 当前会话的业务标识,服务端解析为 `sessionId` | | `agentId` | `Long` | 否 | 可覆盖会话绑定的专家,内部用于构建 Agent | | `modelId` | `Long` | 否 | 动态切换模型;与会话绑定模型不同时回写会话 | | `attachmentIds` | `List` | 否 | 附件 ID,发送前通过 `/chat/attachments` 上传 | **章节来源** - [ChatRequestDTO.java:1-24](file://ai-server/src/main/java/com/zsjz/ai/module/agent/dto/ChatRequestDTO.java#L1-L24) ### SSE 事件类型与增量字段 | 事件名 | 含义 | 关键字段 | 发生时机 | |---|---|---|---| | `tool_call` | 工具调用开始 | `type`=`tool_call`、`toolCallId`、`toolName` | AgentScope 发起工具调用 | | `tool_input` | 工具输入累积完成 | `type`=`tool_input`、`toolCallId`、`toolInput` | 工具参数收集完毕 | | `tool_result` | 工具结果累积完成 | `type`=`tool_result`、`toolCallId`、`toolName`、`toolResult` | 工具执行结束 | | `token` | 文本增量 | `type`=`token`、`data` | 模型逐字输出 | | `thinking` | 模型思考过程 | `type`=`thinking`、`phase`=`start`/`delta`/`end`、`data` | 开启、增量、结束 | | `intent` | 意图识别结果 | 由中间件注入 | 意图识别完成 | | `suggestions` | 下一步建议 | 由 Followup 中间件注入 | 对话结束后追加 | | `graph_data` | 全量图谱数据 | `type`=`graph_data`、`toolCallId`、`graph` | 调用 `get_case_graph` 工具后补发 | | `done` | 本轮对话结束 | `type`=`done`、`sessionKey` | Agent 结束事件 | | `error` | 运行期错误 | `type`=`error`、`error` | 参数/会话/系统异常 | | `heartbeat` | 心跳保活 | `type`=`heartbeat`、`ts` | 每 10 秒一次 | 增量字段说明: - `token.data` 是增量片段,不是完整文本,需要前端拼接。 - `tool_input.toolInput` 和 `tool_result.toolResult` 在对应工具结束时一次性返回完整值。 - `thinking.data` 同样增量拼接,`phase=start` 表示一段新思考开始,`phase=end` 表示该段结束。 - `done.sessionKey` 可用于前端刷新后恢复会话上下文。 **章节来源** - [AgentChatController.java:118-143](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentChatController.java#L118-L143) - [AgentChatServiceImpl.java:479-594](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L479-L594) ### 结束事件与错误事件 - `done`:正常结束,附带 `sessionKey`。 - `error`:参数为空、缺少 `sessionKey`、会话不存在、会话不属于当前案件、模型未配置等错误都会转为 `error` 帧。 - 服务端会在错误情况下尝试把错误消息落库,使刷新会话后仍可见。 **章节来源** - [AgentChatServiceImpl.java:345-370](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L345-L370) - [AgentChatServiceImpl.java:742-776](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L742-L776) ### 心跳保活机制 服务端同时发射两条 Flux: 1. 真实业务事件流。 2. 每 10 秒一次的 `heartbeat` 事件。 心跳帧不参与正文、思考、工具结果累积,仅用于让前端区分“模型仍在处理”和“连接已断”。 **章节来源** - [AgentChatServiceImpl.java:594-600](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L594-L600) ### 中断与重连策略 - 同一会话同一时刻只允许一条 AI 流;重复发送会立即收到 `error` 帧:“该会话正在回复中,请等待当前回复完成后再发送”。 - 用户主动中止 SSE 连接时,若 `AgentResultEvent` 尚未到达,服务端会把已输出的部分文本、工具事件和思考过程异步落库,标记为中断。 - 重连建议: - 前端检测到连接断开或超时后,先判断是否收到 `done`。 - 若未收到 `done`,可用相同 `sessionKey` 和上一次 `message` 重试;如果已经收到 `done`,不应重复发送同一条消息。 - 对并发冲突错误,应提示用户等待或禁用发送按钮。 **章节来源** - [AgentChatServiceImpl.java:379-400](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L379-L400) - [AgentChatServiceImpl.java:576-594](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L576-L594) ### SSE 流程图 ```mermaid flowchart TD Start(["POST /chat/stream"]) --> Validate["校验 message 与 sessionKey"] Validate --> Valid{"参数有效?"} Valid -->|否| ErrorFrame["发送 error 帧"] Valid -->|是| AcquireLock["获取会话级流锁"] AcquireLock --> Locked{"锁可用?"} Locked -->|否| BusyError["发送 '正在回复中' 错误帧"] Locked -->|是| BuildAgent["加载会话/模型/Agent/上下文"] BuildAgent --> StreamEvents["订阅 AgentScope 事件流"] StreamEvents --> ToolCall["tool_call/tool_input/tool_result"] StreamEvents --> Thinking["thinking start/delta/end"] StreamEvents --> Token["token 增量"] StreamEvents --> Done["done + sessionKey"] StreamEvents --> Heartbeat["每 10 秒 heartbeat"] Done --> End(["结束"]) Heartbeat --> End ErrorFrame --> End BusyError --> End ``` **图示来源** - [AgentChatServiceImpl.java:345-600](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L345-L600) ## 依赖关系分析 ### AgentScope、LLM Provider、RAG、Python 执行器的作用 | 组件 | 职责 | 在对话中的作用 | |---|---|---| | AgentScope | 多轮 Agent 编排、工具调度、记忆、技能过滤、Transcript | 承载 ReAct 循环,驱动工具调用与模型交互 | | LLM Provider | 实际大模型连接层 | 被 AgentScope 与 `LlmService` 调用,提供文本生成 | | RAG Schema | 表结构元数据向量化检索 | 通过 `search_table_schema` 工具帮助模型理解数据库结构 | | Python 执行器 | 子进程执行 Python 代码 | 提供数据分析、绘图、DuckDB 查询能力,输出图片与结果 | ```mermaid graph LR Chat["AgentChatController"] --> Svc["AgentChatServiceImpl"] Svc --> AgentScope["HarnessAgent"] AgentScope --> Tools["工具集合"] Tools --> Rag["RagSchemaService"] Tools --> Python["PythonExecutor"] AgentScope --> LLM["LLM Provider"] ``` **图示来源** - [AgentChatServiceImpl.java:400-500](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L400-L500) - [RagSchemaService.java:26-181](file://ai-server/src/main/java/com/zsjz/ai/module/agent/rag/RagSchemaService.java#L26-L181) - [PythonExecutor.java:26-200](file://ai-server/src/main/java/com/zsjz/ai/module/agent/python/PythonExecutor.java#L26-L200) **章节来源** - [LlmService.java:23-200](file://ai-server/src/main/java/com/zsjz/ai/module/agent/llm/LlmService.java#L23-L200) - [RagSchemaService.java:26-181](file://ai-server/src/main/java/com/zsjz/ai/module/agent/rag/RagSchemaService.java#L26-L181) - [PythonExecutor.java:26-200](file://ai-server/src/main/java/com/zsjz/ai/module/agent/python/PythonExecutor.java#L26-L200) ## 性能与限流特性 - 会话级流互斥:同一会话并发流使用 `Semaphore` 非阻塞抢占,避免记忆污染。 - 工具结果截断:根据工具名称限制最大字符数,防止超大 SSE 帧。 - Python 执行超时:子进程按配置超时终止,输出有最大字符截断。 - RAG 索引状态区分:`SUCCESS` 与 `IDLE`,空索引抛可操作错误而非静默空结果。 - 心跳保活:10 秒间隔,避免长连接假死。 **章节来源** - [AgentChatServiceImpl.java:65-90](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L65-L90) - [AgentChatServiceImpl.java:514-535](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L514-L535) - [PythonExecutor.java:140-200](file://ai-server/src/main/java/com/zsjz/ai/module/agent/python/PythonExecutor.java#L140-L200) - [RagSchemaService.java:85-181](file://ai-server/src/main/java/com/zsjz/ai/module/agent/rag/RagSchemaService.java#L85-L181) ## 故障排查指南 ### LLM 不可用 现象: - 创建会话或发送消息时报错。 - `/models/{id}/test` 返回 `success=false`。 - SSE 直接返回 `error` 帧。 排查步骤: 1. 调用 `/models` 确认存在启用模型。 2. 调用 `/models/{id}/test` 查看连通性失败原因。 3. 检查是否设置了默认模型;若未指定且无默认模型,会返回 400。 4. 查看 `LlmService` 日志中的模型名称与错误信息。 可能错误: - 未指定模型且无默认模型。 - 模型配置无效、API Key 错误或网络不可达。 - 模型调用超时(504)。 **章节来源** - [AgentChatServiceImpl.java:420-445](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L420-L445) - [AgentModelController.java:74-91](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentModelController.java#L74-L91) - [LlmService.java:120-200](file://ai-server/src/main/java/com/zsjz/ai/module/agent/llm/LlmService.java#L120-L200) ### RAG 无结果 现象: - 工具调用 `search_table_schema` 返回空。 - 手动调用 RAG 相关接口报 409。 排查步骤: 1. 确认 RAG 开关与嵌入模型可用。 2. 调用 `/chat/reindexWorkspace` 重建索引。 3. 检查索引状态是否为 `SUCCESS`。 4. 若索引为空但能力可用,需先重建再检索。 可能错误: - 未配置嵌入模型。 - 索引未构建。 - 索引已构建但语义检索确实无命中。 **章节来源** - [RagSchemaService.java:60-181](file://ai-server/src/main/java/com/zsjz/ai/module/agent/rag/RagSchemaService.java#L60-L181) - [AgentChatController.java:165-170](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentChatController.java#L165-L170) ### SSE 断流 现象: - 前端长时间收不到事件。 - 浏览器显示连接已关闭但未收到 `done`。 排查步骤: 1. 观察是否收到 `heartbeat`;若无心跳,可能是连接层问题。 2. 若收到 `error`,根据 `error.error` 字段定位。 3. 若未收到 `done`,可视为中断,使用相同 `sessionKey` 重连重试。 4. 若多次收到“会话正在回复中”,应等待当前流结束。 重连建议: - 监听 `error`、连接关闭、超时。 - 未收到 `done` 时重试;收到 `done` 后不再重复发送。 - 前端维护去重队列,避免双击发送导致并发冲突。 **章节来源** - [AgentChatServiceImpl.java:379-400](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L379-L400) - [AgentChatServiceImpl.java:576-600](file://ai-server/src/main/java/com/zsjz/ai/module/agent/service/impl/AgentChatServiceImpl.java#L576-L600) ### Token 过期或被顶下线 现象: - 普通接口返回 HTTP 200 + `body.code=401`。 - 前端跳转登录页。 - `/agent/artifact` 下载失败。 排查步骤: 1. 检查 `x-token` 是否携带。 2. 调用 `/auth/info` 确认当前登录态。 3. 若提示“账号已在其他客户端登录”,说明被顶下线。 4. 登录后重新获取 token 并重试。 **章节来源** - [AuthController.java:19-82](file://ai-server/src/main/java/com/zsjz/ai/module/plat/controller/AuthController.java#L19-L82) - [GlobalExceptionHandler.java:44-75](file://ai-server/src/main/java/com/zsjz/ai/common/exception/GlobalExceptionHandler.java#L44-L75) - [AgentArtifactController.java:33-43](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentArtifactController.java#L33-L43) ### Python 执行失败 现象: - 工具返回 Python 错误。 - 图片无法显示。 - 提示执行环境不可用或超时。 排查步骤: 1. 确认 Python 执行环境已启用。 2. 检查是否安装了 pandas、duckdb、matplotlib。 3. 确认当前打开了案件。 4. 检查工作空间数据库路径是否存在。 5. 查看 Python 子进程 stdout/stderr。 **章节来源** - [PythonExecutor.java:100-200](file://ai-server/src/main/java/com/zsjz/ai/module/agent/python/PythonExecutor.java#L100-L200) - [AgentPythonFileController.java:55-112](file://ai-server/src/main/java/com/zsjz/ai/module/agent/controller/AgentPythonFileController.java#L55-L112) ## 结论 Agent 对话接口以 `/chat/stream` 为核心,基于 AgentScope 的流式事件模型对外暴露 `tool_call`、`token`、`thinking`、`done`、`error`、`heartbeat` 等事件;配套提供模型、专家、工具包、能力、Artifacts、Python 文件与 Insight 研判接口。调用方应正确携带 `x-token`,按事件类型增量渲染,实现心跳检测、中断重连与错误降级,并在 LLM 不可用、RAG 无结果、SSE 断流、Token 过期等场景下依据本文排查路径快速定位问题。