docs: reorganize MVP interview documentation

This commit is contained in:
aruo
2026-07-05 15:29:28 +08:00
parent b22f2d22c8
commit 88e0a6c944
51 changed files with 4352 additions and 1318 deletions
+266
View File
@@ -0,0 +1,266 @@
# 检索与可观测性架构
**更新日期**:2026-07-05
**状态**:当前可运行架构
**参考历史文档**:`archive/2026-07-05-legacy/knowledge-retrieval-architecture.md`
## 1. 定位
本文补充 [rag-architecture.md](rag-architecture.md) 中的检索细节,重点回答:
- 查询如何进入 `lookup_knowledge`。
- L0 和 L1 当前分别承担什么职责。
- 检索结果如何归一化、去重、记录。
- 如何通过 trace 和 eval 判断检索质量。
当前架构与旧版最大的差异是:L0 不再因为唯一命中而默认跳过 L1。L0 是 hint 和解释信号,L1 语义检索是默认召回路径。
## 2. 检索总图
```mermaid
flowchart TD
Query["Agent query / AIOps recommended query"] --> Tool["LookupKnowledgeTool"]
Tool --> L0["KnowledgeIndexService.analyzeQuery"]
L0 --> L0Result["L0 hint: matches / domains / keywords"]
L0Result --> Filter["singleDomainOrNull -> category filter"]
Tool --> L1["VectorSearchService.searchSimilarDocuments"]
Filter --> L1
L1 --> Mode{"retrieval.vector-store.mode"}
Mode -->|auto| Spring["Spring AI VectorStore"]
Spring -->|failure| SDK["Milvus SDK fallback"]
Mode -->|spring-ai| Spring
Mode -->|sdk| SDK
Spring --> Candidates["L1 candidates"]
SDK --> Candidates
Candidates --> Normalize["relevance normalization"]
L0Result --> Normalize
Normalize --> Result["LookupResult"]
Result --> Dedup["RetrievedDocTracker session dedup"]
Dedup --> Final["final tool output"]
Final --> Invocation["tool_invocation"]
Final --> Agent["Agent Executor"]
```
## 3. L0 Hint 层
L0 的输入是原始 query,输出是解释性结构:
```text
matches
matchedKeywords
domains
singleDomainOrNull
```
当前职责:
| 职责 | 说明 |
|---|---|
| domain hint | 判断 query 可能属于哪个知识域 |
| entity / keyword hint | 记录命中的关键词、错误码、服务名等 |
| category filter candidate | 当只有单一领域时,给 L1 一个 metadata filter 候选 |
| trace explanation | 写入 `tool_invocation.retrieval_details`,用于解释检索为什么这么走 |
不再承担:
```text
matches=1 -> skip L1 -> 直接返回 L0 文档正文
```
原因:
- 子串命中不等价于最终相关性。
- L0 没有稳定排序和语义相似度。
- AIOps query 往往包含多个字段,单点关键词命中容易误导。
## 4. L1 语义检索层
L1 通过 `VectorSearchService` 调度,支持三种模式:
| 模式 | 行为 | 用途 |
|---|---|---|
| `auto` | 优先 Spring AI VectorStore,失败 fallback 到 SDK | 默认运行模式 |
| `spring-ai` | 只走 Spring AI VectorStore | 验证框架路径 |
| `sdk` | 只走 Milvus SDK | 对比旧链路或临时回退 |
### Spring AI VectorStore 路径
```text
SearchRequest
-> query
-> topK
-> similarityThresholdAll
-> optional filterExpression
-> VectorStore.similaritySearch
```
### Milvus SDK fallback
```text
query
-> VectorEmbeddingService.generateQueryVector
-> Milvus search(vector, topK, L2)
-> id / content / metadata
```
SDK fallback 保留的价值:
- VectorStore bean 缺失时不让 MVP 主链路中断。
- Spring AI collection/schema 配置异常时可回退。
- 便于 SDK 与 VectorStore 的结果对比。
## 5. 分数与相关性归一化
检索结果输出三类分数字段:
| 字段 | 说明 |
|---|---|
| `score` | 兼容旧逻辑的距离型分数 |
| `rawScore` | 底层检索实现原始分数 |
| `scoreLabel` | 原始分数语义,例如 `similarity` 或 `l2_distance` |
工具层再把 L0/L1 情况归一为:
| relevanceLevel | 含义 |
|---|---|
| `PRECISE` | L0 单命中且 L1 相似度高 |
| `HIGHLY_RELEVANT` | L1 相似度高,或 L0 多命中且 L1 支撑强 |
| `REFERENCE` | 可作为参考,但不足以声明强证据 |
| `DEDUPED` | 同 session 中已检索过,不重复注入上下文 |
归一化结果用于:
- 给 Agent 输出 completeness hint。
- 写入 `tool_invocation.relevance_level`。
- 给 Verifier 构造 `tool_trace_summary`。
- 供 EvaluationService 计算 evidence score。
## 6. 文档切片和 metadata
当前保留 Markdown-aware chunking。
关键 metadata:
```text
docId
chunkIndex
totalChunks
title
breadcrumb
category
source
```
embedding 输入已经增强为:
```text
title + breadcrumb + content
```
这解决旧版检索中的一个主要问题:单个 chunk 被召回后,LLM 不知道它属于哪个文档、哪个章节。
## 7. 输出和记录
`lookup_knowledge` 的输出会进入两条路径:
```mermaid
flowchart LR
LookupResult["LookupResult"] --> Agent["Agent context"]
LookupResult --> Recorder["ToolInvocationRecorder"]
Recorder --> Invocation["tool_invocation"]
Invocation --> Trace["DiagnosisTraceService"]
Invocation --> Summary["ToolTraceSummaryService"]
Summary --> Verifier["chat_verifier"]
Invocation --> Eval["EvaluationService / RAG eval"]
```
`tool_invocation` 中与检索相关的字段:
```text
retrieval_layer
l0_match_count
l1_match_count
retrieval_details
relevance_level
dedup_reason
output_preview
duration_ms
success
```
`retrieval_details` 承载更细信息,例如:
- L0 命中文档标题和路径。
- L1 分数。
- retrieved domains。
- evidence status。
- dedup reason。
## 8. 去重与行动记忆
当前 session 级去重由 `RetrievedDocTracker` 负责。
```text
sessionId + docKey
-> already retrieved?
-> yes: return dedup message and record dedup_reason
-> no: mark retrieved and return evidence
```
去重目的:
- 避免同一文档反复进入上下文。
- 降低 token 浪费。
- 给 Executor 一个“这个方向已经查过”的行动记忆。
注意:去重不是全局缓存,只在当前诊断 session 内生效。
## 9. 检索质量评测
检索质量不能只看一次接口返回,需要用固定 query 回归。
当前评测资产:
| 资产 | 用途 |
|---|---|
| `eval/rag-retrieval/cases/golden-cases.json` | 固定 query 和期望证据 |
| `eval/rag-retrieval/fixtures/` | 离线候选结果 |
| `eval/rag-retrieval/reports/baseline.md` | 人类可读基线 |
| `scripts/eval_rag_retrieval.py` | 离线回归 |
| `scripts/eval_rag_live_acceptance.py` | 运行环境验收 |
评测层次:
```text
offline baseline
-> 不依赖服务和外部组件
live acceptance
-> 调用 /api/search/similar
-> 验证重建索引后的真实检索
trace inspection
-> 检查 Agent 是否真的调用 lookup_knowledge
-> 检查 tool_invocation 证据是否完整
```
## 10. 后续增强
近期优先:
1. 完整 evidence block 输出。
2. 邻居 chunk / 同章节上下文扩展。
3. metadata taxonomy 清理。
4. Query Transformer / MultiQuery 可回退接入。
5. 更完整的 Recall@K、MRR、nDCG 报告。
暂不优先:
- 重新引入 L0 直接返回。
- 一次性迁移所有写入路径。
- 在没有评测收益前引入 rerank / RRF / BM25。