Browse this library

Chinese source article

4.2.1 · Orchard 环境与轨迹

分析 Orchard 的环境服务、训练路线、稀疏奖励、数据规模和可移植轨迹。

View original Markdown ↗

论文:Orchard: An Open-Source Agentic Modeling Framework 作者:Baolin Peng, Wenlin Yao, Qianhui Wu, Hao Cheng, Xiao Yu, Rui Yang, Tao Ge, Alessandro Sordoni, Xingdi Yuan, Yelong Shen, Pengcheng He, Tong Zhang, Zhou Yu, Jianfeng Gao 等(Microsoft Research 等) arXiv:2605.15040(2026-05) GitHub:microsoft/Orchard Dataset:microsoft/Orchard(swe 107K + gui 3K 轨迹)

1. 环境服务与三条训练路线

环境不可复用造成的训练断裂,Agentic modeling 的训练瓶颈不仅在模型算法,也在环境能否稳定、低成本地产生可复现轨迹。

若每个项目各自绑定 sandbox、Harness 与 trainer,数据和评测协议就很难迁移。

Agentic modeling 的目标是把 LLM 变成能规划、推理、用工具、与外部环境多轮交互的自主 Agent。但开源社区长期存在两重断裂:

  1. 基础设施断裂:高性能系统依赖闭源代码、闭源模型或托管服务;开源框架多聚焦 agent orchestration / harness 设计,缺少可扩展的 model training 栈。
  2. 环境不可复用:每个研究项目重建 sandbox、rollout、eval 管道——数据集、训练配方、评测协议无法跨 harness / 域 / 项目移植。

论文论断:环境层不应是某个训练栈的副产品,而应是独立、薄、可自托管的 standalone service——这正是 Microsoft Harness 系列(Orchard → OpenWebRL → OpenForge RL → LongHorizon 对照系)的第一块地基。

Env、Recipes 与 Trainer 的分层,Orchard 的环境服务是公共底座,三条 Recipe 分别定义任务特定的数据、奖励、模型和评测。

公共层提供生命周期与执行原语,Recipe 层再决定数据、奖励、模型和评测。

Orchard 分三层:

层 内容 职责
Recipes Orchard-SWE / Orchard-GUI / Orchard-Claw 轨迹收集、数据策展、reward、policy 优化(SFT+RL)
Orchard Env K8s-native sandbox service + Python SDK 生命周期、exec、文件 I/O、网络策略、REST API
Trainer vendored slime fork RL 训练;rollout 代码在 examples/orchard/

Orchard Env 的关键设计包括:

  • 三层架构:Client SDK → FastAPI Orchestrator → In-pod Agent(注入用户镜像)。
  • Runtime agent injection:init container 注入自包含 Python interpreter 的 exec agent,任意 Docker 镜像零修改接入——支持 SWE-bench 数百种异构镜像。
  • Hot path 优化:创建/删除走 K8s API(cold path);exec / file / health 直连 Pod IP(hot path),绕过 kubectl exec WebSocket 开销。
  • Built-in harnesses:每个 sandbox 预装 codex、claude、pi、opencode、hermes 等于 PATH——换 harness = 改命令,不改镜像。
  • Multi-replica orchestrator:Redis 状态 + 分布式锁;Calico NetworkPolicy 默认 deny-egress;TTL cleanup;API-key auth。

三条 Recipe(同 Env、不同域),Orchard-SWE(Qwen3.5-35B-A3B MoE):

  • 107K 蒸馏轨迹(MiniMax-M2.5 + Qwen3.5-397B,OpenHands + mini-swe-agent harness)。
  • 保留 unresolved 轨迹(多数 prior work 只留 success)。
  • Credit-assignment SFT:retrospective value estimation 从失败轨迹提取 productive rise segments。
  • Balanced Adaptive Rollout (BAR):在线组装 reward-balanced 轨迹组做 sparse-reward RL。
  • 论文 v3 报告:Qwen3.5-35B-A3B 经 RPR-based RL 达 69.7% SWE-bench Verified,加入 value-model reranking 后达 73.0%。这两个数字对应不同推理配置,不能写成同一训练阶段的自然递进。

Orchard-GUI(Qwen3-VL-4B-Thinking):

  • 0.4K SFT + 2.2K RL on live websites;generic ReAct browser harness。
  • WebVoyager 74.1% / Online-Mind2Web 67.0% / DeepShop 64.0% → 平均 68.4%。
  • 超越 235B teacher;长 horizon benchmark 增益最大。

Orchard-Claw(Qwen3-30B-A3B-Thinking):

  • 0.2K Opus 合成任务;SFT+RL across two harnesses。
  • ClawEval 59.6% pass@3(31.7% pass³);换 ZeroClaw 推理 → 73.9% pass@3(+14.3)。

1.1. 系统吞吐、模型结果与数据规模

系统指标、模型成功率和成本估算属于三类证据,不能在没有配置说明时互相替代。

下列数字均对应论文 v3 的特定模型、Harness、任务集与基础设施设置。

Orchard Env 的系统工程指标如下:

指标 Orchard Env 对照
平均 exec 延迟 0.28 s E2B 0.747 s(2.7×慢)、Modal 2.046 s(7.3×慢)
1000 并行 sandbox 100% 成功,26 s 端到端,~154 cmd/s —
128 sandbox × 240 h 成本 673spot∗∗/673 spot /3,362 on-demand Daytona/E2B ~$7,078(0.10× spot)

Terminal-Bench 2.0 无回归(Docker → Orchard Env):GPT-4.1 34.1→35.1,MiniMax-M2.5 52.6→54.4,Qwen3-8B 7.0→8.8——Env 是 drop-in substrate。

Generalization 主题(论文核心 claim):

  • Orchard-SWE 在训练未见 harness Kimi-CLI 上仍 45.0% Verified / 20.1% Terminal-Bench 2.0(OpenSWE-32B → 3.6% / 0.0%)。
  • Orchard-Claw 换强 harness 后 pass³ +9.3 / pass@3 +14.3。
  • Orchard-GUI 4B beat 235B teacher on 2/3 benchmarks。

Dataset(HuggingFace microsoft/Orchard)。 - swe:107,185 rollouts,19,287 unique instances,2,788 repos,均 47.5 turns/trajectory。

  • gui:3,070 judge-verified per-step rollouts,409 WebVoyager-style tasks,含 screenshot multimodal。

Roadmap:Stateful sandboxes(pause/resume/branching)——从轨迹末端的 scalar reward 转向 per-turn Monte-Carlo credit assignment。论文给出明确动机:SWE 轨迹均 47.5 turns,却只有一个 outcome reward——branching 从同一 snapshot fork 多条 continuation 可直接 Monte-Carlo 估计 state value,并把 per-turn credit assignment 从「事后推断」变成「可测量」;prefix sharing 使 tree-structured search 比 flat rollout 便宜。

Trainer 层(slime fork):Orchard 不绑定单一 RL 算法,而是在 trainer/slime/examples/orchard/ 提供 rollout glue;ORCHARD_CHANGES.md 追踪相对上游 slime 的 fork diff——意味着 Recipe 层可换算法(on-policy distillation、rubric process reward、value-model reranking 均在 Orchard-SWE 出现),Env 层保持稳定。

OpenWebRL(姊妹论文,2026-06):在同一 Env 上把 Orchard-GUI 扩展为 live website 在线 RL——fault-tolerant browser env(navigation retry、timeout、structured failure attribution),OpenWebRL-4B 在 Online-Mind2Web 67.0%、DeepShop 64.0%,与 Orchard-GUI 数字互证。OpenWebRL 是 GUI Recipe 的在线延伸。

集群门槛与实验边界,这些限制把已经测量的系统能力与尚待验证的外推结论分开。

部署侧需要 AKS、EKS、GKE 或自建 Kubernetes 集群,对个人开发者仍有门槛;训练侧虽然把 Env 抽成服务,RL 配方仍依赖 slime fork 与特定 rollout 代码。SWE 的信用分配来自事后估计,不是环境原生逐步奖励,branching sandbox 在论文中仍属路线图。

实验侧的 Claw 与 GUI 数据规模有限,稳定性和 scaling 行为没有被充分覆盖。73.0% SWE 结果包含 value-model reranking,不能代表单次策略输出;跨 Harness 的收益也只在论文给出的组合上成立。与后续 OpenWebRL、OpenForge RL 的关系应按具体新增机制理解,不能把整个系列的能力提前归给 Orchard 本体。

Orchard 把 Recipe、Env 与 trainer 分层,核心是让环境生命周期和高频执行路径成为稳定服务。系统拆解必须同时说明控制面和数据面。

可复现轨迹必须记录环境状态。文件、进程、网络和资源元数据都可能改变后续动作,单独保存聊天消息无法重建这些变化。

系统拆解,控制面负责创建和删除,数据面负责高频命令与文件操作,二者的延迟和故障模式不同。

分层的意义是让 Recipe 依赖稳定 API,同时允许底层集群与上层训练算法分别演进。

┌─────────────────────────────────────────────────────────┐
│  Recipes(研究层,可替换)                                  │
│  Orchard-SWE │ Orchard-GUI │ Orchard-Claw │ OpenForge…  │
└──────────────────────────┬──────────────────────────────┘
                           │ REST / SDK
┌──────────────────────────▼──────────────────────────────┐
│  Orchard Env(Foundation — 薄环境服务)                    │
│  SandboxClient → Orchestrator → Pod + In-pod Agent       │
│  create / exec / files / patch / delete / network policy │
└──────────────────────────┬──────────────────────────────┘
                           │
┌──────────────────────────▼──────────────────────────────┐
│  Kubernetes 集群 + 任意任务镜像 + 预装 harness             │
└─────────────────────────────────────────────────────────┘

Quick start:

from orchard_env import SandboxClient

with SandboxClient() as client:
    with client.create_sandbox("python:3.11-slim") as sandbox:
        print(sandbox.exec("echo 'Hello, Orchard!'").stdout)

Env 不假设上层是 trainer、inference backend 还是 task domain——同一 API 可用于 distillation rollout、on-policy RL、evaluation 三阶段。

1.2. 环境服务究竟保存什么状态

把一次 rollout 写成状态机更容易看出 Orchard Env 的职责。沙箱在时刻 tt 的状态记为

Et=(I,Ft,Pt,Nt,Mt),E_t=(I,F_t,P_t,N_t,M_t),

II 是不可变的基础镜像与任务初始材料,FtF_t 是文件系统,PtP_t 是进程集合,NtN_t 是网络策略与连接状态,MtM_t 是资源限制和生命周期元数据。Agent 动作 ata_t 通过环境执行函数产生新状态与观测:

(Et+1,ot+1)=T(Et,at).(E_{t+1},o_{t+1})=T(E_t,a_t).

Harness 决定下一步调用什么工具,trainer 决定怎样用整条轨迹更新策略,Orchard Env 负责让同一个动作在隔离环境中执行并返回结构化结果。这个边界很重要:环境可以确认命令退出码和文件变化,却不知道一段补丁是否真正解决用户问题;验证器可以运行隐藏测试形成奖励,但不应被硬编码进通用 exec API。

创建和删除 Pod 属于控制平面冷路径,命令执行与文件 I/O 属于 rollout 的高频数据路径。若每条命令都经过 Kubernetes API server 的 exec 通道,一条几十轮轨迹会反复支付连接与编排开销。Orchard 把 in-pod agent 注入容器,让 orchestrator 直接访问 Pod IP,正是在稳定服务边界下缩短热路径。性能收益来自系统路径,不表示模型动作更少或任务更容易。

一个五步轨迹,以软件修复为例,初始镜像包含仓库、依赖与失败测试。Agent 依次执行:读取错误日志、定位文件、写补丁、运行局部测试、运行完整测试。环境需要记录每个动作前后的工作目录、命令、退出码、stdout/stderr、超时、文件 diff 和资源消耗。最终 reward 为 1 时,不能反推五步都正确:第二步可能走了弯路,第三步可能引入临时错误,第四步又把它修掉。

若最终测试失败,失败轨迹仍包含可复用片段。比如局部测试从 5 个失败降到 1 个,说明前几步产生了有效进度。Credit-assignment SFT 的问题就是从整条未解决轨迹中识别 productive segments,再把它们转成监督,而不是把所有失败 token 一起丢掉。

长轨迹通常只有稀疏终局奖励,失败样本中仍可能包含有效进度。训练方法需要从轨迹中提取比较信号,同时保留环境转移。

轨迹能否跨 Harness 使用,取决于字段脱离某个 prompt 模板后是否仍可解释。信用分配、轨迹 schema 与受控迁移实验共同检验这种可迁移性。

2. 稀疏奖励与信用分配手算

设一条轨迹有四个决策,最终隐藏测试给 R=1R=1 或 00。最粗糙的 Monte Carlo 回报把同一个 RR 分给每个动作:

Gt=R,t=1,…,4.G_t=R,\qquad t=1,\ldots,4.

成功轨迹中所有动作都被正向强化,包括无效搜索;失败轨迹中真正有用的前置修改也得不到正信号。如果同一中间状态 s2s_2 能够分叉采样四条 continuation,最终奖励为 (1,1,0,0)(1,1,0,0),则状态价值可估为

V^(s2)=1+1+0+04=0.5.\hat V(s_2)=\frac{1+1+0+0}{4}=0.5.

再比较某个动作 aa 后分支均值 0.75 与状态均值 0.5,可以得到近似优势 A^(s2,a)=0.25\hat A(s_2,a)=0.25。这比从单条终局奖励猜测第二步贡献更直接。代价是要从相同文件、进程和环境状态 fork 多次;因此 pause、resume 与 branching 属于环境能力,而不仅是 trainer 算法。

当前路线图中的 stateful sandbox 正在补这一层。实现时 checkpoint 不能只复制文件:后台进程、端口、环境变量、工作目录、临时挂载和随机状态都会影响 continuation。若恢复后的 EtE_t 与原状态不等价,分支回报差异可能来自 checkpoint 漂移,而非 Agent 动作。

BAR 一类 balanced rollout 处理的是另一处稀疏性。假设同一任务采样 8 条轨迹,奖励全为 0,组内策略梯度没有可区分信号;若全为 1,也难以判断哪些行为更好。通过调整任务与 rollout,使 batch 中保留成功和失败样本,可以提高比较信号。但重采样会改变训练分布,必须记录每个任务的原始成功概率和被采样概率,不能把平衡后的训练分布当成真实部署频率。

可移植轨迹需要什么字段,“同一环境可以跨 Harness 复用”要求轨迹脱离某个 prompt 模板仍可解释。一条最小轨迹应包含:环境镜像与任务版本、初始状态标识、模型与 Harness 版本、每步原始动作、工具 schema、观测、文件 diff、验证器版本、奖励分项、终止原因和资源统计。只保存 OpenAI messages 会丢失环境转移;只保存 shell 历史又无法重建模型当时看到的上下文。

失败也要分类。模型选择了错误命令是 policy failure;命令正确但网站超时是 environment failure;验证器误判是 reward failure;Harness 丢失截图或截断 stdout 是 observation failure。将它们都写成 reward=0,会让训练器把基础设施噪声当作模型行为惩罚。Orchard 的薄环境边界提供了统一观测点,但分类规则仍要由 Recipe 明确。

轨迹版本还要处理数据泄漏。同一仓库的相似 issue 若同时进入训练和评测,模型可能复用补丁模式;GUI live site 的内容随时间变化,同一个 task ID 也可能不再等价。数据集应保存仓库 commit、镜像哈希、网站快照或执行时间,并按仓库、任务模板与时间进行分割。

怎样验证 Harness-agnostic,“支持多 Harness”只说明它们能在 Pod 中启动;“训练具有 Harness 泛化”还需要受控实验。固定同一 policy checkpoint、任务实例、环境镜像、工具权限与预算,分别使用训练时 Harness、未见 Harness 和最小工具循环。记录最终成功、工具调用、token、墙钟、环境错误和轨迹长度。

然后交换训练与部署组合:在 Harness A 收集数据并训练,分别在 A、B 评测;再用 Harness B 数据训练,分别在 A、B 评测。若所有模型在 B 上都更好,收益可能来自 B 本身更强;只有跨组合矩阵才能区分 policy 泛化、Harness 增益和二者交互。

环境层还要做无回归测试。相同动作序列在 Docker direct 与 Orchard Env 中执行,最终文件哈希、退出码和测试结果应一致;有差异时检查网络、用户权限、文件系统、时钟与资源限制。论文报告的 Terminal-Bench 对照支持其环境可作为替代底座,但新的镜像、集群策略和版本仍需持续回归。

系统扩展性则用并发曲线报告:沙箱创建成功率、P50/P95 创建时间、命令延迟、吞吐、Redis 与 API server 负载、清理失败和资源泄漏。单次平均 exec 延迟不能证明千并发稳定,也不能直接推算长 RL 任务的总成本。

Orchard 在 Long-Horizon 栈中提供执行环境和轨迹底座;部署期任务状态由上层 Harness 管理。三条 Recipe 的结果也来自不同模型与配置。

v3 的实验数字需要与终局奖励、状态分叉和故障归因一起理解,同时区分当前已经完成的能力与仓库路线图。

2.1. 它在 Long-Horizon 栈中的位置

Orchard 解决“在哪里可靠地产生动作—观测轨迹”,Recipe 解决“怎样从轨迹学习”,Harness 解决“部署时怎样选择动作并维护任务状态”。三层共享一些名词,权威状态却不同。环境中的文件与进程是事实源;Harness 的计划是暂定控制状态;trainer 中的 advantage 是学习估计量。混成一个 JSON 会让恢复和审计都失去边界。

对于 Long-Horizon 研究,Orchard 最关键的价值是把可执行环境变成稳定服务,单个 SWE 或 GUI 分数只是这套底座的一次结果。只有环境能够复现、分叉和验证,长轨迹中的进度、错误传播与恢复才有可测对象。未来 stateful sandbox 真正落地后,还要验证 checkpoint 完整性、分支隔离和成本;路线图本身不能当作已经具备的能力。

Recipe 的共同流程包含五个环节:在 Env 内采集 teacher 与 student 轨迹,保留成功和失败样本,做 SFT 初始化,用稀疏或过程奖励训练,并在训练未见的 Harness、语言或任务上验证迁移。这里容易混淆三个层次:Env 能启动多个 Harness,说明接口兼容;模型在多个 Harness 数据上训练,说明训练覆盖;模型换到未见 Harness 仍提高,才是策略迁移证据。

v3 实验数字应怎样读取,Orchard v3于 2026 年 7 月 30 日修订。摘要中的三个主结果来自三条不同 Recipe,不能拼成一个统一模型。Orchard-SWE 使用 Qwen3.5-35B-A3B,RPR-based RL 在 SWE-bench Verified 达 69.7%,value-model reranking 达 73.0%;Orchard-GUI 使用 4B 视觉语言模型,以 0.4K 蒸馏轨迹和 2.2K 开放任务训练,在 WebVoyager、Online-Mind2Web 与 DeepShop 的平均成功率为 68.4%;Orchard-Claw 用 0.2K 合成任务训练,Claw-Eval 为 59.6% pass@3,搭配 ZeroClaw Harness 时为 73.9%。

73.0% 比 69.7% 高 3.3 个百分点,但增加的是推理期 value-model reranking,不应表述成「RL 又训练到 73.0%」。同理,Claw 从 59.6% 到 73.9% 同时更换 Harness,差值 14.3 个百分点包含 Harness 效应,不能全归给模型参数。论文用这些对照支持环境与轨迹可跨 Harness 使用,不能推出任意 Harness 互换都会提升。

GUI 三项平均值可复算:

Aˉ=74.1+67.0+64.03=68.37%≈68.4%.(3)\bar A=\frac{74.1+67.0+64.0}{3}=68.37\%\approx68.4\%. \tag{3}

这个平均把三个 benchmark 等权处理;它没有按样本量加权,也不表示每类网站都有 68.4% 成功率。报告平均数时应同时保留三列,避免一个任务的优势遮住另一个任务的弱点。

论文还报告环境系统指标:平均 exec 延迟 0.28 秒,对照 E2B 0.747 秒、Modal 2.046 秒;1000 个并行 sandbox 的实验报告 100% 成功、26 秒端到端和约 154 command/s。成本表以 128 个 sandbox 连续 240 小时为场景,Orchard spot 估算为 673 美元、on-demand 为 3362 美元,对照托管方案约 7078 美元。它们是特定云定价、实例和负载下的测量,不是跨地区长期不变的价格。成本结论应复现实例类型、折扣和利用率后再采用。

若按表中数字计算 spot 相对 7078 美元的比例,

6737078≈0.095,(4)\frac{673}{7078}\approx0.095, \tag{4}

约为 0.10 倍;on-demand 比例则为 3362/7078≈0.4753362/7078\approx0.475。因此「约十分之一」只适用于 spot 行,不适用于 Orchard 所有部署方式。

信用分配为何需要环境快照,SWE 轨迹平均 47.5 turns,却常只有终局 reward。将终局 RR 分给所有动作会奖励成功轨迹中的弯路,也会抹掉失败轨迹里的有效修改。若从同一状态 sts_t 分叉 nn 条 continuation,状态价值可以用

V^(st)=1n∑i=1nRi(5)\hat V(s_t)=\frac1n\sum_{i=1}^{n}R_i \tag{5}

估计。假设四个分支奖励为 (1,1,0,0)(1,1,0,0),则 V^(st)=0.5\hat V(s_t)=0.5;某动作后的四个分支为 (1,1,1,0)(1,1,1,0),动作条件价值为 0.75,近似优势为 0.25。这个估计仍有方差,却比单条轨迹事后猜测哪一步有用更直接。

分叉成立的前提是恢复状态等价。设环境快照

Kt=(Ft,Pt,Nt,Wt,Rt),(6)K_t=(F_t,P_t,N_t,W_t,R_t), \tag{6}

FtF_t 是文件系统,PtP_t 是进程,NtN_t 是网络状态,WtW_t 是工作目录与环境变量,RtR_t 是随机状态。只复制文件而遗漏数据库进程、监听端口或随机种子,两条 continuation 的奖励差异就不只来自动作。论文把 stateful sandbox 的 pause、resume、branching 列为路线图;截至 v3,这不能写成 Orchard Env 已提供并验证的现成功能。

BAR 处理的是另一种稀疏性。若同一任务的 rollout 全为 0 或全为 1,组内比较几乎没有区分信号;平衡成功和失败轨迹可增加梯度信息。但重采样改变训练分布。设原任务采样概率为 p(x)p(x),平衡后为 q(x)q(x),若要估计原分布期望,需要重要性权重 p(x)/q(x)p(x)/q(x)。训练可以选择不校正以追求学习效率,评测却必须回到未平衡分布,否则会高估部署成功率。

2.2. 可移植轨迹与故障归因

一条轨迹若只保存消息数组,换 Harness 后往往无法解释。最低字段包括:镜像与任务版本、初始状态、模型和 Harness 版本、工具 schema、每步动作与原始观测、退出码、文件 diff、验证器版本、奖励分项、终止原因和资源统计。涉及网页时还要保存时间与关键响应,涉及仓库时保存 commit;否则相同 task ID 可能已不是相同环境。

失败至少分成四类。Policy failure 是模型选择错误动作;environment failure 是正确动作遇到基础设施故障;observation failure 是 Harness 截断或丢失结果;reward failure 是 verifier 误判。若四类都记为 reward=0,训练器会把集群超时当作模型错误学习。Orchard 的薄服务边界提供统一记录点,但分类标签仍要由 Recipe 和 verifier 共同给出。

验证「Harness-agnostic」要做交叉矩阵。固定模型 checkpoint、任务、镜像、权限与预算,在 A、B 两种 Harness 上评测;再分别用 A 与 B 的数据训练,得到训练×部署的四格结果。若所有模型在 B 上都更高,可能只是 B 更强;若 A 数据训练的模型在未见 B 上仍比基线提高,才支持策略迁移。环境接口能运行 A 与 B 只是必要条件,不是泛化结论。

Orchard 在 Long-Horizon 栈中提供可执行、可扩展的轨迹底座;部署期目标版本、事实审计与恢复仍属于 Harness。它的论文结果表明同一 Env 可以支撑三种 Recipe,也展示失败轨迹和跨 Harness 对照的价值。论文没有证明薄环境自动带来长期一致性,更没有证明路线图中的 branching 已落地。把这条边界写明,才能让环境贡献与模型能力各自接受正确的检验。

迁移到新环境以后,需要先验证动作序列与终态是否等价,再讨论吞吐与成本。微基准不能直接替代完整 rollout。

安全、资源回收和版本锁定同样属于可复现性,环境等价性、生命周期和论文复现边界都应进入验收流程。

把任务从 Docker direct 搬到 Orchard Env 后,成功率相近不等于环境完全等价。验收时应先固定一组动作序列,在两边比较命令退出码、stdout/stderr、最终文件哈希、用户与权限、网络解析、时钟、资源上限和后台进程。对动作 a1:Ta_{1:T},可把环境指纹写成

Φ(ET)=(h(FT),h(PT),h(NT),uT,rT),(7)\Phi(E_T)= (h(F_T),h(P_T),h(N_T),u_T,r_T), \tag{7}

h(FT)h(F_T) 是相关文件哈希,h(PT)h(P_T) 是进程及端口摘要,h(NT)h(N_T) 是网络策略摘要,uTu_T 与 rTr_T 是用户权限和资源限制。两边任务 verifier 一致但 Φ\Phi 不同,仍应调查差异,因为后续更长轨迹可能放大它。

论文报告 Terminal-Bench 2.0 从 Docker 到 Orchard Env 没有回归:GPT-4.1 为 34.1→35.1,MiniMax-M2.5 为 52.6→54.4,Qwen3-8B 为 7.0→8.8。这里的小幅上升不应解释为 Env 提升模型能力;有限样本、运行随机性与基础设施差异都可能产生波动。它支持的是「迁移未显示系统性下降」,不是「换环境会涨分」。

并发实验要分控制面和数据面。创建、删除沙箱经过 Kubernetes API,是低频冷路径;exec、文件 I/O 与健康检查直连 Pod 内 agent,是 rollout 高频热路径。总任务时间近似为

Trun=Tcreate+∑t=1n(Tmodel,t+Texec,t)+Tverify+Tdelete.(8)T_{\mathrm{run}}=T_{\mathrm{create}}+ \sum_{t=1}^{n}(T_{\mathrm{model},t}+T_{\mathrm{exec},t})+ T_{\mathrm{verify}}+T_{\mathrm{delete}}. \tag{8}

平均 exec 从 0.747 秒降到 0.28 秒,若一条轨迹有 100 次串行命令且其他项不变,仅该项理论上少约 46.7 秒;真实收益还受模型生成、并发排队和长命令执行支配。单命令微基准不能直接替代完整 rollout 吞吐。

安全与生命周期不是附加项,训练 Agent 会执行模型生成的命令,隔离边界必须默认不信任轨迹。Orchard 使用 NetworkPolicy 做默认拒绝出站、API key 验证、TTL cleanup、Redis 状态与分布式锁。这些机制各自处理不同风险:网络策略限制数据外传,TTL 回收遗留资源,锁避免多副本同时修改同一 sandbox。任何一项存在都不能替代其余项。

删除沙箱还要验证是否真正回收。应记录创建数、正常删除数、TTL 删除数、删除失败数和残留资源,并满足

Ncreate=Ndelete+Nttl+Nlive+Nleak.(9)N_{\mathrm{create}}= N_{\mathrm{delete}}+N_{\mathrm{ttl}}+N_{\mathrm{live}}+N_{\mathrm{leak}}. \tag{9}

长时间压测中 NleakN_{\mathrm{leak}} 必须可见,不能只报告成功创建率。网络策略也应以实际拒绝测试验收,包括 DNS、元数据服务、集群内其他 Pod 和公网出口;配置文件看起来正确不等于数据面真的阻断。

运行时注入 in-pod agent 使任意镜像不必预装控制服务,但也扩大供应链边界。注入产物应固定版本与哈希,客户端、orchestrator 和 pod agent 的协议版本要协商;否则滚动升级时,同一 REST 请求可能在不同 Pod 得到不同语义。轨迹必须记录这三个版本,才能复现一次失败。

3. 从数据到结论的检查表

v1、v2 与 v3 的训练方法和主数字不同,本文采用 2026 年 7 月 30 日的 v3;67.5% 等早期结果必须标明版本。结果还要区分 policy、Harness 与 reranker,组合系统的分数不能全部归给基础模型。benchmark、样本数、预算和 pass 指标共同构成数字口径,pass@3 与单次成功率不是同一量。

环境结果要附实例、区域、spot/on-demand、并发、持续时间和失败处理;训练结果要附 backbone、数据规模、Harness、reward 与推理配置;迁移结果要给训练×部署 Harness 矩阵。路线图项目单列为「尚未验证」,特别是 stateful pause/resume/branching。按这套口径,Orchard 的可靠结论是:一个薄、可自托管的 Kubernetes 环境服务能够复用于三类 Agentic Modeling Recipe,并在论文设置下给出有竞争力的结果;更广泛的成本、泛化与状态分叉能力仍需在各自环境中复现。

复现时还要锁定官方仓库 commit,而不能只写 main。论文摘要、代码默认配置和数据集卡可能在不同日期更新,三者不一致时,以所复现实验对应的版本为准,并在结果表列出差异。若数据集只提供轨迹而缺少原始环境镜像,就只能复现离线训练或统计,不能声称重现了完整 rollout。相反,环境能够启动但缺少同版模型与 reward 配置,也只能验证系统工程部分。把「论文数字复现」「环境部署复现」「训练路线复现」分开,失败时才知道缺的是哪一层证据。

Orchard Env 把 rollout 环境放进 Kubernetes Pod,模型推理与 trainer 可以在另一组节点。一次 episode 的资源不只包含 GPU token,还包含 sandbox 冷启动、CPU/内存驻留、镜像拉取、网络与验证器。设 episode ii 的总成本为:

Ci=Cmodel,i+Csandbox,i+Cstorage,i+Cnetwork,i+Cverify,i.(10)C_i=C_{model,i}+C_{sandbox,i}+C_{storage,i}+C_{network,i}+C_{verify,i}. \tag{10}

Sandbox 成本可进一步按 Pod 存活时间估算。若分配 cic_i 个 vCPU、mim_i GiB 内存,单价分别为 pc,pmp_c,p_m,持续 tit_i 小时,则:

Csandbox,i=ti(cipc+mipm)+Cstartup,i.(11)C_{sandbox,i}=t_i(c_ip_c+m_ip_m)+C_{startup,i}. \tag{11}

Spot 实例会降低单价,也会增加抢占与恢复成本。报告「比托管 sandbox 便宜」时,需要同时给区域、实例类型、spot 比例、失败重试与资源利用率;脱离这些条件的倍数很快会过期。

启动开销在短任务中占比很高,在长任务中被摊薄。假设创建 Pod 需要 12 秒,100 次 exec 每次 0.28 秒,工具纯调用时间为 28 秒;仅创建就占两者合计的 30%。若 episode 只有 5 次 exec,创建几乎支配环境时间。热池可以减少冷启动,却需要为闲置 Pod 支付资源,并加强租户间清理。

任务入队
  ↓ create Pod / 注入 harness payload
环境就绪
  ↓ model call ↔ exec/file/screenshot/action
轨迹完成
  ↓ 独立 verifier
奖励与事件日志
  ↓ delete Pod / TTL 兜底
资源回收

每一段都应产生状态事件。Pod 创建成功却未通过 health check,属于 environment error;Harness 退出而 verifier 失败,属于 task failure;Verifier 自身超时则单列 verifier error。全都压成 reward 0,会让 trainer 把基础设施噪声当作策略失败。

并发、排队与 GPU 空转,Rollout 中模型生成占 GPU,工具执行与网页等待主要占 CPU/网络。并发 sandbox 的目的之一,是让其他 episode 在某条轨迹等待环境时继续请求模型。设单条 episode 的模型占用比例为 ρ=Tmodel/Trun\rho=T_{model}/T_{run},理想情况下让推理服务持续有请求,大致需要不少于 1/ρ1/\rho 条交错轨迹。

若 Tmodel=30s,Trun=150sT_{model}=30s,T_{run}=150s,则 ρ=0.2\rho=0.2,至少约 5 条完全错开的轨迹才能覆盖等待空隙。现实还有动态批处理、长短轨迹和 Proxy 排队,所需并发更高。并发上升后,Kubernetes 调度、镜像拉取、Redis 锁和网络出口会成为新瓶颈。

应该同时监控 GPU token 吞吐、Proxy 队列深度、Pod 启动 P50/P99、exec P50/P99、有效 episode 比例和 verifier 延迟。GPU 利用率高但有效 episode 比例低,说明系统正在高效生成无用轨迹;Pod 很多但 Proxy 队列为空,可能是环境或 Harness 阻塞。

3.1. 环境状态的数据流

官方架构文档说明,Orchestrator 只通过 Kubernetes API 处理 Pod create/delete;exec、文件 I/O 与 health check 直接访问 Pod IP,避开 Kubernetes API 与 WebSocket 的热路径开销。Harness payload 以只读方式注入,在 Kubernetes 1.33 及以上可使用 image: volume,让 kubelet 每节点拉取一次。

一次 exec 的状态流可以表示为:

xt=(sandbox_id,command,timeout,env,workdir),(12)x_t=(sandbox\_id,command,timeout,env,workdir), \tag{12}

Pod 内 agent 返回:

ot=(exit_code,stdout,stderr,timestamps,resource_usage).(13)o_t=(exit\_code,stdout,stderr,timestamps,resource\_usage). \tag{13}

控制面随后把 oto_t 写入轨迹,并由下一次模型调用消费。exit_code=0 只说明进程正常结束,任务状态仍需 verifier 判断;超时也不说明命令没有产生副作用,恢复时应先读取文件和进程状态。

文件 I/O、apply patch、screenshot 与 action 都要绑定 sandbox ID。分布式锁避免两个 orchestrator 副本同时处理同一生命周期操作,却无法阻止两个 Agent 在同一工作区产生语义冲突;上层调度仍需隔离任务或声明共享写入规则。

把 Docker benchmark 迁到 Orchard Env 时,可以逐层检查环境等价性:镜像和依赖一致;初始文件哈希一致;用户、权限、工作目录与环境变量一致;网络策略满足任务需要;同一参考解得到相同 verifier 结果;已知错误解稳定失败。每层通过后再运行模型,避免用 Agent 分数承担环境调试。

随机性也要记录。数据库生成数据、游戏环境和网页时钟可能让两个 sandbox 从不同初态开始。种子只能控制显式随机源,外部 API 与实时网站仍会漂移。对这类任务,应保存关键初态摘要,或在同一时间窗口交错运行对照系统。

截至 2026 年 10 月,官方仓库仍把 pause、resume、branching 与 prefix sharing 放在 Roadmap,当前 sandbox 生命周期保持线性:创建、驱动若干轮、销毁。现有代码与论文结果已经开源,路线图能力却不能写成已交付功能。

这些能力之所以重要,与 credit assignment 直接相关。若能在第 tt 步保存完整状态 sts_t,从同一快照分叉 KK 条 continuation,就可以估计某动作后的状态价值:

V^(st)=1K∑k=1KR(τk∣st).(14)\hat V(s_t)=\frac1K\sum_{k=1}^{K}R(\tau_k\mid s_t). \tag{14}

当前线性环境要估计同一个量,只能把前缀重新执行 KK 次。假设前缀成本为 CpC_p,每条 continuation 为 CcC_c,无快照成本是 K(Cp+Cc)K(C_p+C_c);共享前缀后约为 Cp+KCc+CsnapshotC_p+KC_c+C_{snapshot}。前缀越长,节省越明显。

完整快照比复制文件困难。进程内存、监听端口、数据库缓冲、网络连接和随机状态都要恢复;外部网站或云资源无法随 Pod 一起回滚。Branching 若复用同一外部账户,多个分支还会互相污染。因而路线图中的「完整状态」必须说明覆盖范围,不能用文件系统 snapshot 代表全部环境。

Pause/resume 也需要版本兼容。恢复时 Pod agent、Harness、镜像和 verifier 若已升级,旧状态可能无法解释。Checkpoint manifest 至少记录镜像摘要、协议版本、资源 ID 与外部依赖,加载前逐项核对。

4. 数据集规模怎样读

官方仓库当前列出 swe 与 gui 两个数据子集。SWE 部分含 107,185 条多轮 rollout,覆盖 19,287 个任务实例、2,788 个仓库,其中 74,649 条 resolved、32,536 条 unresolved,平均每条 47.5 turn;GUI 部分含 3,070 条经 judge 验证的成功逐步轨迹,来自 409 个 WebVoyager 风格任务。

轨迹数不等于独立任务数。SWE 中同一任务可能有多条 rollout,训练/验证划分若只按轨迹随机切分,会让同一 issue 或仓库跨集合泄漏。应按任务、仓库和时间做去重与分组,并公开分割规则。GUI 数据只包含 judge-verified successful rollouts,适合蒸馏成功行为,却不能单独提供完整失败分布。

Resolved/unresolved 也不直接等于每一步的正负标签。未解决轨迹中可能含有有价值的定位、测试和局部修复,Orchard-SWE 的 credit-assignment SFT 正是要回收这些 productive segments。片段选择若依赖事后 value estimate,应记录估计模型和阈值,避免把同一条轨迹在不同版本下切出不同训练集却仍使用同一名称。

从数据到模型结果还隔着 backbone、Harness、reward 与预算。107K 轨迹说明数据规模与来源,69.7% 或 73.0% 则属于具体 Recipe 和 reranking 配置。把两者写在同一段时仍要保留因果边界,数据量本身不保证结果。

大规模 rollout 不会同时结束。软件任务可能跑测试几十分钟,GUI 任务也会被网页加载和限流拖慢。若 trainer 等固定 batch 的全部 episode 返回,最慢轨迹成为同步屏障;若到时间就丢弃,训练集又会偏向短任务。Orchard Env 解决环境启动和交互,trainer 仍需定义 batch 完成与过期策略。

一条队列记录至少包含 task_id、attempt_id、policy_version、sandbox_id、优先级、租约到期时间和重试次数。Worker 领取任务后续租;进程崩溃且租约过期,任务回到队列。重试沿用相同 task_id,新建 attempt_id,这样可以区分一个任务的多次基础设施尝试。

幂等性覆盖控制面和任务面。重复 create 请求不应创建两个活跃 Pod,重复 delete 对已删除对象应安全返回;任务内部的 shell/API 副作用则由 Harness 与环境处理。控制面幂等不能阻止 Agent 重复发送邮件或重复提交远端资源。

故障归因可以用一棵简短决策树:Sandbox 未 ready,归为 startup;交互中 Pod 消失,归为 environment runtime;模型端点超时,归为 inference;Harness 正常结束但 verifier 未通过,归为 task failure;Verifier 自身异常,归为 verifier。每类错误分别统计,只有 task failure 与明确由 policy 引发的安全违规进入负奖励。

重试会改变观测成功率。设一次基础设施成功概率为 qq,在基础设施正常条件下任务成功概率为 pp。不重试时观测成功率为 pqpq。若只对基础设施失败最多重试 rr 次,至少一次获得有效环境的概率为:

qr=1−(1−q)r+1,(15)q_r=1-(1-q)^{r+1}, \tag{15}

观测成功率变为 pqrpq_r。取 p=0.4,q=0.9,r=1p=0.4,q=0.9,r=1,成功率从 0.360.36 升到 0.3960.396。这部分提升来自基础设施恢复,不代表 policy 变强。排行榜若允许不同重试策略,需要同时报告原始 attempt 与去除环境失败后的 conditional success。

任务失败不应无条件自动重跑。多次采样属于 pass@k,消耗更多模型和环境预算;把它混进 infra retry 会虚增单次可靠性。系统要先依据错误类别决定重启环境、继续 checkpoint,还是开始新的 policy sample。

每条 episode 应能从 task 追到 Pod、Harness、模型调用、工具事件、verifier 和删除记录。核心 trace ID 贯穿这些组件,时间戳使用统一时钟;否则 exec P99 上升时,很难判断延迟发生在客户端、orchestrator、Pod agent 还是命令本身。

清理指标要按 namespace、节点与镜像分层。残留 Pod 为零,不代表 PersistentVolume、Secret、Service 和 NetworkPolicy 都已回收。TTL controller 是兜底,正常路径仍应主动删除;若 TTL 删除比例持续升高,说明生命周期代码在漏资源。

安全测试也进入持续集成。准备一个恶意任务尝试访问云元数据、集群 API、其他 Pod、未授权公网域和宿主机路径,预期全部失败;再准备允许域与正常文件操作,确认策略没有把合法任务一并阻断。NetworkPolicy 规则存在只是配置证据,实际连接结果才证明隔离生效。

仓库已经公开环境代码、测试与贡献说明,部署者可以在自己的 Kubernetes 版本上重跑测试矩阵。Kubernetes 1.33 的 image: volume 优化属于条件能力,旧集群会走其他 payload 交付路径;性能报告应写明集群版本,不能把新路径数字默认外推到所有部署。

4.1. 参考资料

Orchard Env 的价值不只在于把容器创建封装成 API,更在于给上层 Recipe 一个稳定的环境语义。若 exec、文件读写和生命周期在版本之间悄悄变化,同一训练脚本会得到不同轨迹,环境便无法成为公共底座。可以把接口契约分成请求语义、执行语义、返回语义与故障语义四层。

请求语义规定命令、工作目录、环境变量、超时和用户身份怎样解释。空工作目录是回到镜像默认目录,还是沿用上一次命令的位置?环境变量是覆盖、合并还是删除?命令字符串由 shell 解析,还是直接作为 argv 执行?这些差异会改变引号、通配符、管道与退出码。Agent 生成的动作必须在记录中保存原始请求和规范化后的执行请求,才能判断错误来自模型还是客户端转换。

执行语义规定每次调用处于怎样的进程与文件状态。若每条命令启动独立 shell,cd 和临时变量不会自然延续;若复用持久终端,前一条命令的后台任务、alias 和当前目录会影响下一条。二者都可以成立,但不能混用。对于训练数据,更稳妥的方式是把依赖状态显式放进请求:传递 workdir、需要的环境变量和会话标识。隐式终端状态越多,轨迹越难跨 Harness 重放。

返回语义至少包含 stdout、stderr、退出码、开始与结束时间、是否超时以及输出是否截断。只返回合并文本会丢失程序把诊断写到 stderr 的事实;只保留收尾阶段若干字符,又可能删除真正的根因。输出过大时可以保存完整内容到对象存储,在轨迹中保留摘要、长度、哈希和截断窗口。模型实际看到哪一部分仍要单独记录,因为完整日志适合审计,不能冒充当时的观察。

故障语义要区分「请求未执行」「执行后失败」「结果可能已产生但确认丢失」。例如客户端超时,不代表 Pod 内命令没有运行;网络在响应返回前断开,文件可能已经写入。若调度器把这类请求直接重试,非幂等动作会执行两次。API 可以为每次动作分配 operation_id,Pod agent 缓存短期结果;同一 ID 重放时返回原结果,新的尝试则使用新 ID。这样至少能把传输重试与策略再次行动分开。

文件接口也有一致性选择。覆盖写入若进程中途死亡,读者可能看到半文件;原子写入可以先写临时文件、同步后重命名。补丁接口要说明基线哈希,避免 Agent 根据旧内容生成的 patch 落到已变化文件上。读取大文件时,分页的偏移按字节还是字符计算,会影响多字节文本。训练模型若依赖一种行为,换环境后便可能失效,因此这些都属于可移植性的一部分。

环境 API 的向后兼容不能只看 HTTP schema。字段仍存在但默认超时从 60 秒变成 10 秒,或者 stdout 截断从尾部改为头部,都会改变策略观察。协议版本应覆盖行为变化,回归测试则用一组带已知副作用的动作检查最终状态。上层轨迹记录客户端、orchestrator 与 Pod agent 三个版本,才能在滚动升级期间定位不同副本的语义差异。

线性一致性与生命周期竞争,多副本 orchestrator 需要处理同一 sandbox 的并发请求。Redis 锁可以序列化创建和删除,却仍要定义 exec 与 delete 冲突时的结果。若删除先取得锁,后到的 exec 应明确返回 sandbox terminating;若 exec 已进入 Pod,删除是等待它完成、发送终止信号,还是立即销毁?不同选择会影响轨迹终止原因和外部副作用。

把 sandbox 生命周期写成状态机更清楚:

Requested→Provisioning→Ready→Terminating→Deleted.\text{Requested}\rightarrow\text{Provisioning}\rightarrow\text{Ready} \rightarrow\text{Terminating}\rightarrow\text{Deleted}.

失败可以从 Provisioning 进入 Failed,从 Ready 因节点丢失进入 Lost。只有 Ready 接受普通执行;Terminating 拒绝新动作但允许查询最终状态;Deleted 的重复删除幂等成功。状态转换附带单调递增版本号,客户端提交动作时携带期望版本。若它基于旧状态操作,服务返回冲突,而非在新 Pod 或正在删除的 Pod 上猜测执行。

创建也会遇到「请求成功、响应丢失」。客户端再次创建时若使用相同 idempotency key,服务应返回已存在的 sandbox;若另建一个 Pod,两个环境都可能继续运行并消费资源。任务层再用 attempt_id 区分有意重试:同一幂等键代表恢复一次控制面调用,新 attempt 代表重新采样。把二者混在一起,会让成功率、成本与 pass@k 全部失真。

租约比永久所有权更适合大规模 worker。Worker 领取 sandbox 后定期续租,租约过期由回收器接管;但一次长命令可能超过续租周期。Pod agent 可以独立报告心跳,orchestrator 同时观察任务租约和环境活性。只因训练 worker 崩溃就立刻杀死 Pod,会丢掉可用于诊断的终态;无限保留又会泄漏资源。可设置短暂隔离窗口,保存事件与必要产物后再删除。