Skip to content

Agent 进阶(七)评估:别再「拍脑袋」调提示词

🕒 Published at:

前面几篇都在教你"怎么把 Agent 做得更好"。但有个尴尬的问题:你怎么知道它真的变好了? 入门时我们靠"手动问几句,感觉还行"。这在真实项目里是致命的——你改了个提示词,凭感觉觉得变好了,结果上线后另一批问题反而答错了。这一篇讲怎么科学地衡量好坏,让优化有据可依。

"凭感觉"为什么害人

设想一个场景。你的问答机器人上线了,用户反馈"有些问题答得不对"。你改了改提示词,自己试了三个问题,都对了,心想"搞定",发布。第二天,新一批投诉来了——你改的时候只顾着修那三个,却把原本答对的另一批给改坏了。你没有一把"尺子",就永远在拆东墙补西墙。

这把尺子,就是评测集(evaluation set):一批固定的、带标准答案的测试题。每次改动后,都用这批题跑一遍,看整体得分是涨了还是跌了。这样你就能理直气壮地说"这次改动,准确率从 78% 提到了 85%",而不是"我感觉好像好点了"。

第一步:攒一个评测集

评测集不需要很大,几十道有代表性的题就能起步。关键是覆盖真实场景,尤其是那些容易出错的、边角的问题。来源可以是:真实用户问过的问题、客服记录里的高频问题、你能想到的刁钻情况。

每道题就是一对"问题 + 标准答案":

python
# 评测集:真实、有代表性的问答对(先攒几十条)
test_set = [
    {"question": "陪产假有几天?", "expected": "15 天"},
    {"question": "滤网多久清洗一次?", "expected": "每周一次"},
    {"question": "机器报错 E45 怎么办?", "expected": "尘盒未装到位,重新安装"},
    # ……继续补充,尤其是容易答错的边角问题
]

第二步:RAG 要分开评"检索"和"回答"

如果你评的是一个 RAG 系统,有个重要技巧:别只看最终答案对不对,要把"检索"和"回答"分开看。 因为答错可能有两个完全不同的原因:

  • 检索没召回:库里明明有答案,但没被检索出来 → 问题在检索环节(回去优化上两篇讲的召回、重排)。
  • 检索对了但答错:正确资料检索到了,模型却没用好、答偏了 → 问题在生成环节(优化提示词)。

这俩的修法完全不同。只看最终对错,你根本不知道该改哪。所以评估 RAG 时,常常分别看两个指标:检索命中率(正确资料有没有被检索到)和回答准确率(最终答案对不对)。定位到是哪一环拖后腿,才能对症下药。

第三步:怎么自动判分——让大模型当"judge"

几十道题,每次改动都人工核对太累。一个实用的办法叫 LLM-as-judge(用大模型当裁判):让另一个大模型来判断"实际回答和标准答案意思是否一致"。它比"字符串完全相等"聪明得多——能识别"15 天"和"十五天"、"每周洗一次"和"一周清洁一次"是一个意思。

下面是一个能直接跑的极简评测脚本:

python
import os
from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="qwen-plus", api_key=os.getenv("DASHSCOPE_API_KEY"),
                   base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", temperature=0)

def my_bot(question: str) -> str:
    """这里换成你真实的 RAG 链 / Agent。演示先随便返回。"""
    return "..."

def judge(question: str, expected: str, actual: str) -> bool:
    """让大模型判断实际回答是否与标准答案一致,返回 True/False"""
    verdict = model.invoke(
        f"问题:{question}\n"
        f"标准答案:{expected}\n"
        f"实际回答:{actual}\n"
        f"实际回答在意思上是否与标准答案一致?只回答一个字:是 或 否。"
    ).content
    return "" in verdict

# 跑整个评测集,统计准确率
correct = 0
for item in test_set:
    actual = my_bot(item["question"])
    ok = judge(item["question"], item["expected"], actual)
    print(("" if ok else ""), item["question"], "", actual)
    correct += ok

print(f"\n准确率:{correct}/{len(test_set)} = {correct / len(test_set):.0%}")

my_bot 换成你真实的问答链,每次改完提示词或换了检索策略,就跑一遍这个脚本,得分一目了然。从"我感觉"升级到"数字说话",这一步是工程化的分水岭。

进阶:现成的评估工具

自己写脚本适合入门、看清原理。真做大了,有更专业的现成工具,帮你把评估做得更细、更省事。最常用的是 RAGAS 和 LangSmith,下面分别说清楚它们各是干嘛的。

RAGAS:专门给 RAG 打分的"体检仪"

RAGAS 是一个专门评估 RAG 系统的框架。它最大的价值,是把我们前面说的"检索和回答要分开评"做成了一套现成的标准指标——你不用自己费劲设计怎么打分,直接调用它内置的指标即可。而且很多指标是用大模型来判断的(本质就是更专业版的 LLM-as-judge)。

它的指标正好对应 RAG 的两个环节,挑最常用的四个用大白话解释:

评"回答"这一环的两个指标:

  • 忠实度(Faithfulness):回答里的每句话,是不是都能在检索到的资料里找到依据,有没有"资料没提、它自己编的"。这是专门用来抓"一本正经胡说八道"的指标。举例:资料只说"保修一年",回答却说"保修一年,且可免费延保"——后半句在资料里查无此据,忠实度就低。
  • 答案相关性(Answer/Response Relevancy):回答有没有切题、有没有答非所问或东拉西扯。用户问"保修多久",你回答"我们的产品质量很好、深受好评"——是句好话,但没回答问题,相关性就低。

评"检索"这一环的两个指标:

  • 上下文精确度(Context Precision):检索回来的一堆资料里,真正相关的有没有排在前面,还是掺了一堆不相干的"垃圾"在前头。它衡量的是检索结果干不干净、排序好不好
  • 上下文召回率(Context Recall):回答问题需要的资料,是不是都被检索到了,有没有漏掉关键的那几段。它衡量的是检索全不全

有了这四个,你就能精确定位问题:忠实度低 → 模型爱编,去收紧提示词;召回率低 → 该找的没找到,回去优化检索(上两篇的召回、混合、重排);精确度低 → 找回来一堆噪音,考虑加重排序。它把"到底哪一环拖后腿"量化得清清楚楚。

用起来的套路是:准备一批数据,每条包含「问题、系统的回答、检索到的资料、标准答案」这几样,喂给 RAGAS,它逐条用大模型打分,最后给出每个指标的平均分。(注意有的指标需要"标准答案"、有的不需要;具体调用方式各版本略有差异,以官方文档为准。)你的数据大致长这样:

python
# 喂给 RAGAS 的一条评估数据大概是这个形状
sample = {
    "question": "保修期多久?",
    "answer": "本产品保修一年。",                    # 你的系统给出的回答
    "contexts": ["……保修政策:自购买之日起保修 12 个月……"],  # 检索到的资料
    "ground_truth": "保修一年",                      # 标准答案(部分指标需要)
}

LangSmith:评估 + 追踪的"一体化工作台"

LangSmith 是 LangChain 官方的平台(注意它是个平台/网站,不是一个装在代码里的库)。在评估这件事上,它把零散的环节整合成了一套顺手的工作流:

  • 数据集管理:把你的评测集存在平台上统一管理,还能把线上真实出问题的 case 一键加进评测集——正好呼应下一篇说的"用真实反馈反哺评测集"。
  • 批量跑分(Experiments):一次性把整个评测集跑一遍,判分方式既可以用它内置的评估器,也可以自定义(包括我们上面那种 LLM-as-judge)。
  • 结果对比:这是它最实用的地方——把"改动前"和"改动后"两次跑分并排对比,哪些题变好了、哪些反而改坏了,一目了然。这正是本篇开头说的"别拆东墙补西墙"的最佳落地。
  • 和追踪打通:某道题答错了,直接点进去就能看到它这次运行的完整链路(检索了啥、调了啥工具、哪步慢),排查起来特别快。这部分正是下一篇《可观测与成本》的主角。

一句话概括两者:RAGAS 侧重"给 RAG 一套现成、细致的评分指标",LangSmith 侧重"把评测集、跑分、对比、追踪整合成一个团队协作的平台"。 实际项目里两者常一起用——用 RAGAS 的指标,在 LangSmith 上管理和对比。

不管用哪个,内核思想都和我们手写的那套一模一样:一批带标准答案的题 + 一套自动判分的方法。先把原理吃透,再上工具就是水到渠成。

Node 侧:LangSmith 是平台,Node 应用照样能接入(管理评测集、跑实验、上报追踪)。RAGAS 目前主要在 Python 生态;Node 项目要评估 RAG,一般走 LangSmith,或用本文前面"LLM-as-judge"的思路自己实现同样的指标逻辑。

小结

这一篇的核心就一件事:给你的 Agent 建一把"尺子"。 攒一个带标准答案的评测集、RAG 要分开评检索和回答、用 LLM-as-judge 自动判分,每次改动都跑一遍看得分涨跌。有了它,优化才不再是拆东墙补西墙,而是稳步向前。

有了衡量好坏的能力,下一篇我们看怎么在线上盯住它:每一步在干嘛、慢在哪、花了多少钱——可观测与成本