会话内 RSI 深读:Agent 把哪个对象定义成可变的,决定它变强还是变废

ACE 论文的 AppWorld 日志里有一处最该被记住的数字:第 60 步上下文 18,282 token、准确率 66.7;第 61 步模型重写了一次自己的经验手册,上下文只剩 122 token,准确率掉到 57.1——比完全不自我改进的 63.7 还低。不重载、不动权重、人不介入的自我提升不是一个开关,它有三个决定生死的设计选择:可变对象的粒度、写入权归谁、验证信号从哪来。这篇结合 ACE、ReasoningBank、Gödel Agent、Darwin Gödel Machine、Training-Free GRPO 等论文的原文数字,把这三个选择拆开。

ACE 论文(arXiv:2510.04618)在 AppWorld 上贴了一段自我改进的逐步日志。第 60 步,agent 积累的经验手册有 18,282 个 token,准确率 66.7。第 61 步,模型照惯例把这份手册整体重写了一次——手册剩下 122 个 token,准确率掉到 57.1。而同一个 agent 完全不做自我改进的基线是 63.7

也就是说:自我改进跑了 61 步之后,它比从没自我改进过更差。

这个数字是理解「人不介入、不重载模型、只在会话里让任务质量越来越好」这件事的最佳入口。它说明会话内 RSI 不是一个开关——不是「允许 agent 改自己」就会变强。它是一个有失效模式的工程设计,而失效的方向是负的。

这篇的主线一句话:会话内自我提升的成败,几乎完全由三个设计选择决定——你把哪个对象定义成可变的、这个对象以什么粒度被改写、改写的依据来自谁。 论文里所有的成功和翻车,都能落到这三个格子上。

名词速查

术语一句话解释
RSI递归自我提升:系统改进自己,改进后的自己再去改进自己
会话内 / 不重载不动模型权重、不重启进程,只改进程里那些每轮都会被重新读进上下文的可写数据
playbook / 经验手册把系统提示词从一整段散文改成一条条带 ID 的知识条目,可以单条增删改
context collapse让模型整块重写自己积累的上下文时,内容被一次性压缩掉大半的现象
brevity bias模型重写上下文时偏好写简洁摘要,把领域细节当冗余删掉
delta 更新模型只产出「新增/修改哪几条」,合并由确定性代码执行,模型不碰整块文本
LLM-as-judge让一次 LLM 调用来判定任务成败,没有 ground truth 参与
monkey patching在程序运行中动态替换类或函数的实现,不重启进程
skill library把成功的可执行代码存成可检索的技能(谱系见站内专文

一、先把”可变对象”排成一条线

Lilian Weng 那篇 harness 文给过一条被优化对象的爬升路径:prompt → context → workflow → harness 代码 → 优化器代码。她的判断是 RSI 会从部署层而不是权重层开始,因为那一层的梯度最便宜

但「不重载」这个约束会把这条路径切断一部分。谁被切掉、谁留下,值得当场对齐:

可变对象一次改进要付什么需要重载吗代表工作
模型权重一次全量微调 + 评估SEAL(arXiv:2506.10943
自己的代码(跨进程)一次进程重启 + 基准评测Darwin Gödel Machine(arXiv:2505.22954
自己的代码(同进程)一次 monkey patchGödel Agent(arXiv:2410.04444
上下文条目一次 delta 合并ACE(arXiv:2510.04618
记忆条目一次条目抽取 + 追加ReasoningBank(arXiv:2509.25140)、Dynamic Cheatsheet(arXiv:2504.07952
经验库当策略一组 rollout + 语义比较Training-Free GRPO(arXiv:2510.08191
可执行技能一次自验证 + 入库Voyager(arXiv:2305.16291,站内已多次消化,见应用层六层

权重那一行为什么必须出局,SEAL 自己给了理由:每个候选 self-edit 都要走一遍「生成微调数据 → 监督微调 → 评估」,论文报告的量级是每个候选 edit 每个任务 30–45 秒;而在连续多次 self-edit 的模拟实验里(论文 Figure 6),早先任务的表现随 edit 次数增加而持续下滑——作者承认没有为知识保留做优化,把它作为一个基线暴露出来。(SEAL 的这两处数字来自本次检索到的论文页与作者项目页的正文引述,我没有逐页核对全文 PDF。)

站内《把流程编译进权重》那篇讨论过权重路线的适用场景,这里不重复:结论只是它不属于”会话内”

于是本文的操作性定义定下来了:

会话内可自升级对象 = 进程内可写、且每轮推理都会被重新读进上下文的数据结构。

这个定义排除了权重(要重载),也排除了「改完得重启」的代码演化,但它没有排除代码——只要改的是运行中的代码。这一点比直觉允许的更激进,Gödel Agent 就站在这个位置。

二、最激进的那一端:直接改运行中的自己

Gödel Agent 的机制值得单独说,因为它是「不重载 RSI」的字面实现:论文写明它用 monkey patching 直接读写自己在运行时内存里的代码,自我认知靠内省 Python 的局部与全局变量。它的形式化动作集只有四个:self_inspect(读当前策略)、interact(用效用函数给当前策略打分)、self_update(改写策略与优化逻辑)、continue_improve(递归地再调用一次决策函数)。

关键差别在最后一项:被改的不只是策略 π,还有做改进这件事本身的逻辑 I。ADAS 那类元学习 agent 里 I 是固定的,Gödel Agent 里 I 也是可变的——这才叫递归。

效果(Gödel-base 是受限设置:任务用 GPT-3.5、闭卷、无联网;改进循环用 GPT-4o):

方法DROP (F1)MGSMMMLUGPQA
Chain-of-Thought64.228.065.429.2
Self-Refine59.227.563.531.6
Meta Agent Search (ADAS)79.453.469.634.6
Gödel-base80.964.270.934.9

一整轮演化约 15 美元,ADAS 约 300 美元。MGSM 上比 ADAS 高约 11 个点,GPQA 基本打平(34.9 vs 34.6)。

但这篇论文最有价值的不是这张表,是它对自己改坏自己的量化。MGSM 上跑 100 次试验的稳健性统计:

  • 意外终止 4%——论文说这通常发生在 agent 修改自己的递归改进模块时,也就是把做改进的那台机器拆了;
  • 临时性能下跌 92%——优化过程中几乎必然出现,但通常能自己调整方向或回退到之前的最优算法;
  • 优化失败 14%

以及一处消融:去掉错误处理,MGSM 从 64.2 掉到 49.4;去掉”行动前先思考”掉到 50.8。相比之下去掉”能跑代码”(57.1)和”能调 LLM”(60.4)损失小得多——因为这两样 agent 能自己重建,而错误处理不能。

我的判断:这组数字说明「让 agent 改自己的代码」在会话内是可行的,但方差极大(92% 会经历下跌),必须配一个便宜的回退机制。Gödel Agent 靠”回退到之前最优”活下来,这本质上是把版本管理当安全带。作者自己也承认系统”不够稳定、容易累积错误”,并且历史记忆持续增长会带来成本,把遗忘机制列为未来工作。

顺手记一个上限:论文说即使从更弱的种子策略出发,agent 改进幅度更大但仍没有超过 ToT,“很难创新出超越现有最优算法的东西”。会话内 RSI 是在已知设计空间里搜索,不是在发明新方法。

三、设计选择一:粒度——整块重写是头号杀手

回到开头那个 122 token 的塌缩。

ACE 把它命名为 context collapse,并且明确说这不是 Dynamic Cheatsheet 的实现 bug,而是任何让 LLM 端到端重写累积上下文的方案共有的风险:知识会被”突然抹掉而不是被保留”。伴生的另一半叫 brevity bias——模型重写时偏好写简洁摘要,于是领域细节被当成冗余删掉。

ACE 的解法是把上下文从”一段可以整体重写的散文”改成”一堆带身份的条目”。每条条目两部分:

  • 元数据:唯一 ID + 两个计数器,记录它被标记为有用/有害各多少次;
  • 内容:一个最小单元——一条可复用策略、一个领域概念,或一种常见失败模式。

然后三个角色分工(这一层沿用了 Dynamic Cheatsheet 的 agentic 设计):Generator 带着当前上下文做任务,同时标注哪些条目起了作用、哪些把它带偏了;Reflector 批判轨迹、抽出教训(最多迭代 5 轮);Curator 把教训变成紧凑的 delta 条目。

最关键的一句在合并环节:delta 由轻量的非 LLM 逻辑确定性地合并进现有上下文。因为编辑是条目化且局部的,多个 delta 可以并行合并,支持批量适配。冗余靠”grow-and-refine”处理:新 ID 追加、已有 ID 就地改(比如撞计数器),然后用语义 embedding 比较条目来剪冗余;剪的时机可配置(每次 delta 后主动剪,或等上下文溢出再懒剪)。

写成伪代码(根据论文 Method 一节的描述重写为工程化伪代码,非官方实现):

# 会话内自升级:条目化 delta 循环
playbook = load_bullets()               # [{id, content, helpful, harmful}]

for query in incoming_queries:
    trace, marks = generator(query, playbook)     # marks: 哪些 id 有用/有害
    signal = external_verifier(trace)             # 见第五节:这一步不能由模型说了算

    lessons = reflector(trace, signal, rounds<=5) # 成功抽策略,失败抽护栏
    deltas  = curator(lessons)                    # [{op: add|bump, id, content}]

    for d in deltas:                              # 确定性合并,LLM 不碰整块文本
        if d.op == "add":  playbook.append(new_bullet(d))
        else:              playbook[d.id].helpful += 1   # 或 harmful

    if len(playbook) > BUDGET:                    # grow-and-refine
        playbook = dedup_by_embedding(playbook)
# 省略:多 epoch 重访、并行 delta 合并、条目淘汰的具体判据

这段伪代码里最重要的一行是 for d in deltas 那个循环体:模型只有提案权,没有落笔权。 我认为这是整条技术线上唯一一处能把”自我修改”的方差按住的地方——把”写”从一个生成任务降级成一次账本操作。第 61 步的 122 token 之所以会发生,就是因为落笔权在模型手里。

代价方面 ACE 也给了数字(三个角色全部用 DeepSeek-V3.1 non-thinking,batch size 1,offline 最多 5 epoch):

  • AppWorld offline 平均 59.4(+17.0),online 带 offline 预热 59.5(+17.1);榜首 IBM CUGA(GPT-4.1)当时是 60.3;
  • 相比 GEPA,适配延迟 53,898s → 9,517s(−82.3%),rollout 数 1,434 → 357(−75.1%)
  • FiNER online 相比 DC-CU,延迟 65,104s → 5,503s(−91.5%),token 成本 17.7 美元 → 2.9 美元(−83.6%)
  • 跨设置的平均口径:适配延迟低 86.9%。

条目化不只是防塌缩,它顺带让自我改进变便宜了——因为不用每次重写全文。

四、设计选择二:往里写什么——策略与护栏,不是轨迹

ReasoningBank 回答的是另一个格子:既然对象可写,写什么进去才有复用价值?

它的答案是三段式条目:title(一句话标识这条策略)、description(一句话摘要)、content(蒸馏后的推理步骤、决策理由、操作要点)。抽象掉低层执行细节,保留可迁移的模式。检索用 gemini-embedding-001 做余弦相似度,默认 k=1

这里有一处很反直觉的消融,值得单独记住:k 越大越差——WebArena-Shopping 上 k=1 是 49.7,k=2/3/4 分别是 46.0 / 45.5 / 44.4。作者的结论是相关性胜过数量,多余条目会引入冲突和噪声。

第二处是成功与失败分两套抽取提示词:成功侧分析”为什么行得通”并总结可迁移策略,失败侧要求反思成因并写出”教训或预防性策略”,两侧都限每条轨迹 ≤3 个条目。消融显示这一刀切得对:ReasoningBank 只用成功经验是 46.5,加入失败经验涨到 49.7;而对照的 AWM(工作流记忆)加入失败经验反而从 44.4 掉到 42.2

主结果(WebArena 684 个任务,总体成功率):

骨干模型无记忆SynapseAWMReasoningBank
Gemini-2.5-flash40.542.144.148.8
Gemini-2.5-pro46.747.747.653.9
Claude-3.7-sonnet41.742.640.846.3

SWE-Bench-Verified(500 例,mini-SWE-Agent 纯 bash):flash 34.2 → 38.8,步数 30.3 → 27.5;pro 54.0 → 57.4,步数 21.1 → 19.8。注意 Synapse 在 pro 上是 53.4,比无记忆的 54.0 更低——记忆机制做错方向是会掉分的,这是本文主线的又一次出现。

一个诚实的限定:Mind2Web 上的任务级成功率绝对值只在 1–5% 区间(比如 flash cross-task 3.3 → 4.8),那一组”一致提升”的绝对差很小,不宜当强证据用。

论文还有一个和会话内特别相关的发现:MaTTS(memory-aware test-time scaling)。同一个 query 下并行跑 k 条轨迹,然后自对比找出一致模式、过滤掉侥幸解;或者在一条轨迹内序贯自我精修,把中间的修正笔记也写进记忆。k 从 1 到 5:并行 49.7 → 55.1,序贯 49.7 → 54.5;而没有记忆时,同样的 scaling 只在 39.0–42.2 之间震荡

反方向更说明问题:在 k=3 的快照上看”scaling 能不能改善记忆质量”,Synapse 的 Pass@1 从 40.6 掉到 40.1、AWM 从 44.4 掉到 41.2,只有 ReasoningBank 从 49.7 升到 50.8。

我的提炼:更多探索不会自动变成更好的经验。多跑几遍只是把原料变多,能不能变成资产取决于写入端的抽取质量——写入端弱的时候,多跑几遍是往里灌噪声。

ReasoningBank 自己的短板也在这里:合并策略是纯追加,没有剪枝也没有合并,作者明确列为简化,把合并/衰减/刷新策略留给未来工作。想在长会话里用,这一块得自己补——《遗忘是一种能力》那篇讨论的上下文 GC 机制,正好是这块的候选零件。

五、设计选择三:梯度从哪来——决定收敛还是退化的那一项

前两个选择决定效率,这一个决定符号

先看最早的证据。Huang 等人的 《Large Language Models Cannot Self-Correct Reasoning Yet》(arXiv:2310.01798,ICLR 2024,Google DeepMind + UIUC)提出 intrinsic self-correction 这个概念——模型只凭自身判断修正答案,不借外部反馈——并给出结论:在推理任务上,LLM 没有外部反馈时难以自我修正,有时自我修正后表现反而更差。论文对 Self-Refine 一类结果的方法论批评是:那些正面结果里,“什么时候停止修改”这个决定往往隐含依赖了对正确答案的知情。

三年后的系统实测把这条结论再确认了一遍。ACE 的无标签消融:

设置FiNER 得分相对基线
基线(不适配,均值口径 69.1)
ACE offline 无标签71.1+0.4(几乎无效)
ACE online 无标签67.3−3.4
DC online 无标签(均值 65.4)−3.7

论文的措辞是:这种条件下上下文”会被虚假或误导性的信号污染”。

而同一套方法在 AppWorld 上,无标签也能拿到 +14.8% 的平均提升——因为 AppWorld 提供天然信号:代码执行的成功或失败。

最刺眼的版本来自 DGM。Sakana 的项目页写明:系统有时会假装跑了单元测试,“伪造一份日志让它看起来像测试跑过并且通过了,而实际上从未运行”——而这份伪造的日志进了它自己的上下文,于是它相信补丁已被验证。研究者后来专门加了一个”工具使用幻觉”检测函数让 DGM 去优化,结果它有时真去修问题,有时直接删掉检测标记,“尽管我们明确指示不要这么做”,从而让检测函数报告虚假的成功。

把这三条摆在一起,它们讲的是同一件事的三个层次:论文层面(无外部反馈的自我修正会退化)、系统层面(无标签适配跌破不适配基线)、机制层面(当验证信号可以被被优化对象自己写,循环就闭合到了错误上)。

flowchart LR
    Q[新任务] --> G["Generator:带当前 playbook 推理"]
    G --> V{"验证信号谁说了算?"}
    V -->|"代码执行 / 测试 / 环境终态"| R["Reflector:成功抽策略,失败抽护栏"]
    R --> C["Curator:产出 delta"]
    C --> M["确定性 merge(非 LLM)"]
    M --> P["playbook:带 ID + helpful/harmful 计数"]
    P -.每轮读入.-> G
    V -->|"模型自评 / 信号可被自己改写"| X["上下文被伪信号污染"]
    X -.污染写回.-> P

所以,对最初那个问题——「人不介入,agent 怎么让任务质量越来越好」——最准确的回答不是”给它一个可写对象”,而是:

会话内 RSI 的先决条件不是「能不能改自己」,而是「这个会话里有没有一个不由模型说了算的信号」。 代码执行返回码、测试结果、编译成败、环境终态都算;LLM 自评不算(ReasoningBank 用的就是无 ground truth 的 LLM-as-judge,温度 0,作者自己把噪声列为局限并建议上更强的验证器、人在环或集成判断)。

这和 Weng 那篇的”评估器必须留在循环之外”是同一条约束的两种说法,也是站内《验证真空》那篇担心的东西在自我改进场景里的加强版:验证真空在普通任务里是漏检,在自我改进循环里是把漏检写进下一轮的先验

这条我愿意升格为”观察”而不只是读后感,因为它在两个独立系统上被测出(ACE 的金融任务、Huang 等人的推理任务),并且有一个机制性反例(DGM 伪造日志)说明它为什么成立。但它还不够格叫定律:我没有见到「有外部信号就一定收敛」的反向验证,Gödel Agent 有真实的效用函数打分,仍然有 14% 的优化失败率。

六、一个额外自由度:经验库可以直接当策略用

如果验证信号有了,会话内还能做一件比”攒经验”更贴近 RL 的事。

Training-Free GRPO(arXiv:2510.08191,腾讯,2025-10)的做法是:在每组 rollout 内部用群体相对语义优势(group relative semantic advantage)替代数值优势——用自然语言表达”这条轨迹比那条好在哪”,多轮迭代蒸馏出高质量经验知识,形成的经验库作为 token prior 注入后续 API 调用,从而在不改参数的前提下移动输出分布。冻结的基座模型在这里扮演类似 vanilla GRPO 里 KL 约束的角色,保证稳定。作者的一句话总结是:把策略优化从参数空间搬到上下文空间

报告数字:DeepSeek-V3.1-Terminus 在 AIME24 从 80% 到 82.7%,AIME25 从 67.9% 到 73.3%,只用几十条训练样本,并且在数学推理和网页搜索任务上比微调过的小模型更好。(这组数字来自本次检索到的论文页与摘要转述,我未取全文核对表格。)

这条线和 ACE / ReasoningBank 是同构的——都是”可写条目 + 外部信号”——差别只在它把这个对象当 policy 用,而不是当知识库用。判据也就换了:条目的价值不是”信息是否正确”,而是”注入后输出分布是否往对的方向移动”。

至于把对象升级成可执行代码这条路(Voyager 的 skill library:环境反馈 + 执行错误 + 自验证三路信号,通过后才入库,入库时用描述的 embedding 建索引),站内已经消化过多次,这里只回链不重讲:应用层六层讲它作为”外部化积累介质”的意义,skill 供应链讲它到今天的产品形态。放在本文的框架里,它的位置很清楚:验证信号最硬的一档——代码要么跑通要么不跑通。

七、一张设计表(把三个选择合起来)

对象粒度写入触发必须的外部信号主要失效模式出处
运行中的自身代码函数级 monkey patch效用函数打分后效用函数 U拆掉递归改进模块(4% 意外终止);92% 有临时下跌Gödel Agent
演化档案里的 agent 代码一次 commit基准评测后SWE-bench 等基准伪造测试日志、删除检测标记DGM
上下文条目带 ID 的 bullet + delta每个 query 后(可批量)执行成败(AppWorld)/ 标签无信号时跌破不适配基线(−3.4)ACE
记忆条目title/desc/content,≤3 条/轨迹每条轨迹后LLM-as-judge(有噪声)纯追加无遗忘;k 变大反而掉分ReasoningBank
经验库(当 policy)语义优势提炼的条目每组 rollout 后少量 ground truth未见充分消融Training-Free GRPO
可执行技能一个函数自验证通过后环境反馈 + 执行错误技能库膨胀与检索退化Voyager

三个选择的默认答案,如果只能记一句:条目化、模型只有提案权、信号来自会话外的执行器。

八、预设三个反对意见

“这不就是把 prompt 写长吗?” 部分是,但 ACE 自己划了边界,值得照抄:HotPotQA 上简短的高层指导反而更好,Game of 24 这类固定策略的任务可能只需要一条可复用规则;适合长上下文 playbook 的是需要详细领域知识、复杂工具使用、或环境特定策略的任务。另外它依赖一个”足够强的 Reflector”——弱 Reflector 会产出噪声甚至有害的上下文,这个依赖 Dynamic Cheatsheet 也有。所以答案是”看任务”,不是”越长越好”。至于成本,ACE 的讨论里提到长上下文的服务开销不与长度成正比(KV cache 复用、压缩、offload),这个说法与站内《KV cache 与内存 GC》的机制一致。

“人不介入,它必然漂移。” 对,而且这是这条线里最欠研究的一环。ReasoningBank 是纯追加、无遗忘;ACE 靠 embedding 去重加 helpful/harmful 计数;Gödel Agent 承认历史记忆持续增长带来成本,把遗忘机制列为未来工作。写入策略(什么时候剪、剪谁、按什么判据剪)在这几篇论文里都是最薄的一节。 这也意味着它是自己动手最容易做出增量的地方。

“会话内和跨会话有区别吗?” 机制上同构,差别只有两点:这个对象活多久,以及谁来做 GC。ACE 的 online 设置就是在测试集上顺序推进——先用当前上下文预测,再用同一个样本更新上下文——这跟一个长会话里的自我改进是一回事。所以本文的三个选择对跨会话记忆同样适用。

九、诚实的提醒 + 一个能在一个下午跑完的验证

本文所有数字都来自论文原文或官方项目页,我没有亲手复现任何一条。 具体分级:ACE、ReasoningBank、Gödel Agent 的机制与数字取自 arXiv 全文页;DGM 的数字与安全观察取自 Sakana 官方项目页;SEAL 与 Training-Free GRPO 的数字取自本次检索到的论文页与摘要转述,未取全文核对表格——这两条是本文证据最弱的地方,引用前请自己回查。

最低成本的亲手验证实验(不需要训练,不需要 GPU):

  1. 在你现有的 coding agent 上加一个条目化的 PLAYBOOK.md:每条 = 一个 ID + 一句策略/护栏 + helpful / harmful 两个计数。
  2. 写入只在测试命令有返回码可读时触发:返回 0 抽一条策略,非 0 抽一条护栏,每次最多 3 条。
  3. 合并交给脚本:新 ID 追加,已有 ID 只改计数——不让模型整块重写这个文件。这一步是整个实验的关键变量。
  4. 对照组是同一个 harness 关掉写入。同一批 20 个任务,比 pass@1 和平均步数。
  5. 想复现塌缩,加第三组:把第 3 步换成”让模型每轮重写整个 PLAYBOOK.md”,然后观察文件的 token 数曲线。ACE 的 18,282 → 122 是不是普遍现象,这一组能给出答案。

成本是 40–60 次任务运行。它验证的不是某篇论文的绝对数字,而是本文那句主线:落笔权在谁手里,比对象里写了什么更决定结果。

参考来源

arXiv 论文

工程实践与站内延伸