
“准确率从 64.2% 提升到 94.8%”很醒目,但若只有 50 道题,每题只算对错,单次整体比例应以 2 个百分点为步长变化。小数不一定错,也可能来自多次平均或不同指标;问题是这些口径有没有写出来。
个人知识库的评估至少拆成三层:是否召回证据、回答是否被证据支持、没有答案时是否克制。不能用一个“准确率”把它们盖住。
平均成功和反复可靠不是一回事
2026 年 10 月 22 日 ThinkingBox 的研究分别报告单次平均、至少一次成功和多次全部成功。它们回答不同问题,排序也可能不同。研究原文
私人 RAG 同样需要记录每次候选与回答,而非只保存一张最终百分比表。先做十几道能人工复核的题,比拿没有标注来源的大表更有价值。

图中的 Recall 为可回答题的 2/3,ABSTAIN 为全部题目中拒答占比 1/4;后者不是拒答正确率。
一个可复算的小评估器
保存为 evaluate.py。金标准和结果都是教学输入,不是某个模型的跑分。
gold = {"Q1": {"A"}, "Q2": {"B"}, "Q3": {"C"}, "Q4": set()}
retrieved = {"Q1": ["A"], "Q2": ["B"], "Q3": ["Z"], "Q4": []}
answerable = [q for q in gold if gold[q]]
unanswerable = [q for q in gold if not gold[q]]
recalls = [
len(set(retrieved[q][:1]) & gold[q]) / len(gold[q])
for q in answerable
]
mean_recall = sum(recalls) / len(recalls)
abstain_rate = sum(not retrieved[q] for q in gold) / len(gold)
correct_abstain = sum(not retrieved[q] for q in unanswerable) / len(unanswerable)
assert abs(mean_recall - 2/3) < 1e-9
assert abstain_rate == 1/4
assert correct_abstain == 1.0
print({"mean_recall@1": mean_recall,
"abstain_rate": abstain_rate,
"correct_abstain_on_unanswerable": correct_abstain})
每道可回答题在这里恰有一个相关文档,因此平均 Recall@1 恰好等于题目命中率。多相关文档时,两者不能直接画等号。没有不可回答题时,拒答正确率应标不可计算,而不是默认 100%。
把测试集留在调参之外
按时间切分笔记,问题也覆盖时间歧义、同名记录、已删除信息、相互矛盾记录。修改阈值时使用调参集;最终测试集冻结,并记录模型、索引、提示和数据版本。
生成回答另行人工标注“每个事实是否有证据”,不能因为召回命中了就判整句答案正确。耗时与成本也独立记录,模拟分数不能变成设备性能。
本文实跑了指标计算,没有运行检索模型或得到私人库准确率。愿意把分母写清楚,评估才真正帮得上下一次改进。
本文强调生活场景RAG评估必须清晰定义各指标分母,避免混淆准确率、召回率与拒答率。提出三层评估框架:证据召回、答案可支持性、拒答合理性;指出平均成功、至少一次成功、全部成功三类指标语义不同且不可互换。主张使用小规模可复算测试集,人工标注来源,冻结测试集以保障调参独立性,并严格区分命中文档与答案正确性。

1068

被折叠的 条评论
为什么被折叠?



