Chico Notes
LLM Wiki / RAG

RAG Bad Case 生产实战:证据冻结、分层诊断、修复与回归闭环

把线上答错、漏召回、错引用、误拒答和权限问题转化为可复现、可归因、可修复、可回归的工程资产,建立从 Trace 到发布门禁的完整坏例处理系统。

持续修订的工程笔记

RAG 系统上线后,最常见的质量反馈通常很短:

这个答案不对。
它为什么没找到那篇文档?
引用指错位置了。
明明有资料,为什么拒答?
刚更新的政策怎么还在用旧版本?
这个用户为什么看到了不该看的内容?

如果团队只有最终答案截图,讨论很快会退化成:

可能是模型幻觉;
要不要换个 Prompt;
Top-K 调大一点试试;
再加一个 Reranker;
这个问题比较特殊。

这种处理方式的问题不是缺少聪明的猜测,而是没有证据链。

一次生产 RAG 回答,至少经过:

用户身份与 Scope
→ Query Classification / Rewrite / Decompose
→ BM25 / Dense / Web / SQL / Graph 召回
→ Filter / RRF / Rerank / Dedup
→ Parent 回填与 Context Pack
→ Prompt Render
→ LLM Generation
→ Citation Mapping
→ Guardrail / Refusal

任何一层都可能导致相同表象:最终答案错误。

Bad Case 分析的目标不是写一段“为什么错了”的解释,而是把一次异常变成:

可复现输入
+
冻结的执行证据
+
分层根因
+
最小修复
+
成对实验
+
回归样本
+
发布门禁

资料快照:本文基于前文已经建立的 RAG 可观测性、评测、发布门禁、Hybrid Search、Reranker、Query Rewriting 与数据一致性设计,核查截至 2026-08-05。示例中的字段、SLO 和严重度规则应按真实业务、合规和流量校准。

RAG Bad Case 生产实战:从坏例入口、证据冻结、分层诊断、链路修复到回归闭环

图 1:坏例处理不是一次调参,而是一条从信号、证据、根因、修复到防复发的完整工程链路。

一句话结论

一条 Bad Case 只有同时满足下面五个条件,才算真正关闭:

  1. 能够用当时的 Scope、版本和数据稳定复现。
  2. 根因被定位到具体链路,而不是笼统归咎于模型。
  3. 修复通过 Baseline / Candidate 成对评测。
  4. 该 Case 已进入 Regression 或 Safety Set。
  5. 下一次发布门禁能够阻止同类问题复发。

推荐流程:

Signal
→ Triage
→ Containment
→ Evidence Freeze
→ Reproduction
→ Layered Diagnosis
→ Root Cause
→ Minimal Fix
→ Paired Evaluation
→ Regression Case
→ Release Gate
→ Online Monitoring

1. 先看完整闭环

坏例分析中最重要的顺序是:

先判断正确证据是否存在;
再判断它是否有资格参与检索;
再看它是否进入候选;
再看它在哪个排序或 Context 阶段丢失;
最后才分析生成模型为什么这样回答。

如果证据根本不在索引里,继续调 Prompt 没有意义。


2. Bad Case 不等于“用户不满意”

Bad Case 是一个需要工程处理的异常样本,通常满足至少一个条件:

  • 预期行为和实际行为不同;
  • 违反安全、权限或数据治理规则;
  • 相比 Baseline 明显回归;
  • 延迟、成本或错误率超出预算;
  • 同类问题重复发生;
  • 解释链路不完整,无法证明答案来源;
  • 模型没有遵循产品定义的拒答或追问策略。

2.1 用户反馈只是 Signal

用户点击差评,可能表示:

  • 答案事实错误;
  • 答案正确但太长;
  • 引用打不开;
  • 权限不符合预期;
  • 用户其实在问另一个问题;
  • 数据本身过期;
  • 产品交互让用户误解。

因此反馈进入系统后必须分诊,不能直接标为 generation_failure

2.2 评测回归也是 Bad Case

即使没有用户投诉,只要 Candidate 出现:

Golden Case 从 pass 变 fail
Safety Case 越权
NDCG 明显下降
Citation ID 无效
P99 爆炸

都应该生成 Bad Case 记录。


3. 先分清 Symptom、Failure Type 和 Root Cause

这三个字段不能混用。

Symptom

用户或系统观察到的表象:

答案错误
无结果
引用错误
延迟过高
误拒答
权限暴露

Failure Type

问题发生在哪一层:

data
parsing
indexing
scope
query_planning
retrieval
fusion
rerank
context
generation
citation
safety
infrastructure

Root Cause

真正导致失败的具体原因:

更新后的文档没有生成 Outbox 事件;
ACL Filter 只应用于 BM25,没有应用于 kNN;
Query Rewrite 删除了错误码 ERR_1205;
RRF rank_window_size 太小;
Reranker 输入被截断,关键结论位于尾部;
Context Packer 按 Parent 去重时保留了旧 revision;
Citation Mapper 使用了重排前的位置索引。

一条高质量结论应该是:

在 Candidate release rag-prod-2026-08-05.3 中,Query Rewrite 将原始错误码 ERR_1205 删除,导致 BM25 exact 通道未命中;Dense 召回只找到通用锁等待文档,最终答案遗漏 TDW 分区删除的专项处理。

而不是:

模型理解错了。


4. Triage:先判断严重度,再决定是否止损

建议严重度:

级别示例默认动作
S0 / Critical跨租户、敏感泄露、危险错误动作立即关闭能力、回滚、通知安全 Owner
S1 / High核心业务事实错误、关键流程误拒答暂停放量、回滚或限流、当天处理
S2 / Medium特定 Query 类型漏召回、引用错位建立 Owner 和修复计划,进入近期版本
S3 / Low表达、格式、轻微冗余纳入普通迭代

4.1 严重度不只看出现次数

一次跨租户暴露即使只发生一次,也比一千次答案略长更严重。

建议考虑:

安全影响
业务影响
用户数量
是否可恢复
是否持续发生
是否影响自动化动作
是否存在外部传播

4.2 Containment 优先于根因分析

S0 / S1 先止损:

  • 关闭相关 Feature Flag;
  • 切回稳定 Release;
  • 禁用问题数据源;
  • 强制 BM25-only 或关闭 Reranker;
  • 清理受污染缓存;
  • 阻止外部 Tool 写操作;
  • 将特定 Tenant 路由回旧版本;
  • 启用更严格的拒答策略。

不要为了收集更多样本,让安全问题继续暴露。


5. 冻结证据:不要用“现在的状态”解释“当时的回答”

RAG Bad Case 证据包:入口事实、检索与生成轨迹、诊断和回归资产

图 2:一个可复现坏例必须冻结当时的用户 Scope、Release、候选、Context、Prompt 和答案;只保存 Query 与最终文本不足以重建执行过程。

文档、索引、Prompt 和模型会继续变化。如果复盘时只读取当前状态,得到的可能不是系统当时看到的内容。

5.1 最小 Evidence Packet

{
  "bad_case_id": "bad_20260805_0042",
  "trace_id": "trace_abc",
  "request_id": "req_xyz",
  "captured_at": "2026-08-05T18:42:00+08:00",
  "release_id": "rag-prod-2026-08-05.3",
  "symptom": "answer_missing_constraint",
  "severity": "high",
  "request": {
    "query": "ERR_1205 在 TDW 分区删除时怎么处理?",
    "conversation_id": "conv_001",
    "tenant_id": "tenant_001",
    "acl_groups": ["data-platform"],
    "time_context": "2026-08-05T18:41:30+08:00",
    "feature_flags": {
      "query_rewrite_enabled": true,
      "reranker_enabled": true
    }
  },
  "artifacts": {
    "query_plan": "artifact://bad_0042/query-plan.json",
    "candidates": "artifact://bad_0042/candidates.jsonl",
    "context_manifest": "artifact://bad_0042/context.json",
    "rendered_prompt": "artifact://bad_0042/prompt.txt.enc",
    "model_output": "artifact://bad_0042/output.json.enc",
    "citation_map": "artifact://bad_0042/citations.json"
  },
  "versions": {
    "application_commit": "abc123",
    "query_plan_version": "query-plan-v8",
    "index_manifest": "kb_chunks_v4",
    "embedding_model_key": "bge-m3|endpoint-a|rev-2",
    "reranker_model_key": "reranker-v2|gpu-a|rev-3",
    "answer_prompt_version": "answer-v16",
    "generation_model": "model-x-rev-4"
  }
}

5.2 Artifact 需要 Hash

{
  "uri": "artifact://bad_0042/context.json",
  "sha256": "2ff4...",
  "size_bytes": 48210,
  "capture_level": "L2_ENCRYPTED_REPLAY",
  "retention_class": "security_90d",
  "encryption_key_id": "kms-rag-prod-03"
}

避免复盘期间 Artifact 被替换或无法证明版本。

5.3 隐私边界

Bad Case 往往包含真实 Query 和文档内容。需要:

  • Tenant 隔离;
  • RBAC;
  • 加密;
  • Retention;
  • 下载审计;
  • Prompt / Context 脱敏;
  • 禁止把 Access Token 和密钥写入 Artifact。

关于采集等级见 RAG 可观测性生产实战


6. 分层诊断漏斗

RAG Bad Case 分层诊断漏斗:从数据、权限、Query Planning、召回、重排、Context 到生成与引用

图 3:诊断按上游事实到下游生成推进。上游未通过时,不应继续用 Prompt 或模型猜测掩盖问题。

每一层输出:

结论:pass / fail / unknown
证据:ID / Rank / Score / Revision / Artifact
根因候选:failure_type / confidence / owner
下一步:reproduce / fix / contain / escalate

7. 第一层:数据和版本是否正确

先问:正确证据是否存在于事实库、解析结果和目标索引?

检查:

MySQL / Source of Truth 是否有最新数据
对象存储中的原文件是否正确
Knowledge / Chunk 状态是否 completed / enabled
source_revision 是否最新
projection_schema_version 是否正确
Elasticsearch 文档是否存在
物理索引和 Alias 是否正确
Embedding 是否由目标模型生成
文档是否被软删除或禁用

7.1 常见根因

  • 入库任务失败;
  • Outbox 事件丢失;
  • Worker 重试耗尽;
  • 索引写入部分失败;
  • Mapping 拒绝新字段;
  • Alias 指向旧索引;
  • 文档 revision 落后;
  • 旧事件覆盖新状态;
  • PDF 表格解析错误;
  • Chunk 切分把标题和正文分开;
  • OCR 缺失关键数字;
  • 新 Embedding 模型只重建了部分数据。

7.2 确定性检查

{
  "knowledge_id": "doc_001",
  "mysql_revision": 47,
  "indexed_revision": 43,
  "projection_schema_expected": 6,
  "projection_schema_actual": 5,
  "status": "stale_projection"
}

如果证据未进入索引,Failure Type 是 data / ingestion / indexing,不是 retrieval


8. 第二层:Scope 与权限是否正确

检查实际编译后的 Scope:

{
  "tenant_id": "tenant_001",
  "knowledge_base_ids": ["kb_rag"],
  "acl_groups": ["employee", "rag-team"],
  "doc_status": ["published"],
  "language": ["zh-CN"],
  "time_range": null,
  "source_types": ["document", "wiki"]
}

8.1 两类相反问题

误过滤。

正确证据有权访问,却因:

  • 错误 ACL;
  • 旧缓存;
  • Language;
  • doc_status
  • 时间范围;
  • KB Selection;
  • Source Filter。

被排除。

越权。

无权证据进入:

  • Retrieval Candidate;
  • Trace Artifact;
  • Context;
  • Citation。

8.2 三类安全指标

Unauthorized Retrieval
Unauthorized Context
Unauthorized Citation

必须分别记录。无权内容没有进入 Prompt,不代表 Retrieval 阶段没有数据暴露。

8.3 Scope 来源

需要区分:

System Scope
→ 由身份、Tenant 和策略系统决定

User Filters
→ 用户主动选择的范围

Planner Filters
→ 模型建议的业务过滤

最终 Scope 必须是安全交集,Planner 不能扩大权限。


9. 第三层:Query Planning 是否漂移

保存并比较:

original_query
normalized_query
standalone_query
lexical_queries
semantic_queries
subqueries
anchors
filters
query_type

9.1 常见根因

  • 删除错误码、版本号或实体 ID;
  • 否定词丢失;
  • AND 被改成 OR;
  • 时间范围变化;
  • 比较对象遗漏;
  • 多问题只保留一部分;
  • Follow-up 指代补全错误;
  • Planner 猜测不存在的实体;
  • HyDE 生成方向错误;
  • Query 数量过多造成候选膨胀。

9.2 Anchor 检查

{
  "original_query": "ERR_1205 在 TDW 分区删除时怎么处理?",
  "anchors": ["ERR_1205", "TDW", "分区删除"],
  "rewritten_query": "数据库锁等待超时如何处理",
  "missing_anchors": ["ERR_1205", "TDW", "分区删除"],
  "status": "rewrite_drift"
}

原始 Query 应保留为一路召回,避免 Rewrite 完全替换精确信号。

详见 Query Rewriting 生产实战


10. 第四层:召回是否找到正确证据

分别检查每一路:

BM25
Dense Vector
Sparse
Web
SQL
Graph
Business API

每个正确证据记录:

是否进入 Candidate
来自哪一路
原始 Rank
原始 Score
Filter 结果
是否达到通道 Top-K

10.1 关键指标

BM25 Recall@K
Dense Recall@K
Union Recall@K
Unique Relevant Gain
Filter Recall Loss

10.2 典型问题

  • Analyzer 破坏专有词;
  • Keyword 字段缺失;
  • Embedding 不适配领域;
  • Query 与文档使用不同模型;
  • kNN num_candidates 太小;
  • similarity 太高;
  • Pre-filter 选择性太强;
  • Top-K 过小;
  • 多 KB 使用不同向量空间;
  • 新文档未 Refresh;
  • 召回服务超时后错误返回空。

10.3 如果正确证据不在候选集

不要继续让 Reranker 背锅。Reranker 不能创造候选。


11. 第五层:融合是否过早丢弃证据

Hybrid Search 中,正确证据可能分别位于:

BM25 Rank 40
Dense Rank 12

如果 RRF rank_window_size = 10,BM25 的信号在融合前已经丢失。

检查:

per-channel rank
rank_window_size
rank_constant
channel weight
fused rank
candidate count before / after fusion

11.1 常见根因

  • RRF Window 等于最终 Context Size;
  • Weighted RRF 过度偏向某一路;
  • 应用层去重使用错误 ID;
  • 多索引迁移产生重复文档;
  • FAQ 和文档索引错误混用;
  • Candidate Budget 被某一 Query 占满。

11.2 应记录 removed_reason

fusion_window_exceeded
duplicate_chunk
stale_revision
same_document_limit
channel_timeout

详见 Elasticsearch Hybrid Search 生产实战


12. 第六层:Reranker 是否误排或截断

检查:

rerank model key
input window
input text
truncated
raw score
normalized score
min_score
output rank
fallback state

12.1 常见根因

  • Candidate Window 太小;
  • 关键证据在长文本尾部被截断;
  • rerank_text 缺少标题或章节;
  • 模型不支持目标语言;
  • min_score 从其他模型复制;
  • Score 被误当成概率;
  • 动态批处理导致超时;
  • Reranker 失败后错误返回空,而不是回退 RRF;
  • 领域 Hard Negative 未覆盖。

12.2 Oracle 检查

将正确证据强制放入候选,仅用于判断:

Reranker 能不能把它排上来?

这不是生产端到端结果,只是模型上限诊断。

详见 Reranker 生产实战


13. 第七层:Parent 回填、去重和 MMR 是否误删

正确 Child 召回后,可能在回填与去重阶段丢失。

检查:

chunk_id
parent_chunk_id
knowledge_id
source_revision
projection_hash
selected_parent
removed_reason

13.1 常见问题

  • Parent ID 指向旧 revision;
  • 同 Parent 只保留了分数较高但证据不足的 Child;
  • 同文档最大 Chunk 数限制过小;
  • MMR 过度追求多样性;
  • 相邻 Chunk 合并截断关键句;
  • 多来源复制被错误去重成一条旧文档;
  • Citation 需要 Child,但 Context 只保留 Parent,映射丢失。

13.2 去重顺序

推荐:

先去除同 Chunk / 同 Revision 重复
→ 再做 Parent 聚合
→ 再做文档级限制
→ 最后做语义多样性

不要在证据身份还未稳定时直接做 MMR。


14. 第八层:Context Pack 是否破坏可回答性

检查最终 Context Manifest:

context_order
citation_key
chunk_id
parent_chunk_id
source_revision
content_hash
token_count
truncated
retrieval_channels
rerank_rank

14.1 常见根因

  • Token Budget 裁掉最后一个必需证据;
  • 系统说明占用过多 Token;
  • 多条重复证据挤占空间;
  • 新旧版本冲突;
  • Evidence 顺序导致模型忽略中间内容;
  • 表格被拆成无意义片段;
  • Parent 太长;
  • Context Compression 删除数值和否定;
  • 引用 Key 与正文顺序错位。

14.2 Context 指标

Context Recall
Context Precision
Evidence Coverage
Redundancy Ratio
Token Efficiency
Conflict Rate

如果 Retrieval Recall 高但 Context Recall 低,问题发生在候选选择之后。


15. 第九层:生成模型为什么没有使用证据

只有在正确证据已经进入最终 Context 后,才进入生成层诊断。

检查:

rendered prompt
prompt version
model route
model revision
temperature
max tokens
finish reason
input / output token
streaming events
guardrail result

15.1 常见根因

  • Prompt 允许使用模型外部知识;
  • 证据冲突但没有冲突处理规则;
  • 没有要求引用关键 Claim;
  • 模型被用户 Prompt Injection 影响;
  • 输出被 max_tokens 截断;
  • Tool Call 结果没有重新进入上下文;
  • 生成模型不适合目标语言或长 Context;
  • Guardrail 删除关键结论;
  • 模型 Route 灰度到了异常版本。

15.2 Claim 级分析

{
  "claim": "删除版本会永久阻止旧 UPSERT",
  "correct": false,
  "supported_by_context": false,
  "citation_ids": ["cite_2"],
  "failure_type": "generation_hallucination"
}

不要只给整篇答案一个分数。


16. 第十层:Citation 是否真正支持 Claim

答案正确但引用错误,也是生产问题。

检查:

Claim → Citation Key
Citation Key → Context Item
Context Item → Chunk / Parent / Revision
Displayed URL / Anchor

16.1 常见根因

  • Citation 使用 Rerank 前 Rank;
  • Context 重排后没有更新编号;
  • Parent 回填后仍引用 Child 的错误 Offset;
  • 文档更新后 Anchor 失效;
  • 多个 Claim 共用一个不完整引用;
  • 引用了主题相关但不支持结论的证据;
  • 无权 Citation URL 泄露。

16.2 指标

Citation Precision
Citation Recall
Invalid Citation Rate
Unauthorized Citation Rate
Anchor Resolution Rate

Citation Accuracy 不等于答案 Faithfulness,需要分别评测。


17. 基础设施和降级也会制造质量问题

有些 Bad Case 不是算法问题:

  • Embedding Endpoint 超时;
  • Reranker GPU 排队;
  • Elasticsearch 部分分片失败;
  • MySQL 连接池耗尽;
  • Web Search 失败;
  • Trace Collector 丢数据;
  • Cache 跨 Release 污染;
  • Deadline 过短;
  • Region 路由错误。

响应中应记录:

{
  "retrieval_mode": "hybrid",
  "degraded": true,
  "degraded_to": "bm25_only",
  "degrade_reason": "embedding_timeout"
}

分析时必须比较:

期望链路
实际链路

不能把降级后的结果当成完整 Hybrid 质量。


18. 复现:把线上问题转成稳定实验

复现环境应冻结:

Dataset Snapshot
Release Manifest
Scope
Query Plan
Index Alias / Physical Index
Model Endpoints
Prompt Versions
Feature Flags
Time Context

18.1 三种复现模式

Exact Replay

使用当时 Artifact 和模型版本,重放尽可能相同的请求。

Current Replay

在当前稳定版本上运行同一输入,判断问题是否仍存在。

Candidate Replay

在修复版本上运行,判断问题是否被解决。

三者不能混为一个结果。

18.2 复现记录

{
  "bad_case_id": "bad_20260805_0042",
  "replay_id": "replay_001",
  "mode": "exact",
  "manifest": "rag-prod-2026-08-05.3",
  "result": "reproduced",
  "attempts": 3,
  "success_rate": 1.0,
  "trace_ids": ["trace_r1", "trace_r2", "trace_r3"]
}

对于非确定性问题,重复运行并记录发生率。


19. 根因结论要有证据和置信度

{
  "bad_case_id": "bad_20260805_0042",
  "root_cause": {
    "failure_type": "query_planning",
    "code": "ANCHOR_DROPPED",
    "summary": "Rewrite 删除 ERR_1205、TDW 和分区删除三个精确 Anchor",
    "confidence": 0.98,
    "evidence": [
      "artifact://bad_0042/query-plan.json",
      "trace://trace_abc/span/query.rewrite",
      "eval://ablation/original-query-vs-rewrite"
    ],
    "owner": "query-planning-team"
  }
}

19.1 unknown 是合法结论

证据不足时可以标记:

root_cause = unknown
confidence = low
next_action = add telemetry

不要为了关闭工单编造确定性根因。


20. 修复策略:优先最小、可验证、可回滚

坏例容易诱导团队一次改很多东西:

换 Embedding
+ 改 Chunk
+ 加 Reranker
+ 改 Prompt

结果即使改善,也不知道哪个变化有效。

推荐:

  1. 先修真正根因;
  2. 一次改变一个主要因素;
  3. 做 Ablation;
  4. 检查其他 Cohort;
  5. 记录成本和延迟;
  6. 设计回滚。

20.1 修复优先级

安全与权限
→ 数据和索引正确性
→ Scope / Query Plan
→ Recall
→ Fusion / Rerank
→ Context
→ Prompt / Generation
→ 表达优化

不要用生成 Prompt 掩盖上游错误。


21. 一条 Bad Case 如何转成 Eval Case

{
  "case_id": "reg_bad_20260805_0042",
  "source_bad_case_id": "bad_20260805_0042",
  "dataset": "rag-eval-regression",
  "severity": "high",
  "question": "ERR_1205 在 TDW 分区删除时怎么处理?",
  "scope": {
    "tenant_id": "tenant_001",
    "knowledge_base_ids": ["kb_data_platform"],
    "acl_groups": ["data-platform"]
  },
  "expected_behavior": "answer_with_citations",
  "anchors": ["ERR_1205", "TDW", "分区删除"],
  "expected_evidence": [
    {
      "knowledge_id": "doc_tdw_partition_delete",
      "section_anchor": "lock-wait-timeout",
      "relevance": 3
    }
  ],
  "required_claims": [
    "说明 1205 是锁等待超时",
    "给出分区删除场景的安全重试与排查步骤",
    "提醒检查长事务和元数据锁"
  ],
  "forbidden_behaviors": [
    "删除错误码 Anchor",
    "只返回通用数据库锁说明",
    "无证据编造参数"
  ],
  "root_cause": "query_planning.anchor_dropped"
}

21.1 Regression Case 的 Definition of Done

  • Baseline 能稳定复现失败;
  • Candidate 稳定通过;
  • Evidence 和 Rubric 经过人工审核;
  • Scope 与安全边界完整;
  • 加入固定 Dataset Version;
  • 进入 Release Gate;
  • Owner 明确。

22. 回归闭环

RAG Bad Case 回归闭环:线上坏例、分诊止损、证据复现、根因、修复、评测和门禁

图 4:工单关闭不等于完成修复。只有 Case、Evidence、Rubric 和 Gate 都建立后,同类问题才真正具备防复发能力。


23. Bad Case 数据模型

执行证据尽量不可变;后续诊断和修复作为新记录追加。


24. Bad Case 状态机

24.1 关闭条件

不能只因为代码已合并就关闭。

至少需要:

root cause documented
fix owner completed
paired eval passed
regression case published
release gate passed
online observation complete

25. Bad Case 记录模板

bad_case:
  id: bad_20260805_0042
  title: Query Rewrite 删除错误码导致专项文档漏召回
  severity: high
  status: diagnosing

  signal:
    source: user_feedback
    trace_id: trace_abc
    release_id: rag-prod-2026-08-05.3
    detected_at: 2026-08-05T18:42:00+08:00

  symptom:
    expected: 回答 TDW 分区删除中的 ERR_1205 处理方式
    actual: 只回答通用数据库锁等待

  containment:
    action: disable_semantic_rewrite_for_error_code_query
    owner: query-planning-team
    completed_at: 2026-08-05T19:05:00+08:00

  evidence:
    packet_uri: artifact://bad_0042/evidence.json
    capture_level: L2_ENCRYPTED_REPLAY

  diagnosis:
    failure_type: query_planning
    root_cause_code: ANCHOR_DROPPED
    confidence: 0.98
    owner: query-planning-team

  prevention:
    regression_case: reg_bad_20260805_0042
    target_dataset: rag-eval-regression
    release_gate_rule: preserve_exact_anchors

26. Owner 如何分配

建议按 Failure Type 路由:

Failure TypePrimary Owner
data / parsingIngestion / Data Quality
indexing / revisionSearch Infrastructure
scope / ACLSecurity / Identity / Retrieval
query_planningQuery Understanding
retrieval / fusionRetrieval Team
rerankRanking / Model Serving
contextContext Engineering
generationPrompt / Model Platform
citationCitation / Frontend / Context
infrastructureSRE / Platform

26.1 一个 Case 可以有多个 Contributor

但必须有一个最终 Owner,避免:

Retrieval 说是数据问题;
Data 说是 Prompt 问题;
Prompt 说是用户问法问题。

Owner 负责推动证据、修复、评测和关闭,不代表所有代码都由该团队修改。


27. 优先级:不是所有坏例都立刻修

可以使用:

Priority Score
=
Severity
× Frequency
× Business Impact
× Recurrence Risk
÷ Fix Cost

但安全问题必须单独处理,不参与普通排序。

27.1 建议队列

Security Incident
Critical Business Regression
Repeated High Frequency
New Release Regression
Long-tail Quality
UX / Style

27.2 聚类而不是逐条调参

将坏例按:

  • Query Type;
  • Failure Type;
  • Data Source;
  • Tenant;
  • Language;
  • Release;
  • Root Cause Code。

聚类。

几十条“人名没召回”可能共享一个 Analyzer 或 Metadata 问题,比逐条增加 Prompt 规则更有效。


28. 自动根因建议可以做什么

系统可以自动生成候选诊断:

expected evidence not indexed
expected evidence filtered by acl_denied
anchor dropped in rewrite
bm25 rank 42 outside fusion window
rerank score below threshold
context budget excluded required group
citation points to stale revision

这些由确定性规则产生,比让 LLM 自由猜根因更可靠。

LLM 可以帮助:

  • 总结 Trace;
  • 归纳相似 Bad Case;
  • 生成复盘草稿;
  • 建议进一步检查;
  • 把技术证据翻译成产品语言。

但最终 Root Cause 必须引用可验证证据。


29. Bad Case Dashboard

建议面板:

Volume

New Cases
Open Cases
Reopened Cases
Cases by Severity
Cases by Release

Root Cause

Data / Scope / Query / Retrieval / Rerank / Context / Generation / Citation
Top Root Cause Codes
Unknown Root Cause Rate

Efficiency

Time to Triage
Time to Contain
Time to Reproduce
Time to Root Cause
Time to Regression Case
Time to Close

Prevention

Regression Case Coverage
Recurrence Rate
Gate Catch Rate
Production Escape Rate

Safety

Unauthorized Retrieval
Unauthorized Context
Unauthorized Citation
Critical Incident Count

30. Bad Case SLO

示例:

S0 Containment P95 < 15 minutes
S1 Triage P95 < 30 minutes
High Severity Root Cause P95 < 2 business days
Regression Case Created < 1 business day after fix
Critical Recurrence Rate = 0
Unknown Root Cause Rate < 10%

这些不是通用标准,但团队应该明确自己的响应目标。


31. 从 Bad Case 到 Release Gate

回归样本进入:

Golden Set
Regression Set
Safety Set
Freshness Set

取决于问题性质。

Release Gate 需要检查:

  • 当前 Case 是否通过;
  • 同 Cohort 是否退化;
  • 修复是否增加延迟或成本;
  • 是否引入新的安全问题;
  • Candidate 是否可回滚。

详见 RAG 发布门禁生产实战


32. 常见反模式

反模式一:只有答案截图

无法知道 Scope、候选、Context 和版本。

反模式二:所有问题都归为模型幻觉

掩盖数据、权限、召回和引用问题。

反模式三:证据不在候选,却先调 Prompt

修错层级。

反模式四:复盘读取当前文档

当前 revision 可能已经不同,无法解释当时回答。

反模式五:只记录最终 Top-K

无法判断证据是在哪一路、哪一步被删除。

反模式六:没有 removed_reason

去重、阈值和 Token Budget 的决策无法解释。

反模式七:修复同时改多个大因素

无法归因,也难回滚。

反模式八:工单关闭但没有 Regression Case

下一次改模型或索引后会再次出现。

反模式九:安全 Bad Case 进入普通优先级队列

权限和敏感暴露必须立即止损。

反模式十:根因置信度被强制写成 100%

证据不足时应标记 Unknown 并补 Telemetry。

反模式十一:只看平均修复指标

可能掩盖特定 Tenant、语言和 Query Type 的复发。

反模式十二:Artifact 无 Retention 和访问控制

Bad Case 系统本身可能成为敏感数据泄露源。


33. 分阶段落地方案

P0:让坏例可复现

  • 每次请求有 Trace ID;
  • Release ID 与 Scope 进入 Trace;
  • 保存 Candidate / Context Manifest;
  • Bad Case Template;
  • Severity 与 Containment;
  • Failure Type Taxonomy;
  • Evidence Packet;
  • Owner Routing;
  • Regression Case;
  • Release Gate 检查。

验收标准:

任何高严重度问题都能回答:
用户当时看到了什么、正确证据在哪一步丢失、由谁修复、如何防复发。

P1:自动诊断和队列治理

  • Expected Evidence 自动对比;
  • Anchor Drift 检测;
  • Filter Recall Loss;
  • Removed Reason;
  • Root Cause Rule Engine;
  • Similar Case Clustering;
  • Replay Runner;
  • SLO Dashboard;
  • Evidence Freeze 自动化;
  • Incident Integration。

P2:规模化质量闭环

  • Active Sampling;
  • 自动 Bad Case 候选发现;
  • 多租户隔离评测;
  • Judge 校准;
  • 自动修复实验建议;
  • Release Impact Analysis;
  • 根因知识库;
  • 跨版本复发检测;
  • 质量成本优化;
  • Agent / Tool Workflow Bad Case。

34. 上线检查清单

  • 每次回答是否有稳定 Trace ID 和 Release ID?
  • 是否保存当时 Tenant、ACL、Feature Flag 和 Time Context?
  • Candidate Manifest 是否包含每一路 Rank、Score 和 Removed Reason?
  • Context Manifest 是否包含 Revision、Hash、顺序和截断?
  • Prompt、模型和索引版本是否可复现?
  • Artifact 是否有 Hash、加密、Retention 和访问审计?
  • Bad Case 是否区分 Symptom、Failure Type 和 Root Cause?
  • 是否有 S0 / S1 的立即止损流程?
  • Unauthorized Retrieval / Context / Citation 是否分别记录?
  • 是否先检查数据和索引,再检查检索算法?
  • Query Rewrite 是否保留错误码、实体、时间和否定 Anchor?
  • BM25、Dense 与 Union Recall 是否分别可见?
  • RRF Window 和每一路候选是否可解释?
  • Reranker 输入、截断、阈值和回退是否可见?
  • Parent / Revision / Document 去重是否记录 Removed Reason?
  • Context Recall 是否与 Retrieval Recall 分开?
  • 答案是否拆成 Claim?
  • Citation 是否能映射回当时的 Context 和 Revision?
  • 降级状态是否进入 Bad Case 证据?
  • 是否支持 Exact / Current / Candidate Replay?
  • 非确定性问题是否记录复现率?
  • Root Cause 是否有证据、置信度和 Owner?
  • Unknown Root Cause 是否会触发补 Telemetry?
  • 修复是否尽量一次改变一个主要因素?
  • 是否做 Baseline / Candidate 成对评测?
  • 每个修复是否创建 Regression 或 Safety Case?
  • 新 Case 是否进入固定 Dataset Version?
  • Release Gate 是否阻止同类问题复发?
  • 是否监控 Reopened / Recurrence Rate?
  • Bad Case 系统是否有安全与隐私治理?
  • 高严重度 Case 是否有响应 SLO?
  • 工单关闭是否要求线上观察完成?

总结

Bad Case 分析的价值,不是让团队更擅长解释错误,而是把错误转化成系统能力:

Signal
→ 发现真实异常

Evidence Freeze
→ 保存当时事实,而不是依赖当前状态

Layered Diagnosis
→ 定位证据在哪一步丢失

Root Cause
→ 用 Trace、ID、Rank、Revision 和 Artifact 证明结论

Minimal Fix
→ 修真正出错的层级

Paired Evaluation
→ 证明修复有效且没有制造新回归

Regression Case
→ 把坏例变成长期测试资产

Release Gate
→ 下一次发布前自动阻止复发

最重要的工程原则是:

没有 Trace 的坏例只是抱怨;没有 Regression Case 的修复只是临时补丁;没有进入 Release Gate 的经验,迟早会在下一次模型、索引或 Prompt 变更中再次丢失。

相关阅读

讨论

继续讨论这篇笔记

有问题、补充案例或不同观点,可以通过 GitHub Discussions 继续交流。

On this page

一句话结论1. 先看完整闭环2. Bad Case 不等于“用户不满意”2.1 用户反馈只是 Signal2.2 评测回归也是 Bad Case3. 先分清 Symptom、Failure Type 和 Root CauseSymptomFailure TypeRoot Cause4. Triage:先判断严重度,再决定是否止损4.1 严重度不只看出现次数4.2 Containment 优先于根因分析5. 冻结证据:不要用“现在的状态”解释“当时的回答”5.1 最小 Evidence Packet5.2 Artifact 需要 Hash5.3 隐私边界6. 分层诊断漏斗7. 第一层:数据和版本是否正确7.1 常见根因7.2 确定性检查8. 第二层:Scope 与权限是否正确8.1 两类相反问题8.2 三类安全指标8.3 Scope 来源9. 第三层:Query Planning 是否漂移9.1 常见根因9.2 Anchor 检查10. 第四层:召回是否找到正确证据10.1 关键指标10.2 典型问题10.3 如果正确证据不在候选集11. 第五层:融合是否过早丢弃证据11.1 常见根因11.2 应记录 removed_reason12. 第六层:Reranker 是否误排或截断12.1 常见根因12.2 Oracle 检查13. 第七层:Parent 回填、去重和 MMR 是否误删13.1 常见问题13.2 去重顺序14. 第八层:Context Pack 是否破坏可回答性14.1 常见根因14.2 Context 指标15. 第九层:生成模型为什么没有使用证据15.1 常见根因15.2 Claim 级分析16. 第十层:Citation 是否真正支持 Claim16.1 常见根因16.2 指标17. 基础设施和降级也会制造质量问题18. 复现:把线上问题转成稳定实验18.1 三种复现模式18.2 复现记录19. 根因结论要有证据和置信度19.1 unknown 是合法结论20. 修复策略:优先最小、可验证、可回滚20.1 修复优先级21. 一条 Bad Case 如何转成 Eval Case21.1 Regression Case 的 Definition of Done22. 回归闭环23. Bad Case 数据模型24. Bad Case 状态机24.1 关闭条件25. Bad Case 记录模板26. Owner 如何分配26.1 一个 Case 可以有多个 Contributor27. 优先级:不是所有坏例都立刻修27.1 建议队列27.2 聚类而不是逐条调参28. 自动根因建议可以做什么29. Bad Case DashboardVolumeRoot CauseEfficiencyPreventionSafety30. Bad Case SLO31. 从 Bad Case 到 Release Gate32. 常见反模式反模式一:只有答案截图反模式二:所有问题都归为模型幻觉反模式三:证据不在候选,却先调 Prompt反模式四:复盘读取当前文档反模式五:只记录最终 Top-K反模式六:没有 removed_reason反模式七:修复同时改多个大因素反模式八:工单关闭但没有 Regression Case反模式九:安全 Bad Case 进入普通优先级队列反模式十:根因置信度被强制写成 100%反模式十一:只看平均修复指标反模式十二:Artifact 无 Retention 和访问控制33. 分阶段落地方案P0:让坏例可复现P1:自动诊断和队列治理P2:规模化质量闭环34. 上线检查清单总结相关阅读