别再凭感觉调 Prompt 了:LLM 应用 Evals 工程实战

上周一,我们的客服机器人在一次 prompt 迭代后,对"我要退款"这类意图的识别率从 91% 悄悄跌到了 74%,整整三天没人发现。发现的方式也很难看——用户投诉量翻了一倍。
这不是个例。"改一处崩另一处"几乎是每个做 LLM 应用的团队都踩过的坑。问题根源不是 prompt 写得差,而是缺乏量化的质量反馈闭环。当你只靠"手动跑几个例子看看感觉"来验证 prompt 改动时,回归问题根本没有防线。
这篇文章讲的就是怎么建这道防线——从零搭一套 LLM Evals 体系,让 prompt 和 agent 的每次迭代都有数据说话。
---
为什么你的 AI 应用需要 Evals
传统软件的质量保障靠单元测试:给定输入,断言输出精确匹配。LLM 的输出是概率性文本,这套逻辑直接失效。
三个最常见的痛点:
迭代没有量化反馈。 改完 prompt 之后你怎么知道变好了还是变差了?靠直觉看几条输出,样本偏差极大。当你的 agent 有 20 个子能力时,改动 system prompt 的某一段可能悄悄影响另外 5 个。
回归风险没有监控。 某次 model 版本升级,或者 retrieval 召回策略调整,都可能在你毫不知情的情况下破坏已有能力。没有 eval 基线,这些漂移是隐形的。
上线后质量无法追踪。 生产环境的用户意图分布会随时间变化,一个三个月前表现良好的 agent 可能已经悄悄退化,而你的 dashboard 里只有业务指标,没有 AI 质量指标。
---
Evals 的四个核心组件
一个可运行的 evals 系统由以下几部分组成:
1. 评测数据集(Golden Set)
Golden set 是你最重要的资产,也是最难建的一步。它由若干条 (input, expected_output) 对组成,覆盖主要功能路径和边界情况。
实践建议:
- 初始 50-100 条即可启动,不要等"足够大"再开始
- 从真实用户输入中采样,而非全靠工程师手写(后者分布偏窄)
- 每次发现线上 bad case,第一时间加入 golden set(让它随错误记录成长)
- 包含"反例":你的 agent 应该拒绝或不应该回答的输入
2. 评分方法
评分方法按确定性从高到低分为三类:
确定性评分适合有标准答案的场景:
- Exact match:输出必须完全等于预期字符串(适合分类标签、结构化字段)
- 正则匹配:输出包含某个模式(适合格式校验,如"回答必须包含价格")
- JSON Schema 校验:agent 输出的 JSON 必须符合指定 schema(适合 function calling 的结构化输出)
基于规则的评分适合有明确约束但形式灵活的场景:
- 长度约束(回答字数在某范围内)
- 关键词包含/排除(回答必须/不能提及竞品名称)
- 工具调用序列是否符合预期
LLM-as-judge适合开放性输出:用一个能力更强的模型(通常是同系列旗舰版)来打分,提供 rubric(评分准则)让它按标准判断。这是目前处理"有用性"、"事实准确性"、"语气是否合适"等主观维度的主流方法。
3. 回归基线
每次迭代前先跑一遍 eval,记录当前分数为基线。之后每次改动后再跑,对比分数变化。
关键原则:不允许任何改动在没有 eval 对比的情况下合并进主分支。 就像写代码必须过 CI,改 prompt 也必须过 eval CI。
4. CI 集成
把 eval runner 加进 CI pipeline(GitHub Actions 或其他),每次 PR 自动跑,分数低于阈值就 block merge。这是从"有 eval"到"eval 真的保护你"的最后一公里。
---
真实工具生态
以下四个工具都经过核实,给出的 URL 为真实官方文档地址。
promptfoo
官网:https://www.promptfoo.dev,文档:https://www.promptfoo.dev/docs
开源,本地运行,用 YAML 配置文件描述整个 eval。最适合"我想先快速跑起来"的团队。支持 exact-match、正则、JSON schema、llm-rubric(LLM 打分)等多种 assertion 类型,支持 prompt × model × test case 的矩阵对比。
Braintrust
官网:https://www.braintrust.dev,文档:https://www.braintrust.dev/docs
托管平台,侧重实验管理和生产监控。核心概念是 Experiment:每次运行生成一个快照,可以在 UI 里对比两次实验的分数变化,也可以对生产 traces 做 online evaluation(实时评分上线后的每条 LLM 调用)。有 Python/TypeScript SDK。
DeepEval
官网:https://deepeval.com,文档:https://deepeval.com/docs
开源框架,Pytest 风格的 API,可以直接 assert LLM 输出。内置 50+ 指标,覆盖 RAG、agent tool-use、对话质量、安全性等维度。本地跑,可选接入 Confident AI 平台做团队级结果共享。
LangSmith
官网:https://www.langchain.com/evaluation,文档:https://docs.langchain.com/langsmith/evaluation
LangChain 团队出品,不限框架(Anthropic SDK、OpenAI SDK 都可接入)。强项是 tracing 与 eval 的深度结合:可以直接从生产 traces 里采样标注,构建 golden set,再反过来跑 eval。annotation queue 机制适合有人工评分需求的团队。
---
一个可落地的最小工作流(基于 promptfoo)
下面是一个真实可运行的示例。场景:对一个客服 agent 的意图识别模块做 eval。
安装:
npm install -g promptfoo
**配置文件 promptfooconfig.yaml:**
prompts:- label: intent-classifierraw: |你是一个客服意图分类器。根据用户消息,从以下类别中选择一个返回:退款、查快递、修改订单、产品咨询、其他只返回类别名,不要解释。用户消息:{{user_message}}providers:- id: openai:gpt-4o-minitests:- vars:user_message: "我的包裹三天了还没到"assert:- type: equalsvalue: 查快递- vars:user_message: "我不想要了,钱退给我"assert:- type: equalsvalue: 退款- vars:user_message: "帮我把收货地址改一下"assert:- type: equalsvalue: 修改订单- vars:user_message: "这款产品适合多大年龄的孩子?"assert:- type: llm-rubricvalue: "回答必须是'产品咨询',不能包含其他类别名称"
运行:
# 跑一遍 eval,结果写入本地,可生成 HTML 报告
promptfoo eval# 改了 prompt 想绕过缓存强制重跑时
promptfoo eval --no-cache
输出会显示每条 test case 的 pass/fail 状态和整体通过率。把这个命令加进 GitHub Actions 的 PR check,就完成了最基本的 eval CI。
---
LLM-as-judge 的三个坑

用 LLM 来打分很方便,但如果对其局限性没有清醒认识,结果会比不用更糟。
坑 1:位置偏差(Position Bias)
当你做 pairwise 比较(让模型选 A 更好还是 B 更好)时,模型有强烈倾向选择排在第一位的答案。IJCNLP 2025 的一项系统性研究(论文链接)分析了 15 个 judge 模型和约 15 万条评测实例,发现这种偏差在不同任务间显著不同,且并非随机噪声。
缓解方法: 对同一对答案做两次评测,交换 A/B 顺序,只有两次结论一致才算有效判断。
坑 2:自我偏好(Self-Preference Bias)
研究表明,用某家公司的旗舰模型打分时,它倾向于给同系列/同风格的输出更高评分。模型规模越大,这种偏好往往越强。
缓解方法: 不要用单一模型做 judge,至少交叉验证两个来自不同公司的模型。
坑 3:打分不稳定(Score Instability)
同一个 prompt 多次调用,LLM judge 给出的分数可能有 ±0.5~1 分的随机波动(5 分制下)。单次评分结论的置信度很低。
缓解方法:
- 固定 rubric:提供非常具体的评分标准("4 分 = 答案完整且包含步骤,3 分 = 答案完整但缺少步骤"),不要只说"打一个 1-5 分"
- 多次采样取均值(3~5 次)
- 对相对重要的决策,用 pairwise 比较代替绝对打分("A 和 B 哪个更好"通常比"给 A 打几分"更稳定)
---
建立 Evals 的节奏
一个可持续的 eval 工作流不是一次性的工程建设,而是嵌入开发节奏的习惯:
- 每次 prompt 变更,先跑 eval,再提 PR
- 每次线上发现 bad case,当天加进 golden set
- 每次 model 版本升级,先在 staging 跑完整 eval,再切流量
- 每月审视 eval 覆盖率:哪些功能路径还没有测试用例?
刚开始时 golden set 只有 30 条也没关系。关键是把这个反馈闭环跑通,让团队建立"改东西先看数据"的肌肉记忆,而不是靠感觉。
---
参考资料
[1] promptfoo 官方文档 — 配置与断言类型:https://www.promptfoo.dev/docs/configuration/reference/
[2] Braintrust — LLM Evaluation 实践指南:https://www.braintrust.dev/articles/llm-evaluation-guide
[3] DeepEval 入门文档:https://deepeval.com/docs/getting-started
[4] "Judging the Judges: A Systematic Study of Position Bias in LLM-as-a-Judge"(IJCNLP 2025):https://aclanthology.org/2025.ijcnlp-long.18/
[5] LangSmith Evaluation 文档:https://docs.langchain.com/langsmith/evaluation
