本页目录
正如我们在 上一篇文章中讨论的那样,使用 LLM 构建应用,需要从根本上改变看待软件开发的方式。你不再设计输入映射到可预测输出的确定性系统,而是在使用本质上不可预测的概率系统。
管理这种不确定性的关键工具是评测。评测就是 AI 工程师的单元测试,是从概率系统中争取可预测性的手段,也是任何 AI 应用走向生产不可或缺的一部分。
下面来拆解评测究竟是什么,以及 AI 应用为什么如此需要它。
为什么传统测试还不够?
传统软件测试依赖输入与输出之间的确定性关系,每个组件都有明确的职责范围:
但 LLM 驱动的系统不同。每个输入都会经历一个难以预测的复杂转换过程:
在 AI 系统中,没有任何改动是真正微小的。模型的注意力与转换机制难以理解;蝴蝶是“flaps”还是“Flaps”翅膀,都可能改变输出。委婉地说,使用它们构建稳健系统必须格外谨慎。
想继续深入: 加入“面向真正工程师的 AI 编码”候补名单
仅靠人工 QA 还不够
快速做出令人印象深刻的 AI 演示很容易,但让 AI 系统真正投入生产并不容易。
更具体地说,你很难判断对应用所做的改动究竟让它变好还是变坏。改完之后,用几个常用提示词试一试,看看是否“感觉”更好——这是一种危险的工作方式。
在确定性软件中,“只做人工 QA”通常还算可行。你说“我新增了一个页面”,QA 团队可以严格测试新页面,再对已有页面进行冒烟测试。
但在概率系统中,这种做法会带来致命问题。任何改动都可能影响整个系统,因此你必须有办法判断系统是在变好还是变坏。
对于更换模型或调整提示词设计等大型改动,尤其如此。
评测
关键是自动化。每次修改应用,或底层模型发生变化时,都需要重新评估应用。
传统确定性系统
在确定性系统中,自动化测试相对直接:输入一些数据,再检查输出即可。
const output = myNormalSystem(input);// Will fail if the output doesn't matchassert(output === "my-desired-output");
这些断言的结果是“通过”或“失败”。通常只有通过全部测试,应用才算具备生产条件。
概率系统
但为 AI 编写这种测试并没有那么直接。
假设应用负责生成文章,你要检查输出是否达到生产质量,可能需要针对以下方面编写断言:
- 事实准确性:检查输出中的所有陈述是否符合事实
- 写作风格:确保文本优雅且写作质量良好
- 提示词忠实度:确保输出确实回应了用户的要求。
这些都是定性指标,不能只用通过或失败表示,而需要转换成一个 score。每次修改应用,都需要知道这次改动让系统提升了 5%,还是下降了 50%。
这正是评测的作用:给出一个分数,用来观察 AI 系统表现得有多好。
三种评测
可以在 AI 系统上运行三种主要评测。
确定性评测
第一种是 确定性评测,可以写成简单断言。
const article = writeArticleWithLLM(prompt);// Article should be more than 300 words longassert(article.length >= 300);// Article should be less than 2,000 words longassert(article.length <= 2000);
它们是传统的通过/失败检查。你向系统传入各种提示词,再逐一检查输出能否通过测试。
这类评测编写简单,但只能覆盖需要评估内容的一部分。
人工评估
对于概率性更强的指标,有两种选择。
你可以使用人工评估检查系统表现是否正确。在缺少大量数据的早期阶段,这往往是唯一选择。
这种方法成本高、耗时长,但所有 AI 系统都会在某种程度上依赖人类输入。
让 LLM 担任裁判
另一种技术是把提示词执行结果传给另一个 LLM,让这个 LLM 充当裁判。这是目前非常流行的 AI 系统评估方式。
假设你想确认应用是否在讲真话,可以把系统输出和一些真实标准答案一起传给另一个 LLM。
可以在 Evalite 文档中看到实际示例。
LLM-as-a-judge 让某些评估成为可能,但也有成本。运行 LLM 很昂贵,因此需要仔细考虑评测频率。例如,每次文件变化都运行评测,成本会高得难以承受。
常见策略是把评测拆成两组:较小的一组用于本地测试,较大的一组每天运行。
如何持续改进评测?
评测是监控和改进 AI 系统的方法,因此用于评估系统的数据集至关重要。
必须确保评测数据能够代表系统在生产环境中遇到的数据。如果构建分类器,就要确保评测覆盖系统将遇到的各种边界情况。
这意味着必须在应用中内置可观测性和反馈系统。应用部署后,用户会成为系统是否有效的裁判。点赞和点踩等简单反馈按钮,就能提供极有价值的表现洞察。
数据飞轮
Vercel,也就是 v0的创造者,曾介绍过 AI 原生飞轮,说明了评测在 AI 开发过程中的重要性。
最好的评测数据来自用户。仔细监控用户如何使用应用,就能建立反馈循环,持续改进系统。来看一个例子:
- A 用户提出要求 让应用“帮我构建一个有格调的 React 应用”
- 应用 生成了一些 React 代码。但它没有让 UI 看起来“有格调”,而是在代码里使用了 class。
- 用户点踩 这个响应,甚至可能留言解释原因。
- 你拿出“帮我构建一个有格调的 React 应用”这条提示词,并为它 创建一项新评测 ,加入评测套件。
- 然后 改进系统 ,直到通过这项评测。
- 然后 re-deploy。下次用户提出同样请求时,就会得到更好的响应。
这就是数据飞轮的实际运转方式。通过仔细监控系统并建立反馈循环,可以确保系统始终在进步。
如何运行评测?
运行评测的方法很多,许多初创公司也进入了这个领域,提供运行评测并在线查看结果的工具。
Braintrust 是一个热门选择。它提供云平台来运行评测、与团队分享结果,并包含许多其他功能。你可以使用其 SDK 以 TypeScript 编写评测,不过平台会限制评测运行频率,在快速迭代时可能令人沮丧。
我维护了一个名为 Evalite的库。它是一个轻量评测运行器,建立在 TypeScript 测试运行器 Vitest 之上。.
Evalite 的设计目标是让你在本地运行评测。它不绑定云平台,因此可以随意频繁运行;如果刚刚入门,这是一个不错的选择。
评测在实践中如何工作?
可以把评测想象成一个函数:
const score = runEval({// 1. The prompts we'll test withdata: ["Fish species in the Mediterranean","Story of the first Moon landing","Are Krakens real?",],// 2. A function to generate outputs based// on our promptstask: async (topic) => {return generateArticle(topic);},// 3. The scorers we'll use to generate// the final scorescorers: [// Checks if output is long enoughlength,// Uses an LLM to check if it's accuratefactualAccuracy,// Uses an LLM to check writing stylewritingStyle,],});// 4. A score between 0-100%console.log(score);
我们传入一组提示词(1)、要运行的任务(2),以及用于给输出评分的方法(3)。
最后得到一个分数,表示函数表现如何(4)。
从本质上说,这就是评测。这个 API 大致受 Braintrust 的 autoevals 库启发。.
关键在评测,笨蛋
这张基于 Vercel AI 原生飞轮的图片,展示了评测对应用产生的影响。
评测应该位于反馈循环的中心。随着更多用户使用应用(分发),他们会带来更多数据(使用);你可以利用这些数据改进应用(数据),再重新运行评测(评测)。
这些评测让你能够应对新技术和新模型,并让系统始终走在持续改进的道路上。