# 模块化 RAG Pipeline 架构 **更新日期**:2026-07-06 **状态**:当前已实现架构 **关联 OpenSpec**:`openspec/changes/archive/2026-07-06-modular-rag-pipeline` ## 1. 定位 本文记录 `lookup_knowledge` 的当前模块化 RAG 实现。它是 [rag-architecture.md](rag-architecture.md) 的落地版,重点说明代码模块、数据契约、降级策略和可观测性边界。 核心目标: - 保留显式 Agent Tool:`lookup_knowledge(query)`。 - L0 只作为 query understanding / filter / rerank / trace hint。 - L1 向量检索作为事实证据来源。 - filtered L1 低质量时,降级为 raw query unfiltered L1 retry。 - 输出 evidence-first contract,替代旧 `primary/supplement`。 ## 2. 当前链路 ```mermaid flowchart TD Agent["Executor Agent"] --> Tool["LookupKnowledgeTool.lookupKnowledge(query)"] Tool --> Transform["KnowledgeQueryTransformer"] Transform --> KQ["KnowledgeQuery"] KQ --> Retriever["KnowledgeDocumentRetriever"] Retriever --> Attempt1["FILTERED_VECTOR or UNFILTERED_VECTOR"] Attempt1 --> Post1["KnowledgeEvidencePostProcessor"] Post1 --> Quality{"usable evidence?"} Quality -->|yes| Pack Quality -->|no and categoryFilter exists| Retry["UNFILTERED_VECTOR_RETRY"] Retry --> Post2["KnowledgeEvidencePostProcessor"] Post2 --> Pack["KnowledgeContextPacker"] Pack --> Assemble["LookupResultAssembler"] Assemble --> Result["LookupResult"] Result --> Dedup["RetrievedDocTracker session dedup"] Dedup --> Recorder["ToolInvocationRecorder"] Recorder --> Trace["tool_invocation.retrieval_details"] Result --> Agent ``` 对应代码: | 阶段 | 类 | 职责 | |---|---|---| | Tool Boundary | `LookupKnowledgeTool` | 接收 Agent 工具调用,编排 pipeline,处理 session dedup 和 recorder | | Query Transformation | `KnowledgeQueryTransformer` | 复用 L0,输出 query hints 和可选 category filter | | Retrieval | `KnowledgeDocumentRetriever` | 调用 `VectorSearchService`,统一 filtered / unfiltered attempt | | Post-Retrieval | `KnowledgeEvidencePostProcessor` | L2 归一化、证据块构建、source dedup、规则 rerank | | Context Packing | `KnowledgeContextPacker` | 按字符预算打包 Agent 可消费 context | | Result Assembly | `LookupResultAssembler` | 统一 evidence result、no-evidence result、dedup result | | Observability | `ToolInvocationRecorder` | 写入 query transform、retrieval trace、rerank trace、context pack summary | ## 3. L0 与 L1 边界 L0 来源于 `KnowledgeIndexService.analyzeQuery`,输出进入 `KnowledgeQuery`: ```text originalQuery rewrittenQuery domainHints matchedKeywords entities categoryFilter l0Titles l0MatchCount ``` L0 可以做: - 给 L1 提供单一 category filter。 - 给 rerank 提供 domain / keyword / entity boost 信号。 - 给 trace 提供解释信息。 L0 不再做: - 不因唯一命中直接返回文档正文。 - 不在 L1 无结果时作为事实证据兜底。 - 不进入 `evidenceBlocks`,除非未来明确引入新的 evidence source 规则。 L1 通过 `VectorSearchService.searchSimilarDocuments(query, topK, category)` 执行,内部仍保留 Spring AI VectorStore 优先和 Milvus SDK fallback。 ## 4. 降级策略 MVP 降级策略保持简单: ```text if categoryFilter exists: run FILTERED_VECTOR if empty / no evidence / top similarity < referenceThreshold: run UNFILTERED_VECTOR_RETRY with original query else: run UNFILTERED_VECTOR ``` fallback reason: | reason | 含义 | |---|---| | `filtered_vector_no_evidence` | filtered L1 无候选或 post-processing 后无 evidence | | `filtered_vector_low_quality` | filtered L1 有候选,但 top normalized similarity 低于 `retrieval.normalization.reference-threshold` | 当 retry 后仍无证据: - `found=false` - `evidenceStatus=no_evidence` - 保留 `retrievalTrace` - 不返回 L0 文档作为事实证据 ## 5. Evidence-First Contract `LookupResult` 当前核心字段: ```text found evidenceBlocks contextPack retrievalTrace rerankTrace relevanceLevel completenessHint retrievedDomainsThisSession message ``` 旧字段已删除: ```text primary supplement ``` 这是一项 L4 breaking interface change。项目内已同步迁移: - `LookupKnowledgeTool` - `ToolInvocationRecorder` - executor prompts - lookup / recorder tests - RAG architecture docs - OpenSpec 主 spec ## 6. Trace 结构 `retrieval_details` 保持 JSON 扩展,不改表结构。关键内容: ```json { "query_transform": {}, "retrieval_trace": { "selected_attempt": "UNFILTERED_VECTOR_RETRY", "fallback_reason": "filtered_vector_no_evidence", "attempts": [] }, "context_pack_summary": {}, "rerank_trace": {}, "evidence_blocks": [] } ``` 这样 Trace API、Verifier、Eval 可以继续从 `tool_invocation` 读取证据链。 ## 7. Review 修正 归档前 review 发现:session dedup 命中时返回 `found=false`,但仍携带 `evidenceBlocks/contextPack`,可能导致 Agent 重复消费证据。 当前行为已修正: - dedup result 不再返回可消费 evidence/context。 - 保留 message、retrieval trace、relevance hint 和 retrieved domains。 - 测试覆盖:`LookupKnowledgeToolTest.sessionDedupDoesNotReturnConsumableEvidenceAgain`。 ## 8. 验证 已执行: ```powershell mvn -q -DskipTests compile mvn -q "-Dtest=LookupKnowledgeToolTest,ToolInvocationRecorderTest" test $env:MILVUS_TOKEN = ; mvn -q test openspec validate --all --strict git diff --check ``` 结果:全部通过。 注意: - `MilvusConnectionTest` 直接读 `MILVUS_TOKEN` 环境变量,不读 Spring 配置。 - 完整测试需要在 Maven 进程里注入该环境变量。 ## 9. 后续演进 建议后续按评测结果推进,而不是先堆复杂能力: - 增加 RAG eval cases:固定 query、期望 source、期望 fallback path。 - 引入更严格的 evidence grounding 检查。 - 当规则 rerank 不足时,再考虑 model-based rerank。 - 当召回覆盖率不足时,再考虑 BM25/RRF/hybrid retrieval。