
系列:生产级 LLM 应用方法论 04
日期:2026-06-18
适合读者:正在建设企业知识库、文档问答、客服助手、代码助手、研究助理或内部 Agent 的工程师、产品负责人和技术负责人。
摘要
前三篇分别讨论了 Prompt Engineering 为什么不够、Context Engineering 是什么,以及上下文压缩与排序怎么做。这一篇进入 RAG 系统里最容易被低估、但最决定上限的问题:检索质量到底怎么评测?
很多团队上线 RAG 时只看最终答案:“答对了吗?有没有幻觉?”这个视角太粗。最终答案错了,可能是检索没有召回正确文档,也可能是召回了但排在第 12 位进不了上下文,还可能是证据进了上下文但模型没有用,甚至可能是答案看起来正确却引用了不支持结论的来源。
所以 RAG 评测要拆成三层:检索是否找到了正确证据,排序是否把正确证据放到前面,生成是否忠实使用了证据。本文给出一套工程化评测方法:如何设计 gold set、如何算 Recall@k / MRR / nDCG / Citation Support,如何记录权限和时效性,如何用一段可运行脚本做离线评测,以及线上应该监控哪些信号。
目录
- 1. 为什么不能只看最终答案
- 2. 把 RAG 链路拆成三层
- 3. 检索质量的核心指标
- 4. 评测集应该怎么设计
- 5. 一个最小 retrieval eval 数据格式
- 6. 离线评测脚本:先把问题定位清楚
- 7. 诊断矩阵:指标差时应该改哪里
- 8. 答案层评测:不要让模型“带着错引用答对”
- 9. 线上监控:离线分数不等于线上可靠
- 10. 常见误区
- 11. 落地路线图
- 12. 发布前自检清单
- 13. 总结
- 参考资料
1. 为什么不能只看最终答案
RAG 的目标不是“让模型看起来引用了资料”,而是让答案能够被外部证据支撑。
如果只看最终答案,会把不同错误混在一起:
| 现象 | 表面表现 | 真正可能的问题 |
|---|---|---|
| 答案错误 | 模型说错政策、数字或步骤 | 检索没召回正确文档;文档过期;模型没用证据 |
| 答案太泛 | 只给常识,没有业务细节 | 召回结果弱相关;上下文缺少 must-have facts |
| 引用存在但不支持结论 | 看起来有来源,点开不相关 | citation 只是装饰,没有做支持性校验 |
| 同一问题多次回答不稳定 | 有时对,有时错 | top-k 排序波动;chunk 重叠噪声大;reranker 不稳定 |
| 用户越权看到信息 | 答案引用了不该访问的文档 | metadata filter 或权限层失效 |
| 旧政策覆盖新政策 | 答案沿用旧版本 | freshness/filter/version priority 没做进检索层 |
这些问题不能靠“再写一句 prompt”解决。RAG 系统必须把检索、排序、上下文和生成拆开评测。
一句工程判断是:
RAG 的第一性评测对象不是答案,而是“证据链是否成立”。
如果证据链不成立,答案越流畅越危险。
2. 把 RAG 链路拆成三层
一个典型 RAG 请求可以拆成三段:
- 检索层:从知识库里找候选文档或 chunk。
- 上下文层:对候选结果做过滤、去重、重排、压缩和预算分配。
- 生成层:模型基于上下文回答,并给出引用或证据说明。

对应的评测问题也不同:
| 层级 | 应该问的问题 | 典型指标 |
|---|---|---|
| 检索层 | 正确证据有没有被找出来? | Recall@k、Hit Rate@k、Coverage |
| 排序层 | 正确证据是否排在足够靠前的位置? | MRR、nDCG@k、Context Precision |
| 上下文层 | 进模型窗口的证据是否干净、不过期、不越权? | Duplicate Rate、Freshness、Permission Violation |
| 生成层 | 答案是否忠实、完整、可追溯? | Faithfulness、Answer Correctness、Citation Support |
OpenAI Retrieval 文档里提到,检索可以做 semantic search、query rewriting、attribute filtering、ranking options,也可以限制 max_num_results。这些不是“调参小项”,而是评测实验的变量。你应该能回答:打开 query rewrite 后 Recall@10 是否提升?把 score_threshold 提高后 Precision 是否提升但 Recall 是否下降?按部门和日期过滤后是否减少越权和过期证据?
3. 检索质量的核心指标
先定义一条样本:
{
"query_id": "refund_001",
"query": "跨境订单退款多久到账?什么情况需要人工审核?",
"gold_doc_ids": ["refund_policy_2026_03"],
"gold_chunk_ids": ["refund_policy_2026_03#chunk_07", "refund_policy_2026_03#chunk_09"],
"required_facts": ["到账时间", "跨境支付需人工审核"],
"user_scope": ["customer_service"],
"as_of": "2026-06-18"
}
检索系统返回:
[
{"chunk_id": "refund_faq_2025_10#chunk_03", "doc_id": "refund_faq_2025_10", "score": 0.83},
{"chunk_id": "refund_policy_2026_03#chunk_07", "doc_id": "refund_policy_2026_03", "score": 0.79},
{"chunk_id": "payment_policy_2026_01#chunk_12", "doc_id": "payment_policy_2026_01", "score": 0.74}
]
下面这些指标各自回答不同问题。
3.1 Hit Rate@k
Top-k 里是否至少出现一个 gold 证据。
适合回答:“这个问题有没有捞到一点正确材料?”
缺点也明显:只要命中一个就算成功,不关心是否命中全部关键证据,也不关心排第几。
3.2 Recall@k
Top-k 里命中的 gold 证据数量,占 gold 证据总数的比例。
如果一个问题必须同时找到“到账时间”和“人工审核条件”,Recall@k 比 Hit Rate 更有意义。很多 RAG 系统答不完整,不是模型不会总结,而是检索只找到了其中一个事实。
3.3 Precision@k
Top-k 里有多少比例是正确证据。
这个指标在上下文预算紧张时很重要。Recall 高但 Precision 低,意味着你确实把正确证据找到了,但也带进来大量噪声。模型在噪声里做推理,稳定性会下降。
3.4 MRR
MRR(Mean Reciprocal Rank)关心第一个正确结果排在第几位。
如果第一个正确 chunk 总是排在第 1 或第 2,MRR 高;如果正确 chunk 经常排在第 8 或第 12,MRR 低。对只取 top-3 或 top-5 进上下文的系统,MRR 非常关键。
3.5 nDCG@k
nDCG 适合 gold 证据有等级的场景。比如一个 chunk 是“直接回答问题的政策条款”,另一个只是“背景解释”,它们不应该同权。
如果你有人工标注的 relevance grade,例如:
- 3:直接支撑答案;
- 2:部分支撑;
- 1:背景相关;
- 0:不相关。
那么 nDCG@k 比简单 Recall 更能反映排序质量。
3.6 Coverage
Coverage 不是标准 IR 指标,但对业务 RAG 很实用。它回答:
问题需要的关键事实类型,是否都被证据覆盖?
例如退款问题需要:
- 时间;
- 渠道;
- 异常条件;
- 审核条件;
- 政策版本。
只命中“时间”不够。Coverage 可以按 required_facts 计算。
3.7 Freshness
RAG 的错误常常不是“没找到”,而是“找到了旧版本”。
Freshness 可以按业务规则定义:
- 是否命中最新版本文档;
- 是否符合
as_of时间; - 是否避开已废止政策;
- 多版本冲突时是否选择优先级最高的来源。
3.8 Permission Violation
企业 RAG 必须把权限当作检索指标,而不是生成层道德提醒。
如果用户无权访问某些文档,检索结果里出现这些文档就已经是系统错误,即使模型最终没有引用。评测集应该包含不同 user_scope、部门、地区、客户等级和数据隔离场景。
3.9 Duplicate Rate
chunk overlap 会提升召回,但也会带来重复。重复结果太多,会挤掉其他证据。
Duplicate Rate 可以按 doc_id、相邻 chunk、文本相似度或 canonical fact 计算。它不一定越低越好,但高到一定程度就说明上下文预算被浪费。
3.10 Citation Support
Citation Support 属于生成层和证据层之间的指标。它问:
答案里的每个关键断言,是否能被引用来源直接支持?
这比“有没有引用”严格得多。RAG 系统最危险的状态是:答案看起来专业、有引用,但引用点开不支持结论。
4. 评测集应该怎么设计
不要从随机用户日志里随便抽 100 条问题就开始算分。那会让评测集偏向高频、简单、表述清楚的问题,掩盖真正会出事故的边界。
一个可靠的 RAG eval set 应该覆盖这些类型:
| 类型 | 例子 | 目的 |
|---|---|---|
| 直接事实 | “企业版支持多少个管理员?” | 测基础召回 |
| 多条件组合 | “跨境订单退款多久到账,哪些情况要人工审核?” | 测多证据覆盖 |
| 版本敏感 | “2026 年 3 月后的退款政策是什么?” | 测时效性 |
| 权限敏感 | “某客户的合同折扣是多少?” | 测 metadata filter |
| 同义表达 | “钱什么时候退回来?” | 测 query rewrite 和语义召回 |
| 反事实/不存在 | “能否 24 小时内保证退款?” | 测拒答和不确定性 |
| 冲突证据 | “新旧政策同时存在时按哪个算?” | 测版本优先级 |
| 长尾术语 | “SLA credit 怎么申请?” | 测领域词表和 hybrid search |
| 引用严格 | “请给出处并引用原文依据。” | 测 citation support |
每条样本至少要有这些字段:
| 字段 | 作用 |
|---|---|
query_id |
稳定追踪和回归测试 |
query |
用户问题原文 |
intent_type |
事实、流程、比较、总结、排障等 |
gold_doc_ids |
正确来源文档 |
gold_chunk_ids |
最小正确证据单元 |
required_facts |
答案必须覆盖的事实 |
negative_doc_ids |
不能被当成依据的相似干扰文档 |
user_scope |
权限上下文 |
as_of |
时间上下文 |
expected_answer_notes |
生成层评测提示,不要求唯一答案 |
这里最费力的是 gold_chunk_ids。但如果没有这个字段,你很难判断检索到底对不对。只标答案不标证据,会把问题又推回“最终答案对不对”的粗粒度评测。
5. 一个最小 retrieval eval 数据格式
可以从 JSONL 开始,不要一上来做复杂平台。
{"query_id":"refund_001","query":"跨境订单退款多久到账?什么情况需要人工审核?","intent_type":"policy_qa","gold_doc_ids":["refund_policy_2026_03"],"gold_chunk_ids":["refund_policy_2026_03#chunk_07","refund_policy_2026_03#chunk_09"],"required_facts":["到账时间","跨境支付需人工审核"],"negative_doc_ids":["refund_faq_2025_10"],"user_scope":["customer_service"],"as_of":"2026-06-18","expected_answer_notes":"必须说明原支付渠道 1-5 个工作日;跨境支付订单进入人工审核;引用 2026-03 版政策。"}
{"query_id":"contract_014","query":"这个客户最新合同里的自动续约条款是什么?","intent_type":"contract_qa","gold_doc_ids":["contract_acme_2026_signed"],"gold_chunk_ids":["contract_acme_2026_signed#chunk_22"],"required_facts":["自动续约期限","提前通知窗口"],"negative_doc_ids":["contract_acme_2025_draft"],"user_scope":["legal","account_acme"],"as_of":"2026-06-18","expected_answer_notes":"只能使用已签署最新版合同,不能引用 2025 草案。"}
{"query_id":"support_033","query":"用户说登录后一直跳回首页,可能是什么原因?","intent_type":"troubleshooting","gold_doc_ids":["sso_runbook_2026_02","cookie_policy_2026_01"],"gold_chunk_ids":["sso_runbook_2026_02#chunk_11","cookie_policy_2026_01#chunk_04"],"required_facts":["SSO callback mismatch","SameSite cookie 配置"],"negative_doc_ids":[],"user_scope":["support_l2"],"as_of":"2026-06-18","expected_answer_notes":"需要给排查顺序,不能只给泛泛登录建议。"}
检索输出也建议记录成 JSONL:
{"query_id":"refund_001","results":[{"rank":1,"doc_id":"refund_faq_2025_10","chunk_id":"refund_faq_2025_10#chunk_03","score":0.83},{"rank":2,"doc_id":"refund_policy_2026_03","chunk_id":"refund_policy_2026_03#chunk_07","score":0.79},{"rank":3,"doc_id":"refund_policy_2026_03","chunk_id":"refund_policy_2026_03#chunk_09","score":0.76}]}
OpenAI File Search 文档里有一个实用点:默认情况下模型输出会带文件引用 annotation,但如果你要分析检索结果本身,需要在请求里显式 include file_search_call.results。做 eval 时不要只存最终 answer,要把搜索 query、top-k 结果、score、metadata、filters 和模型最终引用都存下来。
6. 离线评测脚本:先把问题定位清楚
下面是一段无第三方依赖的 Python 示例。它不负责调用检索服务,只负责读取 gold set 和 retrieval results,然后计算基础指标。真实项目里可以把它接到 CI、离线实验平台或 nightly job。
import json
import math
from collections import Counter
from pathlib import Path
def read_jsonl(path):
with Path(path).open("r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if line:
yield json.loads(line)
def dcg(relevances):
return sum((2 ** rel - 1) / math.log2(i + 2) for i, rel in enumerate(relevances))
def evaluate(gold_path, result_path, k=5):
gold = {row["query_id"]: row for row in read_jsonl(gold_path)}
results = {row["query_id"]: row["results"] for row in read_jsonl(result_path)}
totals = Counter()
sums = Counter()
failures = []
for query_id, item in gold.items():
rows = results.get(query_id, [])[:k]
returned_chunks = [r["chunk_id"] for r in rows]
returned_docs = [r["doc_id"] for r in rows]
gold_chunks = set(item.get("gold_chunk_ids", []))
gold_docs = set(item.get("gold_doc_ids", []))
negative_docs = set(item.get("negative_doc_ids", []))
chunk_hits = [chunk for chunk in returned_chunks if chunk in gold_chunks]
doc_hits = [doc for doc in returned_docs if doc in gold_docs]
hit_at_k = 1.0 if chunk_hits or doc_hits else 0.0
recall_at_k = len(set(chunk_hits)) / max(1, len(gold_chunks))
precision_at_k = len(chunk_hits) / max(1, len(rows))
reciprocal_rank = 0.0
for idx, row in enumerate(rows, start=1):
if row["chunk_id"] in gold_chunks or row["doc_id"] in gold_docs:
reciprocal_rank = 1.0 / idx
break
# 最小版 nDCG:gold chunk 记 3 分,gold doc 记 1 分,其他 0 分。
rels = []
for row in rows:
if row["chunk_id"] in gold_chunks:
rels.append(3)
elif row["doc_id"] in gold_docs:
rels.append(1)
else:
rels.append(0)
ideal = sorted(rels, reverse=True)
ndcg = dcg(rels) / dcg(ideal) if any(ideal) else 0.0
permission_violation = any(doc in negative_docs for doc in returned_docs)
duplicate_rate = 1.0 - (len(set(returned_chunks)) / max(1, len(returned_chunks)))
totals["queries"] += 1
sums["hit_at_k"] += hit_at_k
sums["recall_at_k"] += recall_at_k
sums["precision_at_k"] += precision_at_k
sums["mrr"] += reciprocal_rank
sums["ndcg_at_k"] += ndcg
sums["permission_violation_rate"] += 1.0 if permission_violation else 0.0
sums["duplicate_rate"] += duplicate_rate
if recall_at_k < 1.0 or permission_violation:
failures.append({
"query_id": query_id,
"query": item["query"],
"recall_at_k": round(recall_at_k, 3),
"returned_chunks": returned_chunks,
"gold_chunks": sorted(gold_chunks),
"permission_violation": permission_violation,
})
n = max(1, totals["queries"])
summary = {name: round(value / n, 4) for name, value in sums.items()}
return {"k": k, "summary": summary, "failures": failures[:20]}
if __name__ == "__main__":
report = evaluate("retrieval_eval.jsonl", "retrieval_results.jsonl", k=5)
print(json.dumps(report, ensure_ascii=False, indent=2))
这段脚本故意简单,因为第一版 eval 的目标不是“指标优雅”,而是帮助你把错误分层:
- Recall 低:检索层没找到;
- MRR 低:找到了但排序靠后;
- Precision 低:噪声太多;
- Duplicate Rate 高:上下文预算被重复 chunk 占用;
- Permission Violation 高:权限过滤不能上线;
- nDCG 低:排序没有把强证据放前面。
7. 诊断矩阵:指标差时应该改哪里
评测不是为了得到一个分数,而是为了决定下一步改哪里。
| 评测现象 | 常见原因 | 优先排查 |
|---|---|---|
| Hit Rate@10 低 | query 表达和文档表达差异大;索引缺文档;embedding 不适合领域 | query rewrite、同义词词表、索引覆盖、hybrid search |
| Recall@10 高但 Recall@3 低 | 正确结果在后面 | reranker、ranking options、domain boost |
| Precision@5 低 | top-k 混入大量弱相关片段 | score threshold、metadata filter、query decomposition |
| MRR 低 | 第一个正确结果太靠后 | 重排模型、标题/层级 metadata、文档结构化 |
| nDCG 低 | 强证据没有排在弱证据前 | 人工 relevance grade、业务优先级、source authority |
| Duplicate Rate 高 | chunk overlap 太大;相邻 chunk 都进上下文 | 结果去重、按 doc 限额、MMR、多样性约束 |
| Freshness 差 | 旧文档没有废止标记;日期过滤缺失 | as_of 过滤、版本优先级、索引生命周期 |
| Permission Violation > 0 | 检索前未做权限过滤;只在生成层提醒模型 | 强制 metadata filter、租户隔离、审计日志 |
| 答案错但检索对 | 模型没有忠实使用证据;上下文排序差 | 引用约束、证据编号、答案后验校验 |
| 答案对但引用错 | citation 没校验;引用只是文本装饰 | claim-to-citation 检查、引用片段回放 |
这里有一个容易忽略的顺序:先修权限和时效性,再修召回,再修排序,最后修生成。
原因很简单:如果检索结果里已经有越权或过期内容,生成层越强,越可能把错误证据组织成可信答案。
8. 答案层评测:不要让模型“带着错引用答对”
RAGAS 等工作把 RAG 评测拆成了 answer relevancy、faithfulness、context precision、context recall 等维度;ARES 这类框架也强调用自动化方式评测 RAG 的检索和生成质量。这些方向的共同点是:不要把答案正确性和证据质量混成一个黑盒分数。
工程上可以把答案层评测拆成四个检查:
8.1 Answer Correctness
答案是否覆盖 required_facts,有没有明显事实错误。
这个指标可以由人工、规则、LLM judge 或混合方式完成。高风险任务不要完全依赖单一 LLM judge,至少要抽样人工复核。
8.2 Faithfulness
答案里的关键断言是否都来自上下文证据。
例子:
答案断言:跨境订单退款通常需要 1-5 个工作日,并需要人工审核。
证据 A:退款通常在 1-5 个工作日内退回原支付渠道。
证据 B:跨境支付订单需进入人工审核。
这就是可支持的。如果证据只说“部分异常订单需审核”,答案却写“所有跨境订单都需审核”,就不忠实。
8.3 Citation Support
每个引用是否支撑它旁边的句子。
不要只检查“答案末尾有没有来源列表”。更好的做法是让答案的每个关键句带 citation id,然后逐条校验:
{
"claim": "跨境支付订单需进入人工审核。",
"citation": "refund_policy_2026_03#chunk_09",
"supported": true
}
8.4 Refusal / Insufficient Evidence
当检索不到足够证据时,系统是否会明确说“不足以回答”,而不是编一个看起来合理的答案。
这类样本必须进 eval set。否则系统会在有证据问题上得分很好,但在无证据问题上制造幻觉。
9. 线上监控:离线分数不等于线上可靠
离线 eval 是上线门槛,不是上线后的免死金牌。线上至少监控这些信号:
| 信号 | 说明 |
|---|---|
| 检索空结果率 | 空结果突然上升,可能是索引、权限或查询改写异常 |
| 平均 top-1 / top-5 score | 分数分布漂移,可能说明数据或 query 变了 |
| 低分回答率 | 低检索置信度时仍生成答案,需要关注 |
| 引用点击率/反馈 | 用户是否点击来源,是否认为来源不相关 |
| 人工转接率 | 客服、法务、财务场景里很关键 |
| 版本命中率 | 新政策发布后,旧版本是否仍被命中 |
| 权限拒绝率 | 权限过滤是否异常宽或异常严 |
| p95 延迟 | reranker、query decomposition 和 top-k 扩大会影响体验 |
| 输入 token 分布 | 证据过长会提高成本,也可能挤掉规则 |
| 答案后验校验失败率 | citation support 或 faithfulness checker 的失败趋势 |
更进一步,可以把线上失败样本回流到 eval set:
- 用户点踩或转人工;
- 记录 query、retrieval results、answer、citations、filters;
- 人工标注 gold evidence 和失败原因;
- 加入 regression eval;
- 下次改检索、chunking、reranker 或 prompt 时必须跑过。
这才是 RAG 质量持续提升的闭环。
10. 常见误区
10.1 只用公开 benchmark 判断业务 RAG
BEIR、KILT 等 benchmark 对理解信息检索和知识密集型任务很有帮助,但它们不能替代你的业务 eval set。企业知识库里最难的问题通常是权限、版本、内部术语、流程例外和文档质量。
公开 benchmark 可以用来比较底层检索器,但上线决策必须看业务 gold set。
10.2 把 top-k 调大当成万能解
top-k 变大通常能提高 Recall,但也会增加噪声、token、延迟和引用混乱。正确做法是同时观察 Recall、Precision、MRR、nDCG、答案 faithfulness 和成本。
10.3 只标 gold doc,不标 gold chunk
只标文档粒度会让指标虚高。一个 80 页 PDF 里有正确答案,不代表检索到这个 PDF 的任意 chunk 都算成功。
10.4 不测无答案问题
RAG 系统必须会说“不知道”。无答案问题、权限不足问题、证据冲突问题都应该进 eval。
10.5 把 LLM judge 当绝对真值
LLM judge 很适合扩大评测规模,但它本身也需要校准。建议做法是:
- 关键指标保留人工标注样本;
- LLM judge 输出理由和引用;
- 抽样复核 judge 误判;
- 每次改 judge prompt 也跑回归。
10.6 忽略数据摄取质量
如果 PDF 解析错、表格丢列、标题层级消失、扫描件 OCR 错误,检索评测会持续低分。不要只调 embedding 和 reranker,也要检查 ingest pipeline。
11. 落地路线图
如果从零开始,我建议按四周推进。
第 1 周:建立最小 eval set
- 选 50-100 条真实业务问题;
- 覆盖高频、长尾、无答案、权限、版本和冲突场景;
- 标注
gold_doc_ids、gold_chunk_ids、required_facts; - 固定第一版 JSONL 格式。
第 2 周:跑检索层基线
- 记录 top-10 检索结果;
- 计算 Hit Rate@k、Recall@k、MRR、nDCG;
- 输出失败样本列表;
- 对失败样本按原因分类:缺文档、chunk 不佳、query 不佳、排序不佳、权限/版本错误。
第 3 周:做排序和上下文实验
- 比较不同 chunk size 和 overlap;
- 比较 semantic、keyword、hybrid search;
- 比较 query rewrite 开关;
- 加 reranker 或业务 boost;
- 加去重、source cap、metadata filter;
- 每次只改一类变量,避免无法归因。
第 4 周:接答案层和线上监控
- 加 answer correctness / faithfulness / citation support 检查;
- 记录
file_search_call.results或自建 retriever trace; - 把低置信度、用户差评、人工转接样本回流;
- 在发布流程里设置回归阈值。
第一版阈值可以保守一点,例如:
| 指标 | 上线前建议 |
|---|---|
| Permission Violation | 必须为 0 |
| Hit Rate@10 | >= 0.90 |
| Recall@5 | >= 0.75 |
| MRR | 持续提升,不低于旧版本 |
| Citation Support | >= 0.85,且高风险场景人工抽检 |
| 无答案拒答准确率 | >= 0.85 |
这些数字不是通用标准,只是帮助团队开始讨论 trade-off。真正的阈值要根据业务风险来定。
12. 发布前自检清单
上线前至少问完这些问题:
- 是否有覆盖真实业务的 eval set,而不只是 demo 问题?
- 是否标注了 gold chunk,而不只是 gold answer?
- 是否包含无答案、权限、过期、冲突和长尾术语样本?
- 是否能输出每个 query 的 top-k 结果、score、metadata、filter 和最终引用?
- 是否分别看了 Recall、MRR、nDCG、Permission Violation、Duplicate Rate?
- 是否有答案层的 faithfulness 和 citation support 检查?
- 是否有失败样本回流机制?
- 是否能在模型、embedding、chunking、reranker、prompt 变更后跑回归?
- 是否明确低置信度时的降级策略:拒答、追问、转人工或扩大检索?
- 是否记录了上线版本的知识库快照和评测报告?
如果这些问题答不上来,RAG 系统就还停留在“能演示”,没有进入“可运营”。
13. 总结
RAG 检索质量评测不是一个单一分数,而是一套定位问题的工具箱。
最重要的不是选择 Recall@k 还是 nDCG,而是建立这条链路:
业务问题 -> gold evidence -> top-k 检索结果 -> 排序指标 -> 上下文质量 -> 答案归因 -> 失败回流
当你能把一次错误回答拆成“没召回、排太后、证据过期、权限失效、引用不支持、模型没忠实使用证据”中的某一种,RAG 系统才真正可改进。
下一篇建议继续写:RAG 的引用与归因怎么做:让答案里的每一句关键结论都有可追溯证据。
参考资料
- OpenAI Developers: Retrieval
- OpenAI Developers: File search
- OpenAI Developers: Working with evals
- Es et al., RAGAS: Automated Evaluation of Retrieval Augmented Generation
- Thakur et al., BEIR: A Heterogeneous Benchmark for Zero-shot Evaluation of Information Retrieval Models
- Petroni et al., KILT: a Benchmark for Knowledge Intensive Language Tasks
- Saad-Falcon et al., ARES: An Automated Evaluation Framework for Retrieval-Augmented Generation Systems