Files
SuperBizAgent-java/mvp/architecture/archive/2026-07-22-legacy/modular-rag-pipeline.md
T

202 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 模块化 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 = <application.yml 中的 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。