当前位置:首页>排行榜>接上文档还不够:用评测把 RAG 从「能答」做到「可信」

接上文档还不够:用评测把 RAG 从「能答」做到「可信」

  • 更新时间 2026-10-13 22:35:17
接上文档还不够:用评测把 RAG 从「能答」做到「可信」

上一篇我把制度 FAQ 接进了回答,模型能引用文档了。但交给法务用之前,我得回答一个问题:凭什么相信它?这一篇讲评测:用一张固定的答案表,把「感觉还行」变成「可以验收」。

一、一质疑就改口

说实话,AI 给的答案我总是不太相信,习惯让它再复核一遍。

结果遇到过这种情况:我一质疑,它马上改口。可它改口不是因为核对了事实,而是在迎合我。原来的答案可能是对的,被我一问反而改错了。

所以「让它自己复核」靠不住。同一个模型再看一遍,照样可能错,还可能被带偏。

二、外部标准:一张答案表

要判断对错,得有一个不靠模型说了算的标准,我叫它外部标准。

做法很简单:提前写好题目和正确答案,答案来自制度原文或法务确认过的结论。模型答完,拿它的答案去对这张表。对得上就算过,对不上就算错。我质疑它、它改口都没用,表不会变。

我沿用上一篇的三条虚构 FAQ,出了 5 道题:

题号
问题
标准答案
1
默认付款期限多少天?
30 天
2
违约金最高多少?
合同总额的 10%
3
保密义务合同结束后还管多久?
3 年
4
付款能不能拖到 60 天?
照原文说默认 30 天,不编新规则
5
出差住宿标准是多少?
文档里没有,应回答不知道

第 4 题考它会不会顺着我的问题编规则,第 5 题考它会不会老实说不知道。这两道反例,比前三道更重要。

三、不知道答案,就查出处

很多时候我自己也不知道答案,本来就是想让 AI 帮我研究。这时候没有标准答案可对,怎么办?

办法是检查依据:要求它每个回答都写出处,我点开原文看一眼,对不对得上。没有出处,或者出处里根本没这句话,就不信。这在评测里叫 groundedness,意思是答案是否忠于检索到的原文。

四、先查检索,再查生成

有一道题错了,先查哪儿?我一开始也不清楚。方法是把检索到的段落打印出来,先看一眼:

  • 段落里根本没有正确答案:检索出了问题,去改切块方式或检索条数。
  • 段落里明明写着「30 天」,模型却答了别的:生成出了问题,去改提示词,比如强调「只能根据文档回答」。

先修检索,再改提示,不要一上来就换模型。

下面是最小评测脚本,接着上一篇的 RAG demo 用:

# 接在上一篇 demo 后面:复用 col(Chroma 集合)和 clientCASES = [    {"q": "我们公司采购合同的默认付款期限是多少天?", "expect": "30"},    {"q": "违约金最高是多少?", "expect": "10%"},    {"q": "保密义务在合同终止后还有效多久?", "expect": "3 年"},    {"q": "付款能不能拖到 60 天?", "expect": "30"},    {"q": "出差住宿标准是多少?", "expect": "不知道"},]SYSTEM = (    "你是公司制度助手。只能根据给定文档回答。"    "回答必须包含「依据:」并引用原文。文档里没有就回答「不知道」。")def run(case):    hits = col.query(query_texts=[case["q"]], n_results=2)    context = "\n".join(hits["documents"][0])    r = client.chat.completions.create(        model="gpt-4o-mini",        temperature=0,        messages=[{"role": "system", "content": SYSTEM},                  {"role": "user", "content": f"文档:\n{context}\n\n问题:{case['q']}"}],        timeout=30,    )    answer = r.choices[0].message.content or ""    return context, answerpassed = 0for i, case in enumerate(CASES, 1):    context, answer = run(case)    ok = case["expect"] in answer    cited = "依据" in answer or case["expect"] == "不知道"    passed += ok and cited    print(f"--- 第 {i} 题 {'通过' if ok and cited else '不通过'}")    print("检索到:", context.replace("\n", " | "))    print("回答:", answer)print(f"\n结果:{passed}/{len(CASES)}")

每道题都会打印「检索到」的段落和回答。不通过时,先看检索那一行,就知道该修哪一边。

五、5 道全对才交付

什么程度才敢交给法务用?我给自己定的标准是:5 道全对,每道都带出处,第 5 道必须老实说不知道。

这个门槛看着严,但它清楚。法务验收时不用听我解释「大部分时候挺准的」,只看这张表跑出来是不是 5/5。

FDE 视角的结论:客户信的不是模型,而是你能拿出来的那张评测表。以后每改一次切块、提示词或模型,都先跑一遍这 5 道题,分数掉了就不上线。

下一步:把题目扩到 20 道,加入更多「文档里没有」的反例,再试试让另一个模型当评委,自动判断 grounded。

参考资料

[1] LangSmith Evaluate a RAG application:https://docs.langchain.com/langsmith/evaluate-rag-tutorial

[2] OpenAI Optimizing LLM Accuracy:https://developers.openai.com/api/docs/guides/optimizing-llm-accuracy

— 夏天软件AI —

随机文章