Deep Agents 上下文检索评估任务深度解析:以 cb-cloud-55 多实体对比任务为例
2026/9/10 0:06:53 网站建设 项目流程

Deep Agents 上下文检索评估任务深度解析:以 cb-cloud-55 多实体对比任务为例

【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents

本篇文章以libs/evals/datasets/context-retrieval-evals/cb-cloud-55任务为实例,系统拆解 deepagents 项目中"上下文检索评估"(context-retrieval evaluation)任务的设计原理、文件结构、生成机制与 LLM 评分流程。读者将掌握:一个评估任务如何从 Context-Bench 记录生成、为何"全量交付语料 + 网络白名单"能有效防止作弊,以及其"非字符串相等"的模型裁判评分究竟如何工作,从而可以自行运行、复现并扩展同类评测。

一、任务指令:只有三行,却是一条完整的评测规范

cb-cloud-55任务的指令文件 instruction.md 全文如下:

Who owns more pets: the person with the most credit cards among people who share the same blood type as the owner of the pet named 'Andre' (using highest total bank balance as a tiebreaker), or the person with the most credit cards among people who share the same blood type as the owner of the pet named 'Antonio' (using the same tiebreaker)?

Use only the files under/app/files. Write your final answer (and nothing else) to/app/answer.txt.

三行文本定义了评测的完整契约:

  1. 问题本身:一道典型的multi_entity_comparison(多实体对比)推理题。它要求 Agent 完成一条多跳检索链——先定位名为 'Andre' 与 'Antonio' 的两只宠物 → 查出各自主人 → 匹配主人的血型 → 在同血型人群中找出信用卡数量最多者(平局时以总银行余额最高者打破)→ 再比较这两人各自拥有的宠物数量 → 输出拥有宠物更多之人的姓名。
  2. 数据边界:"Use only the files under/app/files"——回答只能依据沙箱内/app/files目录下交付的语料,不能依赖模型记忆或外部网络。
  3. 输出契约:"Write your final answer (and nothing else) to/app/answer.txt"——最终答案必须以纯文本形式写入指定文件,且只能包含答案本身,不能附加解释。这条约束是后续自动化评分(verifier 读取该文件)的接口约定。

该任务的参考答案(ground truth)记录在 tests/case.json 中:"ground_truth": "Mark Barber"。而 solution/solve.sh 给出了参考解法——它只是简单地printf '%s\n' 'Mark Barber' > /app/answer.txt,说明"答案"本身是唯一的实体名,评测的核心在于 Agent 是否能在多文件语料中检索、关联并聚合出这个实体。

二、任务定位:30 个子集背后的 Context-Bench 语料

cb-cloud-55并非孤立任务,它属于 context-retrieval-evals 数据集。该数据集的定位可以概括为:

  • 来源:任务派生自Context-Benchcloud套件(合成的人 / 车辆 / 宠物 / 账户记录),由libs/evals/harbor_adapters/contextbench适配器从 vendored 的filesystem_cloud.jsonl(100 条记录)生成;每个任务cb-cloud-<i>对应第<i>条记录(0 起始)。
  • 样本策略:仓库从中挑选了 30 个任务组成代表性样本,难度构成是2 easy · 10 medium · 18 hardcb-cloud-55在 task.toml 中被标记为difficulty = "hard"question_type = "multi_entity_comparison"
  • 校准记录:calibration.json 保存了 gpt-5.6-terra 与 gpt-5.6-luna 两个模型对全部 100 个源任务各 6 次 rollout 的配对结果:全量 100 任务 Terra 为 510/600(85.0%)、Luna 为 552/600(92.0%);选中的 30 个任务分别是 153/180(85.0%)与 166/180(92.2%)。其中cb-cloud-55的 Terra pass@6 为 5/6(0.8333),Luna pass@6 为 6/6(1.0)。需要说明的是,difficultysource_difficulty字段保留的是 Context-Bench 的原始难度分层,并非事后按模型表现贴的标签。

值得注意的是,README 中特别强调:每个任务交付的是完整语料(10 个文件),而不是只给"相关文件"。这样 Agent 无法通过"哪些文件被提供了"来反推答案,必须真正执行检索、关联与聚合。这与cb-cloud-55的问题特征完全吻合——血型、信用卡、银行余额、宠物记录分别散布在语料的不同文件中,缺少任何一个文件都无法作答。

三、任务目录解剖:一个自包含的 Harbor 评测包

cb-cloud-55的目录结构如下:

libs/evals/datasets/context-retrieval-evals/cb-cloud-55/ ├── environment/ │ ├── Dockerfile # 运行沙箱镜像定义 │ └── files/ # 语料(git-ignored,由 populate 从单一源恢复) ├── solution/ │ └── solve.sh # 参考答案脚本 ├── tests/ │ ├── case.json # 唯一按任务提交的评测输入(问题 + 标准答案) │ └── (test.sh / judge.py / rubric.txt 由 populate 生成) ├── instruction.md # 任务指令(见第一节) └── task.toml # 任务元数据与网络环境约束

3.1 task.toml:难度、类型与网络白名单

task.toml 的完整内容如下:

version = "1.3" [metadata] source = "contextbench" suite = "cloud" difficulty = "hard" source_difficulty = "hard" question_type = "multi_entity_comparison" [environment] network_mode = "allowlist" allowed_hosts = ["astral.sh", "*.astral.sh", "github.com", "*.githubusercontent.com", "pypi.org", "*.pythonhosted.org", "api.smith.langchain.com", "api.anthropic.com", "api.openai.com", "generativelanguage.googleapis.com", "openrouter.ai", "*.baseten.co", "api.fireworks.ai", "ollama.com", "api.groq.com", "integrate.api.nvidia.com", "api.x.ai"]

关键设计是network_mode = "allowlist":任务不是完全断网,而是只放行特定的包镜像(astral.sh、pypi.org 等,供 Agent 安装运行依赖)与模型提供商的 API 端点(api.anthropic.com、api.openai.com、openrouter.ai 等,供 Agent 调用 LLM 自举)。任意公开网页一律被阻断,因此 Agent 无法上网检索答案,评测的检索能力被严格限定在/app/files语料内部。

3.2 Dockerfile:把"装 curl"从运行时挪到构建期

environment/Dockerfile 是一个刻意精简的镜像:

FROM python:3.12-slim # Pre-install curl at build time (the build phase has network) so the # in-sandbox agent's runtime bootstrap skips apt; runtime egress is then # all-HTTPS via the task's network allowlist. RUN apt-get update \ && apt-get install -y --no-install-recommends curl ca-certificates \ && rm -rf /var/lib/apt/lists/* COPY files/ /app/files/

两个设计点值得注意:

  1. curl 在构建期预装:镜像构建阶段不受任务网络白名单约束,因此可以跑apt-get;而 Agent 在沙箱内运行时 egress 全部走 HTTPS 白名单,apt的 HTTP 流量会被拦截。把 curl 提前装好,Agent 自举时就不必再触发 apt。
  2. 语料挂载点COPY files/ /app/files/与 instruction.md 中的Use only the files under /app/files严格对应。

四、任务的生成机制:adapter 如何把 JSONL 记录变成评测任务

cb-cloud-55的目录并非手工编写,而是由 contextbench 适配器 程序化生成的。理解生成逻辑有助于你自行产出同类任务:

  • 任务 ID 解析parse_task_id()通过正则^cb-(?P<suite>[a-z0-9]+)-(?P<index>\d+)$解析cb-cloud-55,其中55filesystem_cloud.jsonl的 0 起始行号;record_for_task_id()据此取出对应记录。
  • 文件生成generate_task()一次性写出 instruction.md(问题 + 两条沙箱约束)、Dockerfile、.dockerignoresolution/solve.shtests/case.json{"input": ..., "ground_truth": ...})与 task.toml,并把完整语料复制进environment/files/
  • 单一来源(single-source)策略:语料(64.7K 行,单一副本存于harbor_adapters/contextbench/vendor/files/)以及评测器固定文件tests/{test.sh, judge.py, rubric.txt}(单一副本存于 templates/)在 30 个任务间完全一致,因此被 git-ignored,不随任务提交。每个任务唯一提交的评测输入只有tests/case.json
  • 校准分层stamp_calibrated_tiers()会在校准后把difficulty覆盖为测量得到的 tier,同时保留source_difficulty作为溯源。

CLI 入口是 main.py,支持--task-ids(按 ID 生成单个任务)、--limit(生成前 N 个)、--populate(从单一语料源恢复各任务的environment/files/与评测器文件)和--stamp-tiers --calibration(回写校准分层)。

五、评分机制:不是字符串比较,而是 LLM model_judge

评测的关键在于 tests/test.sh 调用的 judge.py。README 明确说明:评分对标上游 Letta letta-evals 的model_judge,用 LLM 对照 vendored 的 rubric 打分(对措辞 / 姓名 / 数字宽容),而不是字符串相等。这对于"Mark Barber"这类自由文本答案尤其重要——Agent 回答 "Mark Barber owns more pets" 与ground_truth并不逐字符相同,但语义完全正确。

judge.py 的关键实现细节:

  1. 提示词构建:读取/tests/case.json得到{input, ground_truth},再读取/tests/rubric.txt(上游 rubric),通过string.Formatter().vformat{input}{ground_truth}{submission}(来自/app/answer.txt)三个占位符替换进 rubric 模板——无 system prompt、无包装,忠实复刻上游。
  2. 结构化输出:以 Chat Completions +response_format: json_schema调用裁判模型,要求返回{score: float in [0,1], rationale}
  3. 温度规则:上游规则被保留——裁判模型若匹配o1/o3/gpt-5则温度用 1.0(这些推理模型会拒绝 0.0 温度,直接调用会 400),其余模型用 0.0。
  4. 容错score = clamp(score, 0.0, 1.0);若/app/answer.txt不存在或裁判调用 5 次重试后仍失败,一律记 0.0,与上游"异常即 0 分"行为一致。
  5. 裁判模型与凭据由 harness 注入JUDGE_MODELS(默认回退gpt-5.6-luna)、OPENAI_API_KEYOPENAI_BASE_URL均来自评测环境变量,代码中不硬编码密钥,也从不打印密钥。

这套设计使得同一个cb-cloud-55可以在更换裁判模型或 harness 版本时保持可复现的评分口径。

六、本地运行与复现路径

由于语料与评测器固定文件是 git-ignored 的,在本地运行前必须先执行 populate。数据集的 dataset.toml 与 README 给出了标准流程:

uv run python -m harbor_adapters.contextbench.main --populate datasets/context-retrieval-evals uv run harbor run --path datasets/context-retrieval-evals ...
  • 第一条命令把单一语料源恢复到每个任务的environment/files/,并把test.sh/judge.py/rubric.txt铺到各任务的tests/下;
  • 第二条命令通过 Harbor 在沙箱内构建镜像、注入网络白名单与 verifier 环境(含裁判模型凭据)、运行 Agent,最后执行 verifier 并把 reward 写入/logs/verifier/reward.txt
  • CI(harbor.yml)在构建任务镜像前会自动执行--populate

运行前提是沙箱环境可访问 task.toml 白名单中的包镜像与模型 API;裁判模型的选择(如JUDGE_MODELS)直接决定最终得分口径。

七、从 cb-cloud-55 提炼评测设计要点

综合以上分析,这个只有三行的指令文件背后,沉淀了 deepagents 上下文检索评测的四条核心设计经验:

  1. 全量语料交付:向 Agent 提供完整语料而非裁剪后的相关文件,杜绝"靠文件集合反推答案",逼出真实的检索能力。
  2. 检索链路足够深multi_entity_comparison题型要求跨文件多跳关联(宠物 → 主人 → 血型 → 同血型人群 → 信用卡/余额排序 → 宠物数对比),任一环节检索失败即整体失败,因此难度被标为 hard。
  3. 网络白名单而非断网:放行包镜像与模型 API 端点以保证 Agent 自举,同时阻断任意网页,把"外部检索"这条作弊路径从机制上封死。
  4. LLM 裁判宽容评分:用 rubric 驱动的模型裁判替代字符串匹配,让语义正确但措辞不同的答案也能获得合理分数,更贴近真实评测需求。

对于想要自己构建上下文检索评测集的开发者,cb-cloud-55及其余 29 个任务(见 context-retrieval-evals/README.md 的任务总表)是一套结构清晰、可复现、可直接扩展的现成模板。

【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询