"感觉效果不太好"不是诊断
你部署了一个 RAG 系统,用户反馈说"答案有时候不准"。
然后呢?你改了 Prompt,感觉好一点。再换了个 Embedding 模型,又好了一点。几轮下来,你也不知道是哪一步起了效果,下次出问题依然无从下手。
这是 RAG 工程中最常见的陷阱:靠直觉调系统,没有量化诊断。
上一篇我们搭建了 RAGAS 评估体系,知道了 4 个指标的含义。这一篇,我们把这 4 个指标变成一套诊断工具------通过故意制造 3 种典型问题,用数据驱动的方式定位根因。
诊断的核心思路:决策树
RAG 系统的回答质量差,根因只有两大类:检索出了问题 或 生成出了问题。
arduino
用户反馈"回答不好"
↓
检查 context_recall(上下文召回率)
├─ 低 ───→ 检索问题
│ ├─ 重要内容没被检索到
│ ├─ Chunk 太小或太大
│ └─ Top-K 不够
│
└─ 正常 ──→ 检查 faithfulness(忠实度)
├─ 低 ───→ 生成问题(幻觉)
│ └─ Prompt 引导模型超出上下文发挥
│
└─ 正常 ──→ 检查 answer_relevancy(答案相关性)
└─ 低 ──→ 答案偏题
└─ Prompt 结构固化,不聚焦问题
逻辑很简单:
- 先看 context_recall------重要内容有没有被检索到?没有的话,问题在检索阶段,再好的 Prompt 也救不了。
- 再看 faithfulness------答案里的内容,有没有超出检索结果的范围?超出了就是幻觉,要修 Prompt。
- 最后看 answer_relevancy------答案有没有直接回答问题?没有就是偏题,同样是 Prompt 问题。
三种典型问题的复现
我们用同一套知识库和测试集,通过改变配置刻意制造 3 种问题,让 RAGAS 量化每种问题的指标特征。
基准配置
python
baseline = RAGPipeline(
chunk_size=512,
chunk_overlap=50,
top_k=4,
prompt_type="baseline", # 正常 Prompt
)
正常的 Prompt 明确要求模型基于上下文回答:
python
PROMPT_BASELINE = ChatPromptTemplate.from_messages([
("system", "你是一个专业的技术问答助手。请严格根据提供的参考资料回答问题。"
"如果参考资料中没有相关信息,请明确说明。回答要简洁准确。"),
("human", "参考资料:\n{context}\n\n问题:{question}\n\n请回答:"),
])
问题一:检索召回不足(chunk 过碎 + top_k 太小)
python
p1_pipeline = RAGPipeline(
chunk_size=64, # 极小 chunk,文档被切成大量碎片
chunk_overlap=0,
top_k=1, # 只取 1 条,大量信息丢失
prompt_type="baseline",
)
为什么这样配置会出问题?
每篇文档被切成几十个 64 字的碎片,一个完整的概念被拆散到多个 chunk 中。top_k=1 只能取回 1 条,即使这 1 条是最相关的,它包含的信息也远不够回答问题。
预期结果:context_recall 大幅下降------重要内容没检索到,faithfulness 和 answer_relevancy 连带受影响。
问题二:生成幻觉(Prompt 引导模型超出上下文)
python
p2_pipeline = RAGPipeline(
chunk_size=512,
chunk_overlap=50,
top_k=4,
prompt_type="hallucination", # 幻觉诱导 Prompt
)
幻觉 Prompt 明确鼓励模型"扩展":
python
PROMPT_HALLUCINATION = ChatPromptTemplate.from_messages([
("system", "你是一个知识渊博的百科全书式 AI 助手。请基于你丰富的知识储备全面回答问题。"
"下面的参考资料仅供参考,你可以在此基础上扩展更多相关知识,不必局限于参考资料内容。"
"尽量补充背景知识和延伸信息,让回答更加丰富。"),
("human", "参考资料:\n{context}\n\n问题:{question}\n\n请给出全面详细的回答:"),
])
为什么这样会产生幻觉?
模型被明确告知"不必局限于参考资料",它会从自身预训练的知识中生成额外内容。这些内容可能是真实的,但 RAGAS 的 faithfulness 指标衡量的是:答案里的每一个声明,能否在检索上下文中找到依据。任何超出上下文的声明都会被标记为幻觉。
预期结果:faithfulness 大幅下降,而 context_recall 不变(检索没问题)。
问题三:答案偏题(Prompt 强制结构化输出)
python
p3_pipeline = RAGPipeline(
chunk_size=512,
chunk_overlap=50,
top_k=4,
prompt_type="offtopic", # 强制学术综述格式
)
偏题 Prompt 要求固定的学术格式:
python
PROMPT_OFFTOPIC = ChatPromptTemplate.from_messages([
("system", "你是一名资深技术研究员,负责撰写学术综述。"
"针对用户的问题,请按照以下固定结构回答:\n"
"1. 技术背景与历史演进\n"
"2. 主要技术流派与对比分析\n"
"3. 当前挑战与未来发展趋势\n"
"回答需要学术化,涵盖广泛,每部分至少 200 字。"),
("human", "参考资料:\n{context}\n\n问题:{question}\n\n请撰写综述报告:"),
])
为什么这样会导致偏题?
用户问的是"什么是 RAG 技术",但模型被迫按"历史演进 + 流派对比 + 未来趋势"三段式输出。RAGAS 的 answer_relevancy 指标衡量的是:答案有多直接地回答了提问。一个 800 字的综述对一个直接的问题来说,相关性得分自然很低。
预期结果:answer_relevancy 大幅下降,而 faithfulness 和 context_recall 正常(内容都来自上下文,只是格式偏了)。
实验结果对比
运行 diagnose.py 后,得到如下对比报告:
diff
================================================================================
RAG 诊断对比报告
================================================================================
指标 基准配置 问题一:检索召回不足 问题二:生成幻觉 问题三:答案偏题
──────────────────────────────────────────────────────────────────────────────
faithfulness 0.829 0.750 0.320 ← ✗ 0.817
answer_relevancy 0.502 0.191 0.487 0.183 ← ✗
context_precision 0.583 0.375 ← ⚠ 0.583 0.550
context_recall 0.625 0.250 ← ✗ 0.625 0.613
──────────────────────────────────────────────────────────────────────────────
平均得分 0.635 0.392 0.504 0.541
================================================================================
数字背后的诊断逻辑:
| 场景 | 问题指标 | 其他指标 | 根因 |
|---|---|---|---|
| 基准配置 | 无异常 | --- | --- |
| 问题一 | context_recall ↓ 0.375 | context_precision 也下降 | Chunk 太碎 + top_k 不足,重要内容没被取回 |
| 问题二 | faithfulness ↓ 0.509 | context_recall 正常 | Prompt 引导模型超出上下文,生成幻觉 |
| 问题三 | answer_relevancy ↓ 0.319 | faithfulness 正常 | Prompt 强制学术格式,答案不聚焦于问题 |
注意问题一中 context_precision 也下降了:chunk 太小意味着每条 chunk 携带的信息极少,即使检索到了也"精度"不足。
决策树诊断输出
程序还会自动输出决策树分析:
markdown
================================================================================
诊断决策树分析
================================================================================
【问题一:检索召回不足】(预期问题类型:context_recall 低)
步骤 1 → 检查 context_recall:下降 +0.375(显著下降)
✗ 诊断:检索阶段有问题
→ 重要内容没被检索到,检查 chunk_size 和 top_k
→ 当前 top_k 可能太小,或 chunk 太碎导致语义不完整
⚠ 附加发现:context_precision 下降 +0.208,检索结果中混入了噪声
【问题二:生成幻觉】(预期问题类型:faithfulness 低)
步骤 1 → 检查 context_recall:下降 +0.000(正常)
步骤 2 → 检查 faithfulness:下降 +0.509(显著下降)
✗ 诊断:生成阶段出现幻觉
→ 答案包含了上下文中没有的内容
→ 修复建议:优化 Prompt,明确要求只基于参考资料回答
【问题三:答案偏题】(预期问题类型:answer_relevancy 低)
步骤 1 → 检查 context_recall:下降 +0.012(正常)
步骤 2 → 检查 faithfulness:下降 +0.012(正常)
步骤 3 → 检查 answer_relevancy:下降 +0.319(显著下降)
✗ 诊断:答案偏题,未直接回答用户问题
→ Prompt 格式要求导致答案冗长或结构固化
→ 修复建议:简化 Prompt,去除强制格式约束
================================================================================
三条诊断路径,精准对应三种问题类型,全部命中。
每种问题的修复方向
问题一:context_recall 低 → 检修检索配置
python
# 修复前:chunk 太碎,top_k 太小
RAGPipeline(chunk_size=64, chunk_overlap=0, top_k=1)
# 修复后:合理的 chunk 大小 + 足够的 top_k
RAGPipeline(chunk_size=512, chunk_overlap=50, top_k=4)
经验值参考:
| 场景 | chunk_size | overlap | top_k |
|---|---|---|---|
| 短问答(技术 FAQ) | 256--512 | 20--50 | 3--5 |
| 长文档理解 | 512--1024 | 50--100 | 4--6 |
| 代码库检索 | 按函数/类分块 | 0 | 3--5 |
问题二:faithfulness 低 → 加固 Prompt
核心原则:明确告诉模型「只依据参考资料回答」,并且设定「没有信息时如何处理」。
python
# 修复:严格约束 Prompt
PROMPT_STRICT = ChatPromptTemplate.from_messages([
("system", """你是一个技术问答助手。
规则:
1. 只能基于「参考资料」中的内容作答
2. 如果参考资料不包含答案,直接回答「根据现有资料无法回答」
3. 不允许添加参考资料之外的信息
4. 回答要简洁,不超过 200 字"""),
("human", "参考资料:\n{context}\n\n问题:{question}"),
])
问题三:answer_relevancy 低 → 简化 Prompt 格式
python
# 修复:去掉固定格式要求,让模型自然回答
PROMPT_FOCUSED = ChatPromptTemplate.from_messages([
("system", "你是技术问答助手。请直接回答问题,简洁准确,不要添加不必要的格式或结构。"),
("human", "参考资料:\n{context}\n\n问题:{question}"),
])
完整代码
完整代码已开源:
核心文件:
rag_pipeline.py--- 支持 3 种 Prompt 类型的 RAG Pipelinediagnose.py--- 3 个问题场景 + 决策树诊断
运行方式:
bash
git clone https://github.com/chendongqi/llm-in-action
cd 09-rag-diagnosis
cp .env.example .env # 填入你的 LLM 和 Embedding API Key
pip install -r requirements.txt
python diagnose.py
小结
这套诊断框架的核心思路是:
- 不靠直觉,靠指标------context_recall、faithfulness、answer_relevancy 分别对应检索、生成、相关性三个维度
- 按决策树顺序检查------先 context_recall,再 faithfulness,最后 answer_relevancy,避免误诊
- 制造对照实验------好配置和坏配置的指标差异才是定位根因的关键证据
在实际项目中,出现问题时先跑一次 RAGAS 评估,看哪个指标最低,再按决策树找方向。这比"调一调感觉好了"要靠谱得多。