Harness 即泛化器:MIT 这项研究,或将重写 Agent 的设计范式
研究对象:《Language model harnesses are compositional generalizers》 作者:Alex Zhang、Omar Khattab(MIT CSAIL / OASYS) 发表:2026 年 7 月 20 日,以博客形式首发(非同行评审) 原文:https://alexzhang13.github.io/blog/2026/harness 解析日期:2026-08-10 前置系谱:Recursive Language Models(2025-10 博客 / arXiv:2512.24601)→ Mismanaged Geniuses Hypothesis(2026-04)→ 本文(2026-07)
目录
- 序:先正名,再论道
- 一、Transformer 为何天生不擅「组合泛化」
- 1.1 先说清「组合泛化」是什么
- 1.2 这不是新发现,是四十年的老账
- 1.3 MIT 这篇如何归因
- 1.4 一个具体后果:长度泛化失败
- 二、Harness 是什么?为何可能成为 Agent 的核心
- 2.1 定义
- 2.2 身份跃迁:从「胶水」到「归纳偏置的载体」
- 2.3 核心判据:Locally In-Distribution(LID,局部分布内)
- 2.4 反面教材:主流 Agent 全在违反 LID
- 2.5 等价类:harness 如何「制造」泛化
- 三、RLM:把上下文当环境,而非输入
- 3.1 一句话定义
- 3.2 演化谱系
- 3.3 接口设计:drop-in 替换
- 四、上下文卸载:长上下文问题的解法
- 4.1 根模型初始看见什么
- 4.2 可用原语
- 4.3 为什么这能解决长上下文
- 4.4 实测
- 五、程序化子调用:为何「代码」比「工具调用」高一个维度
- 5.1 分解空间(space of decompositions)
- 5.2 一个 for 循环的分野
- 5.3 中间结果留在变量里
- 5.4 涌现出的策略
- 六、为何短任务训练能迁移到百万 Token 长任务
- 6.1 实验配置
- 6.2 六个长度泛化环境
- 6.3 三个跨域迁移环境
- 6.4 结果
- 6.5 机理:轨迹被商掉了
- 6.6 最震撼的一个数字(来自 MGH)
- 七、Harness 会成为大模型架构的一部分吗
- 7.1 作者的表态
- 7.2 我的判断
- 7.3 一条反对意见,也须听
- 八、泼冷水:这项研究的局限与可疑之处
- 8.1 它是博客,不是论文
- 8.2 「不就是 subagent 吗」——这个质疑有实锤
- 8.3 泛化不是自动的,需要「推一把」
- 8.4 成本与延迟的真实代价
- 8.5 其他失败模式
- 8.6 一个理论上的隐忧:循环论证的风险
- 九、这对你意味着什么
- 9.1 三条可立即执行的原则
- 9.2 一个视角转换
- 附:一句话速记
- 参考
序:先正名,再论道
外部世界 任务 · 环境 · 工具 Harness 驾驭层 H: s→a 决定模型看见什么 神经网络 Transformer 编码状态 单次调用 主语是 harness,不是模型——归置偏置的载体在中间这一层 全景:外部世界 ⇄ Harness ⇄ 神经网络。七问的答案皆落于中间这一层。君所提之标题「Language Models are Harnessed Generalizers」,与原文略有出入。原题为 「Language model harnesses are compositional generalizers」——直译为「语言模型的外壳,才是组合泛化器」。
一字之差,意思大不同。原题的主语不是「模型」,而是 harness(外壳)。这不是措辞讲究,是论点本身:会泛化的那个东西,不是神经网络,是包着神经网络的那层程序。
还有一件事须先讲明:这是一篇博客,不是一篇经过同行评审的论文。 它有数据、有实验、有形式化,但没有匿名审稿人替你把关。读它当读一份来自一线的实验笔记,而非定论。后文第八节,我会专门泼冷水。
先给一张全景图,把七问的骨架摆出来:
问题 MIT 的回答
┌──────────────┐ ┌────────────────────────┐
│ Transformer │ │ 别修网络,修外壳 │
│ 不会组合泛化 │ ───→ │ Harness 承载归纳偏置 │
└──────────────┘ └────────────────────────┘
│ │
↓ ↓
┌──────────────┐ ┌────────────────────────┐
│ 长上下文腐烂 │ ───→ │ 上下文卸载:变量而非提示 │
└──────────────┘ └────────────────────────┘
│ │
↓ ↓
┌──────────────┐ ┌────────────────────────┐
│ 每域各训一遍 │ ───→ │ 程序化子调用 → 任务同构 │
└──────────────┘ └────────────────────────┘
│
↓
短任务训练 → 长任务/跨域泛化
一、Transformer 为何天生不擅「组合泛化」
1.1 先说清「组合泛化」是什么
组合泛化(compositional generalization):把学过的零件重新拼装,去解没见过的题。
举个最小的例子。你教一个小孩「跳」,再教他「向左转两次」。他从没听过「向左转两次之后跳」,但他一听就会做。这就是组合泛化——零件是旧的,组合是新的,能力自动到位。
人做这事毫不费力,费力到我们意识不到它是一种能力。神经网络做这事,一直不行。
1.2 这不是新发现,是四十年的老账
这笔账最早由 Fodor 与 Pylyshyn 于 1988 年记下:他们批评联结主义模型缺乏 systematicity(系统性)——一个能理解「张三爱李四」的系统,理应自动能理解「李四爱张三」,因为零件相同、只是重组。神经网络做不到这点,说明它学的不是结构,是相关性。
作者在原文里自嘲这是「perhaps boring old concept」(也许无聊的老概念)——老,但没解决。
到了 Transformer 时代,这笔账被算得更清楚了。最硬的一记来自 《Faith and Fate: Limits of Transformers on Compositionality》(Dziri 等,NeurIPS 2023)。他们把多步推理任务画成计算图(computation graph),然后系统地加深加宽,看模型什么时候崩:
| 实验 | 结果 |
|---|---|
| GPT-4 做 3 位 × 3 位乘法 | 59% |
| GPT-4 做 4 位 × 4 位乘法 | 4% |
| 加 few-shot scratchpad 后 3×3 | 59% → 92% |
| 同样加 scratchpad,高复杂度问题 | 仍近 0% |
| GPT-3 在 180 万条乘法数据上穷尽微调至 3×3 满分,测 4×4 | 0% |
| 4×2 乘法中「答案对但中间步骤错」的比例 | 82% |
最后两行是全场最刺眼的。
训练到 3×3 百分之百,4×4 是零。 只多了一位数。零件完全相同(一位乘法、进位、错位相加),只是多组合了一层。模型全崩。
那 82% 的「答案对、过程错」,论文称为 restoration error——它不是算出来的,是记出来的。
Dziri 等人的结论一针见血:Transformer 解组合任务,靠的是 linearized subgraph matching(线性化子图匹配)——把当前推理路径去比对训练时见过的路径。它不是在执行算法,它是在检索路径。 训练分布里有相似子图就对,没有就错。
他们还给了理论证明:自回归生成下,正确率随推理步数指数衰减。每步 1% 错误率,看起来微不足道,几十步之后就是全盘皆输。
1.3 MIT 这篇如何归因
Harness 一文没有重复上述实证,而是把矛头指向架构的归纳偏置层级。作者原话:
“Yet across all of this, generalization itself has been left to the underlying neural network and to its 2017 token-level inductive biases.”
“We think this is because their narrow design space of mostly differentiable neural operators misses something fundamental.”
“it just doesn’t seem that the basic differentiable neural operations put together 5 years after AlexNet are particularly optimal when it comes to encoding the inductive biases we need.”
翻成大白话:Transformer 的归纳偏置是「token 级」的、是「几何」的——注意力算的是向量相似度,位置编码编的是序数关系。这套偏置在「把语言的统计规律吃透」这件事上无与伦比,但它天生不含「把问题拆成子问题」这种符号级、结构级的偏置。
作者说得更狠的一句是:
“the returns on scaling Transformers and related neural architectures are just not budging in terms of being poor compositional generalizers.”
规模上去了,这个毛病纹丝不动。 这是判断”scaling 能否解决一切”的关键证据——不是”还没到时候”,是”这个方向的边际收益在这个指标上约等于零”。
1.4 一个具体后果:长度泛化失败
组合泛化缺失,最日常的表现就是长度泛化(length generalization)失败。原文:
“It is widely known that training Transformer-based LMs on a domain at a particular context length does not necessarily generalize to longer context lengths.”
这就是为什么 Qwen 3.x、Kimi K2.x、GLM 5.x 等生产模型的中训练/后训练阶段,要小心翼翼地把越来越长的数据掺进训练配比。不是因为长数据本身多有营养,是因为不喂就不会。
这是一笔巨大的、重复的、每个新长度档位都要重付一遍的税。
二、Harness 是什么?为何可能成为 Agent 的核心
2.1 定义
作者给的定义相当克制,也相当精确:
“A harness is the program that sits between the external world and the neural network: it decides how to encode the current state of the environment, which can be arbitrarily long and complex, into one or more inputs to the LLM and how to determine the next action.”
形式化写作 H: s → a(状态到动作)。
harness 这个词,在英文里本指给马套的挽具——不是马,但决定马的力气往哪儿使。中文没有完全对应的词,「外壳」「支架」「挽具」「驾驭层」都只得其一半。我姑且译作「驾驭层」,取「驭」字之意:它不产生力,它分配力。
你每天用的东西,全是 harness:Claude Code 的主循环、Cursor 的上下文拼装、LangChain 的 chain、你自己写的那个 while 循环。
2.2 身份跃迁:从「胶水」到「归纳偏置的载体」
这才是全文真正的思想跳跃。
过去我们怎么看 harness?工程胶水。 脏活。模型是主角,harness 是给主角递道具的场务。谁会认真研究场务?
作者说,错了。harness 有一项更根本的权力:
“a more fundamental power of the harness is the ability to simplify the arbitrarily complex state s into potentially many smaller observations o that each individual LM call in the harness can properly handle”
harness 决定「模型看见什么」。 而模型的表现,几乎完全由「它看见什么」决定。
于是那句关键的话出来了:
“We know that Transformers are unreliable at compositional generalization, so we can rely on the harness to define higher-level inductive biases.”
归纳偏置——这个过去只属于「架构设计」的词——被搬到了 harness 上。
这是一次身份跃迁:harness 不再是模型外面的脚手架,它是模型能力的一部分。
2.3 核心判据:Locally In-Distribution(LID,局部分布内)
坏 harness(主流 Agent) 好 harness(LID) 训练 分布 context += obs + obs + obs … 越堆越漂出分布 训练 分布 每次调用都落在分布内 LID 原理:坏 harness 把观察不断 append,使输入漂出分布(context rot);好 harness 把复杂状态拆成许多「熟悉的一刀」,每次调用皆在分布内。那么,什么算好的 harness?作者给了一条判据,我认为这是全文最有价值的一句话:
“a good harness produces observations o that are locally in-distribution (LID), which we define as every individual LM call over this observation being in-distribution with respect to the training data.”
拆开讲:
- 整个任务可以是分布外的(OOD)——它可以是模型从没见过的类型、200 万 token 的长度、全新的领域。
- 但每一次单独的模型调用,必须尽量落在分布内。
这是一种”分而治之”,但分的不是任务,是分布。
打个比方。你请一位只做过江浙菜的厨师做一桌满汉全席——他会崩。但如果你把满汉全席拆成一百道工序,每道工序都是「切丝」「焯水」「勾芡」这类他闭着眼都会的动作,再由一个流程把这一百道工序编排起来——菜就出来了。厨师一点没变,变的是厨房的工作流。
LID 就是这个原则的精确表述:别让厨师面对整桌宴席,只让他面对他熟悉的那一刀。
2.4 反面教材:主流 Agent 全在违反 LID
作者点名批评:
“The length generalization issue especially impacts standard agent designs like ReAct, CodeAct, Claude Code, Codex, etc. which, as we mentioned, rely on appending observations to a growing prefix history of context.”
主流 Agent 的循环长什么样?
context = system_prompt
loop:
action = LLM(context)
obs = env(action)
context += action + obs # ← 罪在此处
每转一圈,context 就长一截。工具输出、思考过程、错误堆栈,全往里堆。转到第 50 圈,这个 prompt 的形态根本不像训练数据里的任何东西。
这正是 context rot(上下文腐烂) 的机理。它不是”记不住”,是”输入漂出了分布“。
我以为,这是理解 context rot 最好的角度。Anthropic 的定义(token 变多→召回变差)是现象描述;LID 给的是机理解释:不是长度本身有毒,是长度带来的形态陌生有毒。
2.5 等价类:harness 如何「制造」泛化
任务 A 任务 B 任务 C Harness H 等价类 [τ] 同一 token 轨迹 结构相似的任务 → 在根模型眼中呈现 token 级相同的轨迹 → 泛化被「构造」出来 等价类:harness 在任务集上诱导等价关系 ∼_H,使同一等价类里的任务在根模型上下文中呈现近乎相同的 token 轨迹(「token 逐个地相似」)。这是全文最漂亮的一段论证,也是理解第 6 问的钥匙。
作者说,一个 harness 会在所有任务上诱导出一个等价关系:
“Formally, a harness induces an equivalence operator ∼H over the set of all task states 𝒯, meaning structurally similar tasks fall under the same harness-induced equivalence class … and produce similar sets of observations for the neural network involved.”
理想的 harness 要做到什么程度?作者用了一个加粗的 literally:
“An ideal harness decomposes a task such that the main context is abstracted to literally appear token-for-token similar for similar problems, i.e. those that fall under the same harness-induced equivalence class [τ′] = {τ ∈ 𝒯 : τ′ ∼ τ}. This isomorphism enables generalizations of the form: if a system can solve task X, it should transitively be able to solve task Y.”
「token 逐个地相似」。不是语义上像,是字面上像。
于是所有轨迹被约化成一个商集(quotient set)——原文记作 Hi/Q:
“the harness induces a quotient set (Hi/Q) over all trajectories, reducing similar tasks to the same token trajectory.”
(作者在脚注里做了严谨性修补:严格来说等价性需定义为「在某度量下落入同一个 ε-球内」,而非精确相等。)
这段论证的逻辑链是:
- Transformer 不会组合泛化 → 需要外部提供高层归纳偏置
- harness H 在任务集 𝒯 上诱导等价关系 ∼H
- 好的 harness 让同一等价类里的任务,在根模型的上下文中呈现近乎相同的 token 轨迹
- 于是轨迹空间被商掉,相似任务变成同构(isomorphic)
- 在任务 X 上学到的策略,自动迁移到任务 Y
泛化不再是”希望模型学会”的事,而是”被 harness 构造出来”的事。
这是我读这篇文章最大的收获。过去我们把泛化当成一种祈求——祈求模型在足够多数据上涌现出它。现在有人说:泛化可以是一种工程构造。
三、RLM:把上下文当环境,而非输入
Harness 是纲领,RLM 是它的具体实现。RLM 是前作(Zhang、Kraska、Khattab,arXiv:2512.24601),须先讲透。
3.1 一句话定义
“a general inference paradigm that treats long prompts as part of an external environment and allows the LLM to programmatically examine, decompose, and recursively call itself over snippets of the prompt.”
范式对比,一目了然:
| 传统 | RLM | |
|---|---|---|
| 上下文的身份 | 输入(prompt 里的文本) | 环境(外部变量) |
| 模型如何获取 | 注意力,一次性全看 | 写代码,按需切片 |
| 公式 | output = model(query + context) |
output = model.interact_with(env) |
| 上限 | 上下文窗口 | 几乎无上限 |
3.2 演化谱系
作者自陈 RLM 是 CoT、ReAct 之后的下一个里程碑。这条谱系很清楚:
| 范式 | 年份 | 动作是什么 | 上下文在哪 |
|---|---|---|---|
| CoT | 2022 | 生成中间推理 token | prompt 内 |
| ReAct | 2023 | 调用预定义工具 | prompt 内,且持续增长 |
| CodeAct | 2024 | 执行代码 | prompt 内,且持续增长 |
| RLM | 2025 | 执行代码 + 递归调自己 | prompt 外,在 REPL 里 |
RLM 与 CodeAct 的分野,恰恰在最后一格:CodeAct 会写代码,但上下文还在窗口里;RLM 把上下文搬出去了。
3.3 接口设计:drop-in 替换
作者的工程品味在此处显露:
# 原来
response = gpt5.completion(messages)
# 现在
response = rlm.completion(messages)
从调用方看,RLM 就是一个”语言模型”。 同样的签名,同样的语义,text → text。里面藏着一整棵递归调用树,外面完全无感。
这个设计的意义不小:它意味着 RLM 可以像一个组件一样,塞进任何现有系统。不需要改架构,不需要改权重,不需要重训。
四、上下文卸载:长上下文问题的解法
4.1 根模型初始看见什么
长上下文输入 5,000,000 字符 传统:整段塞进 prompt,注意力逐个 token 扫 context REPL 变量(外部) ≈20 tok 根模型只见元数据 存为变量 可见性下沉 上下文卸载:500 万字符的输入在根模型上下文里只占约 20 个 token(仅元数据)。要看,模型自己写代码去取——符号操作绕开了注意力。这是全篇最该记住的一个技术细节。RLM 的初始提示,给根模型的不是内容,是元数据:
Your context is a str with 5,000,000 total characters,
broken into chunks of lengths: [5000000].
就这一句。
模型知道有个东西在,知道它多大,但看不见里面一个字。 要看,得自己写代码。
500 万字符的输入,占了根模型上下文窗口大约 20 个 token。
4.2 可用原语
REPL 环境里备好的工具:
| 原语 | 作用 |
|---|---|
context |
输入数据,作为字符串变量 |
llm_query(prompt, model) |
单次 LLM 调用(快,约 50 万字符量级) |
llm_query_batched(prompts) |
并行多次调用 |
rlm_query(prompt, model) |
派生一个子 RLM(自带 REPL) |
rlm_query_batched(prompts) |
并行多个子 RLM |
SHOW_VARS() |
列出 REPL 中所有变量 |
print() |
查看输出 |
FINAL(answer) / FINAL_VAR(name) |
终止并返回 |
主循环默认最多 30 轮迭代。安全阀有五道:max_iterations、max_budget(美元)、max_timeout、max_errors、max_depth。
4.3 为什么这能解决长上下文
关键在于符号操作绕开了注意力。
要在 10 万行里数出符合某模式的条目,传统做法是让模型一边生成 token 一边注意这 10 万行——又贵又不准。RLM 的做法是:
matches = [line for line in context.split('n') if pattern in line]
FINAL(len(matches))
一次 LLM 调用都不用。 精确、廉价、可验证。
需要语义理解时才递归:
chunks = [context[i:i+10000] for i in range(0, len(context), 10000)]
results = [llm_query(f"Extract entities from: {c}") for c in chunks]
FINAL(llm_query(f"Synthesize: {results}"))
这就是 map-reduce。但请注意分野——这不是人写死的 pipeline,是模型自己在运行时决定要 map-reduce 的。
RAG 是「预先定好一套检索管线,每次查询走一遍」;RLM 是「不预定任何管线,让模型在查询时写一段代码,描述它此刻想要的检索行为」。前者把检索凝固成系统组件,后者把检索还原为模型的运行时决策。
4.4 实测
| 任务 | RLM | 基线 |
|---|---|---|
| OOLONG @ 132k tokens | RLM(GPT-5-mini) ≈ 48 | vanilla GPT-5 ≈ 14 |
| OOLONG-PAIRS @ 32k | RLM-GPT-5 58% | GPT-5 ≈ 0%,检索/摘要 agent ≈ 0.3% |
| OOLONG-PAIRS @ 1M | RLM-GPT-5 仍约 50% | — |
| BrowseComp+ (1K 文档) | RLM-GPT-5 91.3% | GPT-5 因超窗无法作答;摘要 agent 70.5% |
| BrowseComp+ | RLM-Qwen3-Coder-480B 44.7% | 同底座摘要 agent 38.0% |
| BrowseComp+ | RLM-Qwen3-8B 14% | Qwen3-8B 0% |
三个数字值得单独品:
- 小模型套壳打赢大模型。 GPT-5-mini 的 RLM 在 OOLONG 上正确数是 GPT-5 的两倍以上,且每次查询更便宜。
- 0% → 14%。 Qwen3-8B 的上下文窗口只有 32,768 token,面对百万级输入本来就是零。套上 RLM,它能干活了。
- 1M token 下仍保持约 50%。 这是”不随长度腐烂”最直接的证据。
成本方面,作者称 RLM “up to 3x cheaper”——因为模型只调取相关片段,而非让整个序列参与每个 token 的注意力计算。
五、程序化子调用:为何「代码」比「工具调用」高一个维度
5.1 分解空间(space of decompositions)
要理解这一节,得先引入 MGH 里的一个关键概念。作者在 MGH 中写道:
“Defining the space of decompositions the LM is allowed to express is important for ensuring the individual LM calls stay ‘in-distribution’. How we define ‘decomposition’ has an exponentially large impact (with respect to depth) on the tasks solvable via decomposition.”
你允许模型用什么语言来表达”怎么拆”,决定了它能拆到什么程度。 而这个影响是随深度指数级放大的。
5.2 一个 for 循环的分野
作者给了最锋利的一刀对比:
“In long-context tasks, for example, tool-call-style subagents prevent the root LM from decomposing the context into arbitrarily many chunks, inhibiting its ability to scale. In RLMs, the space of decompositions is expanded so as to allow an efficient representation of decomposition into arbitrarily many subtasks (e.g. using a
forloop), which suddenly enables the system to handle near-infinite context.”
请看这两种写法:
工具调用式(ReAct / 函数调用):
{"tool": "subagent", "args": {"chunk": "……第一块的全部文本……"}}
{"tool": "subagent", "args": {"chunk": "……第二块的全部文本……"}}
{"tool": "subagent", "args": {"chunk": "……第三块的全部文本……"}}
拆一千块,就得在上下文里写一千次调用,且每次都要把内容原样塞进 JSON。根模型的窗口瞬间爆掉。分解的成本,与分解的数量成正比。
程序化式(RLM):
results = llm_query_batched([f"...{c}" for c in chunks])
一行。拆一千块和拆一百万块,根模型看到的 token 数完全一样。
分解的成本,与分解的数量脱钩了。
这就是”代码高一个维度”的确切含义。代码有循环、有递归、有变量绑定——它可以用有限的符号,表达无限的结构。而 JSON 工具调用是平铺的,写多少就是多少。
5.3 中间结果留在变量里
第二个关键点:光卸载初始输入不够。
工具输出、子调用结果会持续写回主上下文,轨迹一长,照样漂出分布。RLM 的解法是——子调用的结果也存成 REPL 变量:
partial = llm_query_batched(prompts) # 结果在变量里,根模型看不见
merged = merge(partial) # 继续在环境里加工
FINAL_VAR("merged") # 直接返回变量,不经过模型生成
FINAL_VAR 尤其精妙:输出长度也解除了限制。答案在 REPL 里拼装完成,不需要模型一个 token 一个 token 地吐出来。
5.4 涌现出的策略
有趣的是,这些策略没有一条是写死的,全是模型在任务压力下自己长出来的:
- Peek-Filter-Recurse:先
print(context[:1000])探结构 → 关键词过滤 → 对候选递归 - Parallel Semantic Labeling:逐行
llm_query分类(昂贵但准确) - Progressive Answer Construction:分节生成,
FINAL_VAR返回 - Self-Verification:先解,再另起一个子调用验证
第四条尤其有意思——模型自发学会了让”另一个自己”来检查答案。 没人教它。
六、为何短任务训练能迁移到百万 Token 长任务
这是七问中最反直觉的一问,也是这篇研究的核心贡献。
6.1 实验配置
| 项 | 设置 |
|---|---|
| 底座模型 | Qwen3-30B-A3B-Instruct-2507(RLM 与基线同一底座) |
| 基线 | 原生 Transformer(长设定下加 YaRN 外推) |
| RL 算法 | prime-rl,Decoupled PPO + GRPO 式 advantage + KL loss |
| 训练规模 | 150 步,batch 64,每样本 4 rollouts;每 10 步评测 |
| 跨域实验 | 500 步,每 20 步存 checkpoint |
| 算力 | 8×H100 节点(Laude Institute 提供) |
关键在于:训练只在短任务上做,评测只在长任务上做。
6.2 六个长度泛化环境
| 环境 | 训练长度 → 评测长度 | 任务定义 |
|---|---|---|
| MRCRv2 | 64k → 2M(2-needle / 8-needle) | 在大量对话语料中找第 i 个满足查询的「针」句 |
| GraphWalks | <128k → >1M | 从图中抽取满足简单约束的节点 |
| LongBenchPro | 32k → 256k | 覆盖 11 类 QA / 代码 / 推理的选择题 |
| OOLONG [trec-coarse] | 32k → 256k | 对数据集做聚合统计式提问 |
| OOLONG-Pairs | 输入 8k→32k,输出 7k→146k | 找出满足约束的元素对 |
| Ada-LEval [best-answer] | 8k → 128k | 大量候选与干扰项中挑最合适答案 |
注意 OOLONG-Pairs:它测的是输出长度泛化——7k 到 146k,20 倍。这一维度极少有人测。
6.3 三个跨域迁移环境
这组实验更狠——训练与评测的领域完全不同,只有底层策略相同:
| 训练 | → 评测 | 指标 |
|---|---|---|
| OOLONG:关于 Jeopardy TREC 问题的聚合 | 关于「垃圾邮件/正常邮件」的聚合 | reward |
| OBLIQ-Bench Analogues:搜同一作者写的散文 | 搜需要相同推理过程的数学题 | nDCG@10 |
| OBLIQ-Bench Descriptive:找特定立场的推文 | 搜含错误的 Wildchat 对话 | nDCG@10 |
第二行请细看:训文学,考数学。 token 分布毫无重叠,唯一共通的是「搜索 + 相似性判断」这个潜在结构。
6.4 结果
原文的总结:
“Training on only short tasks generalizes to held-out tasks 8–32x longer, with roughly 10x the eval lift with the same train lift over training the underlying Transformer directly.”
⚠️ 须先声明一处:原文从未给 train lift / eval lift 下过定义或公式,全文仅三处使用,皆为定性表述。以下解读系按上下文推断,非作者原意,读者宜自行保留判断: – train lift(推断):在短训练任务上,训练后相对初始 checkpoint 的性能增益 – eval lift(推断):在长任务 / 跨域评测上,训练后相对初始的性能增益
因此,”roughly 10x the eval lift” 的准确语义应读作:在 train lift 相当的前提下,RLM 的 eval lift 约为直训 Transformer 的 10 倍——它是一个「两个系统之间的比值」,不是「某个绝对指标涨了 10 倍」。这个区别很重要。
正常的机器学习直觉是:eval lift < train lift(泛化必有损耗)。
而这篇的结果是:
“the eval lift for the RLM matches or exceeds the train lift, while the base Transformer struggles to generalize.”
RLM 的评测增益,追平甚至超过训练增益。
超过是怎么回事?作者给了解释,这也是全文最有画面感的一段:
“we find that the RLM starts with a non-generalizable solution that only works on short tasks but eventually discovers a more generalizable decomposition strategy, yielding a higher eval lift than train lift.”
模型先学会一个偷懒解法(短任务上够用),继续训练,它自己发现了一个更普适的分解策略。短任务上得分没怎么变(本来就满分了),长任务上却豁然开朗。
⚠️ 两处不可混为一谈:原文描述这一「自发发现」现象时并未点名是哪个任务(只说”in some length-generalization experiments”)。而 MRCRv2 恰恰是反例——在那个环境里 RLM 学不会正确策略,作者不得不加提示(详见 8.3)。所以这不是一条普遍规律,是一个在部分环境上观察到的、令人鼓舞但不保证复现的现象。
还有个对照特别扎心:
“the train reward of the base Transformer generally exceeds that of the RLM despite clear gaps in performance on the eval”
基线在训练集上分更高,在测试集上却不行。 这是”背题”的教科书式特征。
以及:
“On MRCRv2, GraphWalks, OOLONG, and OOLONG-Pairs, the trained Qwen3-30B-A3B-Instruct-2507 RLM approaches or exceeds an RLM with a frontier model, GPT-5.5 on the long eval”
30B 的开源模型,套上训练过的 RLM 外壳,在长任务上追平乃至超过用 GPT-5.5 跑的同一外壳。
6.5 机理:轨迹被商掉了
训练轨迹 · 78,138 字符 评测轨迹 · 618,252 字符 token_lcs = 0.824 根模型视角:同一道题 输入涨 8 倍,轨迹仍是 8 轮——外部复杂度被 harness 商掉了 机理(商集):训练与评测轨迹被 harness 诱导的等价类「商掉」,相似度 token_lcs=0.824(判为近乎同一)。这正是短训迁移百万 token 的根。为什么能这样?回到第二节的等价类。
作者做了一件很扎实的事:直接测量轨迹相似度。取最优 checkpoint 的评测轨迹,去比对它此前见过的所有训练轨迹,用五种距离度量:
| 度量 | 定义 |
|---|---|
| Edit | token 级、长度归一化的 Levenshtein 距离 |
| Contain | 3-gram 词包含(非对称):1-|N3(xeval)∩ N3(xtrain)||N3(xeval)| |
| Jaccard | 3-gram Jaccard:1-|N3(xeval)∩ N3(xtrain)||N3(xeval)∪ N3(xtrain)| |
| Weighted Jaccard | 1-∑t min(ctrain(t), ceval(t))∑t max(ctrain(t), ceval(t)) |
| Length | 纯长度比(内容无关):1-min(|xtrain|,|xeval|)max(|xtrain|,|xeval|) |
聚合方式为最近邻期望:
即:对每条评测轨迹 e,找出它与此前所有训练轨迹中最相似的那一条的距离,再对全部评测轨迹取期望。绘图时展示的是相似度 1-d(cdot,cdot)。
注意这个度量的性质:它问的是「评测时走的路,在训练时是否走过类似的」,而非「平均而言像不像」。这对”等价类”论证是恰当的——等价类只要求存在一个同类成员,不要求与所有成员都像。
结论:
“what the RLM’s individual LM calls see, even across a longer time horizon, are much closer to what they may see during training than just a base LM call.”
附录中有一个具体案例,是我认为全文最有说服力的一条证据:
| 训练轨迹 | 评测轨迹 | |
|---|---|---|
| 任务 | OOLONG(短) | OOLONG(长) |
| 输入规模 | 78,138 字符 | 618,252 字符 |
| 根模型轮数 | 8 轮 | 8 轮 |
| reward | 1.00 | 1.00 |
| token_lcs 相似度 | — | 0.824(判定 NEARLY_IDENTICAL,93/100) |
输入涨了近 8 倍,根模型的轨迹还是 8 轮,token 级最长公共子序列相似度 0.824。
从根模型的视角看,这根本就是同一道题。
这就是”商集”的实物证据——外部世界的复杂度被 harness 吸收掉了,抵达神经网络的那部分,几乎没变。
6.6 最震撼的一个数字(来自 MGH)
MGH 一文中有一个实验,比本文任何数字都更刺激:
“We find that while
RLM(Qwen3-4B-Instruct)solves nearly 0% of the tasks, it gets 100% after only RL training on a significantly simpler setting (32k context, 1 needle).”
任务是 MRCRv2,1M 上下文,8 根针——这是各家前沿模型报告里的标准长上下文硬骨头。
- 模型:Qwen3-4B。四十亿参数。
- 训练:只在 32k 上下文、1 根针的简单设定上做 RL。
- 结果:1M 上下文、8 根针,100%。
上下文长 30 倍,针数 8 倍,一个 4B 模型,满分。
请把这个数字,和第一节 Faith and Fate 的那个数字并排放:
| Transformer 直接训练 | RLM harness | |
|---|---|---|
| 训练设定 | 3位×3位乘法,180 万样本,练到 100% | 32k 上下文,1 根针 |
| 泛化目标 | 4位×4位(多一位) | 1M 上下文,8 根针(长 30 倍) |
| 结果 | 0% | 100% |
同样是”加一点点难度”,一个全崩,一个满分。 差别不在模型——差别在外面那层壳。
这一对照,是我认为这篇研究最值得记住的东西。
七、Harness 会成为大模型架构的一部分吗
7.1 作者的表态
原文结尾说得相当明确:
“In short, better returns on scaling require compositional generalization, and the capacity for compositional generalization looks like it has to largely live in what today we refer to as a harness, but which in the future may blur quite seriously with what we consider the fundamental architecture of our frontier AI systems.”
「严重模糊」。作者没说”harness 会变成架构”,他说的是两者的边界会消失。
同时他给了一记警告,我认为极为清醒:
“It is easy to walk away from these powerful early results thinking that we should all be tinkering with harness designs or imposing our problem-specific intuitions around overly structured programmatic strategies such as MapReduce or dynamic programming. But make no mistake, doing that we will inevitably run afoul of the bitter lesson and fall by the wayside within months.”
别手搓 harness。 手搓 MapReduce 策略、手搓动态规划模板,就是重蹈”苦涩教训”的覆辙——几个月内必被通用方法碾过。
正确的做法是:
“We can now encode far higher-level and more symbolic inductive biases and train our systems end-to-end with RL.”
设计的是「分解空间」,训练的是「怎么分解」。 前者是人的活,后者是 RL 的活。人只负责把地板铺好,不负责规定怎么走。
7.2 我的判断
我认为答案是:会,但不是以今天大多数人想象的形式。
分三层说。
第一层:形式上不会「合并」。 harness 是离散的、符号的、有副作用的(执行代码、读写变量、调外部进程)。Transformer 是连续的、可微的、无状态的。这两样东西在数学性质上不兼容,硬塞进一个可微计算图里,代价极大而收益不明。至少在可见的未来,REPL 不会变成一个 layer。
第二层:但训练时会「合流」,而这已经发生了。 这才是这篇研究真正的分水岭意义。
看清楚这个演变:
| 阶段 | harness 的身份 | 谁在优化它 |
|---|---|---|
| 2023 ReAct | 推理时的脚手架 | 人,手写提示词 |
| 2024 CodeAct | 推理时的脚手架 | 人,手写工具 |
| 2025 RLM(推理版) | 推理时的脚手架 | 人,手写系统提示 |
| 2026 RLM(RL 训练版) | 训练环路的一部分 | 梯度 |
当你用 RL 在 harness 里训练模型,harness 就已经进入了模型的训练分布。 模型的权重开始为”在这个壳里生存”而优化。它学会了什么时候该 grep、什么时候该递归、怎么切块、怎么用变量。这些行为沉淀进了权重。
此时你把模型从壳里拿出来,它就是个普通模型;放回壳里,它是个会分解的系统。壳与权重,已经共同演化了。 这在功能意义上,就是”harness 成为了架构的一部分”——只不过它体现在权重里,不体现在计算图里。
第三层:最终形态可能是「协议标准化」,而非「代码内化」。 我猜测未来的路径是:
- 模型厂商会规定一套标准的分解原语(类似今天的 function calling 已经被标准化进 API 和训练数据)
- 模型在预训练/中训练阶段就大量接触这套原语的轨迹
- 于是「递归自调用」变成和「输出 JSON」一样的原生能力
- 外部只需提供一个符合协议的执行环境
这与 tool use 的历史完全同构。 2023 年工具调用是外部 scaffold,你得自己写解析器;2026 年它是模型原生能力,写进了 API 规范。递归分解正走在同一条路上。
所以我的完整答案是:harness 不会变成一个 layer,但会变成一份协议 + 一批权重里的习惯。 而这,实质上就是架构的一部分。
7.3 一条反对意见,也须听
有人会说:这不过是把「设计架构」的难题,换成了「设计 harness」的难题——问题没解决,只是搬了个家。
这话有几分道理,但我不完全同意。理由是:harness 的设计空间,比可微算子的设计空间友好得多。
改架构要重训,一次几百万美元,反馈周期以月计。改 harness 是改代码,反馈周期以小时计。迭代速度差三个数量级。 在一个方向不明的探索期,能快速试错的那条路,胜算高得多。
况且作者已经说了:不要手搓,要用 RL 训。人只定义空间,机器搜索其中的解。 这恰恰是”苦涩教训”所允许的那种人类介入——定义搜索空间,而非规定搜索结果。
八、泼冷水:这项研究的局限与可疑之处
好文章不做复读机。以下是我认为读这篇研究时必须挂在心上的疑点。
8.1 它是博客,不是论文
Harness 一文未经同行评审。前作 RLM 的 arXiv 预印本也标注”尚未完成正式同行评审”。没有匿名审稿人去质疑它的实验设计、去要求补充消融、去核对统计显著性。
尤其是:文中大量报告的是”train lift / eval lift”这类相对量,而非各环境的绝对分数表。 我在原文与镜像站都未找到「step-0 与最终 checkpoint 在每个环境上的具体 reward 数值表」。相对提升在基线很低时极易被放大——从 1% 涨到 3%,也是 200% 的提升。 这一点无法核验,是我最大的保留。
8.2 「不就是 subagent 吗」——这个质疑有实锤
Hacker News 上关于 RLM 的顶部评论就是这句。而它并非无理取闹:
- 论文的默认递归深度是 1。 也就是说,子调用只是普通 LLM 调用,不是子 RLM。所谓”递归”,实际运行时只有一层。
- 独立复现(Daren Wang,用 DeepSeek v3.2 与 Kimi K2)发现:depth-2 反而更差——模型过度思考,检索任务准确率下降,执行时间从 3.6 秒膨胀到 344.5 秒。近百倍。
- 论文自己的消融显示:在 Qwen3-Coder-480B 上,无子调用版本在 4 个 benchmark 中的 2 个上胜过完整 RLM。
所以真正起作用的是什么?大概率是上下文卸载(把 prompt 变成可 grep 的变量),而不是递归。递归是名字里最性感的部分,却可能是贡献最小的部分。
这不否定研究价值,但它修正了叙事重心:“Recursive” 这个词,有点名不副实。
8.3 泛化不是自动的,需要「推一把」
原文自己承认:
“Length generalization occurs because the RLM learns a generalizable strategy, but this is not always guaranteed. In many of the short settings above, one viable strategy is to just offload the entire problem to a single sub-call and return this as a solution, effectively becoming equivalent to the long-context Transformer baseline.”
短任务上有个偷懒解:整个问题甩给一个子调用。短任务上它有效,长任务上它就退化成了基线本身。
在 MRCRv2 上,作者不得不加了一条 “nudge to decompose”(提示去分解)的用户消息,模型才学到正确策略。作者的辩解是”我们的直觉是规模上去后不需要监督”——这是直觉,不是证据。
还有一条:
“In many cases, the RLM will still choose to print out task-specific information and pass it back to the main context.”
模型自己在破坏 LID。 它会把任务特定信息打印回主上下文——这正是理论上最该避免的事。作者说”应该可以训掉”,但没训。
8.4 成本与延迟的真实代价
| 维度 | 代价 |
|---|---|
| 训练运行时 | 比原生 Transformer 慢 1.5–3 倍(多步 + 等子调用) |
| 推理延迟 | 秒到分钟级;子调用阻塞,无 prefix caching |
| 成本方差 | 中位数成本不错,但 95 分位是中位数的 10 倍 |
| 成本可预测性 | 差——模型自己决定派生多少子调用 |
那个 95 分位的长尾,对生产系统是硬伤。你没法给用户承诺一个响应时间,也没法给财务承诺一个单位成本。
(公平地说,作者指出这个开销随任务复杂度的扩展性很好:在 8×H100 上给 30B 模型训一个普通 ReAct agent,因为上下文膨胀,本身就已经很难了。)
8.5 其他失败模式
社区观察到的(部分论文亦承认):
- 过度递归:Qwen 系尤其容易逐行发子调用,本可批处理
- 验证死循环:反复验证得到不一致结果,最后选错
- 终止接口混淆:在 REPL 变量里拼好了完美答案,却调用
FINAL(生成的答案)而非FINAL_VAR(变量名),功亏一篑 - 基线只学会格式:跨域实验中,基线 Transformer 早期的 eval 提升”主要来自学会正确的答案格式,且迅速衰减”——这说明跨域对照组的可比性有限
8.6 一个理论上的隐忧:循环论证的风险
最后一条是我自己的疑虑,原文未讨论。
LID 原则说:好 harness 让每次调用落在分布内。等价类论证说:好 harness 让相似任务呈现相同轨迹。
问题是——“好 harness”是怎么定义的? 按结果定义(能泛化的就是好的),那论证就成了”能泛化的 harness 能泛化”。要跳出这个圈,需要一个独立于结果的、可先验计算的 LID 度量。
作者确实往这个方向走了一步(Figure 8 的五个距离度量),但他自己也承认这些只是 proxy:
“the plots above don’t fully capture the semantic similarities between these trajectories… A more principled distance metric will factor in token similarity and semantic similarity.”
在有了可先验计算的 LID 度量之前,”设计好 harness”仍然是一门手艺,不是一门工程。 这是这个理论框架当前最大的空缺。
九、这对你意味着什么
抛开学术,落到实处。
9.1 三条可立即执行的原则
其一:别再往 context 里堆东西了。
如果你在写 Agent,检查你的主循环里有没有 context += observation。有,就是在制造 context rot。
改法:把工具输出存成变量,只把「变量名 + 元数据(类型、长度、前 100 字符)」放回上下文。需要时再取。
其二:给模型代码,而不是给模型工具列表。
工具调用的分解成本与分解数量成正比;代码的分解成本与数量脱钩。如果你的任务需要”对 N 个东西各做一次”,且 N 可能很大,一个 for 循环胜过 N 次函数调用。
其三:用 LID 做设计判据。
设计 harness 时,反复问一句:「这次调用的 prompt,长得像模型训练时见过的东西吗?」
不像,就再拆一层。
9.2 一个视角转换
这项研究真正改变的,是「泛化从哪来」的答案。
- 旧答案:泛化来自模型。数据更多、参数更大、训练更久,泛化自然涌现。
- 新答案:泛化也可以来自系统结构。把任务约化到模型的舒适区,泛化就是被构造出来的。
君在提问中说:「未来的大模型竞争,也许不仅仅是模型参数规模的竞争,而是:如何设计一个更优秀的模型外部智能系统。」
这个判断,我认为大体是对的,但需要加一个重要的限定——作者本人在结尾专门反对了”手搓 harness”这条路。
所以更准确的表述应该是:
竞争不在于「谁的 harness 写得巧」,而在于 「谁定义的分解空间更大、且能被 RL 有效搜索」。
前者是手艺人的竞争,会被苦涩教训清算。后者是系统设计者的竞争,才是这篇研究真正指向的战场。
人定义空间,机器搜索解。 这是我从这篇研究里读到的、最值得带走的一句。
附:一句话速记
| 问 | 答 |
|---|---|
| Transformer 为何不会组合泛化 | 归纳偏置停在 token 级与几何级,缺符号级结构偏置;实证见 Faith and Fate:3×3 训满分,4×4 得零分 |
| Harness 是什么 | H: s→a,夹在世界与网络之间的程序;它决定模型看见什么,因而承载归纳偏置 |
| RLM 核心思想 | 上下文是环境不是输入;rlm.completion() 原地替换 llm.completion() |
| Context 卸载如何解决长上下文 | 长 prompt 存为 REPL 变量,根模型初始只见元数据(500 万字符 ≈ 20 token);符号操作绕开注意力 |
| 程序化子调用为何提升泛化 | 代码有循环与递归,分解成本与分解数量脱钩;中间结果留在变量里,主上下文不膨胀 |
| 短训练为何能迁移到百万 token | harness 诱导等价类,长短任务在根模型眼中呈现近乎相同的轨迹(78K→618K 字符,同为 8 轮,相似度 0.824) |
| Harness 会入架构吗 | 不会变成 layer,但会变成协议 + 权重里的习惯;RL 训练已使二者共同演化 |
参考
一手: – Zhang, A. & Khattab, O. (2026). Language model harnesses are compositional generalizers. https://alexzhang13.github.io/blog/2026/harness/ – Zhang, A., Li, Z. & Khattab, O. (2026). The Mismanaged Geniuses Hypothesis. https://alexzhang13.github.io/blog/2026/mgh/ – Zhang, A. L., Kraska, T. & Khattab, O. (2025). Recursive Language Models. arXiv:2512.24601 · https://alexzhang13.github.io/blog/2025/rlm/ – 代码:https://github.com/alexzhang13/rlm · https://github.com/alexzhang13/rlm-minimal
理论溯源: – Fodor, J. & Pylyshyn, Z. (1988). Connectionism and Cognitive Architecture: A Critical Analysis. – Lake, B. & Baroni, M. (2018). Generalization without Systematicity(SCAN). ICML. – Kim, N. & Linzen, T. (2020). COGS: A Compositional Generalization Challenge. EMNLP. – Dziri, N. et al. (2023). Faith and Fate: Limits of Transformers on Compositionality. NeurIPS. – Vaswani, A. et al. (2017). Attention Is All You Need. arXiv:1706.03762.
相关范式: – Yao, S. et al. (2023). ReAct. arXiv:2210.03629. – Wang, X. et al. (2024). CodeAct. arXiv:2402.01030.
