Files
SuperBizAgent-java/mvp/architecture/retrieval-observability.md
T

7.3 KiB
Raw Blame History

检索与可观测性架构

更新日期:2026-07-06 状态:当前可运行架构
参考历史文档:archive/2026-07-05-legacy/knowledge-retrieval-architecture.md

1. 定位

本文补充 rag-architecture.md 中的检索细节,重点回答:

  • 查询如何进入 lookup_knowledge。
  • L0 和 L1 当前分别承担什么职责。
  • 检索结果如何归一化、去重、记录。
  • 如何通过 trace 和 eval 判断检索质量。

当前架构与旧版最大的差异是:L0 不再因为唯一命中而默认跳过 L1,也不在 L1 失败时作为事实证据兜底。L0 是 hint 和解释信号,L1 语义检索是默认召回路径。

2. 检索总图

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 / spring-ai| Spring
    Mode -->|sdk| SDK

    Spring --> Candidates["L1 candidates"]
    SDK --> Candidates
    Candidates --> Quality{"filtered L1 usable?"}
    Quality -->|no| Retry["raw query unfiltered L1 retry"]
    Quality -->|yes| Post["post-retrieval processing"]
    Retry --> Post
    L0Result --> Post
    Post --> Pack["context packing"]
    Pack --> Result["LookupResult evidenceBlocks/contextPack/traces"]

    Result --> Dedup["RetrievedDocTracker session dedup"]
    Dedup --> Final["final tool output"]
    Final --> Invocation["tool_invocation"]
    Final --> Agent["Agent Executor"]

3. L0 Hint 层

L0 的输入是原始 query,输出是解释性结构:

matches
matchedKeywords
domains
singleDomainOrNull

当前职责:

职责 说明
domain hint 判断 query 可能属于哪个知识域
entity / keyword hint 记录命中的关键词、错误码、服务名等
category filter candidate 当只有单一领域时,给 L1 一个 metadata filter 候选
trace explanation 写入 tool_invocation.retrieval_details,用于解释检索为什么这么走

不再承担:

matches=1 -> skip L1 -> 直接返回 L0 文档正文
L1 无可用证据 -> 返回 L0 文档正文

原因:

  • 子串命中不等价于最终相关性。
  • L0 没有稳定排序和语义相似度。
  • AIOps query 往往包含多个字段,单点关键词命中容易误导。

4. L1 语义检索层

L1 通过 VectorSearchService 调度,支持三种模式:

模式 行为 用途
auto 优先 Spring AI VectorStore,失败 fallback 到 SDK 默认运行模式
spring / spring-ai 只走 Spring AI VectorStore 验证框架路径
sdk 只走 Milvus SDK 对比旧链路或临时回退

Spring AI VectorStore 路径

SearchRequest
  -> query
  -> topK
  -> similarityThresholdAll
  -> optional filterExpression
  -> VectorStore.similaritySearch

Milvus SDK fallback

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

post-retrieval 层再把检索候选归一为:

relevanceLevel 含义
PRECISE L1 相似度高且 query hint 与候选证据互相支撑
HIGHLY_RELEVANT L1 相似度高
REFERENCE 可作为参考,但不足以声明强证据
DEDUPED 同 session 中已检索过,不重复注入上下文

归一化结果用于:

  • 给 Agent 输出 completeness hint。
  • 写入 tool_invocation.relevance_level。
  • 给 Verifier 构造 tool_trace_summary。
  • 供 EvaluationService 计算 evidence score。

6. 文档切片和 metadata

当前保留 Markdown-aware chunking。

关键 metadata:

docId
chunkIndex
totalChunks
title
breadcrumb
category
source

embedding 输入已经增强为:

title + breadcrumb + content

这解决旧版检索中的一个主要问题:单个 chunk 被召回后,LLM 不知道它属于哪个文档、哪个章节。

7. 输出和记录

lookup_knowledge 的输出会进入两条路径:

flowchart LR
    LookupResult["LookupResult: evidenceBlocks/contextPack/traces"] --> 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 中与检索相关的字段:

retrieval_layer
l0_match_count
l1_match_count
retrieval_details
relevance_level
dedup_reason
output_preview
duration_ms
success

retrieval_details 承载更细信息,例如:

  • L0 命中文档标题和路径。
  • L1 attempts、fallback reason、分数和 similarity。
  • retrieved domains。
  • evidence status。
  • dedup reason。
  • evidence block summaries。
  • context pack summary。
  • rerank trace。

8. 去重与行动记忆

当前 session 级去重由 RetrievedDocTracker 负责。

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 运行环境验收

评测层次:

offline baseline
  -> 不依赖服务和外部组件

live acceptance
  -> 调用 /api/search/similar
  -> 验证重建索引后的真实检索

trace inspection
  -> 检查 Agent 是否真的调用 lookup_knowledge
  -> 检查 tool_invocation 证据是否完整

10. 后续增强

近期优先:

  1. 邻居 chunk / 同章节上下文扩展。
  2. metadata taxonomy 清理。
  3. Query Transformer / MultiQuery 可回退接入。
  4. 更完整的 Recall@K、MRR、nDCG 报告。

暂不优先:

  • 重新引入 L0 直接返回。
  • 重新引入 L0 文档作为 L1 失败时的事实证据兜底。
  • 一次性迁移所有写入路径。
  • 在没有评测收益前引入模型 rerank / RRF / BM25。