Files
SuperBizAgent-java/docs/RAG-Agent如何读relevance_level.md
T
zhuyongxin 7ae9707a3b feat(harness,rag): dual LLM audit fields, run conclusion, and hybrid quality
Persist provider reasoning and assistant text separately on agent_reasoning_audit
(DeepSeekAssistantMessage path), extract diagnosis_run.conclusion, enrich RAG
tool audit (step_id/query/qualityScore), gate empty mysql tools, drop devtools,
and align MVP docs after live E2E verification.
2026-07-28 19:43:13 +08:00

397 lines
13 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.
# Agent 如何读 `relevance_level`:它是什么、不是什么
**日期**:2026-07-28
**范围**:`lookup_knowledge` 投影给 Agent 的粗粒度相关度标签
**读者**:要在 Diagnosis Agent / 工具契约里正确使用知识库结果的工程与提示词同学
**关联**:
- ACI 契约:`RagToolResult.relevance_level` / `RagRelevanceLevel`
- 计算:`KnowledgeEvidencePostProcessor` → `qualityScore` 阈值
- 质量统一:`docs/RAG-Hybrid质量分与后处理.md`
- 多路与 RRF:`docs/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<br/>有没有]
RL[relevance_level<br/>有多贴·粗]
EX[excerpt<br/>说什么·细]
TC[truncated<br/>是否被截断]
end
ES --> USE[Agent 使用]
RL --> USE
EX --> USE
TC --> USE
USE --> NOTE[结论锚在 excerpt<br/>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 |