diff --git a/mvp/architecture/README.md b/mvp/architecture/README.md index be5159b..7cf4e6c 100644 --- a/mvp/architecture/README.md +++ b/mvp/architecture/README.md @@ -1,6 +1,6 @@ # MVP 架构文档 -**更新日期**:2026-07-26 +**更新日期**:2026-07-28 **状态**:当前单 Diagnosis Agent + Harness 架构 当前文档入口: @@ -12,7 +12,8 @@ | [harness-quality-gates.md](harness-quality-gates.md) | Run、Tool、Evidence、Semantic、Release 与 Trace Recorder 门禁 | | [session-trace-lifecycle.md](session-trace-lifecycle.md) | sessionId/runId、SSE、统一 Timeline 和 reasoning audit 生命周期 | | [diagnosis-information-gain-stop-architecture.md](diagnosis-information-gain-stop-architecture.md) | 已实施的信息增益评价、Harness 饱和检测、Draft 合同失败降级与证据不足停止设计 | +| [rag-knowledge-retrieval-architecture.md](rag-knowledge-retrieval-architecture.md) | 当前 `lookup_knowledge` 检索:MilvusClientV2 dense+BM25 hybrid、chunk 证据身份、重建运维 | -2026-07-22 前的多角色编排、双入口和旧证据链文档已移动到 `archive/2026-07-22-legacy/`,仅用于历史决策追溯,不代表当前运行时。 +2026-07-22 前的多角色编排、双入口和旧证据链文档已移动到 `archive/2026-07-22-legacy/`,仅用于历史决策追溯,不代表当前运行时。其中旧 RAG 描述(Spring AI VectorStore 主路径 + Milvus SDK fallback)已被当前 hybrid 实现取代,请以 [rag-knowledge-retrieval-architecture.md](rag-knowledge-retrieval-architecture.md) 为准。 当前普通 Trace 与 Provider reasoning 审计使用独立存储和独立接口。Reasoning 访问控制、保留期限、加密要求以及真实 Provider/V015 验证仍由 ISS-015 跟踪,不能把“数据已分表”理解为“治理已经完成”。 diff --git a/mvp/architecture/current-mvp-architecture.md b/mvp/architecture/current-mvp-architecture.md index 5329156..7d7a63e 100644 --- a/mvp/architecture/current-mvp-architecture.md +++ b/mvp/architecture/current-mvp-architecture.md @@ -1,12 +1,14 @@ # 当前 MVP 架构 -**更新日期**:2026-07-23 +**更新日期**:2026-07-28 **状态**:当前可运行架构 ## 1. 系统定位 SuperBizAgent 是面向故障诊断的可追踪 Agent 应用。当前系统只保留一个拥有 Tool loop 的 `Diagnosis Agent`;Harness 负责确定性的预算、取消、工具边界、证据验真、语义审查和安全发布。 +知识检索当前为显式 `lookup_knowledge` 工具 + 单一 MilvusClientV2 后端(dense / dense+BM25 hybrid)。详细链路见 [rag-knowledge-retrieval-architecture.md](rag-knowledge-retrieval-architecture.md)。 + ## 2. 分层 ```mermaid @@ -63,6 +65,29 @@ Agent 只看到三个固定 Tool: 每次调用由框架提供 `tool_call_id`,Harness 校验 exact run、只读、Schema、预算和容量。Redis 保存 TTL 内完整 canonical invocation;MySQL `tool_invocation` 只保存长期有界 metadata,不保存完整参数、SQL/日志正文、raw response 或 Agent projection。 +### 4.1 `lookup_knowledge` 检索边界 + +```text +Agent + -> RagToolAdapter / ToolBoundary + -> LookupKnowledgeTool + -> L0 hint(可选 category filter) + -> KnowledgeSearchPort + -> VectorSearchService + -> MilvusHybridKnowledgeStore # 唯一知识向量后端 + -> RagResultProjector # 有界 Agent 投影 +``` + +要点: + +- 默认 `retrieval.search.mode=hybrid`:dense ANN + BM25 sparse ANN + RRFRanker。 +- 也可切 `dense`:仅 dense ANN。 +- 已移除知识路径上的 legacy `MilvusServiceClient` search 与 `vector-store.mode=sdk|spring|auto` 路由。 +- 证据按 chunk 级 `evidenceKey` 去重;Agent 侧 `document_id` 为 chunk 级身份。 +- 知识库全量重建:`python scripts/rebuild_hybrid_knowledge.py --confirm REBUILD`,默认操作 collection `biz`。 + +完整 schema、模式、重建与历史差异见 [rag-knowledge-retrieval-architecture.md](rag-knowledge-retrieval-architecture.md)。 + ## 5. Trace 与持久化 ```text @@ -90,6 +115,13 @@ chat_session(sessionId) Reasoning endpoint 是敏感审计面,不属于普通业务 API。当前已完成数据和查询隔离;认证授权、保留期限、加密要求及真实 Provider 验证仍由 ISS-015 收敛。Feedback、文档与检索 API 保持独立;已删除的旧诊断和 Redis conversation Session endpoint 不提供兼容分支。 +与知识检索相关的独立 API: + +- `POST /api/knowledge/init`:导入/增量初始化 `knowledge_base` +- `POST /api/knowledge/rebuild-hybrid?confirm=REBUILD`:清空并重建 dense+BM25 collection(默认 `biz`) +- `GET /api/knowledge/stats`:文档元数据统计 +- `GET /milvus/health`:MilvusClientV2 健康检查与 knowledge collection 名 + ## 7. 安全边界 - 普通 SSE、Trace、Evidence Snapshot、业务结果和应用日志不输出或保存 reasoning 原文。 diff --git a/mvp/architecture/rag-knowledge-retrieval-architecture.md b/mvp/architecture/rag-knowledge-retrieval-architecture.md new file mode 100644 index 0000000..2649bd8 --- /dev/null +++ b/mvp/architecture/rag-knowledge-retrieval-architecture.md @@ -0,0 +1,328 @@ +# RAG 知识检索架构 + +**更新日期**:2026-07-28 +**状态**:当前可运行架构 +**关联实现**:`lookup_knowledge`、`MilvusHybridKnowledgeStore`、`KnowledgeSearchPort` +**关联运维**:`scripts/rebuild_hybrid_knowledge.py`、`POST /api/knowledge/rebuild-hybrid` + +## 1. 定位 + +知识检索是 Diagnosis Agent 的显式证据工具,不是隐式 Advisor。 + +```text +Diagnosis Agent + -> lookup_knowledge(query) + -> Harness ToolBoundary / ACI projection + -> EvidenceGuard 只认当前 Run 的 READY canonical 证据 +``` + +目标: + +- 保留 Agent 可见的工具调用与证据边界 +- 用单一向量后端完成 dense + BM25 hybrid 检索 +- 用 chunk 级证据身份保证同文档多片段可同时进入上下文 +- 检索行为可配置、可重建、可审计 + +## 2. 稳定边界 + +```mermaid +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. 当前主链路 + +```mermaid +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 当前后端 + +```text +写入: + VectorIndexService + -> MilvusHybridKnowledgeStore.upsertChunk + +读取: + VectorSearchService + -> MilvusHybridKnowledgeStore.searchDense + -> MilvusHybridKnowledgeStore.searchHybrid +``` + +默认 collection: + +```yaml +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: + +```text +BM25(search_text -> sparse_vector) +``` + +索引: + +```text +vector -> IVF_FLAT + L2 +sparse_vector -> SPARSE_INVERTED_INDEX + BM25 +``` + +写入时: + +- `content` 保存原始 chunk 正文 +- `search_text` / dense embedding 使用 `Title + Path + Content` 拼装文本 +- metadata 必须带 `docId`、`chunkIndex`,供 chunk 级证据身份使用 + +## 6. 检索模式 + +配置: + +```yaml +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 + +```text +query + -> embedding + -> dense ANN on vector + -> topK +``` + +### 6.2 hybrid(当前默认) + +```text +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 与降级 + +```text +if L0 给出唯一 domain: + 先 filtered 检索 + if 无证据或 topSimilarity < referenceThreshold: + 再 unfiltered retry +else: + 直接 unfiltered +``` + +这里的 filter 是 metadata category / kb_scope 约束,不是第二套向量库。 + +## 7. 证据身份与去重 + +Delivery 1 已落地: + +```text +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 日常写入 + +文档上传 / 知识库初始化: + +```text +markdown + -> frontmatter + body + -> DocumentChunkService + -> dense embedding + search_text + -> MilvusHybridKnowledgeStore.upsertChunk + -> MySQL api_document + L0 memory index +``` + +### 10.2 全量重建 + +危险操作,需显式确认: + +```bash +python scripts/rebuild_hybrid_knowledge.py --confirm REBUILD +``` + +等价 API: + +```text +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 结果与检索命中为准