← 科研空间 首页
arXiv:2605.20086 cs.NE / cs.AI / cs.LG ZIB-IOL × HKBU × RIKEN 28 pages, 12 figures

What Do Evolutionary Coding Agents Evolve?

进化式编码代理到底在进化什么?——EvoTrace 数据集与 EvoReplay 方法论,揭开 LLM 驱动进化搜索的内部机制

阅读基础:arXiv TeX 源码 + HTML 全文 + GitHub 仓库 · 检索日期:2026-07-10

📄 原版 PDF 🔗 arXiv 💻 GitHub

先给结论

这篇论文做了一件很少有人做的事:不看你最终得了多少分,而是拆开进化搜索的全过程,看 LLM 驱动的编码代理到底在改什么。

~30% 新增代码行是之前删过的(byte-identical cycling),121 次运行中 118 次单调增长
0.76 同 prompt 重放 10 次的得分中位数 / 原始得分,但程序几乎从不字节级复现
13/15 单程序 24 次 BO 调参就能匹配或超越进化运行最终最优的中间程序数

一句话总结:进化式编码代理的大部分分数提升来自超参微调 + 短周期代码循环,而非真正的算法结构创新。真正有效的编辑类型(External dependency、Efficiency、Architectural change)在搜索分布中反而很稀少。Benchmark 分数不能区分"发现了新结构"和"反复调参+过拟合"。

研究动机

LLM + 进化搜索的范式(FunSearch, AlphaEvolve 等)在数学发现和算法设计中取得了亮眼成绩。但一个根本问题始终没有被回答:

这些系统到底在进化什么? 最终分数的提升可以来自完全不同的机制:

  • 新算法结构:真正发现了新的程序逻辑
  • 超参微调:只是在已有策略上改数字
  • 知识重组:把 LLM 内部已有的知识重新拼装
  • 过拟合:针对评估器漏洞的 hack

现有工作通常只报告最终最优分数,但这个数字掩盖了改进的路径和机制。而且这些系统相对于独立采样、贪心修正等 baseline 的优势高度敏感——取决于任务设计、初始化、评估器配置和模型选择。

论文的核心问题:What do evolutionary coding agents evolve, and how do their search dynamics produce improvements?

Edit taxonomy with 9 categories
Figure 1:进化式编码代理的 9 种编辑类型分类。每个面板展示一个典型的 parent–child diff(绿色=新增,红色=删除),从最小数值改动(单个 literal 变更)到结构重写(14 边形替换为两个同心七边形)。编辑通常多标签共存。

数学表示及建模

进化式编码代理的形式定义

论文定义了一个 evolutionary coding agent 为具备以下组件的系统:

一个 search trace 是该系统产生的完整记录:程序、分数、执行反馈、parent-child 关系、prompt、模型选择和中间产物。

程序的结构-参数分解

论文将程序 $p$ 分解为结构 $s$ 和超参向量 $\theta \in \Theta_s$,即 $p = s(\theta)$。固定结构 $s_0$,对 $\theta$ 做贝叶斯优化得到调参上界:

$$f^{\star}_{\mathrm{BO}}(s_0) = \max_{\theta} f(s_0(\theta))$$

调参间隙(tuning gap)衡量进化增益中多少来自结构发现而非参数搜索:

$$\Delta(s_0) = f^{\star}_{\mathrm{evo}} - f^{\star}_{\mathrm{BO}}(s_0)$$

如果 $\Delta(s_0)$ 很小,说明进化运行的大部分增益可以通过对单个中间程序做超参优化来替代——进化搜索做的事情和简单调参没太大区别。

EvoTrace:统一 trace 模式

不同框架记录的搜索状态各不相同,直接跨系统比较很困难。EvoTrace 将每次运行规范化为统一 JSONL schema,覆盖:

记录完整源码(而非仅分数日志)是关键设计选择——它使得 BO baseline 的 literal 提取、cycling 分类器和同 prompt 重放都成为可能。

EvoTrace and EvoReplay overview
Figure 2:EvoTrace 将每次进化运行记录为结构化对象(程序、parent-child 图、prompt/上下文、分数、评估器元数据)。EvoReplay 从这些 trace 中重建局部搜索状态并执行受控干预:同 prompt 重放、BO 调参、静态分析、cycling 检测、消融、修复、上下文/模型替换。

EvoReplay:四大能力

(a) 静态分析

将不同后端规范化为统一的 per-edit 表(parent, child, prompt, score, diff)。LOC、超参数量、谱系深度、best-so-far 轨迹——所有框架一套代码路径。

(b) LLM-as-judge 标注

对每个 parent-child diff 请求 LLM judge 返回编辑类别 + 驱动分数变化的行标签。支持批处理、重试、schema 验证、缓存。换 judge 模型不需重跑搜索。

(c) BO 调参基线

一次 LLM 调用识别可调常数 → 自动改写为 PARAMS 块 → gp_minimize 24 次评估。隔离结构 vs. 参数成分。

(d) 突破稳定性分析

对任何候选程序,用原始或替换模型重新执行其保存的生成 prompt,$n=10$ 次重采样。失败模式是双峰分布而非高斯——因此用 (parse success) × (eval success) × (score conditional on success) 三元组来总结。

9 种编辑类型分类法

作者通过手动检查跨框架、语言和模型采样的 parent-child 编辑,归纳出 9 种反复出现的编辑类型,迭代直到不再出现新类别:

最高频Hyperparameter tuning
修改数值常量,如学习率、迭代次数、阈值
高频Local refinement
小范围局部修改,非数值
高效用Architectural change
改变算法结构,如 14-gon → 2×7-gon
最高效用External dependency
引入新库/依赖
高效用Efficiency
优化计算效率
Composition
组合多个策略/组件
Bug fix
修复错误
Pruning
删除冗余代码/逻辑
Refactor
重构,不改变行为

算法流程 / 方法

EvoReplay 工作流

EvoReplay 的核心思想是把被动日志变成实验对象:搜索图中的任意一点都可以被重新执行、扰动、调参或重新评判。

数据收集流程:

  1. 选择任务(6 个数学构造 + 10 个 C++ 竞赛编程)
  2. 选择框架(OpenEvolve / GEPA / EvoX / ShinkaEvolve)
  3. 选择 LLM(deepseek-reasoner / claude-sonnet-4-6 / claude-haiku-4-5 / gemini-3-flash / deepseek-chat)
  4. 运行 100 次搜索迭代
  5. 记录完整 trace → 规范化为统一 JSONL schema
  6. 用 EvoReplay 做静态分析、LLM-as-judge 标注、BO 调参、重放稳定性测试

BO 调参基线流程

  1. Knob 识别:一次 deepseek-reasoner 调用,识别目标程序中的可调数值常量,提议每个 knob 的 log/linear 区间
  2. 自动改写:将程序改写为顶层 PARAMS
  3. BO 循环gp_minimize 24 次调用(8 次随机 + 16 次 BO 采集),使用相同的评估器 harness

Cycling 检测器

对每个 parent-child diff,确定性检查:新增的行中,有多少是同一谱系之前已删除过的 byte-identical 行? 这是一个纯确定性、可复现的检测器,不依赖 LLM。

实验设计

121 进化搜索运行总数
10,672 唯一程序
18,400 LLM 调用

四个维度

维度 配置 说明
框架 OpenEvolve, GEPA, EvoX, ShinkaEvolve Archive-based / 反思式 prompt 进化 / Meta-evolution / Bandit 搜索
模型 deepseek-reasoner, claude-sonnet-4-6, claude-haiku-4-5, gemini-3-flash, deepseek-chat 覆盖 reasoning/non-reasoning、多供应商
任务 6 个 Python 数学 + 10 个 C++ ALE-bench 数学构造(circle packing, Heilbronn, autocorrelation...)+ 竞赛编程(ahc008–ahc046)
迭代 100 次/run 有/无 diff-based generation 两种模式

四类诊断实验

§5.1 静态分析

LOC/超参数量随时间的变化、谱系深度、预算利用率、编辑分类法的频率 vs. 效用视图、ALE 公私分泛化

§5.2 Cycling 检测

确定性检测:新增行中有多少是之前删过的?span 长度分布、跨框架/语言/模型稳定性

§5.3 重放稳定性

36 个 best-so-far 事件,每个用原始 prompt 重放 10 次:parse/eval/exact-match/score 四问

§5.4 调参间隙

36 个中间程序,每个做 24 次 BO 调参,比较 BO 上界 vs. 进化运行最终最优

实验结果

1. 程序形态变化:数学任务增长,ALE 任务原地修改

LOC and hyperparameter count over iterations
Figure 3:Best-so-far 程序长度(LOC,左)和数值常量数(右),均按种子值归一化。数学运行(n=59)LOC 中位数最终比 1.33×,超参 1.70×;ALE 运行(n=62)两者均 ≈1.0×——在大种子上原地精炼。

谱系深度短:最终最优回到种子的 parent 链——ALE 中位数 4,数学中位数 6。"Jackpot-then-flat" 模式主导:大部分迭代预算花在不贡献最终最优的死分支上。数学任务中 best-so-far 在 75% 预算时达到,ALE 更早(49%)。

2. 公私分泛化:ALE 公开分数不可信

关键发现:在 ALE-bench 上重新评估公开 best-so-far 链在 AtCoder 私有测试集上的表现,四个框架中有两个在至少 30% 的问题上过拟合。同一问题可以跨框架翻转泛化符号:在 ahc024 上,OpenEvolve 私有增益 +1,606,而 ShinkaEvolve 在同一问题上损失了 1,610 分——尽管公开分数变化为正。

3. 编辑分类法:频率 ≠ 效用

Edit label prevalence
Figure 4(a):各标签频率——Hyperparameter tuning 主导搜索分布。
Edit helpfulness odds ratio
Figure 4(b):单编辑正向得分变化的 odds ratio——External dependency(3.58×)、Efficiency(1.61×)、Architectural change(1.55×) 最高。

最常改善单次编辑的类别(External dependency, Efficiency, Architectural change不是进化搜索花最多精力做的类别(Hyperparameter tuning, Local refinement)。大部分分数增益来自一小撮编辑类型,而那一小撮在搜索分布中很稀少。

LLM-as-judge 标注与人类盲标的一致性:macro $\kappa = 0.77$,micro-$F_1 = 0.90$,exact-match 74.5%。编辑通常多标签(67.4% 有 ≥2 个标签),最常见组合是 Hyperparameter tuning + Local refinementComposition + Hyperparameter tuning

4. Cycling:~30% 的新增代码是之前删过的

进化搜索中约 30% 的新增代码行是与同一谱系之前删除行 byte-identical 的重新引入。该比率在 121 次运行中的 118 次中单调增长(中位数 per-iteration 斜率 +0.0030)。这不是晚期病态——在几乎所有运行的整个轨迹中都存在。中位数 span 仅 5 次迭代(短周期 churn)。跨全部四个框架、两种语言、五个模型稳定。

5. 重放可复现性:结构可复现,词法不可复现

Target Parse Eval Exact Replay/Orig. Pattern
中位数(36 targets) 1.00 1.00 0.00 0.76
circle_packing_iter68_improve 1.00 1.00 ≥0 ≈1.00 紧密复现
second_autocorr_iter79_improve 1.00 1.00 0.00 0.96 parent-revert
circle_packing_iter32_neutral 0.50 0.50 0.00 双峰失败
heilbronn_convex_iter100_regress 1.00 1.00 0.00 1.11 重放超越退化

重放几乎总能产生可运行的程序(parse 和 eval 成功率中位数 1.00),但几乎从不产生原始程序(exact-match 中位数 0.00)。然而它们从不同程序中恢复了中位数 0.76 的原始分数:分数增益从同一 prompt 上下文广泛可复现,但具体程序只是更宽分布中的一次采样。

6. 调参间隙:BO 24 次就能匹配进化 100 次的最终最优

BO 结果 # targets
BO 改善原始分数 22
无变化 8
BO 退化 6
总计 36

与进化运行的最终最优比较时,BO 在 15 个中间程序中的 13 个上匹配或超越(中位数 delta +0.025)。最大个案:heilbronn_tri_dsr_nodiff 上进化达到 0.521,而 BO 从同一运行的中间程序达到 0.886(1.70× 进化最终最优)。

在数学任务上,对单个中间程序做 24 次 BO 调参就能在 13/15 的中间程序上匹配或超越进化运行 100 次迭代的最终最优。晚期进化迭代在数学上很大程度上可以被事后超参调优替代。

我的评论

亮点

局限与疑问

对实践者的启示

  1. 报告数学 benchmark 分数时,应同时报告单程序调参上界 $f^{\star}_{\mathrm{BO}}(s_0)$,让结构 vs. 参数的分解可见
  2. ALE 上公开分数必须配对私有测试重评,否则过拟合不可见
  3. 搜索策略应考虑 lineage-aware credit assignmentdeletion-aware novelty filters、向 prompt 暴露 parent 的删除历史——防止搜索重做已丢弃的工作
  4. 不要只看最终分数;trace 级指标(cycling 率、编辑类型分布、谱系深度)才是诊断搜索健康度的正确工具

One More Thing

论文中一个容易被忽略但很有深意的观察:重放几乎从不产生原始程序,但通常恢复大部分分数(中位数 0.76)。这意味着 LLM 驱动的进化搜索中的"突破"不是一个程序,而是一个结构概念在程序空间中的多次采样。突破的是 prompt + context 对应的结构邻域,不是具体的代码实例。

这暗示了一个有趣的方向:如果我们接受"程序只是结构概念的一次采样",那么进化搜索的真正单位应该是结构概念的转移而非程序的继承。当前的 parent-child 图可能不是搜索动力学的正确描述——我们需要的是 concept-level lineage 而非 program-level lineage。这与程序感知多样性/相似性度量(论文引用的 Vendi Score、code similarity 工作)形成呼应,但走得更远:搜索空间不是程序空间,而是程序背后的策略/概念空间

Reference / Evidence

📄 arXiv 论文页
arXiv:2605.20086 — What Do Evolutionary Coding Agents Evolve?
📄 arXiv HTML 全文
arXiv HTML — 实验性全文 HTML 版本
💻 EvoReplay GitHub
ZIB-IOL/EvoReplay — 开源分析与重放工具包
📊 EvoTrace 数据集
HuggingFace: ZIB-IOL/EvoTrace — 121 次进化搜索运行 trace
📄 PDF 全文
arXiv PDF — 28 pages, 12 figures, 12 tables
📄 TeX 源码
arXiv TeX Source — CC BY 4.0 许可