Files
SuperBizAgent-java/mvp/architecture/rag-knowledge-retrieval-architecture.md
T
zhuyongxin 2f40536248 docs(mvp): document dense+BM25 hybrid knowledge retrieval
Add current RAG architecture covering MilvusClientV2 hybrid search,
chunk evidence identity, rebuild ops, and update the MVP architecture
index and system overview links.
2026-07-28 09:56:08 +08:00

9.0 KiB
Raw Blame History

RAG 知识检索架构

更新日期:2026-07-28
状态:当前可运行架构
关联实现:lookup_knowledge、MilvusHybridKnowledgeStore、KnowledgeSearchPort
关联运维:scripts/rebuild_hybrid_knowledge.py、POST /api/knowledge/rebuild-hybrid

1. 定位

知识检索是 Diagnosis Agent 的显式证据工具,不是隐式 Advisor。

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

目标:

  • 保留 Agent 可见的工具调用与证据边界
  • 用单一向量后端完成 dense + BM25 hybrid 检索
  • 用 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"]
        Store["MilvusHybridKnowledgeStore"]
    end

    Agent --> Tool
    Tool --> Adapter
    Adapter --> Backend
    Backend --> Port
    Port --> Store
    Adapter --> Projector
    Adapter --> Canonical
边界 职责 不负责
Agent 决定何时检索、如何用证据写报告 不直接访问 Milvus / MySQL 元数据表
Harness Tool 校验、投影裁剪、canonical 存证 不改写检索排序算法
Retrieval L0 hint、dense/BM25 召回、后处理、打包 不绕过 ACI 直接给 Agent 原始库响应

3. 当前主链路

flowchart TD
    A["lookup_knowledge(query)"] --> B["KnowledgeQueryTransformer"]
    B --> C["L0 hint: domain / keywords / categoryFilter"]
    C --> D["KnowledgeDocumentRetriever"]
    D --> E["KnowledgeSearchPort"]
    E --> F["VectorSearchService"]
    F --> G{"retrieval.search.mode"}
    G -->|dense| H["MilvusHybridKnowledgeStore.searchDense"]
    G -->|hybrid| I["MilvusHybridKnowledgeStore.searchHybrid"]
    H --> J["candidates + chunk identity"]
    I --> J
    J --> K["KnowledgeEvidencePostProcessor"]
    K --> L["evidenceKey dedup / maxChunksPerDocument / return-n"]
    L --> M{"filtered low quality?"}
    M -->|yes and had categoryFilter| N["unfiltered retry"]
    N --> K
    M -->|no| O["KnowledgeContextPacker"]
    O --> P["LookupResultAssembler"]
    P --> Q["RagResultProjector"]
    Q --> R["Agent-facing RagToolResult"]

对应代码:

阶段 类 职责
Tool 编排 LookupKnowledgeTool 串联 transform / retrieve / post / pack
Query 理解 KnowledgeQueryTransformer + KnowledgeIndexService L0 只产 hint 与可选 category filter
检索端口 KnowledgeSearchPort / VectorKnowledgeSearchAdapter 屏蔽底层存储细节
检索门面 VectorSearchService dense 或 hybrid 路由
向量后端 MilvusHybridKnowledgeStore 唯一知识库读写后端(MilvusClientV2)
后处理 KnowledgeEvidencePostProcessor 归一化、规则 boost、chunk 去重、相关度等级
打包 KnowledgeContextPacker 有界 context pack
投影 RagResultProjector 只暴露 Agent 可见 evidence 字段

4. 唯一向量后端:MilvusClientV2

4.1 已废弃路径

以下路径不再用于 lookup_knowledge:

  • legacy MilvusServiceClient search / insert
  • retrieval.vector-store.mode=sdk|spring|auto
  • Spring AI VectorStore 作为知识检索主路径

4.2 当前后端

写入:
  VectorIndexService
    -> MilvusHybridKnowledgeStore.upsertChunk

读取:
  VectorSearchService
    -> MilvusHybridKnowledgeStore.searchDense
    -> MilvusHybridKnowledgeStore.searchHybrid

默认 collection:

milvus:
  collection: biz

重建时会 drop + recreate 该 collection,并按 dense + BM25 schema 重建。

5. Collection Schema

biz(可配置)逻辑字段:

字段 类型 用途
id VarChar PK chunk 级主键
content VarChar 返回给 Agent 的原文片段
search_text VarChar + analyzer BM25 输入文本
sparse_vector SparseFloatVector BM25 Function 输出
vector FloatVector dense embedding
metadata JSON docId / chunkIndex / category / kb_scope / title / breadcrumb 等

Function:

BM25(search_text -> sparse_vector)

索引:

vector        -> IVF_FLAT + L2
sparse_vector -> SPARSE_INVERTED_INDEX + BM25

写入时:

  • content 保存原始 chunk 正文
  • search_text / dense embedding 使用 Title + Path + Content 拼装文本
  • metadata 必须带 docId、chunkIndex,供 chunk 级证据身份使用

6. 检索模式

配置:

retrieval:
  search:
    mode: hybrid   # dense | hybrid
  hybrid:
    rrf-k: 60
  kb-scope: ""
rag:
  retrieve-k: 20
  return-n: 5
  max-chunks-per-document: 2

6.1 dense

query
  -> embedding
  -> dense ANN on vector
  -> topK

6.2 hybrid(当前默认)

query
  -> path A: dense ANN(query embedding)
  -> path B: BM25 sparse ANN(raw query text)
  -> Milvus hybridSearch + RRFRanker(k)
  -> topK fused hits

阈值兼容:

  • 后处理仍按 dense 兼容 L2 距离做 normalizeL2
  • hybrid 命中若能从并行 dense 结果拿到同 id 的 L2,则回填该分数
  • 仅 BM25 命中、无 dense 分时,按弱相关处理,避免虚高 PRECISE

6.3 category filter 与降级

if L0 给出唯一 domain:
  先 filtered 检索
  if 无证据或 topSimilarity < referenceThreshold:
    再 unfiltered retry
else:
  直接 unfiltered

这里的 filter 是 metadata category / kb_scope 约束,不是第二套向量库。

7. 证据身份与去重

Delivery 1 已落地:

evidenceKey =
  docId#chunk-{chunkIndex}
  fallback: vector:{id}
  fallback: rank:{n}

规则:

  • 去重按 evidenceKey,不是按 source 文档路径
  • 同文档不同 chunk 可同时保留
  • rag.max-chunks-per-document 限制单文档最多进入结果的 chunk 数
  • rag.return-n 限制后处理后最多返回条数
  • Agent 投影中的 document_id 使用 chunk 级 evidenceKey

这保证 hybrid 召回的多片段不会在后处理/投影阶段被文档级折叠吞掉。

8. L0 / L1 职责

层 做什么 不做什么
L0 domain/keyword hint、可选 category filter、trace 解释、轻规则 boost 不直接当事实 evidence
L1 dense/BM25 事实证据召回 不依赖 frontmatter 关键词命中才返回正文

L0 命中文档正文不会在 L1 失败时兜底成 evidence。

9. Agent 可见契约

Agent 只看到有界 RagToolResult:

  • evidence_status
  • tool_call_id
  • query
  • evidence[]:document_id / source / title / breadcrumb / excerpt
  • relevance_level
  • truncated / returned_count

不暴露:

  • raw score / fused score
  • retrievalTrace / rerankTrace
  • contextPack 全文
  • Milvus 内部字段与凭据

完整内部结果仍在 LookupResult 中,供审计与调试使用。

10. 写入与重建

10.1 日常写入

文档上传 / 知识库初始化:

markdown
  -> frontmatter + body
  -> DocumentChunkService
  -> dense embedding + search_text
  -> MilvusHybridKnowledgeStore.upsertChunk
  -> MySQL api_document + L0 memory index

10.2 全量重建

危险操作,需显式确认:

python scripts/rebuild_hybrid_knowledge.py --confirm REBUILD

等价 API:

POST /api/knowledge/rebuild-hybrid?confirm=REBUILD

服务端顺序:

  1. drop + recreate milvus.collection(默认 biz)
  2. 清空 MySQL api_document
  3. 清空内存 L0
  4. 扫描 knowledge_base/**/*.md(跳过 README.md)force 导入

不会修改磁盘上的 knowledge_base/ 源文件。

11. 与旧文档的差异

旧描述(已归档) 当前实现
Spring AI VectorStore 主路径 + SDK fallback 单一 MilvusClientV2 后端
retrieval.vector-store.mode=auto/sdk/spring 已移除;改为 retrieval.search.mode=dense/hybrid
source 级 evidence 去重 chunk 级 evidenceKey 去重
应用层 sparse-lite lexical 伪 hybrid 库内 dense ANN + BM25 + RRFRanker
新建 biz_hybrid 过渡 collection 默认使用并重建 biz

历史材料见:

  • mvp/architecture/archive/2026-07-22-legacy/rag-architecture.md
  • mvp/architecture/archive/2026-07-22-legacy/modular-rag-pipeline.md

12. 当前已知边界

  • hybrid 依赖云端/实例支持 BM25 Function 与 sparse index
  • 全量重建受 embedding API 与 Milvus 写入延迟影响,可能较慢
  • L0 关键词匹配仍较粗,只作 hint,不作主召回
  • 尚未做邻块上下文自动扩展、cross-encoder rerank、真 query rewrite
  • totalVectors 统计接口仍可能返回 0,不代表 collection 为空;以 rebuild/init 结果与检索命中为准