Deep Agents Eval 测试套件全解析:从轨迹断言到外部基准的端到端评测体系

📅 发布时间:2026/9/10 5:53:58
Deep Agents Eval 测试套件全解析:从轨迹断言到外部基准的端到端评测体系
Deep Agents Eval 测试套件全解析从轨迹断言到外部基准的端到端评测体系【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents导读本文围绕 Deep Agents SDK 评测体系的测试核心——libs/evals/tests/evals/目录展开系统讲解其目录结构、pytest 基础设施、基于轨迹trajectory的正确性 效率双轨断言模型、LLM-as-judge 自动打分、JSON 效率报告插件以及 MemoryAgentBench、tau2-bench airline 与 BFCL v3 等外部基准的接入方式。读完本文你将掌握如何阅读、运行、扩写这套真实调用 LLM 的端到端行为评测套件并理解每个组件背后的源码实现与数据流。目录全景tests/evals 承担什么角色tests/evals/是 Deep Agents SDK 的行为评测测试套件所在目录。它与传统单元测试不同每个 eval 都会用一个真实的 LLM 运行一个 agent捕获完整轨迹工具调用、文件变更、最终回复然后从正确性和效率两个维度打分。目录的官方说明见 tests/evals/README.md其明确列出的组件包括组件职责conftest.pypytest 夹具--model选项、model/model_name夹具、LangSmith 实验元数据utils.py核心框架AgentTrajectory、断言类、TrajectoryScorer、run_agentllm_judge.py基于 openevals 的 LLM-as-judge 断言pytest_reporter.py自定义 pytest 插件产出效率总结报告fixtures/静态测试数据如摘要种子消息data/基准样本数据FRAMES、Nexus、BFCL v3与 BFCL API 实现memory_agent_bench/MemoryAgentBenchICLR 2026评测运行器tau2_airline/tau2-bench 航空领域评测来自 Sierra Research 的 tau-benchMIT License从仓库结构看该目录与libs/evals/tests/unit_tests/纯单元测试并列体现了单元测试验证机制、evals 验证端到端行为的分层设计。根 libs/evals/README.md 将其定位为面向 Deep Agents SDK 的端到端行为评测套件并说明每个 eval 都会把完整轨迹与正确性、效率分数同步到 LangSmith。基础设施层conftest.py 的 pytest 集成conftest.py 是整套评测的 pytest 入口承担三个关键职责。1. 启动即校验LangSmith 追踪与模型必须就绪pytest_configure在会话启动阶段就强制两条前置条件不满足则直接pytest.exit必须开启 LangSmith 追踪LANGSMITH_TRACING、LANGSMITH_TRACING_V2、LANGCHAIN_TRACING_V2、LANGCHAIN_TRACING任一为true即可否则整套测试被跳过并给出明确报错必须传入--model每个 eval 都依赖真实模型缺失时直接退出。此外它还注册了三类自定义 markerconfig.addinivalue_line(markers, eval_category(name): ...) config.addinivalue_line(markers, eval_tier(name): ...) config.addinivalue_line(markers, repl(*allowed): ...)其中eval_category用于分组如memory、tool_useeval_tier用于区分baseline回归门槛与hillclimb进度追踪两个层级repl用于声明可选的 REPL 后端与--repl quickjs搭配。2. 全套 CLI 选项pytest_addoption暴露了评测专用的命令行参数选项说明--model必填评测使用的模型标识如--model claude-sonnet-4-6--eval-category可重复只运行指定类别的 eval如--eval-category memory --eval-category tool_use--eval-category-exclude可重复排除指定类别优先于 include--eval-tier可重复只运行指定层级的 eval--openrouter-provider逗号分隔的 OpenRouter 供应商白名单如MiniMax,Fireworks--openrouter-allow-fallbacks允许 OpenRouter 在列表供应商不可用时回退默认严格不回退--openai-reasoning-effort仅对 OpenAI 模型生效取值为minimal/low/medium/high/xhigh--repl可选 REPL 中间件当前支持quickjspytest_collection_modifyitems会依据eval_category/eval_tiermarker 对收集到的测试项做过滤并且如果传入的 include/exclude 值与测试中实际存在的 marker 值对不上会直接以返回码 1 退出避免静默跑空。3. 夹具体系model_name由pytest_generate_tests把--model参数化到每个测试model通过init_chat_model构建真实模型实例。源码中对 OpenRouter 前缀强制设置 120 秒超时规避 SDK 默认 5 秒读超时导致的 TCP 悬挂对openai:前缀显式开启use_responses_api并可叠加reasoning_effortlangsmith_experiment_metadatasession 级记录model、运行日期与deepagents_version作为 LangSmith 实验元数据。核心框架utils.py 的轨迹与断言模型utils.py 是整个评测框架的心脏约 1500 行定义了从轨迹建模到断言执行的全套机制。AgentTrajectory 与 AgentStepdataclass(frozenTrue) class AgentStep: index: int # 从 1 开始计数 action: AIMessage # agent 的输出可能包含工具调用 observations: list[ToolMessage] dataclass(frozenTrue) class AgentTrajectory: steps: list[AgentStep] files: dict[str, str] property def answer(self) - str: ... # 最后一步的文本内容 def pretty(self) - str: ... # 人类可读的轨迹摘要AgentTrajectory把agent.invoke()的原始结果messages 列表 files 通道规整为结构化数据AIMessage构成 step、ToolMessage挂到对应 step 的 observationsfiles则统一转换为dict[str, str]兼容字符串与{content: ...}两种表示。pretty()生成的格式会被llm_judge.py直接复用作为判官 prompt 的输入。此外_strip_common_zero_width会剔除零宽字符避免模型插入的隐形 Unicode 破坏字符串比对。双轨断言体系正确性硬校验 效率软记录框架定义了两种断言基类SuccessAssertion正确性违反即通过pytest.fail硬失败测试EfficiencyAssertion效率只记录日志、永不让测试失败。每个断言都实现check(trajectory) - bool与describe_failure(trajectory) - str失败信息会附带完整轨迹打印便于定位问题。正确性断言SuccessAssertion工厂函数与字段如下断言核心字段语义FinalTextContainstext,case_insensitive最终回复必须包含子串FinalTextExcludestext,case_insensitive最终回复不得包含子串FinalTextContainsAnytexts,case_insensitive最终回复至少包含一组等价措辞之一如 unknown/no data/n/a用于检验诚实承认信息缺失而非幻觉编造FinalTextMinLengthn最终回复去除空白后至少 n 字符用于过滤凑字数的收尾话术FileEqualspath,content轨迹中的文件内容与期望完全一致FileContains/FileExcludespath,substring文件包含/不包含某子串FileAbsentpath文件路径必须不存在比FileExcludes更严格——删除操作会把 key 从 files 通道中整个移除ToolCalledname,step,args_contains,args_equals轨迹中必须存在匹配的工具调用ToolNotCalled同上轨迹中不得出现匹配的工具调用硬失败版用于拦截无目标却反射性调用 update_goal之类的行为工具调用的选择器有两条构造期防线_validate_tool_call_selectorstep必须为正1-indexedargs_contains与args_equals互斥避免歧义匹配让ToolNotCalled空转通过。效率断言EfficiencyAssertion断言字段语义AgentStepsn轨迹恰好 n 个 agent stepToolCallRequestsn工具调用请求总数恰好为 nMaxToolCallRequestsn工具调用请求数至多 n用于捕获简单任务却 cargo-cult 规划工具的退化ToolCallname,step,args_contains,args_equals特定工具调用发生过软记录TrajectoryScorer两段式构建器dataclass(frozenTrue) class TrajectoryScorer: _success: tuple[SuccessAssertion, ...] () _expectations: tuple[EfficiencyAssertion, ...] () def success(self, *assertions: SuccessAssertion) - TrajectoryScorer: ... def expect(self, *, agent_stepsNone, tool_call_requestsNone, tool_callsNone) - TrajectoryScorer: ....success()追加硬校验.expect()追加效率期望二者都返回新的 scorer不可变风格。_assert_expectations在断言执行时先通过_log_efficiency把实际/期望的agent_steps、tool_call_requests写入 LangSmith feedbackt.log_feedback再依次执行成功断言任一不满足即pytest.fail并记录correctness0。run_agent / run_agent_async统一入口def run_agent(agent, *, query, model, initial_filesNone, scorerNone, thread_idNone, eval_metadataNone, extra_stateNone) - AgentTrajectory:run_agent封装了构造输入 → 记录 LangSmith 输入 → invoke → 记录输出 → 构建轨迹 → 执行断言的完整链路支持同步/异步两个版本。extra_state允许注入中间件持有的状态如{rubric: ...}供RubricMiddleware使用thread_id缺省时自动生成 UUID。每个 eval 测试本质上就是创建一个 agent、调一次run_agent、挂一个TrajectoryScorer。扩展正确性手段llm_judge.py 的 LLM-as-judge当字符串断言无法覆盖语义标准时llm_judge.py 提供了基于 openevals 的LLMJudge断言def llm_judge(*criteria: str, judge_model: str _DEFAULT_JUDGE_MODEL, include_tool_calls: bool False) - LLMJudge:关键设计逐条独立判分每个 criterion 通过create_llm_as_judge独立评估所有 criterion 通过断言才算成功任一失败即硬失败并发评估多个 criterion 通过ThreadPoolExecutor最多 8 个 worker并行调用结果按下标归位保证失败信息确定有序单条失败不会短路其余评估两种上下文include_tool_callsFalse默认时判官只看 agent 的文本回复适合评判说了什么True时判官看到完整轨迹工具调用 文本适合评判做了什么如是否真的写了文件。判官 prompt 明确提示工具调用是真实执行过的动作应视为行为证据失败诊断describe_failure给出逐条判分注释llm_judge_all_passed聚合分数回写 LangSmith健壮性轨迹为空、判官调用抛错、openevals 返回结构异常都会给出明确报错。默认判官模型为claude-sonnet-4-6见_DEFAULT_JUDGE_MODEL。结果落盘pytest_reporter.py 与效率指标pytest_reporter.py 是注册在conftest.py中的 pytest 插件pytest_plugins [tests.evals.pytest_reporter]在会话结束后汇总并输出 JSON 报告。核心行为改写 pytest 退出码pytest_sessionfinish中当单个 eval 失败exitstatus1但确有测试运行时会把会话退出码改写为 0。这是有意为之——评测失败不应中断 CI 流水线后续聚合/报告步骤必须照常执行但如果一个测试都没跑配置错误或收集崩溃则保留非零退出码响亮失败效率数据收集通过_evals_utils._on_efficiency_result回调接收每个测试的EfficiencyResult并补记duration_s与passedLangSmith 实验链接会话开始时若设置了LANGSMITH_TEST_SUITE会预创建 LangSmith 实验并在终端输出公开/内部对比链接失败明细每个失败测试记录test_name、category、failure_message超长信息截断到 30k 字符约 7500 token供后续--retry-failed复用。报告中的关键指标插件计算并通过终端与 JSON 报告输出的指标包括指标计算方式说明correctnesspassed / total整体正确率category_scores按eval_category分组的 passed/total分类正确率step_ratiosum(actual_steps) / sum(expected_steps)步数效率比无期望时为空tool_call_ratiosum(actual_tool_calls) / sum(expected_tool_calls)工具调用效率比solve_ratepassed 且含步数期望与耗时的测试的 expected_steps/duration 均值失败测试计 0求解速率median_duration_s各测试 call 阶段耗时的中位数延迟表现JSON 报告可通过--evals-report-file或环境变量DEEPAGENTS_EVALS_REPORT_FILE指定路径报告包含created_at、sdk_version、model、计数、上述指标、experiment_urls、experiment_links与failures数组。数据资产fixtures/ 与 data/fixtures/静态测试数据例如summarization_seed_messages.json供摘要类测试复用。data/benchmark_samples/三个精选外部基准子集的样本——frames_final.json检索类、nexus_final.json推理类、bfcl_v3_final.json函数调用类。external_benchmarks.py 从这些文件各选取 5 个高难度用例并断言数量构成curated_external_hard子集FRAMES检索/文件回退_create_file_backed_agent用固定 system prompt 构造 agentinitial_files注入工作区文件用归一化子串存在断言评分忽略空白、大小写与引号变体Nexus推理同样采用文件回退 文本评分BFCL v3有状态工具调用data/bfcl_apis/下实现VehicleControlAPI、MessageAPI、TradingBot、TravelAPI、TicketAPI五个有状态 API 类。评测把 API 的公开方法包装为StructuredTool注入 agent用MemorySaver做多轮对话最后重放 ground truth 调用到全新实例上逐属性对比模型实例与真值实例的最终状态——即状态一致性评分比比对调用字符串更严格。外部基准接入一memory_agent_bench/memory_agent_bench/ 是 MemoryAgentBenchICLR 2026的评测运行器核心是 configs.py 中的DatasetConfig数据类dataclass(frozenTrue) class DatasetConfig: split: str # HuggingFace 数据集 split如 Conflict_Resolution source: str # 与数据集 metadata.source 匹配的来源标识 chunk_size: int 4096 # 记忆阶段每个文本块的 token 预算 max_samples: int 1 # 评估的上下文样本数上限 max_questions: int | None None # 每个样本的提问数上限配置按四个能力维度组织每个维度配多档上下文长度或难度维度配置示例关注点Conflict_Resolution单跳/多跳CR_SH_6K~CR_SH_262K、CR_MH_6K~CR_MH_262K事实合并与冲突消解Test_Time_LearningICLTTL_BANKING77、TTL_CLINIC150、TTL_NLU、TTL_TREC_COARSE/FINE、TTL_RECSYS测试期学习/上下文内分类Accurate_RetrievalAR_RULER_QA1/QA2、AR_LONGMEMEVAL、AR_EVENTQA_FULL/64K/128K精确检索含多跳与时间推理Long_Range_UnderstandingLRU_INFBENCH_SUM、LRU_DETECTIVE_QA长程理解生成与推理问答ALL_CONFIGS汇总全部 23 个配置CI_CONFIGS提供面向 CI 的高信号子集每类 2 个、偏向更难变体注释中给出了如SH64K 在合理上下文长度下梯度良好MH6K 是最便宜的近零 canary等选型理由。配套的 data_utils.py 负责从 HuggingFace 拉取数据并按配置切分eval_utils.py 提供评测逻辑test_memory_agent_bench.py 将其接入 pytest。外部基准接入二tau2_airline/tau2_airline/ 是 tau2-bench 航空领域的 vendored 实现源自 Sierra Research 的 tau-benchMIT License。目录下的data/db.json、policy.md、tasks.json为领域数据且按约定必须与上游逐字节一致不得重新格式化详见 libs/evals/AGENTS.md。其核心是多轮对话编排器 runner.pyrun_multi_turn让 deepagents agent 与 LLM 驱动的用户模拟器UserSimulator来回对话最多 30 轮DEFAULT_MAX_TURNS记录完整 transcript、工具调用日志与终止原因user_stop/max_turnsfor turn in range(max_turns): trajectory run_agent(agent, queryuser_msg, modelmodel, thread_idthread_id) agent_msg trajectory.answer ... user_msg user_sim.respond(agent_msg)配合 domain.py领域模型与工具、user_sim.py用户模拟器、evaluation.py结果评分test_tau2_airline.py 将整套流程接入评测套件。这种agent 对打 LLM 模拟用户的范式能覆盖自由对话式任务弥补单轮 prompt 评测的不足。如何运行这套评测虽然tests/evals本质上是 pytest 测试仓库推荐通过规范入口deepagents-evalsconsole script定义于 libs/evals/pyproject.toml 的[project.scripts]运行详见 libs/evals/AGENTS.md# 单模型单次运行 deepagents-evals run --model claude-opus-4-7 # 按类别与层级过滤输出 JSON 报告 deepagents-evals run --model openai:gpt-5.5 \ --eval-category memory --eval-tier baseline --report evals_report.json # 多次运行并聚合统计 deepagents-evals trials --model openai:gpt-5.5 --trials 3 # 只重跑上次失败的用例 deepagents-evals trials --model openai:gpt-5.5 --trials 1 \ --retry-failed trial_runs/trials_summary.jsonCLI 还提供list发现类别/层级/模型/eval、aggregate聚合离线报告、radar生成雷达图、catalog/model-groups检查生成文档等子命令DEEPAGENTS_EVALS_MODEL环境变量可省略--model。运行前置条件与 pytest 层一致必须开启 LangSmith 追踪LANGSMITH_TRACINGtrueLANGSMITH_API_KEY并配置与所选模型匹配的 provider key。make evals MODEL...、make evals-trials MODEL... TRIALS...仍可用CI 采用的形式CLI 是其超集。CLI 的退出码语义是自动化接入的关键0表示成功1表示存在评测失败由trials_summary.json中聚合的counts.failed.mean 0判定而非单次 pytest 退出码——因为 pytest_reporter 会把单次运行的退出码改写成 02表示配置错误或生成文档过期3表示没有可用报告。请勿解析人类可读输出应以退出码与trials_summary.json驱动自动化。聚合报告的 JSONC 结构metrics、counts、category_scores、trials各字段及每 trial 的experiment_urls、pytest_returncode均记录在 libs/evals/AGENTS.md 中可供读者直接参考对接。延伸阅读libs/evals/tests/evals/README.md——本套件的目录索引与组件清单libs/evals/tests/evals/utils.py——轨迹与断言核心框架libs/evals/tests/evals/conftest.py——pytest 集成与模型夹具libs/evals/tests/evals/pytest_reporter.py——效率报告插件libs/evals/tests/evals/external_benchmarks.py——FRAMES/Nexus/BFCL v3 精选子集评测libs/evals/AGENTS.md——deepagents-evalsCLI 用法、退出码与报告 schemalibs/evals/README.md——评测套件总览libs/evals/EVAL_CATALOG.md、libs/evals/MODEL_GROUPS.md——完整 eval 清单与模型分组目录【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考