Absolute Zero: Reinforced Self-play Reasoning with Zero Data

Paper: arXiv:2505.03335 Code: LeapLabTHU/Absolute-Zero-Reasoner Code reference: paper @ 41ed983c (2025-06-01)

1. Motivation (研究动机)

现有 RLVR(Reinforcement Learning with Verifiable Rewards)虽然避免了对 chain-of-thought 标注的依赖,但仍然建立在人工策划的问题-答案分布上:人类或更强模型要先定义 query、目标答案、评测域,再让模型通过 outcome reward 学会解题。论文指出,这种“zero setting”并不是真的 zero data,因为训练分布仍然是人工规定的;当高质量 reasoning 数据越来越稀缺、构造成本越来越高时,这条路线本身会成为扩展瓶颈。

这篇论文要解决的不是“如何在既定数学/代码题集上做更好的 RL”,而是“如何让模型在完全没有外部训练数据的情况下,自主提出可学任务并通过解决这些任务持续提升 reasoning”。作者把这个目标称为 Absolute Zero:模型不再被动接收人类定义的题目,而是同时扮演 proposer 和 solver,在 environment 的可验证反馈约束下自己构造课程、自己求解、自己更新。这个问题值得研究有三个层面的原因。第一,它直接回应了 reasoning 训练的数据可扩展性问题,把扩展压力从人工标注转移到模型和环境交互上。第二,如果未来模型能力超过人类,人类设计的任务可能不再提供足够 learning signal,模型需要能发现“对自己仍然有学习价值”的任务。

第三,若这一范式成立,reasoning 的提升可以更多依赖 grounded、verifiable 的环境反馈,而不是脆弱的 reward model 或越来越贵的数据生产流水线。

论文在动机部分还隐含了一个更尖锐的判断:现有 post-training 工作大多默认“题目分布已经给定”,于是研究重点放在更强优化器、更长 rollout 或更稳 reward shaping 上;但如果训练题目本身过窄,模型最终学到的往往只是对某类 benchmark 的过拟合策略,而不是更一般的 reasoning habit。Absolute Zero 因而把研究重心前移到“谁来定义训练任务”这一层,认为这比单纯改进 RL update 更接近真正的长期瓶颈。 作者选择 code reasoning 作为第一落地点,也正是出于这个动机约束。数学、定理证明或开放文本推理虽然同样重要,但很难在 zero-data 场景下同时满足开放性与可验证性;Python 程序执行环境则天然提供了状态转移、答案校验与安全边界,使“自提出任务”不会立即退化为不可判分的自由文本游戏。换句话说,论文不是声称 code 是 reasoning 的终点,而是把它作为最适合检验 Absolute Zero 假设的实验场。

Figure 1 解读:这张 teaser 图给出论文最核心的 claim。AZR 在完全不使用人工标注或 curated reasoning data 的前提下,同时提升 code 与 math 两类 benchmark;作者强调它不仅优于各自领域的 base model,还超过若干使用数万条人工整理样本训练出来的 “zero reasoner”,因此论文关注点并非“在单一域刷分”,而是证明 zero-data self-play 可以产生跨域 general reasoning gain。

2. Idea (核心思想)

核心 insight 是:如果有一个既开放又可验证的环境,那么模型不必等待人类提供题目,而可以把“提出任务”和“解任务”同时纳入同一个 RL 闭环,让 task proposal 本身也成为被优化对象。Absolute Zero 用 learnability reward 奖励“哪些自提出任务最能让自己学到东西”,再用 solve reward 奖励“是否真正解对这些任务”,从而把 curriculum discovery 和 capability improvement 统一进一次 self-play。关键创新可以概括成三点。

第一,把 code executor 视为可验证环境,使 proposer 生成的程序/输入/输出 triplet 能被自动检查语法、安全性、确定性与答案正确性。第二,让一个统一 LLM 同时扮演 proposer 和 solver,而不是分成 teacher/student 两个模型。第三,针对 3 个 task type 和 2 个 role 的联合训练,提出 Task-Relative REINFORCE++ (TRR++),分别为 6 种 task-role 配置建 baseline,降低多任务 RL 的方差。

它与现有 zero RLVR 方法的根本区别在于:OpenReasonerZero、SimpleRL-Zoo、PRIME-Zero 这类方法仍然需要人类定义好的 math/code 训练集,只是不用 CoT 标注;而 Absolute Zero 训练期间根本不消费人类 QA 数据,唯一外部结构性先验是 Python 执行环境和 very small seeding buffer。与 AlphaZero 式自博弈也不同,AZR 不在固定规则游戏中对弈,而是在 open-ended code reasoning space 中通过程序执行器获得 grounded feedback。

更具体地说,AZR 的核心不是“让模型自己出题”这个表面动作,而是把 task proposal 也纳入可优化的 policy space。传统 curriculum learning 往往由外部 teacher、启发式难度调度器或人工规则来决定下一步学什么;AZR 则要求 proposer 直接为“哪些任务最具 learnability”负责。这样一来,训练目标不再只是提升求解正确率,还隐式要求模型学会辨认什么样的任务处在自己的 capability frontier 附近。

这也是它与 teacher-student self-play 的差异所在。若 proposer 和 solver 是两个独立模型,teacher 很容易朝着让 student 失败最多的方向出题,却未必真的有助于学习;而在 AZR 中,同一个参数化模型同时承担 proposal 与 solving,两种角色共享表示与能力边界,proposal policy 因而更倾向于寻找“当前刚好可学”的任务,而非纯粹对抗性的 impossible tasks。 从这个角度看,AZR 想回答的其实不是单一算法问题,而是一个更一般的 scaling hypothesis:当外部高质量 reasoning data 不再线性增长时,模型能否靠 environment-grounded self-play 自己制造下一阶段所需的训练信号。论文把这一假设压缩到一个可实验检验的 setting 中,并通过 code executor 让“自我生成数据”第一次变成可重复、可验真的 RL 闭环。

3. Method (方法)

3.1 Overall framework

Absolute Zero 的整体目标写为: 这里 proposer 先生成 task proposal ,environment 与构造函数 把它变成有效任务 ;solver 再对 query 生成答案 learnability reward 负责衡量这个 task 是否值得学,solve reward 负责衡量是否解对。论文真正落地的实例叫 Absolute Zero Reasoner (AZR),将 reasoning 空间限制在 Python code reasoning 上,以便 environment 既足够开放,又能用 deterministic execution 给出 verifiable feedback。

Figure 2 解读:图中把三种 paradigm 并排比较。Supervised Learning 依赖人类提供 query、answer、reasoning trace;RLVR 去掉了 rationale 标注,但仍需要人类给 query 和 gold answer;Absolute Zero 则把“定义任务分布”这件事也交回模型本身。它不是简单减少监督,而是把学习闭环从“人定义题,模型做题”改写为“模型定义题,环境验证题,模型再做题”。

Figure 3 解读:这张图是数学定义到训练流程的桥。单个 policy 在 propose 分支输出 task proposal 并收到 ,在 solve 分支读取由 environment 构造出的 并输出答案、收到 。重点不是两个角色轮流运行,而是同一个参数化模型在同一训练过程中被 jointly optimized,从而把“出题能力”和“解题能力”耦合起来。

Figure 4 解读:这张训练总览图把 AZR 的工程化细节串起来。每个 iteration 先从 buffer 中取历史 triplet 作为 proposer 的参考,生成 abduction / deduction / induction 三类候选任务;经过 syntax、安全和 determinism 过滤后,这些 triplet 一方面写回 buffer 扩充 curriculum,另一方面转换成 solver query 交给同一个模型求解;最后 proposer reward 和 solver reward 一起进入 PPO-style 更新。它展示了为什么 authors 说 AZR 的关键不是单次“生成一道题”,而是一个持续增长的 self-generated task ecology。

从方法论上看,Figure 4 也揭示了 AZR 与很多“generate-then-filter”流水线的差别。这里的 filter 不是离线数据清洗,而是训练闭环的一部分:通过合法性检查留下来的任务会改变后续 buffer 分布,进而改变 proposer 下几轮看到的参考样本。因此 verifier 不只是守门员,也是 curriculum dynamics 的组成部分。

3.2 Three reasoning task types

AZR 将 code reasoning 拆成 3 类互补 task,它们恰好对应 3 种基本推理方式:

  1. Abduction:给程序 和输出 ,要求模型反推一个可能输入
  2. Deduction:给程序 和输入 ,要求模型推出输出
  3. Induction:给若干输入输出对 和自然语言 message ,要求模型归纳出函数

这样设计有两个好处。第一,这 3 类任务都能被 Python executor 自动验证,因此 reward 不依赖 learned RM。第二,它们诱导出不同 cognitive behavior:abduction 更容易出现试错和 search,deduction 更偏 execution tracing,induction 则更接近从 examples 中 synthesize rule。论文后续观察到 token length 与行为模式确实会随 task type 明显变化,说明 proposer 并不是在机械地产生一种题,而是在探索不同 reasoning mode。

3.3 Buffer initialization and task proposal

AZR 不是从完全空白开始训练。Algorithm 1 先用 InitSeeding(π_θ) 初始化三个 buffer:。论文正文说明初始化大小为 ,其中 ,并且在 seeding 阶段不做参数更新;代码侧 configs/azr_ppo_trainer.yaml 里的 seed_batch_factor: 4 与论文 Table 3 一致。对 abduction / deduction,seed 来自初始 triplet;

对 induction,则采样程序再生成匹配输入集合和 message。进入 self-play 后,buffer 有 3 个作用。第一,abduction / deduction proposer 会均匀采样 个历史 triplet 作为 in-context references,然后被 prompt 去生成“不同于这些例子”的新任务;论文 Table 3 把 固定为 6,代码中对应 azr.reward.generation_reward_config.include_references: True 以及 proposer prompt 逻辑。

第二,induction proposer 从 里抽程序,生成 个输入和一段 message;论文 Table 3 把估计任务准确率的 sample 数固定为 8,代码中对应 azr.reward.n_samples: 8。第三,当某一步 proposer 产出的合法任务少于 batch size 时,用历史 buffer 回填,保证 solver 训练稳定。这里的直觉很重要:AZR 并不是让 proposer 无约束地“随便发明题目”,而是让它在最近历史经验周围做 controlled expansion。

references 既提供 task manifold 的局部先验,又通过“生成不同于过去样本”的约束鼓励多样性。这样 proposer 学到的不是纯随机出题,而是逐步把 buffer 推向更丰富、更可学的区域。

def init_seed_buffers(base_model, batch_size: int, seed_factor: int = 4):
    target_size = batch_size * seed_factor
    D_abd, D_ded, D_ind = [], [], []
    while len(D_abd) < target_size or len(D_ded) < target_size:
        triplet = sample_seed_triplet(base_model)
        if valid_triplet(triplet):
            D_abd.append(triplet)
            D_ded.append(triplet)
    while len(D_ind) < target_size:
        program = random.choice(D_abd + D_ded)["program"]
        inputs, outputs, message = propose_induction_seed(base_model, program)
        if valid_induction_triplet(program, inputs, outputs, message):
            D_ind.append({"program": program, "inputs": inputs, "outputs": outputs, "message": message})
    return D_abd, D_ded, D_ind
def propose_tasks(policy, D_abd, D_ded, D_ind, k_refs: int = 6):
    proposals = []
    for task_type in ["abd", "ded"]:
        refs = random.sample(D_abd if task_type == "abd" else D_ded, k_refs)
        program, io_hint = policy.propose_code_io(task_type=task_type, references=refs)
        proposals.append({"task_type": task_type, "program": program, "io_hint": io_hint})
    base_program = random.choice(D_abd + D_ded)["program"]
    inputs, message = policy.propose_induction(program=base_program)
    proposals.append({"task_type": "ind", "program": base_program, "inputs": inputs, "message": message})
    return proposals

3.4 Task validation and construction

论文第 3.3.3 节把 valid task 的构造定义得非常严格。无论是 abduction / deduction 的 还是 induction 的 ,都必须经过 3 类检查:

  1. Program integrity:程序能运行、能返回值,说明至少语法与基本执行有效。
  2. Program safety:禁止危险模块,论文 Figure 10 明示了 subprocesssys.exitos.environmultiprocessingthreading 等 forbidden modules。
  3. Determinism:同一输入重复执行 次必须输出相同结果;论文把 固定为 2。

只有通过这些检查,proposal 才会被转成完整 triplet 并写入 buffer。对 solver 侧的 task construction,作者定义: 其中 induction 只给一半 test cases 和 message,让 solver 归纳程序后再在保留样本上验证。 released code 中,这套逻辑主要落在 absolute_zero_reasoner/rewards/reward_managers.pyCodeIORewardManager 与 trainer 构造阶段的 executor 校验上。它会解析 proposer 输出,检查格式块、抽取 code/input/output,然后调用 executor 的 check_all(...) 做 determinism、imports、安全性与错误检查。这里可以看到论文与代码在术语上是一致的:论文讲“syntax/safety/determinism”,代码对应 parse_* + check_all(..., check_determinism=True, banned_keywords=...)。 这个 validation layer 还有一个隐含作用:它把 proposer 的创造空间限制在“程序语义可解释”的区域。模型当然可以尝试投机,但只要输出不能被 executor 还原成明确、可执行、可重复的 task,样本就不会进入后续训练分布。

def validate_and_construct(task, executor, banned_modules, repeat_runs: int = 2):
    program = task["program"]
    if task["task_type"] in {"abd", "ded"}:
        input_value = task["io_hint"]
        ok, output_value = executor.check_all(
            code=program,
            inputs=input_value,
            banned_keywords=banned_modules,
            check_determinism=True,
        )
        if not ok:
            return None
        return {"program": program, "input": input_value, "output": output_value}
    inputs = task["inputs"]
    outputs = []
    for inpt in inputs:
        ok, out = executor.check_all(
            code=program,
            inputs=inpt,
            banned_keywords=banned_modules,
            check_determinism=True,
        )
        if not ok:
            return None
        outputs.append(out)
    return {"program": program, "inputs": inputs, "outputs": outputs, "message": task["message"]}

方法上的关键直觉是:AZR 成功的前提不是 proposer 足够聪明,而是 environment 足够严格。若没有安全、可执行、确定性过滤,proposer 很容易通过构造不可验证、模棱两可或 reward-hack 的伪任务拿到假信号。作者因此选择把可学习空间收缩到 deterministic Python programs;这牺牲了开放性,但换来了 reward correctness 和训练稳定性。

3.5 Answer verification and learning rewards

solver reward 也按 task type 分开定义。对于 deduction,直接比较 ;对于 induction,比较归纳得到的程序在全部隐藏测试上是否满足 ;对于 abduction,不能直接比较输入 ,因为程序不一定是 bijection,所以论文改成检查: 这个设计非常关键,因为它把“找到任一满足输出约束的输入”视为成功,而不是强行匹配唯一 gold input,从而保证 abduction reward 与任务语义一致。proposer reward 的口头定义是 learnability reward:鼓励模型提出“让自己最能进步”的任务。论文正文并未把这个 reward 写成完整封闭公式,而是通过 task proposal accuracy estimation 与 role-wise RL 更新来实现。

结合代码可以看出,training pipeline 把 proposer 与 solver 都放进同一 PPO-style trainer,由 task-type-specific reward manager 统一提供 token-level score / reward,再做后续 advantage 归一化。这里有一个很关键的细节:learnability 不是“题越难越好”,而是“对当前 solver 最有训练价值越好”。如果 proposer 总是生成 trivially solvable 的样本,solver reward 会饱和,几乎不给增益;

如果 proposer 一味生成无法验证或远超当前能力边界的样本,任务会在过滤阶段被拒绝,或者只留下接近零信息量的失败信号。AZR 想要逼近的是二者之间那条窄带,也就是 capability frontier 附近的可学区域。因此,proposer reward 与 solver reward 在语义上是互补关系。前者近似回答“这道题值不值得被放进训练分布”,后者回答“放进去之后模型有没有真的学会”。论文没有把两者人为拆成先 curriculum search、后 supervised solving 的两阶段流程,而是让它们在同一个 on-policy 更新里共同塑形,这也是其 self-play 味道最浓的部分。

这一步也解释了为什么 AZR 能避免很多 self-generated data 方法常见的 distribution collapse。只要 proposer 生成的任务不再具有学习价值,它即便形式合法,也不会持续带来高 learnability signal;反过来,只要 solver 开始稳定掌握某类模式,proposal policy 就需要继续外推到新的可学区域,否则整体回报会停滞。换句话说,reward 设计在这里承担了自动课程推进器的职责。

3.6 Task-Relative REINFORCE++ (TRR++)

多任务训练下,如果所有样本共享一个 baseline,会把不同 task type / role 的 reward scale 混在一起,造成方差与 credit assignment 问题。作者因此从 REINFORCE++ 变体出发,为 3 个 task type 2 个 role 一共 6 个配置分别统计均值与标准差,定义: 这比 GRPO 式 per-question baseline 更粗,但比单一 global baseline 更细,属于针对 AZR 结构量身定做的 variance reduction。直观上,propose-abduction 的 reward 分布和 solve-induction 的 reward 分布几乎肯定不同,若不分开标准化,优化器会偏向 reward scale 更容易波动的子任务。

def task_relative_reinforce_pp(samples):
    grouped = defaultdict(list)
    for item in samples:
        grouped[(item["task_type"], item["role"])].append(item["reward"])
    stats = {
        key: (torch.tensor(vals).mean(), torch.tensor(vals).std().clamp_min(1e-6))
        for key, vals in grouped.items()
    }
    for item in samples:
        mu, sigma = stats[(item["task_type"], item["role"])]
        item["advantage"] = (item["reward"] - mu) / sigma
    return ppo_update(samples)

3.7 训练算法总览

Algorithm 1 的主循环可以概括为:初始化 seed buffers;每轮先做 propose phase,生成并验证新 triplet、更新 buffers;再做 solve phase,从三类 buffer 中采样 solver tasks、执行求解、计算 proposer/solver rewards;最后使用 TRR++ 统一更新单个 policy。

def azr_train_step(policy, buffers, batch_size):
    new_tasks = []
    for _ in range(batch_size):
        for proposal in propose_tasks(policy, buffers["abd"], buffers["ded"], buffers["ind"]):
            task = validate_and_construct(proposal, executor=python_executor, banned_modules=FORBIDDEN_MODULES)
            if task is not None:
                buffers[proposal["task_type"]].append(task)
                new_tasks.append(task)
    solver_batch = sample_solver_queries(new_tasks, buffers, batch_size=batch_size)
    rollout = solve_queries(policy, solver_batch)
    rewards = score_propose_and_solve(rollout, buffers)
    return task_relative_reinforce_pp(rewards)

Code reference: paper @ 41ed983c (2025-06-01) — pseudocode and mapping based on this commit

Paper ConceptSource FileKey Class/Function
PPO-style AZR training entryabsolute_zero_reasoner/main_azr_ppo.pyrun_ppo, TaskRunner.run
AZR self-play trainerabsolute_zero_reasoner/trainer/ppo/azr_ray_trainer.pyCodeIORayPPOTrainer
Task proposal / solver data constructionabsolute_zero_reasoner/data_construction/constructor.pyget_gen_code_io_data, get_pred_code_io_data
Reward parsing and task validationabsolute_zero_reasoner/rewards/reward_managers.pyCodeIORewardManager, parse_code_input_output, parse_inputs_message
Execution-based verificationabsolute_zero_reasoner/utils/code_utils/python_executor.pyPythonExecutor, check_all
Determinism / safety helper checksabsolute_zero_reasoner/utils/code_utils/checks.pycheck_composite_function, check_no_definitions

论文公式与 released code 实现差异:论文 Table 3 报告 Max Prompt Length = 6144Train Batch Size = 64 * 6Total Steps = 500,而仓库默认配置 absolute_zero_reasoner/configs/azr_ppo_trainer.yaml 当前显示 data.max_prompt_length: 8096data.train_batch_size: 1024trainer.total_epochs: 30trainer.total_training_steps: null。README 明确提示“复现实验请使用 paper branch”,因此本文中的训练配置以论文 Table 3 为主,代码默认配置视为后续演化版本,不直接等同于 paper setting。

4. Experimental Setup (实验设置)

4.1 Datasets and task sources

AZR 自身训练数据源是 zero data:不使用人工 curated math/code QA 对。训练中唯一“数据结构”来自 seed buffers 和模型在线 self-propose 的 triplet。对比 baseline 的训练数据则来自 Table 4:

  • Oat-7BSimpleRL-Zoo:8.5k math pairs。
  • OpenReasonerZero:57k STEM + math samples。
  • PRIME-Zero:457k math + 27k code problems。
  • CodeR1-Zero-7B-LC2k-1088:2k Leetcode pairs。
  • CodeR1-Zero-7B-12k-832:2k Leetcode + 10k TACO pairs。
  • AceCoder-*:22k code data。
  • AZR-7B / AZR-7B-Coder:No data。

4.2 Baselines

主实验基于 Qwen2.5-7B 家族展开,base models 包括 Qwen2.5-7B-BaseQwen2.5-7B-CoderQwen2.5-7B-InstructQwen2.5-Math-7B。对比方法覆盖 code-oriented zero reasoners(AceCoder、CodeR1)与 math-oriented zero reasoners(Oat、ORZ、SimpleRL-Zoo、PRIME-Zero)。论文还补充了 3B、14B、Llama3.1-8B 等缩放实验,但主表 Table 1 聚焦 7B。

4.3 Evaluation metrics

OOD code benchmarks 有 3 个:HumanEval+MBPP+LiveCodeBench v1-5。OOD math benchmarks有 6 个:AIME'24AIME'25AMC'23MATH500MinervaOlympiadBench。ID benchmarks 有 3 个:CruxEval-ICruxEval-OLiveCodeBench-Execution。论文使用 greedy decoding 报告所有 baseline 与 AZR 结果,并把 code average、math average 与 overall average 定义为各自 benchmark 均值,以及 Pass@k 分析另外出现在 Figure 8,用于说明 base model 与 AZR 在多次采样下的 gap 是否仍然存在。

4.4 Training config

论文 Table 3 给出的 paper setting 如下:

  • 模型配置:Max Prompt Length = 6144Max Response Length = 8096Seed Batch Factor = 4Max Programs = 16384
  • 训练设置:Train Batch Size = 64 * 6Learning Rate = 1e-6Optimizer = AdamWGrad Clip = 1.0Total Steps = 500
  • RL 设置:Algorithm = TRR++KL Loss = FalseKL Reward = FalseEntropy Coefficient = 0.001PPO Epochs = 1N Rollouts = 1Temperature = 1.0Top-P = 1.0K References = 6N Samples to Estimate Task Accuracy = 8

代码仓库 paper 分支中能对齐到的字段包括:absolute_zero_reasoner/configs/azr_ppo_trainer.yamlactor_rollout_ref.actor.optim.lr: 1e-6actor_rollout_ref.actor.grad_clip: 1.0actor_rollout_ref.actor.ppo_epochs: 1actor_rollout_ref.rollout.temperature: 1.0actor_rollout_ref.rollout.top_p: 1actor_rollout_ref.rollout.n: 1actor_rollout_ref.actor.entropy_coeff: 0.001azr.reward.n_samples: 8ray_init.nnodes: 1trainer.n_gpus_per_node: 8。但如上所述,prompt length / batch size / total steps 在当前配置文件中与论文表格不完全一致,因此训练配置应以论文 Table 3 为准,并把代码值视为 evolving implementation snapshot。

5. Experimental Results (实验结果)

5.1 Main benchmark numbers

Table 1 的主结论是:AZR-7B-Coder 在 overall average 与 coding average 上达到当时 SOTA,并且训练过程中未使用任何外部数据。论文正文明确写到,它比此前最强模型在 AVG 上高 1.8 个绝对点,在 CAvg 上高 0.3 个绝对点。

按论文给出的聚合结果:

ModelBasedataCode AvgMath AvgTotal Avg
Qwen2.5-7B--52.027.539.8
Qwen2.5-7B-Ins--56.337.046.7
Qwen2.5-7B-Coder--56.623.940.2
Oat-7BMath8.5k36.942.439.7
SimpleRL-ZooBase8.5k54.038.546.3
OpenReasonerZeroBase57k48.043.445.7
PRIME-ZeroCoder484k+27k37.245.841.5
CodeR1-LC2kIns2k60.535.648.0
CodeR1-12kIns10k61.333.547.4
AceCoder-RMIns22k58.337.447.9
AceCoder-RuleIns22k55.436.946.2
AceCoder-RMCoder22k57.327.542.4
AceCoder-RuleCoder22k60.028.544.3
AZR-7BBaseNo data67.238.452.8
AZR-7B-CoderCoderNo data68.039.153.6

其中 AZR-7B 相对 base model 的增益约为 +15.2 / +10.9 / +13.0(Code Avg / Math Avg / Total Avg),AZR-7B-Coder 相对 coder base 的增益约为 +11.4 / +15.2 / +13.4。这正是论文强调的“虽然训练只发生在 code executor 环境里,但 math reasoning 也显著提升”的证据。

Figure 9 解读:这张图把 AZR-Base-7B 与 ORZ、SimpleRL-Zoo、Qwen2.5-7B 放在统一 general reasoning 视角下比较。关键观察不是单个 benchmark 上偶尔领先,而是 across code 与 math 的更稳定抬升,支撑作者“AZR 学到的是更通用 reasoning,而不是对某个 curated domain 的过拟合”的论点。

5.2 In-distribution and scaling observations

论文 Figure 6 显示 ID 与 OOD benchmark 都随着训练步数提升;而 Table 5、Figure 30-33 则说明 3B、7B、14B 和 coder/base 变体整体都能从 Absolute Zero 中获益。作者特别总结了三个现象:

  • Code priors amplify reasoning:Qwen-Coder-7B 初始 math 比 Qwen-7B 低 3.6 分,但经 AZR 训练后反超 0.7 分,说明 coding prior 可能增强 downstream reasoning improvement。
  • Cross-domain transfer is more pronounced for AZR:expert code RL 模型在 math 上平均只涨 0.65 分,而 AZR-Base-7B 与 AZR-Coder-7B 分别涨 10.915.2
  • Bigger bases yield bigger gains:3B、7B、14B coder 模型的总分收益分别约 +5.7+10.2+13.2,显示 scaling 仍有收益。

Figure 8 解读:Pass@k 图说明 AZR 的优势并不依赖 greedy decoding 的偶然性。随着采样次数增加,base model 与 AZR 都会受益,但 AZR 的曲线整体更高,表明它不仅 first-try accuracy 更好,候选分布本身也更强。

5.3 Ablation findings

Table 2 的消融主要问两件事:task type 是否都必要,以及 proposer role 的设计是否真的重要。论文结论很直接:

  • 去掉 induction,或者只保留 deduction,会带来明显性能下降。
  • proposer 不看 个 references(即 unconditional generation)会退化。
  • 完全去掉 proposer-role training 也会退化。

这说明 AZR 的效果不是单纯来自“在 code executor 上做 solve-side RL”,而是来自“任务生成 + 任务求解”的闭环本身;尤其 induction task 与 conditioned proposer 对 general reasoning 提升是 essential,而非可有可无的装饰。

5.4 Qualitative behaviors and limitations

论文给出的 qualitative 发现很有价值。作者观察到 induction 任务中模型经常自然产生“注释作为中间计划”的行为,类似 ReAct 的 scratchpad;abduction 更容易出现 trial-and-error;不同 task type 的 token length 成长速度不同,abduction 增长最快。这些都说明 self-play 并未把模型推向单一答题模板,而是在不同 reasoning mode 下诱导出不同策略。限制方面,论文明确承认至少有四点。第一,AZR 当前强依赖 deterministic Python environment,开放性来自 code,但仍局限于可执行、可验证程序空间。

第二,为简化 verifier,作者排除了 stochastic program,因此环境表达能力仍被约束。第三,虽然 OOD math/code benchmark 提升显著,但训练任务本身仍主要是 code reasoning,不代表已经解决广义 open-world self-improvement。第四,作者在 Llama3.1-8B 上观察到偶发的 “uh-oh moment” safety issue,说明完全自博弈式 reasoning 训练需要更系统的 safety-aware control。

总体上,这篇论文最重要的结论不是“零数据也能训出一个不错的 7B reasoner”,而是证明了一个更激进的命题:如果 environment 能提供真实、严格、可验证的反馈,reasoning model 的学习分布可以由模型自己逐步发明,而不是永远被人工题库绑定。AZR 仍然是受限实例,但它为 self-improving reasoning systems 提供了一个清晰、可执行、且结果足够有说服力的第一版原型。