Agent评测框架调研报告
发布于
我站在什刹海边 一切甜蜜与我无关
Agent 评测框架调研报告
面向有 Agent 开发经验、但第一次系统了解评测框架的程序员
摘要
Agent 评测要解决的不是“能不能跑通”,而是三个问题:同一批任务换了 Prompt、模型或代码之后是否真的变好了;任务失败时问题出在最终回答、工具调用、执行路径还是运行成本;成功和失败案例能否沉淀为下一轮可重复运行的数据。
常见工具可以先按评测入口理解:
- 代码驱动的评测入口:把 Agent、测试样本和评测逻辑放在代码仓库附近,修改代码后本地或在 CI 中运行一批任务,再查看分数和回归结果。DeepEval 是典型代表,Ragas 也更接近这一入口。
- 运行数据驱动的评测入口:先记录 Agent 的运行过程,再围绕 Trace 调试、沉淀数据集、运行实验和比较版本。Langfuse 是典型代表,LangSmith 和 Phoenix 也为类似的平台型工作流。
这里的划分描述的是默认使用入口,不是能力边界。两类工具都在向对方扩展能力;真正影响日常体验的,是评测从哪里启动、数据在哪里流转,以及失败后能否快速回到执行过程。

1. 先把 Agent 评测对象说清楚
普通模型调用通常只有一进一出:
问题 → 模型 → 答案
Agent 会规划、选择工具、读取外部信息,并可能多次调用模型:
用户任务 → 理解任务 → 选择工具 → 调用工具 → 读取结果 → 继续规划 → 输出答案或执行动作
所以一次 Agent 任务至少要看四件事:
| 评测对象 | 需要回答的问题 | 常见证据 |
|---|---|---|
| 任务结果 | 最终答案或动作是否满足目标 | 最终回答、结构化结果、状态变化 |
| 工具行为 | 工具、参数和调用顺序是否正确 | 工具名、参数、调用顺序、错误码 |
| 执行过程 | 是否出现重复、绕路或异常步骤 | Trace、模型调用、重试、异常 |
| 运行代价 | 延迟、Token、费用和失败率是否可接受 | 时间、Token、成本、成功率 |

一个分数只能告诉我们“哪里变差了”,过程记录才能帮助回答“为什么变差了”。两种评测入口最终都会用到 Dataset、Run、Evaluator 和 Score,只是把哪个对象放在中心不同。
2. 两种评测入口
2.1 代码驱动的评测入口
典型代表:DeepEval
这类入口从测试样本开始。Agent 代码、评测逻辑和数据集通常与代码仓库一起维护,运行方式接近集成测试:
Dataset → 运行当前版本 Agent → Evaluator / Metric → Score → CI 回归检查
它最适合回答:
我改了 Prompt、工具描述或路由逻辑,当前代码版本是否比上一版更好?
它的优势是启动快、版本关系清楚、容易放进本地命令或 CI。它的主要入口是测试代码和测试报告,因此复杂执行过程的长期浏览、线上案例沉淀和团队共享,通常需要额外的平台能力。
2.2 运行数据驱动的评测入口
典型代表:Langfuse
这类入口从一次真实运行开始。Agent 可以继续运行在本地、测试环境或线上,平台只负责接收 Trace 和结果,再提供查询、评分、数据集和实验能力:
Agent 运行 → Trace / Result 进入平台 → 定位问题 → 沉淀 Dataset → Experiment → 比较版本
它最适合回答:
这次任务每一步发生了什么?哪些真实案例值得加入下一轮回归?
它的优势是能把最终结果和执行证据放在一起,便于调试、协作和持续积累。代价是需要接入 Trace、维护平台工作区,并考虑数据存储、隐私和运行成本。
两种入口的差异可以压缩成一句话:
代码驱动的入口先定义“要测什么”;运行数据驱动的入口先保留“实际发生了什么”。
| 对比维度 | 代码驱动的评测入口 | 运行数据驱动的评测入口 |
|---|---|---|
| 默认起点 | 测试样本、测试文件或 CI | Agent 的一次运行和 Trace |
| 核心对象 | Test Case、Metric、Score | Trace、Dataset、Experiment |
| 主要动作 | 重跑同一批任务,检查回归 | 查看过程、沉淀案例、比较实验 |
| 典型价值 | 发布前回归门禁 | 失败诊断和持续数据积累 |
| 常见落点 | Git 仓库、本地环境、CI | 平台工作区、Trace 和实验记录 |
两类入口不是互斥选择。实际工程中,代码驱动的入口适合发布前回归,运行数据驱动的入口适合失败诊断和持续积累。
3. 代码驱动的入口:DeepEval
3.1 先准备一次可评测的 Test Case
DeepEval 的基本单位是 Test Case。它把一次 Agent 交互需要的输入、实际结果、预期结果和过程信息放在一起,供不同 Metric 使用。
| 字段 | 含义 | 例子 |
|---|---|---|
| `input` | Agent 收到的任务 | 查询北京明天天气 |
| `actual_output` | Agent 实际返回 | 明天降雨概率 80%,建议带伞 |
| `expected_output` | 可选的参考结果 | 应给出正确的天气建议 |
| `tools_called` | 实际调用的工具 | `weather` |
| `expected_tools` | 可选的预期工具 | `weather(city=北京, date=明天)` |
| `retrieval_context` | 可选的检索内容 | 检索到的天气信息 |
| `token_cost / time` | 运行成本和耗时 | 1,240 tokens、2.8s |
Test Case 不是只保存最终答案;需要哪些字段,取决于这次评测想检查什么。不同字段对应不同的评测问题:
| 想检查的问题 | 主要使用的数据 |
|---|---|
| 最终回答是否正确 | `input`、`actual_output`、`expected_output` |
| 工具是否调用正确 | `tools_called`、`expected_tools` |
| 检索内容是否支持回答 | `actual_output`、`retrieval_context` |
| 运行成本是否达标 | `token_cost`、`time` |
如果评测只关心最终结果,可以先从输入、实际输出和参考结果开始;涉及工具、RAG 或运行成本时,再补充对应字段。Test Case 的作用,是把一次交互整理成可重复评测的数据。

3.2 从 Agent 运行记录到 Metric 分数
- Test Case 解决“评测数据从哪里来”
- Metric 解决“按什么标准判断”
DeepEval 不会自动得到 Agent 调用了哪些工具。实际项目中,工具调用和最终回答通常来自 Agent 框架的回调、Trace、日志或运行代码,再整理为
LLMTestCase和ToolCall。
Metric 可以使用确定性规则、参考答案比较或模型评审。它最终输出分数、是否通过以及失败原因。

3.3 不同评测范围,回答不同问题
当 Test Case 准备好之后,还要决定评测观察到哪一层。DeepEval 通常可以从端到端、轨迹和组件三个范围观察同一个 Agent:
| 评测范围 | 主要问题 | 典型数据或对象 |
|---|---|---|
| 端到端 | 整个任务是否完成 | 输入、最终输出、目标 |
| 轨迹 | 决策和动作链路是否合理 | 工具调用、步骤顺序、模型调用 |
| 组件级 | 某个工具、检索器或模型调用是否可靠 | 单个组件的输入、输出和指标 |

评测范围决定“看哪一层”,Metric 决定“用什么标准判断”。同一个 Agent 可以同时有端到端结果、轨迹结果和组件级结果,不必压缩成一个总分。这些范围可以组合使用,也不代表严格的对象包含关系。
3.4 运行评测并检查回归
Test Case 和评测范围确定后,就可以运行当前版本的 Agent,收集实际输出和过程信息,再应用 Metric 生成分数或通过状态:
准备 Test Case → 运行当前 Agent → 收集回答与工具轨迹 → 应用 Metric → 查看分数和失败样本
最自然的回归循环是:
改代码 → 跑 benchmark → 看回归 → 决定是否合入
不同评测方式适合检查不同内容:
| 评测方式 | 适合检查的内容 |
|---|---|
| 确定性规则 | 工具名、参数、状态码、步骤数 |
| 参考答案比较 | 结构化结果、固定字段、标准答案 |
| LLM Judge | 答案质量、目标完成度、轨迹合理性 |
| 人工评审 | 复杂任务和边界案例 |
DeepEval 适合快速建立最小 benchmark、版本化评测逻辑、接入 pytest 或 CI,并用自定义规则检查工具名、参数、调用次数和结构化结果。下面用同一条任务展示一次真实运行:先让错误样本失败,再修复 Agent,最后重跑并检查回归。

4. 运行数据驱动的入口:Langfuse
Langfuse 的基本工作方式,是先把 Agent 的真实运行记录下来,再围绕这些运行记录进行调试、评分、数据集沉淀和版本比较。
因此它通常先回答:
这次 Agent 执行过程中,每一步发生了什么?
在掌握执行过程之后,再进一步回答:
这次运行是否满足目标?新的版本是否有所改进?
4.1 先记录一次可分析的 Agent 运行
Langfuse 的评测基础不是一条孤立的最终答案,而是一条包含执行过程的 Trace。Agent 每完成一个重要步骤,就把对应的输入、输出和状态记录下来。 一次天气查询可以被记录为:
Trace: 查询北京明天天气
├── Agent:理解用户意图
├── Generation:决定调用 weather
├── Tool:weather(city=北京, date=明天)
├── Generation:解释工具结果
└── Final Answer:给出是否带伞的建议
| Langfuse 对象 | 在这条运行中的作用 |
|---|---|
| Trace | 表示一次完整的 Agent 任务 |
| Observation | 表示任务中的一个执行步骤 |
| Generation | 表示模型生成或模型调用 |
| Span / Tool | 表示工具调用或普通程序步骤 |
| Score | 表示对结果或过程的评价 |
Langfuse 的重点不是只保存“Agent 最后说了什么”,而是把最终结果和产生结果的过程放在同一条运行记录中。

4.2 Evaluator 如何读取 Trace 并生成 Score
Trace 记录 Agent 实际发生了什么,Evaluator 定义如何判断这次运行,Score 保存判断结果。三者分别承担“证据、判断和结果”的职责。
Evaluator 是一个独立的评测单元。它可以针对某类运行被配置和执行,也可以对一批 Trace 逐条评估。每执行一次,Langfuse 都会记录这次评测的状态、分数和解释。
Agent 运行
↓
Trace 记录回答、工具调用和执行步骤
↓
Evaluator 读取 Trace
↓
Evaluator Run 执行判断
↓
Score + Comment 写回平台
工具调用需要由 Agent 运行时通过 SDK、OpenTelemetry 或框架集成写入 Trace。Evaluator 再读取工具名、参数、工具结果和最终回答,根据预先设定的评测标准进行判断。

Evaluator 可以采用不同的评测方式:
| Evaluator 类型 | 适合判断的问题 | 输出形式 |
|---|---|---|
| 代码规则 | 工具名、参数、JSON、状态码是否正确 | 通过 / 失败,或 0 / 1 |
| LLM-as-a-Judge | 回答质量、完整性、相关性、任务完成度 | 连续分数 + 解释 |
| 人工评审 | 复杂案例、边界情况和有争议的结果 | 人工分数 + 备注 |
| 外部评测器 | 业务系统或其他评测平台提供的结果 | 外部评分写回 Langfuse |
因此,Langfuse 中的一次评测可以概括为:Trace 提供证据,Evaluator 执行判断,Evaluator Run 记录执行过程,Score 保存结果。相同的 Evaluator 既可以用于单条运行,也可以用于批量 Trace 和 Dataset Experiment。
4.3 从真实运行到 Dataset 和 Experiment
单次 Trace 适合回答“这次为什么失败”,但无法稳定回答“新版本是否整体变好了”。Langfuse 因此允许把真实运行中的任务沉淀为 Dataset Item,再用同一批任务运行不同版本的 Agent。

Dataset Item 可以保存用户输入、预期结果、关键约束和必要的元数据,作为之后重跑的任务样本。后续运行产生的新 Trace 则记录这一版本实际采用的工具、步骤和最终结果。
可以把三个对象理解为:Dataset 固定“要做什么”,Trace 记录“实际怎么做”,Experiment 比较“不同版本做得怎么样”。
4.4 运行实验、比较版本并理解边界
Dataset 和评测标准确定后,就可以让不同版本的 Agent 运行同一批任务。每一次实验都会产生新的 Trace 和 Score,平台再把这些结果汇总到一起,帮助比较 Prompt、模型、检索策略或代码版本的变化。
固定 Dataset
↓
运行版本 A
↓
运行版本 B
↓
分别记录 Trace 和 Score
↓
比较成功率、工具正确性、质量、延迟和成本
Langfuse 更适合查看复杂执行过程、持续沉淀真实案例、多人共享评测结果,以及比较实验版本。它需要额外配置 Trace 接入、数据存储和平台工作区,也要考虑运行数据的隐私和长期成本。
Agent 可以继续运行在本地、测试环境或线上服务中,Langfuse 通过 SDK、OpenTelemetry 或框架集成接收运行记录。它不要求 Agent 必须由 Langfuse 启动,关键是 Agent 能够把运行过程和结果写入平台。对于只有几十条样本、主要用于发布前回归的早期 benchmark,代码驱动的评测入口通常更轻量。
5. 其他框架如何放在同一张图里
| 框架 | 更自然的使用入口 | 主要特点 | 适合优先关注的问题 |
|---|---|---|---|
| DeepEval | 代码驱动 | Test Case、指标、pytest / CI | 修改代码后是否回归 |
| Ragas | 代码驱动 | RAG 指标和实验比较 | 检索内容是否有用、回答是否有依据 |
| Langfuse | 运行数据驱动 | Trace、Dataset、Experiment | 失败过程如何定位、案例如何沉淀 |
| LangSmith | 运行数据驱动 | Trace、Dataset、Evaluation,LangChain / LangGraph 生态结合紧密 | 生态内的调试和评测协作 |
| Phoenix | 运行数据驱动 | OpenTelemetry / OpenInference、开源和自托管 | 标准化 Trace 和可观测性 |
6. 实际使用时,差异主要体现在哪里
这一节作为例会演示的路线。前面的章节已经解释了两类入口和各自的核心对象,这里只说明现场应该按什么顺序操作、每一步让听众看到什么,以及需要准备哪些截图。
演示可以使用同一个天气查询任务,让两种入口形成对照:DeepEval 展示如何从测试代码得到回归结果;Langfuse 展示如何从一次真实运行进入 Trace、Evaluator 和 Experiment。
6.1 DeepEval:从测试代码到回归结果
DeepEval 的演示从代码仓库中的 Dataset 和评测脚本开始,完整展示一次“准备数据、定义评分器、运行 Agent、执行评测、查看结果”的路径。它和 Langfuse 的演示步骤对应,但每一步都通过代码和命令完成。
第一步:准备 Dataset
DeepEval 的 Dataset 由代码文件维护。本次 Demo 使用 dataset.json 保存 4 个天气 Case,每个 Case 包含用户问题、期望调用的工具参数以及对最终回答的要求。

这一步固定的是“要评测哪些任务”。和 Langfuse Dataset Item 存在平台中不同,DeepEval 的 Dataset 通常就是仓库里的 JSON、Python 列表或测试数据文件。
第二步:定义评分器
准备好 Dataset 后,在评测脚本中定义如何判断 Agent 的表现。本次 Demo 使用两个评分器:ToolCorrectnessMetric 检查工具名称和参数,GEval 使用 LLM-as-a-Judge 评估回答是否正确使用天气结果,并给出合理的出行建议。

这里的 Metric 承担和 Langfuse Evaluator 类似的职责:它定义“按照什么标准判断”。不同之处在于,DeepEval 的 Metric 直接写在评测代码附近。
第三步:运行 Agent
评分之前,先让每个 Case 真实运行一次 Agent。模型根据用户问题决定是否调用 get_weather,工具访问 Open-Meteo 获取天气数据,Agent 再根据工具结果生成最终回答。

这一步产生后续评测需要的证据:实际回答、实际工具名、工具参数以及工具返回的天气结果。
第四步:执行评分器
Agent 运行完成后,DeepEval 将每次运行整理为 LLMTestCase,再把实际工具调用转换为 ToolCall,交给两个 Metric 执行评测。

这里体现了代码驱动入口的特点:评测从测试脚本启动,多个 Case 按照同一组 Metric 执行,不需要先在平台中创建实验。
第五步:查看分数和评测原因
评测完成后,DeepEval 输出每个 Metric 的分数、阈值、通过状态和原因,同时汇总整体通过率。

如果修改 Agent 的 Prompt、工具定义或路由逻辑,只需要重新运行同一个评测脚本,就可以比较修改前后的结果。这就是 DeepEval 中“测试代码 → Metric → Score → 回归检查”的闭环。
这组截图串起了 DeepEval 的完整使用路径:Dataset 固定评测任务,Metric 定义评分标准,Agent 产生运行证据,评测器计算分数,最终输出每条 Case 的结果和整体通过率。
6.2 Langfuse:从一次运行到评测实验
第一步:准备 Dataset
Langfuse 可以把真实运行中的代表性案例整理成 Dataset。每个 Dataset Item 保存之后需要重复运行的任务输入、预期输出和相关元数据。

这一步固定的是“之后要做什么”。同一批 Dataset Item 可以被不同版本的 Agent 反复运行,从而让后续比较具有可比性。
第二步:配置 Evaluator
Dataset 确定后,需要配置 Evaluator 来判断 Agent 的输出质量。截图中的 Evaluator 使用 LLM-as-a-Judge:它接收诊断请求和待评估的诊断报告,按照结论明确性、证据充分性、逻辑一致性、置信度合理性、可操作性以及完整性与规范性等维度进行评分,并输出 0 到 1 的分数。

第三步:运行一次 Experiment
在 Dataset 页面启动 Experiment 时,Langfuse 提供两种运行方式:通过用户界面配置 Prompt 或模型,也可以通过 SDK / API 接入已有代码,执行自定义评测逻辑。本次演示通过 Experiment 运行同一批 Dataset Item。

启动后,每个 Dataset Item 会产生一次实验运行。Agent 的输出和执行过程会继续写入 Trace,Evaluator 则根据配置对这些结果进行评分。
第四步:查看 Experiment 运行结果
Experiment 运行完成后,可以查看每条 Dataset Item 对应的 Trace、延迟、成本和 Evaluator 分数。截图中每一行对应一个样本,评测结果会和 Trace 入口放在同一张结果表中。

如果某条样本得分较低,可以从结果表进入对应 Trace,查看模型调用、工具调用、最终输出和评测评论,定位分数下降的原因。
第五步:比较多次 Experiment
当 Agent、Prompt 或模型发生变化后,可以再次运行同一 Dataset。Langfuse 会把多次 Experiment 放在一起,比较平均分数、延迟和成本等结果。

7. 怎么选择评测入口

可以先按工作问题选择入口,再选择具体工具:
| 当前最关心的问题 | 更自然的起点 | 选择原因 |
|---|---|---|
| 改代码后快速跑一批任务 | DeepEval | 测试和当前代码版本放在一起,容易接入 CI |
| 主要研究 RAG 和检索指标 | Ragas | 指标和实验比较更集中 |
| 需要查看 Agent 的完整执行路径 | Langfuse、Phoenix、LangSmith | Trace 是默认工作对象 |
| 已经使用 LangChain / LangGraph | LangSmith | 生态和运行记录结合更紧 |
| 希望自托管并使用 OpenTelemetry | Phoenix 或 Langfuse | 更适合围绕标准 Trace 建设 |
| 希望从真实运行反哺测试集 | Langfuse、LangSmith、Phoenix | Dataset 和 Trace 之间的流转更自然 |
建议的最小落地路径
收集一批真实任务
↓
固定输入、预期结果和关键工具行为
↓
先建立最终结果、工具行为和运行代价三类指标
↓
接入本地回归或 CI
↓
为运行保留 Trace,持续收集失败样本
↓
根据调试、协作和线上观测需求决定是否平台化
8. 结论
选择 Agent 评测框架时,先看团队的主要工作方式:
- 如果首要任务是让 benchmark 可重复运行、进入 CI 并检查回归,优先考虑代码驱动的评测入口;
- 如果首要任务是理解复杂 Agent 为什么失败,并持续积累真实案例,优先考虑运行数据驱动的评测入口;
- 如果两类需求同时存在,可以让前者负责发布前门禁,让后者负责线上诊断、数据集沉淀和持续实验。
第一阶段不必一次解决所有评测问题。先固定一批真实任务,明确最终结果和关键工具行为,再逐步补充 Trace、LLM Judge、人工评审和平台协作能力。评测框架负责把流程执行起来,指标定义、样本覆盖和评测稳定性仍然需要单独验证。
参考资料
- DeepEval Evaluation Introduction
- DeepEval LLM Test Case
- Ragas Experiments
- Langfuse Evaluation Overview
- Langfuse Datasets
- Langfuse Evaluate with Datasets
- Phoenix
- LangSmith