# Agent 如何读 `relevance_level`:它是什么、不是什么 **日期**:2026-07-28 **范围**:`lookup_knowledge` 投影给 Agent 的粗粒度相关度标签 **读者**:要在 Diagnosis Agent / 工具契约里正确使用知识库结果的工程与提示词同学 **关联**: - ACI 契约:`RagToolResult.relevance_level` / `RagRelevanceLevel` - 计算:`KnowledgeEvidencePostProcessor` → `qualityScore` 阈值 - 质量统一:`RAG-Hybrid质量分与后处理.md` - 多路与 RRF:`RAG排序-多路召回与RRF.md` - **运行时 Trace / 审计**:`mvp/architecture/RAG检索可观测性与审计.md` --- ## 1. 一句话定义 **`relevance_level` 是对「这一次 `lookup_knowledge` 调用整体有多相关」的粗档标签,不是某一条 evidence 的分数,也不是 0~1 的相似度。** Agent 真正写诊断、做引用时,仍应以 `evidence[]` 里的 excerpt 为准;`relevance_level` 只帮助判断:**这批评据大概有多硬、还要不要再查。** ```mermaid flowchart LR subgraph tool["lookup_knowledge 结果"] ES[evidence_status] EV[evidence excerpt] RL[relevance_level] TR[truncated] end ES --> DEC{Agent 决策} EV --> DEC RL --> DEC TR --> DEC DEC --> A1[写结论 / 引用] DEC --> A2[再查 / 换工具] DEC --> A3[证据不足降级] ``` --- ## 2. 它出现在哪里 成功(或有结果)的知识库工具投影里,典型形状: ```json { "evidence_status": "EVIDENCE_FOUND", "tool_call_id": "call-…", "query": "用户/Agent 的检索句", "evidence": [ { "document_id": "doc#chunk-0", "source": "…", "title": "…", "breadcrumb": "…", "excerpt": "…" } ], "returned_count": 3, "relevance_level": "PRECISE", "truncated": false } ``` 要点: - JSON 字段名是 **`relevance_level`**(snake_case) - Java 枚举:`RagRelevanceLevel`(`PRECISE` / `HIGHLY_RELEVANT` / `REFERENCE`) - 无可用证据或质量不够时,字段常为 **null / 省略**(`NON_NULL`) - Agent **看不到** raw L2、RRF 分、`retrievalTrace`、`rerankTrace`(ACI 有意裁掉) ```mermaid flowchart TB subgraph internal["内部 LookupResult(审计/调试)"] QS[qualityScore / topSimilarity] RT[retrievalTrace / rerankTrace] CP[contextPack 全文] SC[raw score / scoreLabel] end subgraph project["RagResultProjector"] P[裁剪与规范化] end subgraph agent["Agent 可见 RagToolResult"] A1[evidence_status] A2[tool_call_id / query] A3[evidence excerpt 列表] A4[relevance_level 可选] A5[returned_count / truncated] end internal --> P --> agent ``` --- ## 3. 枚举值怎么理解 | 值 | 产品语义 | Agent 侧更合理的用法 | |----|----------|----------------------| | **PRECISE** | 整体很贴:当前 top 证据质量高,继续同题检索不太可能更准 | 优先依据 `evidence[]` 组织结论;避免无意义的重复 `lookup_knowledge` | | **HIGHLY_RELEVANT** | 高度相关(枚举保留) | 与 PRECISE 类似,略保守表述即可 | | **REFERENCE** | 可作参考,但不到「已精准命中」 | 可引用,但结论留余地;缺维度时换 query 再查或叠日志/指标 | | **null / 不出现** | 没有可报的粗相关档(无证据或 top 质量偏低) | **不要**当成知识库已证实;按证据不足处理 | ### 和 `evidence_status` 的分工 | 字段 | 回答的问题 | |------|------------| | `evidence_status` | 这次有没有合法、可引用的证据(如 `EVIDENCE_FOUND` / `NO_EVIDENCE`) | | `relevance_level` | **有证据时**,整体有多贴(粗档) | | `evidence[]` | 具体可以引用哪些片段 | 没有证据时,不应指望靠 `relevance_level`「升级」出结论;契约上也不会用 level 把空结果扮成有证据。 ```mermaid flowchart TB ES{evidence_status} ES -->|NO_EVIDENCE| N1[不要当知识库已证实] ES -->|EVIDENCE_FOUND| RL{relevance_level} RL -->|PRECISE| U1[优先引用 excerpt · 少重复检索] RL -->|REFERENCE| U2[可引用 · 结论留余地] RL -->|null / 缺省| U3[有块但质量偏低 · 慎用强结论] RL -->|HIGHLY_RELEVANT| U4[与 PRECISE 类似 · 略保守] ``` --- ## 4. 它是怎么算出来的(实现口径) ### 4.1 只看「本轮第一名」的 qualityScore 后处理在完成排序、去重、截断之后: ```text 取 originalRank 最优(排序后第一条)的 qualityScore ≥ highly-relevant-threshold (默认 0.75) → PRECISE ≥ reference-threshold (默认 0.5) → REFERENCE 否则 / 无可用证据 → null ``` 配置(`application.yml`): ```yaml retrieval: normalization: max-l2-distance: 2.0 highly-relevant-threshold: 0.75 reference-threshold: 0.5 ``` 因此: - level 描述的是 **整次调用的 top 质量**,不是每条 evidence 各打一档 - 列表里第 2、第 3 条即使偏弱,只要 top1 够高,整次仍可能是 `PRECISE` ```mermaid flowchart TB RET[检索有序候选] --> POST[后处理:保 originalRank · 去重 · 截断] POST --> TOP[取排序后第一条 qualityScore] TOP --> T1{≥ 0.75?} T1 -->|是| PRECISE[PRECISE] T1 -->|否| T2{≥ 0.5?} T2 -->|是| REF[REFERENCE] T2 -->|否| NULL[null / 不报档] ``` ### 4.2 qualityScore 从哪来(和检索 mode 绑定) 统一经 `RetrievalScoreNormalizer.toQualityScore`: | `retrieval.search.mode` | top qualityScore 含义 | |-------------------------|------------------------| | **dense** | top1 的 L2 归一化:约 `1 - L2 / maxL2Distance` | | **hybrid** | **优先**同 id 的 `denseDistance`(绝对 L2 质量,供闸门/level);无 dense 邻域时 **rank 回退** | ```mermaid flowchart LR subgraph dense_mode["mode=dense"] L2[score = L2] --> QD[quality = 1 - L2/max] end subgraph hybrid_mode["mode=hybrid"] RRF[RRF 序 = originalRank] --> SORT[列表顺序] DD[denseDistance 可选] --> QH{有 dense?} QH -->|是| QL[quality = L2 归一化] QH -->|否| QR[quality = rank 映射] end QD --> LV[relevance_level] QL --> LV QR --> LV ``` 读 level 时注意: > **dense 下的 PRECISE ≈「向量足够近」** > **hybrid 下的 PRECISE ≈「top1 的绝对/回退 quality 跨过了 0.75」**;排序仍跟 RRF,不是「又变回只信 L2 排序」。 不要把 hybrid 的 level 读成与 dense **完全同一把尺子**,但也不要再假设「rank1 永远 PRECISE」(在附带 denseDistance 后,远邻 decoy 可以很低分并触发 filter fallback)。 ### 4.3 关于 HIGHLY_RELEVANT 枚举和旧文档里仍有三档。历史上大致是: ```text 高分 + L0 hint 支撑 → PRECISE 高分但无 hint → HIGHLY_RELEVANT 中等分 → REFERENCE ``` 质量分统一之后,当前实现是:**≥ 0.75 直接 PRECISE**,不再要求 L0 contains 才能精准。 因此运行时 **很少再单独产出 HIGHLY_RELEVANT**;读旧 trace / 旧快照时仍可能见到。 --- ## 5. Agent 应该怎么读(建议协议) ### 5.1 推荐读法 ```text 1. 先看 evidence_status 2. 再读 evidence[] 的 excerpt(唯一可引用正文) 3. 用 relevance_level 调节「敢多敢少」与「要不要再查」 ``` ```mermaid flowchart TB START[收到 RagToolResult] --> S1{evidence_status} S1 -->|无证据| FAIL[不编造 · 换工具或安全降级] S1 -->|有证据| S2[精读 evidence excerpt] S2 --> S3{relevance_level} S3 -->|PRECISE| C1[结论可较硬 · 少重复同 query 检索] S3 -->|REFERENCE| C2[结论留余地 · 可换问法或叠日志指标] S3 -->|缺省| C3[慎用强结论 · 优先补查] C1 --> CITE[引用必须落在 excerpt] C2 --> CITE C3 --> CITE ``` | 组合 | 建议行为 | |------|----------| | FOUND + PRECISE | 以 excerpt 为主写结论;少重复同 query 检索 | | FOUND + REFERENCE | 可引用,表述保守;缺关键事实则改写 query 或换工具 | | FOUND 但 level 空 | 有块但质量闸门偏低:慎用强结论,优先补查 | | NO_EVIDENCE | 不编造知识库依据;走其他证据工具或安全降级 | ### 5.2 明确不要这样读 1. **不要当逐条相关度** 没有 `evidence[i].relevance_level`;不能说「第 2 条是 REFERENCE」。 2. **不要当连续分数** 没有 0.83;只有粗档。不要在推理里假装有精确分。 3. **不要在 hybrid 下当成绝对语义相似度** 序数 quality 下 PRECISE 很常见,表示「本轮第一够格」,不等于「全局语义必近」。 4. **不要代替 excerpt 引用** level 不能当证据正文;Gatekeeper / EvidenceGuard 认的是可核对片段与引用约束。 5. **不要和 Harness 验真混为一谈** level 是检索侧粗标;工具生命周期、`evidence_status`、守卫校验是另一层。 6. **不要用它驱动跨 mode 对比** 同一 query 切 dense/hybrid 时,比命中集合与排名;别只比「是不是都 PRECISE」。 --- ## 6. Agent 看不见、但会影响 level 的内部量 便于排查「为什么突然全是 PRECISE / 总是 null」: | 内部量 | 作用 | Agent 是否可见 | |--------|------|----------------| | `qualityScore` / `topSimilarity` | 定 level、低质 retry | 否 | | `originalRank` | 排序权威;hybrid quality 输入 | 否 | | `score` + `scoreLabel` | dense=L2 / hybrid=融合侧 | 否 | | L0 domain/keyword | 现仅 hitReasons 解释,不改序、不抬 level | 否(reasons 也可能被投影裁掉) | | `completenessHint` | 内部完整度文案 | 通常否 | | category filter + unfiltered retry | 低质时可能换一批 evidence 再定 level | 过程 trace 否 | 投影原则(ACI):模型只要能理解与引用结果;**不给 raw score、阈值、trace。** ```mermaid flowchart TB subgraph pipe["检索管道内部"] STORE[Milvus hybrid/dense] NORM[toQualityScore] POST[PostProcessor] STORE --> NORM --> POST end POST --> LV[relevance_level] POST --> EB[evidenceBlocks] POST --> TR[traces · 通常不投影] EB --> PROJ[RagResultProjector] LV --> PROJ PROJ --> AGENT[Agent Observation] ``` --- ## 7. 和相邻概念的边界 ```text evidence_status 有没有证据 relevance_level 有的话有多贴(粗) evidence[].excerpt 贴在哪一段文字上(细、可引用) truncated 列表是否被预算截断(可能还有更好的没展示) information_gain 等 诊断环路里「这轮工具对任务有没有增益」(另一契约) ``` ```mermaid flowchart TB subgraph fields["同一次工具结果里的分工"] ES[evidence_status
有没有] RL[relevance_level
有多贴·粗] EX[excerpt
说什么·细] TC[truncated
是否被截断] end ES --> USE[Agent 使用] RL --> USE EX --> USE TC --> USE USE --> NOTE[结论锚在 excerpt
level 只调力度] ``` `truncated=true` 时:即使 `PRECISE`,也只说明 **已返回子集里的 top 很强**,不保证库内没有更相关却被截掉的块。 --- ## 8. 提示词 / 产品文案可用的短说明 可直接给模型或文档的精简版: ```text relevance_level 是本次知识库检索的整体相关度粗标: - PRECISE:当前证据整体很贴,优先引用 evidence 写结论,避免无意义重复检索 - REFERENCE:仅供参考,结论需留余地,必要时换问法或改用其他工具 - 缺省:不要把本次结果当作高置信知识库证实 务必以 evidence 中的 excerpt 为唯一引用依据;不要编造未出现的文档内容。 在 hybrid 检索下,PRECISE 更多表示「本轮排序第一档」,不是精确相似度分数。 ``` --- ## 9. 常见误读示例 | 误读 | 更正 | |------|------| | 「PRECISE 所以三条 evidence 都精准」 | 只保证 top 质量跨线;其余条只是同批返回 | | 「没有 relevance_level 就是工具失败」 | 更可能是无证据或质量偏低;看 `evidence_status` | | 「hybrid 全是 PRECISE 说明召回完美」 | 可能只是 rank1→quality=1.0 的档位特性 | | 「REFERENCE 的 excerpt 不能引用」 | 可以引用,但结论强度应下调 | | 「level 高就可以跳过 excerpt」 | 不可;引用与验真仍看正文 | --- ## 10. 结语 `relevance_level` 是检索链路送给 Agent 的 **粗粒度驾驶辅助**: - 告诉模型这批评据大概硬不硬 - **不**替代 excerpt,**不**暴露打分细节,**不**等于逐条标注 在 dense 模式下,它更接近「向量有多近」; 在 hybrid 主路径下,它更接近「本轮融合第一名是否跨过质量门槛」。 读的时候记住三句即可: ```text 1. 先 status,再 excerpt,最后才看 level 2. level 管「敢多敢少」,excerpt 管「说了什么」 3. hybrid 的 PRECISE ≠ 绝对语义满分 ``` --- ## 附录:代码与规格锚点 | 项 | 位置 | |----|------| | Agent 结果契约 | `RagToolResult` / `RagRelevanceLevel` | | 投影 | `RagResultProjector` | | 等级计算 | `KnowledgeEvidencePostProcessor.computeRelevance` | | 质量分 | `RetrievalScoreNormalizer` | | 规格 | `openspec/specs/aci-evidence-tool-contracts`、`rag-retrieval-quality-score` | | 架构 | `mvp/architecture/RAG知识检索架构.md` §9 |