Agent 与 RAG.md 38 KB

Agent 与 RAG

本文引用的文件

  • AgentChatController.java
  • AgentChatServiceImpl.java
  • AgentMessage.java
  • AgentChatSession.java
  • RagIndexStatus.java
  • RagSchemaService.java
  • RagSchemaSearchTool.java
  • SqlAnalysisTool.java
  • PythonAnalysisTool.java
  • PythonExecutor.java
  • ChatAttachmentService.java
  • ArtifactService.java
  • IntentService.java
  • FollowupService.java
  • EmbeddingProvider.java
  • EmbeddingModelFactory.java
  • InsightServiceImpl.java
  • AI_AGENT.md
  • agent-data-model.md

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 关键数据模型关系
  6. Agent 对话流程详解
  7. RAG 与向量检索
  8. 工具调用与产物管理
  9. 意图识别、追问建议与 Insight
  10. 典型调用示例
  11. 依赖关系分析
  12. 性能特征
  13. 常见问题排查
  14. 结论

简介

Agent 与 RAG 是清鉴平台中面向纪检监察与经侦场景的对话式研判能力。其目标是让业务人员用自然语言与案件数据交互:前端通过 SSE 流式对话,后端基于 AgentScope 的 HarnessAgent 驱动 LLM,并结合 pgvector 做表结构与知识库语义检索、意图识别、SQL 与 Python 执行器、附件解析、产物管理与 Insight 结构化研判输出。

从仓库定位看,Agent 子系统位于 ai-server 的 module/agent 域,使用 Spring Boot 3 + MyBatis-Plus + AgentScope 2.0.1;主库为 PostgreSQL + pgvector,分析库为 DuckDB(按工作空间切换),Redis 用于会话缓存与记忆隔离,Elasticsearch 用于知识文档索引。

章节来源

  • AI_AGENT.md:1-120

项目结构

Agent 相关代码集中在后端 ai-server 中,整体采用领域分层:

层级 职责 典型路径
Controller 接收 REST/SSE 请求、做参数校验后调 Service module/agent/controller
Service 会话、流式对话、RAG、Insight、模型能力等核心逻辑 module/agent/service/*
Tools Agent 可被 LLM 调用的能力,如 SQL、Python、表结构检索 module/agent/tools/*
RAG 嵌入模型路由、模板结构向量索引、状态查询 module/agent/rag/*
Attachment 附件上传、内容提取、向量化与注入块 module/agent/attachment/*
Artifact SQL/分析工具全量结果 CSV 产物管理 module/agent/artifact/*
Intent/Followup 意图识别与下一步追问建议 module/agent/intent/*、module/agent/followup/*
Entity/Mapper Agent 会话、消息、RAG 索引状态等持久化模型 module/agent/entity/*、module/agent/mapper/*
graph TB
    FE["前端<br/>SSE 客户端"] --> CC["AgentChatController"]
    CC --> ACS["AgentChatServiceImpl"]
    ACS --> AS["AgentService / HarnessAgent"]
    ACS --> ATT["ChatAttachmentService"]
    ACS --> INT["IntentService"]
    ACS --> FLW["FollowupService"]
    AS --> TOOLS["工具集"]
    TOOLS --> SQLT["SqlAnalysisTool"]
    TOOLS --> PYT["PythonAnalysisTool"]
    TOOLS --> RSST["RagSchemaSearchTool"]
    RSST --> RSS["RagSchemaService"]
    RSS --> EPM["EmbeddingProvider / EmbeddingModelFactory"]
    SQLT --> ART["ArtifactService"]
    ACS --> DB["PostgreSQL + pgvector"]
    SQLT --> DUCK["DuckDB 工作空间库"]

图示来源

  • AgentChatController.java:1-170
  • AgentChatServiceImpl.java:345-582
  • RagSchemaService.java:1-181
  • EmbeddingModelFactory.java:1-187

章节来源

  • AI_AGENT.md:120-250

核心组件

组件 说明 关键行为
AgentChatController 聊天入口 提供会话 CRUD、消息列表、发送消息、SSE 流、附件上传、知识库重建接口
AgentChatServiceImpl 对话主服务 会话归属校验、模型选择、Agent 事件转 SSE、工具调用聚合、思考过程与产物落库
RagSchemaService RAG 门面 判断向量能力、重建模板结构索引、查询索引状态、语义检索表结构
SqlAnalysisTool SQL 与分析工具 execute_sql、list_tables、render_chart,只读 DuckDB,结果落产物 CSV
PythonAnalysisTool Python 工具 沙箱执行 pandas/numpy/duckdb/matplotlib,返回 stdout/stderr/imageUrls
PythonExecutor Python 子进程执行器 工作空间快照、超时强制终止、图片收集、权限黑名单
ChatAttachmentService 附件编排 上传校验、内联/Python直读/RAG 三路分流、三重归属校验
ArtifactService 产物服务 全量 CSV 落盘、预览列头、安全路径解析
IntentService 意图识别 轻量 LLM 分类 + 历史语义增强,fail-open
FollowupService 追问建议 对话结束后生成方向 + 可执行追问,fail-open
EmbeddingProvider 嵌入模型路由 本地 ONNX 与在线 DashScope/Ollama/OpenAI 二选一
EmbeddingModelFactory 嵌入实例工厂 从 model 表构建 agentscope EmbeddingModel
InsightServiceImpl 结构化研判 独立会话/消息表、动态提示词、独立 Agent 池、SSE 流式输出

章节来源

  • AgentChatController.java:1-170
  • AgentChatServiceImpl.java:1-200
  • RagSchemaService.java:1-181
  • SqlAnalysisTool.java:1-200
  • PythonAnalysisTool.java:1-69
  • PythonExecutor.java:1-200
  • ChatAttachmentService.java:1-200
  • ArtifactService.java:1-200
  • IntentService.java:1-146
  • FollowupService.java:1-200
  • EmbeddingProvider.java:1-201
  • EmbeddingModelFactory.java:1-187
  • InsightServiceImpl.java:1-200

架构总览

Agent 对话不是简单的一次 HTTP 问答,而是“前端 SSE → 后端 Service → AgentScope HarnessAgent → LLM Provider → 工具 → 产物/向量/数据库”的多阶段流水线。

sequenceDiagram
    participant FE as "前端"
    participant CC as "AgentChatController"
    participant ACS as "AgentChatServiceImpl"
    participant AS as "AgentService/HarnessAgent"
    participant LLM as "LLM Provider"
    participant T as "工具"
    participant PG as "PostgreSQL/pgvector"
    participant DK as "DuckDB"
    participant FS as "文件系统/产物"

    FE->>CC: POST /js/a/chat/stream
    CC->>ACS: stream(ChatRequestDTO)
    ACS->>ACS: 校验 sessionKey、案件上下文、模型
    ACS->>AS: getOrCreateAgent(workspaceId, agentRowId, modelId)
    AS->>LLM: 流式调用(DashScope/Ollama/OpenAI)
    LLM-->>AS: ToolCallStartEvent / TextBlockDeltaEvent / ...
    AS->>T: 调用工具(execute_sql / execute_python / search_table_schema)
    T->>DK: execute_sql 只读查询
    T->>FS: 写 CSV 产物
    T->>PG: 向量检索(可选)
    AS-->>ACS: AgentEvent 流
    ACS-->>FE: tool_call → tool_input → tool_result → token → done

图示来源

  • AgentChatController.java:120-170
  • AgentChatServiceImpl.java:345-582
  • SqlAnalysisTool.java:1-200
  • RagSchemaSearchTool.java:1-52

关键数据模型关系

AgentChatSession

agent_chat_session 表示一次对话会话,属于某个工作空间(case_id)和某个 Agent 方案(agent_id),并可绑定一个具体模型(model_id)。它保存会话标题、上下文 JSON、消息数量、累计 token、是否置顶、附件元数据以及创建/更新时间。

字段 含义
id 雪花 ID
agent_id 关联 Agent 方案行
model_id 会话绑定的模型配置 ID,为空时使用默认模型
case_id 工作空间/案件 ID
title 会话标题
context 会话上下文 JSON
message_count 消息条数
total_tokens 累计 token 数
pinned 是否置顶
attachments 附件元数据 JSON
create_at/update_at 时间戳

AgentMessage

agent_message 存储每轮用户提问与助手回复。消息包含角色、正文、正文类型、token 计数、JSONB 元数据、工具调用事件、父消息、消息类型、回复目标消息、收藏标记等。

字段 含义
id 雪花 ID
session_id 所属会话
role user / assistant 等
content 正文
content_type 正文类型
token_count token 计数
metadata JSONB:思考过程、错误标志等
tool_events JSONB:工具调用链序列化
parent_id 父消息 ID
message_type 消息类别
reply_to_message_id 回复的目标消息
starred 是否收藏
create_at 创建时间

RagIndexStatus

rag_index_status 记录每个工作空间的模板结构向量索引状态。它包括嵌入模型 ID、维度、pgvector 向量表名、结构指纹、表数量、状态、最近错误、索引时间与更新时间。

字段 含义
workspace_id 工作空间 ID(主键)
embedding_model_id 使用的嵌入模型
embedding_model_name 嵌入模型名称
dimensions 向量维度
vector_table pgvector 向量表名
schema_fingerprint 结构指纹
table_count 已索引表数量
status idle/indexing/success/failed
last_error 最近错误信息
indexed_at/update_at 索引与更新时间
erDiagram
    AGENT_CHAT_SESSION {
        bigint id PK
        bigint agent_id
        bigint model_id
        bigint case_id
        string title
        text context
        int message_count
        bigint total_tokens
        boolean pinned
        text attachments
        datetime create_at
        datetime update_at
    }

    AGENT_MESSAGE {
        bigint id PK
        bigint session_id FK
        string role
        string content
        string content_type
        int token_count
        jsonb metadata
        jsonb tool_events
        bigint parent_id
        string message_type
        bigint reply_to_message_id
        boolean starred
        datetime create_at
    }

    RAG_INDEX_STATUS {
        bigint workspace_id PK
        bigint embedding_model_id
        string embedding_model_name
        int dimensions
        string vector_table
        string schema_fingerprint
        int table_count
        string status
        string last_error
        datetime indexed_at
        datetime update_at
    }

    AGENT_CHAT_SESSION ||--o{ AGENT_MESSAGE : "一对多"

图示来源

  • AgentChatSession.java:1-58
  • AgentMessage.java:1-55
  • RagIndexStatus.java:1-59

章节来源

  • AgentChatSession.java:1-58
  • AgentMessage.java:1-55
  • RagIndexStatus.java:1-59

Agent 对话流程详解

前端发起 SSE 请求

前端向后端 /js/a/chat/stream 发起 POST 请求,请求体为 ChatRequestDTO,通常携带:

字段 含义
message 用户问题
sessionKey 会话 ID(字符串)
modelId 可选:本次动态切换的模型 ID
attachmentIds 可选:附件 ID 列表

后端控制器直接返回 Flux<ServerSentEvent<String>>,不包装成统一 Result,因为 SSE 帧本身承载多种事件类型。

章节来源

  • AgentChatController.java:120-170

会话与模型校验

AgentChatServiceImpl.stream 先校验消息非空,再取当前打开案件的 caseId,然后解析 sessionKey。若缺少有效会话 ID,会直接返回错误帧。同一会话使用 Semaphore 做流级互斥:同一时刻只允许一条 AI 流,避免多个标签页或重试造成 Agent 记忆污染。

模型优先级为:

  1. 请求体 modelId
  2. 会话绑定的 model_id
  3. 系统默认模型

如果都没有默认模型,则抛出“未指定模型且无默认模型”的错误。

章节来源

  • AgentChatServiceImpl.java:345-480

AgentScope 事件到 SSE 帧

Agent 流通过 HarnessAgent.streamEvents 产出事件,Service 把它们转换成以下 SSE 帧:

帧类型 含义
intent 意图识别结果
suggestions 下一步追问建议
tool_call 工具开始调用
tool_input 工具入参完整文本
tool_result 工具结果文本(可能截断)
token 助手回答增量文本
thinking 模型思考过程 start/delta/end
graph_data 关系图谱全量数据帧
done 一轮结束,附带 sessionKey
error 错误终止
flowchart TD
    Start["收到 ChatRequestDTO"] --> Validate["校验消息与会话"]
    Validate --> Model{"是否指定模型"}
    Model -->|否| UseDefault["使用会话或默认模型"]
    Model -->|是| DynamicSwitch["动态切换模型并回写会话"]
    UseDefault --> BuildCtx["构建 RuntimeContext"]
    DynamicSwitch --> BuildCtx
    BuildCtx --> Events["监听 HarnessAgent 事件"]
    Events --> ToolCall{"是否工具调用"}
    ToolCall -->|是| EmitTool["发送 tool_call/tool_input/tool_result"]
    ToolCall -->|否| Token["发送 token/thinking"]
    EmitTool --> Done{"是否结束"}
    Token --> Done
    Done --> Persist["异步持久化助手消息与工具事件"]
    Persist --> End["发送 done 帧"]

图示来源

  • AgentChatServiceImpl.java:345-582

章节来源

  • AgentChatServiceImpl.java:345-582

RAG 与向量检索

向量能力开关

向量能力由两个层次控制:

  1. 应用层开关:etl.rag.enabled
  2. 嵌入模型可用性:本地 ONNX 或在线 embedding 模型

RagSchemaService.isAvailable 要求两者同时满足。若不可用,search 会抛 409,提示“未配置嵌入模型”。

章节来源

  • RagSchemaService.java:60-100
  • EmbeddingProvider.java:1-201

嵌入模型路由

EmbeddingProvider 根据 zsjz.embedding.enabled 决定走本地还是在线:

模式 实现 特点
本地 EmbeddingService(ONNX) 无需网络,模型目录缺失时不可用
在线 EmbeddingModelFactory 构建 agentscope EmbeddingModel 支持 DashScope/Ollama/OpenAI

在线模式从 agent_model 表中查找 type='embedding' 的活跃模型,并缓存 30 秒。本地模式下,向量表名带模型后缀(例如 _bge_m3),避免本地与在线向量混用。

章节来源

  • EmbeddingProvider.java:1-201
  • EmbeddingModelFactory.java:1-187

表结构向量索引

RagSchemaService 是模板结构向量索引的统一门面。真正的索引实现是 AiCleanTemplateVectorIndex,它将 table_info/table_field 与 ai_clean_template/ai_clean_field 两套模板库元数据向量化进全局 pgvector 表,而不是扫描案件 DuckDB。

关键接口:

接口 作用
isAvailable() 判断 RAG 能力是否可用
reindexWorkspace(workspaceId) 全量重建索引,幂等覆盖
getStatus(workspaceId) 查询索引状态
search(query, topK) 按自然语言检索物理表与物理列

章节来源

  • RagSchemaService.java:1-181

工具中的 RAG

RagSchemaSearchTool.searchTableSchema 注册为 Agent 工具 search_table_schema,供 LLM 在需要理解有哪些表、字段含义或编写 SQL 时调用。它把 RagSchemaService.search 的结果序列化为 JSON 传给模型。

章节来源

  • RagSchemaSearchTool.java:1-52

工具调用与产物管理

SQL 工具

SqlAnalysisTool.execute_sql 在当前工作空间的 DuckDB 上执行只读 SQL,白名单前缀包括 select、with、pragma、describe、show、explain。它还禁止危险函数,如 read_csv、glob、attach、detach、install、load、copy、export、import、getenv、setenv 等。

执行策略是流式 + 产物:

  • 每行写入 CSV 产物
  • 内存只保留头部若干行作为预览
  • 返回 artifact 元数据、列定义、头部预览、总行数

章节来源

  • SqlAnalysisTool.java:1-200

Python 工具

PythonAnalysisTool.executePython 调用 PythonExecutor.execute,在隔离子进程中执行 Python 代码。执行环境限制:

  • 每次执行使用独立临时目录
  • 超时强制终止
  • 输出截断
  • 图片移动到工作空间产物目录
  • 通过 ETL_DB_PATH 访问 DuckDB 快照副本,而非原库

    flowchart TD
    Call["execute_python(code)"] --> CheckEnv["检查 Python 环境与依赖"]
    CheckEnv --> ValidCode["校验代码黑名单"]
    ValidCode --> Workspace["获取当前工作空间"]
    Workspace --> Snapshot["导出 DuckDB 快照副本"]
    Snapshot --> Subprocess["启动 Python 子进程"]
    Subprocess --> Timeout{"是否超时"}
    Timeout -->|是| Kill["强制终止并返回超时错误"]
    Timeout -->|否| Collect["收集 stdout/stderr/图片"]
    Collect --> Result["返回 exitCode、stdout、stderr、imageUrls、durationMs"]
    

图示来源

  • PythonAnalysisTool.java:1-69
  • PythonExecutor.java:1-200

章节来源

  • PythonAnalysisTool.java:1-69
  • PythonExecutor.java:1-200

附件与产物

附件上传走 ChatAttachmentService.upload,按类型分为三路:

  1. 内联:小文档或小表格全文进入消息
  2. Python 直读:大表格只扫描行数、表头、样本,注入文件路径与指引
  3. RAG:大文档全文落 sidecar,向量化后按用户问题检索片段注入

产物由 ArtifactService 负责:工具查出的全量表格结果写成 CSV,前端只拿 artifact 元数据与头部预览,真实全量数据通过产物路径下载。

章节来源

  • ChatAttachmentService.java:1-200
  • ArtifactService.java:1-200

意图识别、追问建议与 Insight

意图识别

IntentService.safeAnalyze 在把用户问题交给 Agent 之前,复用会话模型做一次轻量 LLM 调用,完成意图分类与语义增强。它是 fail-open 设计:任何异常、超时、解析失败都返回 null,不阻塞主链路。

它会加载最近 N 条消息历史,截断过长内容,拼接系统提示词与用户提示词,并通过结构化输出约束返回意图结果。

章节来源

  • IntentService.java:1-146

追问建议

FollowupService.safeSuggest 在对话结束后,根据最近几轮上下文和本轮问答生成“方向 + 可直接发送的追问”。它同样 fail-open,并对弱模型输出做清洗:去重、过滤空话、限制长度与方向数。

章节来源

  • FollowupService.java:1-200

Insight 结构化研判

InsightServiceImpl 是对象关系分析的智能研判服务。它与通用对话的关键差异是:

  • 存储独立:agent_insight_* 两张表
  • 提示词动态:创建会话时拼好 sysPrompt 并落库
  • 实例池独立:不走通用 Agent 池
  • 排序用 seq:避免 id 与 create_at 同毫秒撞车
  • 会话级互斥:进程内 Semaphore + DB 状态位

章节来源

  • InsightServiceImpl.java:1-200

典型调用示例

以下示例描述 API 调用方式,不展示后端源码。

示例一:发送消息

  1. 前端先调用 POST /js/a/chat/messages,请求体为 SendMessageDTO,包含 sessionId 和 message。
  2. 或者直接使用 SSE 流:POST /js/a/chat/stream,请求体为 ChatRequestDTO。
  3. 后端返回 SSE 帧序列:
    • tool_call:工具开始
    • tool_input:工具入参
    • tool_result:工具结果
    • token:逐字增量文本
    • done:本轮结束
    • error:错误

参考实现位置

  • AgentChatController.java:120-170
  • AgentChatServiceImpl.java:345-582

示例二:选择模型

  1. 创建会话时可在 CreateChatSessionDTO 中传入 modelId。
  2. 发送消息时也可在 ChatRequestDTO 中传 modelId,实现动态切换。
  3. 若请求模型与会话绑定不同,后端会在模型校验通过后回写会话 model_id。
  4. 如果没有默认模型且请求也未指定,会返回 400:“未指定模型且无默认模型,请先选择模型”。

参考实现位置

  • AgentChatServiceImpl.java:430-500

示例三:开启 RAG

  1. 确认 etl.rag.enabled 已启用。
  2. 配置嵌入模型:
    • 本地模式:设置 zsjz.embedding.enabled=true 并提供模型目录。
    • 在线模式:在 agent_model 表添加 type='embedding' 的活跃记录,provider 可为 DashScope、Ollama 或 OpenAI 兼容。
  3. 调用 GET /js/a/chat/reindexWorkspace?id={workspaceId} 重建模板结构向量索引。
  4. 调用 RagSchemaService.getStatus 或前端对应接口查看索引状态。
  5. 在对话中让 LLM 调用 search_table_schema 工具进行语义检索。

参考实现位置

  • RagSchemaService.java:60-181
  • EmbeddingProvider.java:1-201
  • EmbeddingModelFactory.java:1-187
  • RagSchemaSearchTool.java:1-52

示例四:查看工具调用结果

  1. 发送消息后观察 SSE 帧:
    • tool_call 携带 toolCallId 与 toolName
    • tool_input 携带累积后的工具入参
    • tool_result 携带工具返回文本
  2. 对于 execute_sql,前端应读取响应中的 artifact 元数据,通过产物接口预览或下载 CSV。
  3. 对于 execute_python,响应中包含 exitCode、stdout、stderr、imageUrls、durationMs。
  4. 对于 get_case_graph,后端还会额外下发 graph_data 帧,包含全量关系图数据。

参考实现位置

  • AgentChatServiceImpl.java:480-582
  • SqlAnalysisTool.java:1-200
  • PythonAnalysisTool.java:1-69
  • ArtifactService.java:1-200

依赖关系分析

组件耦合关系

classDiagram
    class AgentChatController {
        +stream()
        +sendMessage()
        +uploadAttachment()
        +reindexWorkspace()
    }

    class AgentChatServiceImpl {
        +createSession()
        +stream()
        +listSessions()
        +getSession()
        +persistAssistantMessage()
        +persistUserMessage()
    }

    class RagSchemaService {
        +isAvailable()
        +reindexWorkspace()
        +getStatus()
        +search()
    }

    class RagSchemaSearchTool {
        +searchTableSchema()
    }

    class SqlAnalysisTool {
        +executeSql()
        +listTables()
        +renderChart()
    }

    class PythonAnalysisTool {
        +executePython()
    }

    class PythonExecutor {
        +isAvailable()
        +execute()
    }

    class ChatAttachmentService {
        +upload()
        +buildBlocks()
    }

    class ArtifactService {
        +export()
        +headRows()
    }

    class EmbeddingProvider {
        +isLocal()
        +isAvailable()
        +embed()
        +modelName()
        +dimensions()
    }

    class EmbeddingModelFactory {
        +resolveDefault()
        +create()
    }

    AgentChatController --> AgentChatServiceImpl : "调用"
    AgentChatServiceImpl --> RagSchemaService : "重建索引"
    AgentChatServiceImpl --> ChatAttachmentService : "附件注入"
    AgentChatServiceImpl --> SqlAnalysisTool : "工具"
    AgentChatServiceImpl --> PythonAnalysisTool : "工具"
    PythonAnalysisTool --> PythonExecutor : "执行"
    RagSchemaSearchTool --> RagSchemaService : "检索"
    RagSchemaService --> EmbeddingProvider : "嵌入能力"
    EmbeddingProvider --> EmbeddingModelFactory : "在线模型"

图示来源

  • AgentChatController.java:1-170
  • AgentChatServiceImpl.java:1-200
  • RagSchemaService.java:1-181
  • EmbeddingProvider.java:1-201
  • EmbeddingModelFactory.java:1-187

外部依赖

外部系统 用途 风险点
AgentScope Agent 运行时、工具调度、事件流 LLM Provider 连接、工具 schema 装配
DashScope/Ollama/OpenAI LLM 与嵌入模型推理 网络延迟、密钥过期、维度不一致
PostgreSQL/pgvector 平台元数据、Agent 会话、向量索引 向量表损坏、维度不匹配
DuckDB 工作空间分析库 文件锁、只读白名单绕过
Redis 会话/缓存 内存不足、连接中断
Elasticsearch 知识文档索引 集群不可用、索引分片异常

章节来源

  • AI_AGENT.md:60-120

性能特征

环节 特征 优化要点
SSE 流 Reactor 非阻塞流式转发 避免单帧过大;工具结果有字符上限
工具调用 LLM ReAct 循环 减少无关工具;控制结果大小
SQL 执行 流式 + 产物 CSV 不要在前端渲染全量表格
Python 执行 子进程 + 快照副本 控制数据量与超时
向量检索 pgvector 相似度 保持索引重建;注意本地/在线向量表隔离
意图/追问 轻量 LLM 辅助 fail-open,失败不阻塞主链路
会话并发 进程内 Semaphore 多实例部署需补充 DB 状态位

[本节为通用性能讨论,不直接分析具体文件]

常见问题排查

SSE 断连

现象:前端连接建立后很快断开,或长时间没有新帧。

可能原因:

  1. 用户主动中止流式请求。
  2. 同一会话并发发送多条消息,被流闸门拒绝。
  3. 后端订阅线程取消或上游事件流异常。
  4. 网络代理或负载均衡关闭空闲长连接。

排查步骤:

  • 检查后端日志中是否出现 Chat stream error。
  • 检查是否在同一会话快速双击发送,导致“该会话正在回复中”错误帧。
  • 检查代理层是否对 SSE 长连接有限制。
  • 如果是多实例部署,确认进程内 Semaphore 不会误判其他实例的流。

参考实现位置

  • AgentChatServiceImpl.java:345-420

模型不可用

现象:创建会话或发送消息时报错“未指定模型且无默认模型”,或 LLM 调用失败。

可能原因:

  1. agent_model 中没有 default_model=true 的活跃 type=llm 模型。
  2. DashScope/Ollama/OpenAI 配置不完整,如缺少 apiKey 或 baseUrl。
  3. 网络不通、API Key 无效、模型名不存在。
  4. 调用超时:流式分片间隔超时或总时长超限。

排查步骤:

  • 检查模型管理页面是否已有默认模型。
  • 检查 provider 归一化:含 ollama 走 Ollama;含 dashscope/阿里/通义/qwen 走 DashScope;其余走 OpenAI 兼容。
  • 对在线嵌入模型检查 dimensions 是否与返回向量维度一致。
  • 对 LLM 调用检查是否触发 504 超时。

参考实现位置

  • AgentChatServiceImpl.java:450-500
  • EmbeddingModelFactory.java:80-187
  • LlmService.java:1-200

向量检索无结果

现象:调用 search_table_schema 或 RAG 接口返回空,或报“表结构向量索引为空”。

可能原因:

  1. etl.rag.enabled=false。
  2. 未配置嵌入模型。
  3. 尚未重建索引。
  4. 索引存在但文档数为 0。
  5. 本地与在线向量表混用:不同向量空间无法互相召回。

排查步骤:

  • 调用 GET /js/a/chat/reindexWorkspace?id={workspaceId} 重建索引。
  • 检查 RagSchemaService.getStatus 返回的 status、vectorTable、dimensions。
  • 检查 EmbeddingProvider.isAvailable() 与 unavailableMessage()。
  • 确认本地与在线模式没有混用同一向量表。

参考实现位置

  • RagSchemaService.java:60-181
  • EmbeddingProvider.java:60-160

Python 执行器权限或超时

现象:execute_python 返回错误、超时、找不到数据库文件或图片无法显示。

可能原因:

  1. Python 环境未安装 pandas、duckdb、matplotlib。
  2. 当前没有打开的案件,CaseContextHolder 为空。
  3. 工作空间 DuckDB 文件不存在或未初始化。
  4. Python 脚本运行超过 python.timeoutSeconds。
  5. 子进程尝试直接写案件原库,被 Java 侧写锁挡住。
  6. 图片 URL 前缀与服务端 context-path 不一致。

排查步骤:

  • 检查 PythonExecutor.isAvailable() 与环境检测日志。
  • 检查工作空间 dbPath 是否存在。
  • 检查 Python 超时配置是否过小。
  • 确认 Python 代码使用 os.environ['ETL_DB_PATH'] 连接快照副本。
  • 检查产物图片对外地址是否为 /js/a/py/files/{workspaceId}/{execId}/{filename}。

参考实现位置

  • PythonExecutor.java:1-200
  • PythonAnalysisTool.java:1-69

附件上传失败

现象:上传后状态为 FAILED,或提示不支持的文件类型、文件大小超限。

可能原因:

  1. 未打开案件。
  2. 请求 caseId 与当前打开案件不一致。
  3. 文件类型不在允许后缀列表中。
  4. 文件超过文档或表格大小上限。
  5. Tika 无法解析文档内容。
  6. Excel 解析失败,sidecar CSV 生成失败。

参考实现位置

  • ChatAttachmentService.java:60-200

Insight 研判卡住

现象:Insight 会话长时间 STREAMING,或再次追问时报“正在进行中”。

可能原因:

  1. 同一会话并发发送追问。
  2. 进程内 Semaphore 未释放。
  3. 多实例部署下,另一实例持有 DB 状态位。
  4. LLM 或工具调用长时间无响应。

排查步骤:

  • 检查 Insight 会话状态位。
  • 检查是否有重复提交。
  • 检查 Agent 事件流是否到达 AgentEndEvent。
  • 检查工具调用是否卡在 SQL、Python 或外部 API。

参考实现位置

  • InsightServiceImpl.java:100-200

结论

Agent 与 RAG 在清鉴平台中构成了从自然语言到数据分析的闭环:前端通过 SSE 获得实时流式体验,后端通过 AgentScope 组合 LLM、工具、向量检索与产物管理,最终输出文本、图表、CSV 产物、关系图和结构化 Insight。

实践中最关键的是三个边界:

  1. 模型边界:明确对话模型与嵌入模型,区分 DashScope/Ollama/OpenAI 与本地 ONNX。
  2. 数据边界:DuckDB 只读、附件三重归属、产物按工作空间隔离、向量表按模型隔离。
  3. 流程边界:意图识别和追问建议是辅助链路,fail-open;主对话流必须保证会话互斥、事件完整、产物可靠。

只要维护好模型配置、RAG 索引状态、Python 环境和附件权限,Agent 与 RAG 就能稳定支撑“问一句、查一张表、跑一段分析、出一种结论”的研判流程。