ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

AI Agent评测的持续演进:从静态基准到Computer Anthology实践

AI Agent评测的持续演进:从静态基准到Computer Anthology实践 AI Agent 的能力评估正在从“单次对话是否答对”转向“多步操作是否做成事”。这就带来一个新问题传统静态 benchmark 很难跟上模型和工具持续迭代的速度。Computer Anthology 这个命名所代表的 benchmark family正是针对这个困境提出的一种解法不发布一个固定测试集而是维护一组能够不断演进、按能力域分层、支持版本回放的评测任务集合。这篇文章会围绕这类基准家族展开解释 AI Agent 评测为什么不能只靠单一数据集然后从零搭建一个最小可运行的 Agent 评测环境再讨论指标设计、任务版本化、持续演进机制以及常见排查路径。读完后你既能理解 Computer Anthology 背后的设计理念也能在自己的项目里落地一套最小可复用的 Agent 评测流程。1. AI Agent Benchmark 的演进压力为什么静态数据集不够用1.1 从“模型单次回答”到“智能体多步操作”的评估差异传统大语言模型评测通常给模型一个问题然后根据标准答案判断对错。比如阅读理解、数学计算、代码生成都属于“单次输出”类任务。评测流程非常稳定输入文本模型输出文本字符串或语义相似度判定结果。但 AI Agent 的目标不是“说出答案”而是“完成任务”。任务过程中Agent 需要理解目标、拆分步骤、选择工具、传参调用、读取返回结果、修正计划最后才给出结论。评测对象因此不再是单个输出而是完整的trajectory轨迹也就是 Agent 从开始到结束的每一步动作和中间状态。这种差异带来的核心变化是没有唯一标准答案。同一个任务可以有多条路径都能成功。不能只比对最终文本。Agent 可能没调用工具但靠环境信息“猜”对了结论。失败节点更难定位。是模型规划错了还是工具参数传错了还是环境返回格式变化了任务结果可能受随机性影响。模型采样、工具返回顺序、并行执行结果都会导致分数波动。传统评测和 Agent 评测可以这样对比对比维度传统 LLM BenchmarkAI Agent Benchmark任务形态单轮问答、代码生成、文本分类多步任务、工具调用、环境交互期望输出标准答案或固定格式完成目标允许不同路径判定方式文本匹配、语义相似度、单测轨迹检查、最终效果检查、成本检查失败模式答案错误规划错误、参数错误、工具异常、循环卡死结果稳定性较高受随机性和环境状态影响较大基准维护成本较低需要持续维护工具 mock、环境镜像、检查器传统方式无法直接迁移到 Agent 场景因为 Agent 的“正确”是过程与结果共同决定的。这也是 Computer Anthology 这类 benchmark 强调“围绕 Agent 行为设计任务”的原因。1.2 单一 Benchmark 失效的三个典型场景静态 benchmark 在 Agent 评测里非常容易失效常见的场景有三个。场景一工具 API 更新后任务立即过时。Agent 评测任务通常会绑定外部工具比如天气查询、数据库查询、网页检索。如果工具的参数结构或返回字段变了旧任务的检查器就会全部失效。比如原来天气接口返回temperature后来改成tempAgent 调用了正确的接口但评分器还在读temperature于是报错。任务没有变但评测基础设施已经过期。场景二训练数据污染导致分数虚高。模型可能见过 benchmark 里的题目和标准操作路径。它不再“推理着完成任务”而是“背出答案”。这时分数不能反映 Agent 在真实环境下的能力。静态 benchmark 一旦公开且长时间不更新污染问题会越来越严重。场景三任务多样性不足导致能力评估偏差。如果 benchmark 只覆盖网页搜索Agent 在代码执行、数据库操作、本地文件操作上的能力就被忽略了。某个 agent 在单一场景下表现很好换到真实业务场景立刻退化。单一 benchmark 很难覆盖 Agent 所需的全部能力域。Computer Anthology 这类方案采用了“家族化”结构用一组任务集而不是一个任务集来评估 Agent并且让任务本身能够持续演进。家族的意义在于不同任务覆盖不同能力版本机制保证历史结果可对比增量更新避免数据污染。1.3 “持续演进”为什么是 Agent 评测的刚需Agent 模型迭代速度快工具生态变化也快。一个 benchmark 如果半年不更新它的区分度会快速下降。持续演进意味着定期加入新任务模拟新场景。旧任务保留作为回归测试。任务标注版本保证已发布的分数有比较基准。更新记录可审计能回答“这个分数是在哪个任务集版本上跑出来的”。这更像软件工程里的测试用例库而不是一次性的考试卷。理解这一点后面的工程实现才有方向。2. Computer Anthology 基准家族的核心设计逻辑2.1 任务集按能力域分层而不是按题目类型堆叠一个合格的 Agent benchmark family不能简单地把几十个任务塞进一个目录。它应该围绕能力域组织任务。Computer Anthology 这个方向通常包含以下能力域能力域典型任务示例评估重点信息获取查询天气、搜索新闻、读取网页检索准确性、参数构造、结果解析工具调用调用 REST API、执行 SQL、操作文件工具选择、参数类型、错误处理代码执行写脚本、运行命令、修复报错代码正确性、执行结果、调试效率多轮决策订票流程、填写表单、多步排查状态管理、计划调整、目标保持安全边界拒绝越权操作、识别敏感数据合规性、权限控制、风险判断每个能力域下的任务除了有 prompt 之外还应该有元信息。任务元信息至少要包含task_id唯一标识。schema_version任务 Schema 版本方便升级。domain能力域。instruction给 Agent 的目标描述。tools允许使用的工具定义。checker判定方式。difficulty难度用于分层统计。tags标签用于筛选和组合。这样设计的好处是研究者可以只选择某个能力域的子集做测试也可以跨域聚合出综合分数。2.2 版本化和增量更新是两个关键机制版本化解决“结果可对比”的问题。每次任务更新都不应该抹掉历史任务而是标记新版本。比如weather_query_001在 v1 阶段依赖旧天气接口升级到 v2 时保留 v1 任务目录同时新建weather_query_002。这样团队可以同时运行两个版本观察新版本是否带来额外的区分度。增量更新解决“评测能力滞后”的问题。每次发布新任务就像给项目新增测试用例。任务目录是开放的新增任务不需要修改旧任务的检查器。增量更新必须配套回归机制新任务加入后要跑一遍全部旧任务确认旧能力没有下降。真正的持续演进不是“做一次更新”而是建立一套任务变更审批、验证、发布流程。比如新任务提交到candidate/目录。用两个以上 Agent 试跑确认任务可完成且不是 trivial。人工审查检查器是否公平。合并到released/目录并打上版本 tag。触发完整回归生成对比报告。2.3 设计目标要翻译成工程约束Computer Anthology 这类基准家族设计目标不是“题目多”而是“评测可信”。可信意味着可复现、可比较、可扩展。为了做到这一点工程上通常立几条约束工具环境必须 mock 或快照化避免真实服务状态干扰。检查器必须同时有正例和反例测试。正例验证任务能过反例验证错误操作过不了。每个任务必须声明资源成本上限避免 Agent 无限循环。评测结果必须保存轨迹原文方便事后定位问题。任务变更必须记录 change log方便回溯。这些约束看似繁琐但会在后面构建实验环境时体现出价值。3. 动手搭建一个最小 Agent Benchmark 评测环境3.1 环境准备与依赖下面搭建一个最小但完整的 Agent 评测实验。目的是跑通“任务定义 - Agent 运行 - 检查器判定 - 结果输出”这条链路。这里使用 Python 3.10 以上版本核心依赖是 OpenAI Python SDK 和环境变量管理。如果你使用的是其他 OpenAI 兼容服务只需要修改 base_url 和 api_key。mkdir agent-benchmark cd agent-benchmark python -m venv .venv source .venv/bin/activate pip install openai python-dotenv这里不接入真实工具服务而是用本地函数模拟天气工具。原因有两点一是评测过程要稳定本地函数没有网络抖动二是真实 API 参数变化容易让任务失效mock 工具更适合作为初版实现。3.2 任务定义JSON Schema 与检查器项目目录结构可以这样组织agent-benchmark/ ├── benchmark/ │ ├── tasks/ │ │ └── tool_use/ │ │ └── weather_query_001/ │ │ ├── task.json │ │ └── evaluator.py │ ├── runners/ │ │ ├── base_agent.py │ │ ├── mock_agent.py │ │ └── llm_agent.py │ └── eval.py ├── tools/ │ └── weather_server.py └── requirements.txt创建第一个任务文件benchmark/tasks/tool_use/weather_query_001/task.json{ task_id: weather_query_001, schema_version: 1.0, domain: tool_use, instruction: 查询北京今日天气并根据温度判断是否适合户外跑步。, tools: [ { name: weather.get_current, description: 获取指定城市当前天气, parameters: { type: object, properties: { city: { type: string, description: 城市名称 } }, required: [city] } } ], checker: { type: python, entry: evaluator.py:check_result }, tags: [weather, tool_use, basic], difficulty: 0.3, expected_keyword: 适合 }这个文件描述了三件事Agent 需要完成什么目标、它可以调用什么工具、评测方如何判定结果。接下来创建 mock 天气工具tools/weather_server.pydef get_current_weather(city: str) - dict: data { 北京: {temperature: 24, condition: 晴}, 上海: {temperature: 30, condition: 多云}, 广州: {temperature: 32, condition: 小雨}, } if city not in data: return {error: fcity {city} not found} return data[city]这个函数返回固定数据保证评测稳定。真实项目中可以用 HTTP server 模拟同样逻辑。创建检查器benchmark/tasks/tool_use/weather_query_001/evaluator.pyimport json def check_result(trajectory, task): # trajectory 是 Agent 运行过程中的消息列表 tool_calls [] final_message None for step in trajectory: if getattr(step, tool_calls, None): tool_calls.extend(step.tool_calls) if step.role assistant and getattr(step, content, None): final_message step.content if not tool_calls: return {pass: False, reason: no_tool_call} first_call tool_calls[0] if first_call.function.name ! weather.get_current: return {pass: False, reason: wrong_tool} arguments json.loads(first_call.function.arguments) if arguments.get(city) ! 北京: return {pass: False, reason: wrong_city_arg} if not final_message or task[expected_keyword] not in final_message: return {pass: False, reason: answer_missing_keyword} return {pass: True, reason: }检查器检查的是 Agent 的轨迹而不是最终答案字符串。它要求Agent 确实发起了工具调用。调用了期望的工具。参数里的城市正确。最终回答里包含判定关键字。这种设计可以避免 Agent 不查天气直接猜测答案。3.3 实现最小 Agent Runner先实现两个 runner一个用于快速验证检查器逻辑的 mock agent一个基于大模型 API 的真实 agent。benchmark/runners/mock_agent.pyclass MockAgent: def __init__(self, name): self.name name def run(self, instruction, tools): weather_tool tools[0] # 模拟模型生成一个 tool call tool_call types.SimpleNamespace( idcall_1, typefunction, functiontypes.SimpleNamespace( nameweather_tool.name, arguments{city: 北京} ) ) assistant_message types.SimpleNamespace( roleassistant, contentNone, tool_calls[tool_call] ) tool_message types.SimpleNamespace( roletool, tool_call_idcall_1, content{temperature: 24, condition: 晴} ) final_message types.SimpleNamespace( roleassistant, content北京今日天气晴朗温度24度适合户外跑步。, tool_callsNone ) return [assistant_message, tool_message, final_message]为了减少依赖这里使用types.SimpleNamespace来模拟消息结构。benchmark/runners/llm_agent.pyimport json from openai import OpenAI class LLMAgent: def __init__(self, modelgpt-4o-mini, max_steps5, temperature0): self.model model self.max_steps max_steps self.temperature temperature self.client OpenAI() def run(self, instruction, tools): tool_schemas [ { type: function, function: { name: t.name, description: t.description, parameters: t.parameters, } } for t in tools ] messages [ {role: system, content: 你是一个需要在必要时调用工具来帮助用户完成任务的智能体。}, {role: user, content: instruction} ] trajectory [] for _ in range(self.max_steps): response self.client.chat.completions.create( modelself.model, messagesmessages, toolstool_schemas, temperatureself.temperature, ) message response.choices[0].message trajectory.append(message) if not getattr(message, tool_calls, None): break messages.append(message) for tool_call in message.tool_calls: tool next(t for t in tools if t.name tool_call.function.name) args json.loads(tool_call.function.arguments) result tool.handler(**args) messages.append( { role: tool, tool_call_id: tool_call.id, content: json.dumps(result, ensure_asciiFalse), } ) return trajectory这里的思路是Agent 先返回一个 assistant 消息。如果消息里包含tool_calls就把这些调用依次执行把结果作为tool类型消息追加到上下文再让模型继续生成直到没有新的工具调用或者达到max_steps上限。max_steps是防止 Agent 陷入死循环的关键参数。真实评测中还要加时间限制和 token 限制。3.4 加载任务并运行评测benchmark/eval.pyimport importlib.util import json import pathlib import sys sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) from tools.weather_server import get_current_weather from runners.mock_agent import MockAgent from runners.llm_agent import LLMAgent WINDOW default def load_task(task_dir): task_path pathlib.Path(task_dir) task json.loads((task_path / task.json).read_text(encodingutf-8)) evaluator_path task_path / evaluator.py spec importlib.util.spec_from_file_location(fevaluator_{task[task_id]}, evaluator_path) module importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return task, module def run_eval(task_dir, runner): task, evaluator_module load_task(task_dir) tools [ { name: weather.get_current, description: 获取指定城市当前天气, parameters: { type: object, properties: {city: {type: string}}, required: [city] }, handler: get_current_weather, } ] tools [type(Tool, (), t)() for t in tools] trajectory runner.run(task[instruction], tools) result evaluator_module.check_result(trajectory, task) return { task_id: task[task_id], runner: getattr(runner, name, runner.__class__.__name__), result: result, trajectory: trajectory, } if __name__ __main__: task_dir benchmark/tasks/tool_use/weather_query_001 agent MockAgent(namemock_agent) report run_eval(task_dir, agent) print(json.dumps(report[result], ensure_asciiFalse, indent2))运行 mock agent预期输出{ pass: true, reason: }再用真实大模型运行export OPENAI_API_KEYyour_key python -c from benchmark.eval import run_eval from benchmark.runners.llm_agent import LLMAgent report run_eval(benchmark/tasks/tool_use/weather_query_001, LLMAgent()) print(report[result]) 由于大模型生成存在随机性推荐先设置temperature0。即使这样模型也可能拒绝调用工具直接回答天气情况。这正是需要检查器检查轨迹而不是最终答案的原因。注意mock agent 是用来验证评测框架正确性的不是用来当真实成绩的。真实评测必须使用目标 Agent 来跑。4. 评测维度与指标设计不要让一个分数掩盖全部问题4.1 从任务完成度到过程质量的多层指标Computer Anthology 这类基准家族单个任务通常产出多个信号而不只是一个pass/fail。原因是任务成功与否不是 Agent 能力的全部。一个 Agent 可能最终完成了任务但中间调用错了三次工具或者消耗了大量 token或者差一点删除重要文件。常见 Agent 评测指标包括指标含义计算方式典型问题任务成功率检查器判定最终目标达成率通过任务数 / 总任务数只看结果忽略过程工具调用合法率工具名、参数、类型是否合法合法调用次数 / 总调用次数参数合法但结果错误无效操作次数调用不存在工具或重复失败统计平均每次任务失败次数次数多说明规划能力弱最终答案质量答案是否完整、准确、不冗余人工或语义模型打分主观性强成本消耗token 数、调用次数、延迟平均每任务成本不同模型成本不可直接对比安全违规是否越权、泄露敏感信息、执行高风险操作规则检查器扫描轨迹需要专门设计安全任务这些指标不是互相替代而是互相补充。4.2 结果聚合分域报告比总分更重要如果只输出一个总成功率Agent 在某个能力域的短板会被其他能力域的平均水平掩盖。推荐至少从两个维度聚合按任务难度聚合简单任务成功率、中等任务成功率、困难任务成功率。按能力域聚合工具调用成功率、代码执行成功率、多轮决策成功率。宏平均和微平均的选择也会影响结论。宏平均对每个任务等权微平均对每个实例等权。任务数量不平衡时微平均会偏向任务多的能力域。4.3 资金和稳定性控制Agent 评测通常需要跑多次取均值因为大模型采样和工具执行顺序都可能带来波动。建议固定推理参数temperature0固定随机种子。同一 Agent 在同一任务上至少跑 3 次记录范围而不是单点值。报告success1、success3或平均成功率。如果使用自身不确定性的 Agent必须记录运行日志方便二次确认。分数波动不是 bug而是 Agent 评测的固有特征。只有在多重验证下差异才具有可比性。5. 构建“持续演进”机制版本化、回归与 CI5.1 任务注册表与版本约定要把一个 benchmark 变成可演进家族任务目录不只是“放题目”还要作为注册表管理。建议每个任务目录有固定文件结构benchmark/ └── released/ └── tool_use/ └── weather_query_001_v1/ ├── task.json ├── evaluator.py └── README.md在task.json中增加revision字段{ task_id: weather_query_001, revision: v1, schema_version: 1.0, status: released, changelog: [2025-01-01 initial release] }当任务不再使用不要直接删除而是标记{ status: deprecated, deprecated_at: 2025-06-01, reason: weather API schema changed }保留已废弃任务的完整历史是保证评测结果可比的重要前提。5.2 新增和修改任务的标准流程持续演进必须建立流程。一个可执行的新任务发布流程如下在candidate/目录创建任务文件和检查器。使用一个强 Agent 和一个弱 Agent 分别试跑确认任务对能力有区分度。为检查器编写至少两个前置测试一个正例轨迹一个错误轨迹。跑最小回归确认新任务不影响旧任务。评审通过后移动到released/对应目录。给整个 benchmark 打版本 tag比如anthology-2025.06。如果只是修改某个任务的 instruction也要变更revision而不是覆盖原文件。这样此前在该任务上的所有分数仍然能追溯到正确版本。5.3 在 CI 里跑每日回归Agent benchmark 的价值在于长期跟踪。建议在 CI 中设置定时任务每天运行全部任务并生成对比报告。一个简化版 GitHub Actions 工作流name: agent-benchmark-regression on: schedule: - cron: 0 2 * * * workflow_dispatch: jobs: eval: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-pythonv5 with: python-version: 3.11 - run: pip install -r requirements.txt - run: python benchmark/run_all.py --output-dir result - uses: actions/upload-artifactv4 with: name: eval-report path: result/运行脚本应该输出一个时间戳、commit hash、任务集版本、每个 Agent 在每个任务上的结果。这样才能回答“某次分数变化到底是模型变好了还是评测集变更了”。5.4 防止任务失效和污染的机制持续演进的 benchmark 还需要主动对抗两类风险一是任务失效。工具 API、外部网站、依赖库都可能变化。对抗方式是尽量使用 mock 服务、固定容器镜像、固定依赖版本。任何外部资源都要做快照或版本锁定。二是数据污染。一个公开的 benchmark 被模型训练集收录后得分会失真。对抗方式包括设置私有 holdout 任务集只在小范围内部使用。对同一任务生成多种指令表达降低记忆可能性。持续新增任务确保评测集永远包含新数据。对已污染任务标记contaminated统计时单独区分。这些机制都可以在基准家族的架构内实现不需要另起炉灶。6. 常见问题与排查路径6.1 Agent 跑不通时按这个顺序检查刚搭好评测环境时最容易出现的问题是 Agent 直接报错或没有返回结果。不要急着改检查器先确认链路。现象可能原因检查方式处理建议API 请求报 401缺少 API Key 或 Key 无效检查环境变量OPENAI_API_KEY重新写入正确的 Key工具调用参数解析失败模型返回 JSON 不合法打印 tool_call.function.arguments在请求中要求严格 JSON或在代码里做容错Agent 没有调用工具直接回答prompt 或模型能力问题打印完整 trajectory调整 system prompt必要时降低 max_steps 检查是否因为步数不足任务超时或 token 用尽max_steps 设置太小或模型循环调用查看每次调用返回的 usage增加 max_steps同时设置总 token 上限检查器报 no_tool_call检查器读取结构不一致确认 trajectory 里消息是否包含 tool_calls 字段统一消息结构保证 runner 和 evaluator 里字段名一致排查顺序建议先检查输入任务是否加载成功再检查工具注册是否出现再检查 Agent 返回的 trajectory 是否完整最后才检查检查器逻辑。用一个最小 mock agent 先跑通框架再接真实模型能省去大量定位时间。6.2 分数忽高忽低问题可能不在模型如果你发现同一个 Agent 在同一任务的得分不稳定先不要怀疑模型能力。常见原因有三个使用了真实工具服务服务端返回波动。没有固定temperature和随机种子模型输出不稳定。检查器判断依赖最终回答文本同一意思不同表达会被误判。对应解法使用 mock 工具或录制回放工具。固定temperature0多次运行取平均。检查器中增加语义判断或允许多个关键词。6.3 任务更新后旧结果无法对比这是最常见的版本管理问题。如果你直接把task.json里的 instruction 改了旧结果自然无法对比。因为旧成绩不是在新指令下测得的。正确做法是旧任务目录原样保留新建一个weather_query_001_v2目录并在changelog中写明变更内容。整个 benchmark 发布时打新 tag同时保留旧 tag 对应的完整代码快照。6.4 检查器误判的调试思路检查器误判会让 benchmark 失去可信度。常见情况是Agent 明明完成了任务但检查器报失败或者 Agent 明显没完成但检查器放行了。调试时要看两样东西完整轨迹日志。检查器针对该轨迹的执行过程。建议在检查器函数中添加调试参数输出中间判断结果。更稳妥的做法是维护一组 golden trajectory每次修改检查器后都跑这些轨迹确认正例仍然通过、反例仍然失败。GOLDEN_CASES [ { name: positive_case, trajectory: [...], expected: True, }, { name: no_tool_call, trajectory: [...], expected: False, }, ]检查器代码的每次变更都要以 golden cases 回归作为准入门槛。7. 最佳实践与扩展方向7.1 从 Computer Anthology 这类基准家族中提炼的检查清单在落地自己的 Agent 评测体系前可以先用下面的清单做评估自查是否每个任务都有唯一 ID 和版本号是否每个 Agent 结果都保存了完整轨迹是否每个任务都使用 mock 或快照环境避免外部依赖波动是否每个检查器都被正例和反例验证过是否定期运行全量回归并有历史对比报告是否在没有确认任务版本的情况下轻易比较不同模型得分是否区分了学习环境与生产环境是否跟踪了 token 成本、延迟、工具调用次数等过程指标是否考虑了任务污染风险和私有 holdout 任务这些条目看似基础却是保证 benchmark 长期有效的关键。7.2 学习环境与生产环境的差异学习环境目标是快速跑通流程。这时可以使用 mock 工具和少量任务。只记录单次运行结果。不追求严格的版本化。使用小模型降低成本。生产环境完全不同。需要沙箱化工具环境限制 Agent 网络访问和文件权限。固定容器镜像或虚拟环境确保每次评测一致。接入监控日志、指标、成本告警。设置重试策略和超时熔断。任务更新走评审流程。生成自动对比报告发送到团队。不要在学习环境里得出的结论直接换算到生产环境两者目标不一样。7.3 下一步扩展方向Computer Anthology 这类基准家族的下一步大概率会围绕几个方向延伸一是从静态任务走向动态任务。任务不是一次写死而是根据 Agent 行为生成新的子任务或对抗样本。二是从单 Agent 走向多 Agent 协作评估 Agent 之间的信息传递、冲突处理和任务分配。三是从文本和代码扩展到多模态比如截图识别、界面操作、音频输入。四是加入更强的安全评测验证 Agent 是否能在提供能力的同时遵守权限边界和数据合规要求。对于开发者来说最重要的事情不是等待官方 benchmark 发布而是先建立自己的评测体系。一个足够小的、能持续演进的任务集比一个很大但无法更新的任务集更有价值。回到 Computer Anthology 的设计思路核心并不复杂基准不再是一次性的试卷而是一个带有版本、历史、回归机制的评测资产库。所有做 AI Agent 应用落地的人都应该尽早把评测资产纳入日常开发流程。这样模型一迭代、工具一升级、新场景一出现你都能立刻知道 Agent 的能力是否真的跟上了。
返回列表