Files
SuperBizAgent-java/mvp/architecture/RAG知识检索架构.md
zhuyongxin 473bb5d004 docs(mvp): update RAG docs for py-rag extraction
- rewrite RAG architecture doc for py-rag service contract mapping, ingest and rebuild ops
- refresh observability/trace doc for post-L0 single-attempt semantics
- add py-rag chain exploration note; mark superseded Milvus/L0 notes with status banners
- close ISS-017 (superseded by L0 sinking); mark knowledge_domain table orphaned
- refresh architecture/mvp/engineering indexes
2026-09-30 17:03:50 +08:00

11 KiB
Raw Permalink Blame History

RAG 知识检索架构

更新日期:2026-09-29
状态:当前可运行架构
关联实现:lookup_knowledge、KnowledgeSearchPort、PyRagKnowledgeSearchAdapter、PyRagClient
关联契约:py-rag 仓库 docs/Java接入文档.md(API v1,冻结面)
关联运维:py-rag /api/v1/collections:rebuild(全量重建)、py-rag /api/v1/documents:ingest(单文档入库)

1. 定位

知识检索是 Diagnosis Agent 的显式证据工具,不是隐式 Advisor。 检索算法(dense+BM25 融合、rerank、判级)与文档入库(解析、frontmatter、分块、向量化) 全部由独立的 py-rag 知识服务承担;Java 侧只保留 harness 消费面与 HTTP 客户端。

Diagnosis Agent
  -> lookup_knowledge(query)
  -> Harness ToolBoundary / ACI projection
  -> EvidenceGuard 只认当前 Run 的 READY canonical 证据

目标:

  • 保留 Agent 可见的工具调用与证据边界
  • 检索/入库基础设施外置为独立服务,Java 侧不感知引擎细节
  • 用 chunk 级证据身份保证同文档多片段可同时进入上下文
  • 检索行为可配置、可重建、可审计

2. 稳定边界

flowchart LR
    subgraph AgentBoundary["Agent boundary"]
        Agent["Diagnosis Agent"]
        Tool["lookup_knowledge"]
    end

    subgraph HarnessBoundary["Harness boundary"]
        Adapter["RagToolAdapter"]
        Projector["RagResultProjector"]
        Canonical["Redis canonical invocation"]
    end

    subgraph RetrievalBoundary["Retrieval boundary"]
        Backend["LookupKnowledgeTool"]
        Port["KnowledgeSearchPort"]
        Remote["PyRagKnowledgeSearchAdapter"]
        Service["py-rag 知识服务 (HTTP /api/v1)"]
    end

    Agent --> Tool
    Tool --> Adapter
    Adapter --> Backend
    Backend --> Port
    Port --> Remote
    Remote -->|HTTP| Service
    Adapter --> Projector
    Adapter --> Canonical
边界 职责 不负责
Agent 决定何时检索、如何用证据写报告 不直接访问 py-rag / MySQL 元数据表
Harness Tool 校验、投影裁剪、canonical 存证 不改写检索排序算法
Retrieval 请求映射、后处理、打包;py-rag 承担召回/融合/rerank/判级 不绕过 ACI 直接给 Agent 原始库响应

3. 当前主链路

flowchart TD
    A["lookup_knowledge(query)"] --> B["原始 query 直传(L0 已下沉 py-rag)"]
    B --> C["KnowledgeDocumentRetriever"]
    C --> D["KnowledgeSearchPort"]
    D --> E["PyRagKnowledgeSearchAdapter"]
    E -->|POST /api/v1/search| F["py-rag: dense+BM25 融合 / rerank / 判级"]
    F --> G["hits + evidenceKey(docId#chunk-N)"]
    G --> H["KnowledgeEvidencePostProcessor"]
    H --> I["evidenceKey dedup / maxChunksPerDocument / return-n"]
    I --> J["KnowledgeContextPacker"]
    J --> K["LookupResultAssembler"]
    K --> L["RagResultProjector"]
    L --> M["Agent-facing RagToolResult"]

对应代码:

阶段 类 职责
Tool 编排 LookupKnowledgeTool 串联 retrieve / post / pack;UNFILTERED 单 attempt 主路径
检索端口 KnowledgeSearchPort / PyRagKnowledgeSearchAdapter 防腐层;请求映射 + 命中归一化
HTTP 客户端 PyRagClient API v1 调用、错误信封(E_*)、X-Request-ID、分端点超时
后处理 KnowledgeEvidencePostProcessor qualityScore(RERANK 直传)、chunk 去重、相关度等级
打包 KnowledgeContextPacker 有界 context pack
投影 RagResultProjector 只暴露 Agent 可见 evidence 字段

2026-09-29 抽离时删除的 Java 侧组件:MilvusHybridKnowledgeStore、VectorSearchService、 VectorKnowledgeSearchAdapter、RrfFusion / LexicalRanker(融合评分下沉)、 KnowledgeIndexService / KnowledgeDomainService(L0 索引)、 DocumentChunkService / FrontmatterParser / TextExtractorService(入库解析)、 KnowledgeQueryTransformer(L0 query 理解)。

4. py-rag 检索契约映射

请求映射(PyRagKnowledgeSearchAdapter):

Java(KnowledgeSearchRequest) py-rag(/api/v1/search) 说明
query query 原始检索句直传,服务端自行处理边界与精排
mode=DENSE mode=semantic 纯向量,对照/排障用
mode=HYBRID mode=hybrid dense+BM25 融合,线上主路径(retrieval.search.mode: hybrid)
topK retrieve_k / return_n / max_chunks_per_document 三者同置 topK:chunk 去重截断由 Java 后处理器统一负责,避免服务端预截断
categoryFilter category L0 下沉后恒为 null(不过滤)
— kb_scope 不传,由 py-rag 部署配置决定

响应映射:

py-rag Java(KnowledgeSearchHit) 说明
evidence_key evidenceKey / docId / chunkIndex docId#chunk-N,与 EvidenceGuard 验真约定一致
excerpt content 进入 context pack 的正文
quality_score score / rawScore rerank 绝对相关分 [0,1],越大越好
— scoreLabel=RERANK RetrievalScoreNormalizer 对 RERANK 分支 quality 原样 clamp,不走 L2/rank 归一化
relevance_level (参考值) Java 后处理按同阈值(0.75/0.5)独立判级,语义一致
evidence_status=no_evidence 空列表 正常业务响应(服务端保证 hits=[]),Agent 侧按"无知识可用"处理

超时与重试矩阵见 py-rag 仓库 docs/Java接入文档.md 第 6 节;Java 侧由 pyrag.* 配置承载。

5. 入库与重建

5.1 日常写入

业务上传(DocumentController /api/documents/upload)
  -> MySQL api_document(业务元数据:faultSource 等)+ 本地原件保存
  -> PyRagClient.ingest(multipart 透传原件 + category)
  -> py-rag:解析 / frontmatter 校验 / 分块 / 向量化 / 索引

简单上传(FileUploadController /api/upload)
  -> 本地保存 + PyRagClient.ingest(category 可选参数,缺省 default;入库失败不影响上传成功语义)

MySQL api_document.docId 取 py-rag 返回的 doc_id(路径 slug + 内容 SHA-256 前 8 位), 与检索 evidence_key 的 docId 段对齐;chunk_count 取 ingest 响应。

5.2 全量重建

POST /api/v1/collections:rebuild?confirm=REBUILD   (py-rag 服务端)
GET  /api/v1/tasks/{task_id}                       (任务状态)
  • rebuild 为 py-rag 异步任务;执行期间 ingest 返回 409(E_REBUILD_IN_PROGRESS),search 不受影响
  • 原料为 py-rag 服务端 data/knowledge_base/ 下历次 ingest 落盘的 md
  • 旧 Java 侧 POST /api/knowledge/rebuild-hybrid 与 scripts/rebuild_hybrid_knowledge.py 已删除

5.3 单文档删除

py-rag API v1 没有单文档删除端点。DELETE /api/documents/{docId} 只删 MySQL 元数据与本地原件; py-rag 侧已入库内容需全量重建后才会消失(见 DocumentManagementService.deleteDocument 注释)。

6. 部署与配置

pyrag:
  base-url: ${PYRAG_BASE_URL:http://localhost:8000}
  connect-timeout-ms: 3000
  search-read-timeout-ms: 5000     # 正常 300–800ms(含 rerank 外呼)
  ingest-read-timeout-ms: 30000
  default-read-timeout-ms: 10000
  • Milvus / etcd / MinIO 随 py-rag 部署,不再由本仓库 docker-compose.yml 管理(compose 仅剩 MySQL/Redis)
  • vector-database.yml 已删除;Makefile 的 up/down/status 只管 MySQL/Redis
  • retrieval.search.mode: hybrid 语义保留:映射 py-rag 的 hybrid / semantic

7. 证据身份与去重(不变)

evidenceKey = docId#chunk-{chunkIndex}
  fallback: vector:{id}
  fallback: rank:{n}
  • 去重按 evidenceKey,同文档不同 chunk 可同时保留
  • rag.max-chunks-per-document / rag.return-n 在 Java 后处理器生效
  • Agent 投影中的 document_id 使用 chunk 级 evidenceKey,EvidenceGuard 据此验真

8. Agent 可见契约(不变)

Agent 只看到有界 RagToolResult:

  • evidence_status / tool_call_id / query
  • evidence[]:document_id / source / title / breadcrumb / excerpt
  • relevance_level(PRECISE / REFERENCE;RagRelevanceLevel.HIGHLY_RELEVANT 为保留档)
  • truncated / returned_count

不暴露:raw score、retrievalTrace / rerankTrace、contextPack 全文、py-rag 地址与凭据。 完整内部结果仍在 LookupResult 中,供审计与调试使用。Trace / 审计读法见 RAG检索可观测性与审计.md。

9. L0 下沉

L0 query 理解(domain/keyword hint → 可选 categoryFilter)随本次抽离整体下沉 py-rag:

  • KnowledgeQueryTransformer / KnowledgeIndexService.analyzeQuery 已删除
  • lookup_knowledge 直传原始 query;categoryFilter 恒为 null,走 UNFILTERED 单 attempt
  • LookupKnowledgeTool 中 filtered→unfiltered 降级分支保留但不可达(作为未来 Java 侧过滤策略的兜底骨架)
  • RetrievalTrace.queryHints 恒为空结构;attempt 命名只剩 UNFILTERED_VECTOR

10. 与旧文档的差异

旧描述(2026-07-28 版) 当前实现(2026-09-29 抽离后)
进程内 MilvusClientV2,dense+BM25+RRF py-rag 服务端承担;Java 经 KnowledgeSearchPort → HTTP
retrieval.search.mode 切 Milvus 查询算法 同名配置映射 py-rag hybrid / semantic
scoreLabel 仅 dense | hybrid,L2/rank 归一化 新增 RERANK:py-rag rerank 绝对分直传
L0 hint + categoryFilter + filtered/unfiltered retry L0 下沉;原始 query 直传,单 attempt
Java 侧 frontmatter 解析 / 分块 / embedding 入库 py-rag documents:ingest;Java 只做 MySQL 元数据 + 原件保存
POST /api/knowledge/rebuild-hybrid 重建 py-rag POST /api/v1/collections:rebuild
GET /milvus/health 健康检查 py-rag GET /api/v1/health(含 milvus/embedding/rerank 探针)
删除文档同步删向量索引 仅删 MySQL+本地文件;py-rag 侧靠全量重建生效

历史材料见:

  • mvp/architecture/archive/2026-07-22-legacy/rag-architecture.md(Milvus 前身)
  • mvp/engineering/rag/Milvus-Hybrid接入清单.md(进程内 Milvus hybrid 接入纪要,已过时)
  • 本仓库 git 历史:refactor/extract-rag-module 分支,71 文件 / 约 -8000 行

11. 当前已知边界

  • py-rag 判级阈值(0.75/0.5/0.3)未校准,quality_score 仅供排序与展示参考(契约已知边界)
  • frontmatter 的 keywords/summary/covers/when_to_retrieve 当前仅上传方提供;Java 侧 LLM 补全(原 DocumentFieldEnricher)已随抽离移除,待 py-rag 开放
  • knowledge_base/ 历史原料需在 py-rag 侧完成一次性 ingest 迁移后方可检索
  • 无单文档删除;下线文档靠 py-rag 全量重建
  • eval/rag-retrieval 离线基线基于旧 L0/scoreLabel 语义构建,抽离后需重新校准(见 mvp/engineering/rag/RAG离线评测-基线设计.md 顶部说明)
  • Trace/审计细节与限制见 RAG检索可观测性与审计.md