评估

你改了个提示词,试了一次,答案看起来更好了,然后你发布了。一周后用户撞上了它悄悄变糟的情况。评估(evaluation 的简称)就是解决方案:对你的 AI 功能是否有效的可重复测试,一组输入配上好的输出应该是什么样子,每次都用同样的方式评分,这样你就能知道一个改变是否真的有帮助。模型是一个概率黑箱,每次运行时对同一个问题的回答都不一样,所以测量是唯一的办法,这种纪律感是把演示和产品区分开来的很大一部分。
为什么凭眼感判断失败
手工检查你的 AI 的答案一开始感觉还不错。你运行一个提示词,读取回复,看起来不错,然后继续。问题在于有三件事悄悄地对你不利,而你已经经历过所有这些。
这三件事是:
- 输出会变化。 同一个提示词可以在每次运行时给出不同的答案,所以一个好的结果不能保证下一次也会好。
- 改变会导致回退。 一个修复一个情况的提示词编辑经常会破坏你没有看到的另一个情况。
- 它无法扩展。 你可以读五个答案。但每次你改一行时,你无法读五百个。
这些都不意味着你做错了什么。这意味着凭眼感判断是一个这么大的任务的错误的工具,有一个更平静的方式来做这件事。
构建一个评估集
一个评估集是一个测试用例的列表。每个用例有一个输入和对它什么是好输出的说明。从小开始。十到二十个覆盖你的常见情况加上几个诡异边界情况的用例比没有远有用得多,而且你可以在发现野外的新失败时扩展这个集合。
# 评估集:输入和预期的标签
eval_set = [
{"input": "食物很冷,送到得很晚。", "expected": "NEGATIVE"},
{"input": "我人生中最好的一顿饭!", "expected": "POSITIVE"},
{"input": "还不错,没什么特别的。", "expected": "NEUTRAL"},
# ...随着你发现新的边界情况添加真实情况和边界情况
]当用户报告一个坏答案时,用它应该给出的输出将其添加到集合中。你的评估集然后成为每个你永远不想再犯的错误的不断成长的记忆,就像你修复的一个 bug 变成你保持的一个测试的方式一样。
如何评分
不同的任务需要不同的评分,所以第一步是匹配检查到你期望的答案类型。
- 精确匹配在有一个正确答案时有效:一个分类标签、一个提取的字段、一个是或否。你直接比较输出到预期值。
- 基于准则的评分在没有单一正确答案时有效,像一个摘要或一个回复。你检查输出是否满足条件:摘要是否提到了关键事实?它是否在 50 字以下?语气是否礼貌?
- LLM-as-judge 使用第二个模型调用来对你的准则针对输出评分。它扩展到简单检查无法捕获的模糊质量问题,但法官本身是一个模型,所以它可以是错的,而且你现在和然后对抗人的判断检查它。
# 在评估集上精确匹配评分
def run_evals(eval_set, classify):
# 通过的测试数
passed = 0
for test in eval_set:
output = classify(test["input"])
if output == test["expected"]:
passed += 1
else:
print(f'失败: "{test["input"]}" -> 得到 {output},期望 {test["expected"]}')
print(f"{passed}/{len(eval_set)} 通过了")精确匹配是最友好的开始地方,它适合前面章节的分类和提取工作完美。LLM-as-judge 的想法有效是因为发现一个答案是否满足一个标准通常是一个比生产答案更简单的预测,就像评阅一个文章比写一个更简单。但法官是另一个有同样缺陷的预测器,所以把它的分数作为一个有用的估计,给它一个清晰的标准,并现在和然后对你自己的样本检查它的等级。
在每次改变时运行它们
一个评估集只在你实际运行它时有用。像对待代码一样对待你的提示词:在你发布对提示词、模型或你的检索的改变之前,运行评估并比较分数到它之前是什么。如果数字下降了,你导致了回退,即使你的一个手工测试碰巧看起来不错。
这是把提示词工程从猜测变成你可以有信心迭代的东西。改变什么,测量它,保持得分更高的,丢弃得分更低的。这是让普通软件可靠的同样循环,现在应用到 AI 功能的模糊部分。
如果分数下降了,你导致了回退。一个幸运的手工测试不会推翻集合,所以每次让数字做平局决定者。
实际中
上一个部分的 run_evals 函数是一个完整的,如果小的话,评估工具。你把它指向你的分类器和你的评估集,它告诉你有多少用例通过并准确显示哪些失败:
run_evals(eval_set, classify_review)
# 失败: "还不错,没什么特别的。" -> 得到 POSITIVE,期望 NEUTRAL
# 2/3 通过了那一个失败的线值一打成功的手工测试,因为它指向一个真实的弱点你现在可以修复并重新测量。最后一章,安全和限制,在你把这些中的任何一个放在真实用户面前之前覆盖风险设计对抗。
run_evals 的小工具已经赚回它的价值:它给你一个分数和失败的精确用例。修复一个,再运行它,看数字移动。接下来,Safety and limits 覆盖在真实用户到达之前要防守对抗什么。 
