deepagents 多文件上下文检索评估任务 cb-cloud-7 全解析:set_intersection 结构、生成机制与评分实现
【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents
本篇以 libs/evals/datasets/context-retrieval-evals/cb-cloud-7 为解剖样本,拆解 deepagents 仓库中"多文件上下文检索评估(context-retrieval evals)"任务的完整技术链路:任务命题格式、目录结构、Harbor 任务生成器、沙箱网络白名单,以及基于 LLM 的评分器(judge)实现。读完本文,你既能理解 cb-cloud-7 这类set_intersection难题的命题与推理逻辑,也能掌握如何基于仓库中的适配器生成、填充、校准并运行自己的上下文检索评估任务。
一、任务速览:一个"集合交集"型多跳检索问题
cb-cloud-7 是 context-retrieval-evals 数据集(30 个任务的代表性样本)中的第 7 号任务,对应 Context-Benchcloud套件的 0-based 第 7 条记录。其命题 instruction.md 全文如下:
Among people with 4 or more internet accounts who have the same blood type as the owner of pet 'Randall', who lives in the same state as the owner of pet 'Isabel'?
指令约束为:
Use only the files under
/app/files. Write your final answer (and nothing else) to/app/answer.txt.
即:Agent 只能读取沙箱内/app/files下的语料文件,并将唯一答案写入/app/answer.txt。标准答案记录在 tests/case.json 中:
{"input": "Among people with 4 or more internet accounts who have the same blood type as the owner of pet 'Randall', who lives in the same state as the owner of pet 'Isabel'?", "ground_truth": "Crystal Andrews"}该任务的元数据由 task.toml 声明:
version = "1.3" [metadata] source = "contextbench" suite = "cloud" difficulty = "hard" source_difficulty = "hard" question_type = "set_intersection"从question_type = "set_intersection"可以推断,该命题的推理链本质上是多次"集合求交":
- 先通过宠物名
Isabel定位其主人,确定其居住州; - 通过宠物名
Randall定位其主人,取其血型; - 在"居住在该州的人"集合中,与"血型相同的人"集合、"互联网账户 ≥ 4 的人"集合求交集,得到唯一目标人
Crystal Andrews。
这类题目迫使 Agent 在多文件语料间做跨文件 join 与聚合,无法靠单文件或记忆作答。README 中记录了该任务在源评估运行中的表现:cb-cloud-7属于 hard 档,Terra 与 Luna 两个模型均取得 pass@6 = 6/6。
二、任务目录结构:一次"全量语料 + 标准答案 + 评分器"的打包
每个cb-cloud-<i>任务目录都包含五类文件,cb-cloud-7 的完整结构如下:
cb-cloud-7/ ├── instruction.md # 命题与输出约束(上文已展示) ├── task.toml # 任务元数据与沙箱网络配置 ├── environment/ │ └── Dockerfile # 沙箱镜像:python:3.12-slim + curl + 语料 ├── solution/ │ └── solve.sh # 参考答案脚本(写入标准答案) └── tests/ └── case.json # 唯一提交的逐任务评分输入(问题 + 标准答案)需要特别说明的是:每个任务都打包了完整的 10 个文件语料,但语料本身是 git-ignored 的。README 明确指出,语料单副本位于 harbor_adapters/contextbench/vendor/files(约 6.47 万行),通过populate_corpus恢复到每个任务的environment/files/;而tests/下不变的验证器文件(test.sh、judge.py、rubric.txt)也采用同样的单源策略,分别由 templates 与 vendor 目录统一提供。每个任务实际提交(committed)的只有tests/case.json。
这种"全量语料交付"设计是本数据集的核心理念:Agent 无法通过"看文件名就猜该读哪个"来偷懒,必须真正执行检索、join 与聚合才能作答。
三、任务是如何生成的:adapter 与 CLI 的实现细节
任务的生成逻辑在 libs/evals/harbor_adapters/contextbench 包中,由两个模块协作完成:
3.1 adapter.py:从记录到任务目录的转换
adapter.py 的核心函数是generate_task(...),它读取filesystem_cloud.jsonl中的第 N 条记录(line_index),然后:
- 将
vendor/files/下的全部.txt语料拷贝到environment/files/(_copy_corpus按文件名排序逐文件复制); - 由记录中的
input(问题)与ground_truth(答案)生成instruction.md、solution/solve.sh、tests/case.json; - 按固定模板写出
environment/Dockerfile与task.toml。
其中instruction.md的写盘逻辑可见于_write_task_files:将问题文本与固定的两行约束拼接:
(task_dir / "instruction.md").write_text( f"{question}\n\n" "Use only the files under `/app/files`. Write your final answer (and nothing else) " "to `/app/answer.txt`.\n" )而参考答案脚本 solve.sh 由shlex.quote(answer)生成,cb-cloud-7 的成品是:
#!/bin/sh set -eu printf '%s\n' 'Crystal Andrews' > /app/answer.txtsolve.sh用于校验整个评分链路(沙箱 → 答案文件 → judge)可跑通,也方便人工核对标准答案。
3.2 main.py:四个互斥的 CLI 子命令
main.py 提供以下参数:
| 参数 | 作用 |
|---|---|
--task-ids ID [ID...] | 按 id 生成指定任务,如cb-cloud-7;id 形如cb-<suite>-<i>,i为 jsonl 的 0-based 行号 |
--limit N | 省略--task-ids时生成前 N 个任务 |
--output-dir DIR | 任务输出目录(生成模式下必需) |
--populate DIR | 把单源语料与不变验证器文件恢复到数据集目录下每个任务(git-ignored 文件的再生成),与--task-ids/--limit互斥 |
--stamp-tiers DIR(配合--calibration FILE) | 用校准结果覆盖每个任务task.toml中的difficulty,同时保留source_difficulty以记录来源标签 |
其中parse_task_id用正则^cb-(?P<suite>[a-z0-9]+)-(?P<index>\d+)$解析任务 id,并通过record_for_task_id校验记录存在。--stamp-tiers的实现(stamp_calibrated_tiers)会以正则替换task.toml中的difficulty = "..."行,且只接受easy/medium/hard三档。
四、沙箱环境:Dockerfile 与网络白名单
任务在 Docker 沙箱中运行,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/三个要点:
- 基础镜像为
python:3.12-slim; - 在构建阶段(有网络)预装
curl与ca-certificates,这样运行期沙箱内的 Agent 引导流程无需再执行apt,运行期出网全部走 HTTPS; - 语料被拷贝到
/app/files/,与指令中的约束路径一一对应。
沙箱的网络策略定义在 task.toml 的[environment]段:
[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"]从adapter.py的注释可以确认设计意图:这是"白名单而非断网"——Agent 在沙箱内运行,需要访问包镜像源(pypi.org等)完成引导,以及所选模型的 API 端点(各家模型厂商域名)来推理作答;但任意外部网站仍被阻断,防止 Agent 通过网络直接查答案。白名单只覆盖"API 端点",从不覆盖"答案来源",从而保证评估的公平性。注意api.smith.langchain.com是 LangSmith 可观测性端点,api.openai.com同时服务于模型调用与(可选的)judge 调用。
五、评分机制:LLM judge 而非字符串比对
本数据集刻意不用"答案字符串相等"来打分,而是复刻上游 Letta letta-evals 的RubricGrader(OpenAI provider),对措辞、姓名、数字做到宽容匹配,分数分桶为 0.0 / 0.5 / 1.0。入口是每个任务的 tests/test.sh(单源模板):
#!/bin/sh set -eu # Faithful Letta model_judge grader; writes /logs/verifier/reward.txt itself. python3 /tests/judge.py真正的评分逻辑在 templates/judge.py,其关键实现细节:
- 读取三个输入:
/tests/case.json(本任务的问题 + 标准答案)、/tests/rubric.txt(评分规则模板)、/app/answer.txt(Agent 提交的答案); - 提示词构造:用
string.Formatter().vformat将{input}、{ground_truth}、{submission}三个占位符替换进 rubric 模板,没有 system prompt、没有额外包装,与上游逐字一致; - 响应格式:通过 Chat Completions 的
json_schema响应格式要求 judge 输出{score: float in [0,1], rationale}结构化对象; - 温度规则:上游规定 judge 模型若匹配
o1/o3/gpt-5前缀则以 temperature 1.0 调用(这类推理模型拒绝 0.0,否则 API 直接 400),其余模型用 0.0; - 容错:
score = clamp(float(score), 0.0, 1.0);任何异常按 0.0 计分(与上游一致);调用失败最多重试 5 次; - 结果落盘:将分数写入
/logs/verifier/reward.txt。
judge 模型与凭证完全来自 harness 注入的环境变量(JUDGE_MODELS、JUDGE_PROVIDER、OPENAI_API_KEY、OPENAI_BASE_URL),代码中不硬编码任何密钥。与上游的两处刻意差异也写在文件头注释中:judge 模型由 deepagents harness 的JUDGE_MODELS指定(例如gpt-5.6-luna),而非上游的gpt-5-mini;提交内容取自/app/answer.txt而非 Agent 的最后一条助手消息。
六、运行评估:从 populate 到 harbor run
由于语料与验证器文件是 git-ignored 的,直接运行前必须先用--populate恢复。README 给出的标准流程(在libs/evals目录下执行):
uv run python -m harbor_adapters.contextbench.main --populate datasets/context-retrieval-evals uv run harbor run --path datasets/context-retrieval-evals ...populate_corpus会扫描数据集目录下所有source = "contextbench"的任务目录,逐个恢复environment/files/语料与tests/{test.sh,judge.py,rubric.txt},同时保持每个任务已提交的tests/case.json不变。CI(harbor.yml)在构建任务镜像前会自动执行--populate,确保流水线可复现。
若只关心单个任务的生成与检查,也可以走生成路径:
uv run python -m harbor_adapters.contextbench.main \ --task-ids cb-cloud-7 \ --output-dir /path/to/datasets/context-retrieval-evals七、数据集全景:cb-cloud-7 在 30 个任务中的定位
README 将该数据集定位为 "A Harbor dataset of 30 context-retrieval tasks for Deep Agents"。cb-cloud-7 的选取来自对 100 个源任务的抽样,保留了全语料聚合结果(Terra 510/600 = 85.0%、Luna 552/600 = 92.0%;抽样 30 个为 153/180 与 166/180)。任务难度分层表显示:
| task | source tier | Terra pass@6 | Luna pass@6 | type |
|---|---|---|---|---|
cb-cloud-7 | hard | 6/6 | 6/6 | set_intersection |
README 强调difficulty与source_difficulty是 Context-Bench 源分层而非事后模型表现标签,配对结果仅作为抽样依据,不是排行榜目标。30 个任务覆盖 9 种题型(set_intersection、multi_hop_chain、multi_entity_comparison、cross_file_counting、aggregation、comparison_tiebreak、negation、temporal_reasoning等),cb-cloud-7 正是"集合交集"题型的代表:跨文件检索、多次条件过滤与聚合,是检验 Agent 长上下文检索与多跳推理能力的标准样本。
八、小结与延伸阅读
cb-cloud-7 作为 deepagents 上下文检索评估集的一个 hard 档样本,麻雀虽小五脏俱全:命题层面是典型的多跳 set_intersection,工程层面则完整演示了"全量语料交付 + 网络白名单沙箱 + LLM 宽容评分"的评估范式。理解它即可举一反三地读懂其余 29 个任务,也能直接复用 harbor_adapters/contextbench 的生成器扩展自己的评估语料。
进一步阅读建议:
- 数据集总览与难度分层:context-retrieval-evals/README.md
- 任务生成适配器:adapter.py(生成/填充/校准三大能力)
- CLI 驱动:main.py
- 评分器模板:judge.py 与 test.sh
- 同题型对照任务:cb-cloud-53(同为
set_intersection的 medium 档样本)
【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考