deepagents 多文件上下文检索评估任务 cb-cloud-7 全解析:set_intersection 结构、生成机制与评分实现
2026/9/10 10:50:24 网站建设 项目流程

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"可以推断,该命题的推理链本质上是多次"集合求交":

  1. 先通过宠物名Isabel定位其主人,确定其居住州;
  2. 通过宠物名Randall定位其主人,取其血型;
  3. 在"居住在该州的人"集合中,与"血型相同的人"集合、"互联网账户 ≥ 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.shjudge.pyrubric.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.mdsolution/solve.shtests/case.json
  • 按固定模板写出environment/Dockerfiletask.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.txt

solve.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/

三个要点:

  1. 基础镜像为python:3.12-slim
  2. 构建阶段(有网络)预装curlca-certificates,这样运行期沙箱内的 Agent 引导流程无需再执行apt,运行期出网全部走 HTTPS;
  3. 语料被拷贝到/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_MODELSJUDGE_PROVIDEROPENAI_API_KEYOPENAI_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)。任务难度分层表显示:

tasksource tierTerra pass@6Luna pass@6type
cb-cloud-7hard6/66/6set_intersection

README 强调difficultysource_difficulty是 Context-Bench 源分层而非事后模型表现标签,配对结果仅作为抽样依据,不是排行榜目标。30 个任务覆盖 9 种题型(set_intersectionmulti_hop_chainmulti_entity_comparisoncross_file_countingaggregationcomparison_tiebreaknegationtemporal_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),仅供参考

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

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

立即咨询