迈向开放式进化智能体

社区文章 发布于 2025 年 8 月 4 日

执行摘要

我们使用 OpenEvolve(一个开源的进化编码智能体)对 AlgoTune 基准套件上的 29 个实验进行了全面分析,结果显示专有模型和开源模型都取得了显著的性能提升。值得注意的是,像谷歌的 Gemma 3 27B 和阿里巴巴的 Qwen3-Coder 480B 这样的开源模型展现了令人印象深刻的优化能力,能够与闭源模型相媲美,有时甚至能以独特的方式超越它们。Gemini Flash 2.5 实现了 2.04 倍的最高加速比,Gemma 3 27B 和 Qwen3-Coder 分别达到了 1.63 倍和 1.41 倍。

AlgoTune 是评估算法优化能力的关键基准,包含图算法、线性代数运算和优化问题等多种计算任务。与专注于正确性的传统编码基准不同,AlgoTune 专门衡量性能提升——挑战系统不仅要解决问题,还要使现有解决方案更快。每个任务都提供一个基线实现,并通过严格的性能分析来衡量加速比,这使其特别适合于迭代优化代码的进化智能体。

Executive Dashboard

仪表盘概览:这个 2x2 的可视化总结了关键的实验发现

  • A. 温度优化研究:展示了纯温度比较(0.2、0.4、0.8),性能曲线清晰
  • B. 扩展迭代:展示了从 100 次迭代增加到 200 次迭代后持续的性能增益
  • C. 所有测试模型(最佳配置):全面比较所有 10 个独特模型在各自最佳配置下的表现
  • D. 并行性影响:显示了串行评估导致的严重性能下降

主要发现

  1. 更多迭代带来更好结果:200 次迭代实现了 2.04 倍的加速比,而 100 次迭代为 1.64 倍(提升 24%)
  2. 专业化胜过规模:Qwen3-Coder(480B MoE,编码专用)优于 Qwen3-235B 通用模型
  3. 进化策略依赖于模型:强大的编码模型在基于 diff 的进化中表现出色;较弱的模型需要完全重写
  4. 温度优化至关重要:0.4 被证明是 Gemini 模型的最佳温度(1.29 倍 vs 0.2 温度下的 1.17 倍)
  5. 构件(Artifacts)提升性能:包含调试构件使结果提高了 17%
  6. 并行性至关重要:串行评估灾难性地失败(性能下降 50%,速度慢 14 倍)

表现最佳者

模型 配置 AlgoTune 分数 最佳任务
Gemini Flash 2.5 200 次迭代,diff,温度 0.4 2.04x count_connected_components: 95.78x
Gemini Flash 2.5 100 次迭代,diff,温度 0.4 1.64x psd_cone_projection: 32.7x
Gemma 3 27B 100 次迭代,diff 1.63x psd_cone_projection: 41.1x
Qwen3-Coder 480B 100 次迭代,diff,温度 0.6 1.41x psd_cone_projection: 41.9x

实验统计

  • 总实验数: 29
  • 测试模型:10 个独特模型(Gemini 家族、Qwen 家族、Meta、Google Open、集成模型)
  • 评估任务:30 个 AlgoTune 基准测试
  • 最佳总体结果:2.04 倍加速比(Gemini Flash 2.5,200 次迭代)
  • 最差结果:0.396 倍(串行 diff 评估 - 性能下降 50%)
  • 测试的温度范围: 0.2, 0.4, 0.8
  • 进化策略:基于 Diff 和完全重写
  • 评估方法:并行(16 个工作进程)与串行比较

目录

  1. 实验概述
  2. 方法论
  3. 详细结果
  4. 进化代码分析
  5. 参数优化研究
  6. 模型比较
  7. 技术实现
  8. 结论

详细实验分析

实验概述

实验阶段

  • 阶段 1:初始实验与参数调优
  • 阶段 2:扩展迭代实验与新模型测试

测试模型

  1. Gemini 家族

    • Flash 2.5: 谷歌的高效编码模型
    • Flash 2.5 Lite: 用于基线测试的较小变体
  2. Qwen 家族

    • Qwen3-Coder-480B-A35B-Instruct: 480B MoE 模型,35B 激活参数,编码专用
    • Qwen3-235B-A22B: 235B 通用模型
    • Qwen3-32B: 较小变体
  3. 其他模型

    • Gemma 3 27B: 谷歌的开源模型
    • Llama 3.3 70B: Meta 的最新模型
    • 集成配置

实验类别

  1. 基线测试 (7 个实验): 建立模型基线
  2. 温度研究 (3 个实验): 寻找最佳温度
  3. 参数调优 (8 个实验): 优化各种参数
  4. 模型比较 (6 个实验): 跨模型分析
  5. 扩展迭代 (4 个实验): 更多进化次数的影响

方法论

AlgoTune 集成

  • 使用 algotune_to_openevolve.py 将 30 个 AlgoTune 任务转换为 OpenEvolve 格式
  • 任务涵盖多种算法类别:图、线性代数、优化
  • 使用 AlgoTune 的标准评估:加速比的调和平均值

进化方法

  • 基于岛屿的 MAP-Elites: 4 个岛屿,定期迁移
  • 级联评估: 快速验证 → 性能测试 → 完整评估
  • 两种进化策略:
    • 基于 Diff: 增量式代码更改
    • 完全重写: 完整函数再生

性能指标

AlgoTune 使用对数性能标度,该标度会转换为加速因子

# AlgoTune score calculation
speedup = (10 ** (performance * 3)) - 1  # Convert from log scale
algotune_score = harmonic_mean(all_speedups)  # Overall benchmark score

调和平均值强调在所有任务上的一致性能——模型必须在所有 30 个基准测试中表现良好才能获得高分。

详细结果

性能排名 - 所有实验

Performance Rankings

图表说明:水平条形图显示了所有实验的 AlgoTune 分数(加速比的调和平均值)。绿色条表示良好性能(>1.5x),蓝色表示中等(1.2-1.5x),橙色表示一般(1.0-1.2x),红色表示较差(<1.0x)。1.0x 处的虚线代表基线性能。

阶段 1:基线实验

1. Gemini Flash 2.5 Lite 基线

  • 配置:完全重写,温度 0.8,4k tokens
  • 结果:1.10 倍加速比
  • 关键学习:建立了优化的基线

2. 进化策略发现

在 Flash Lite 上比较基于 diff 与完全重写

  • 完全重写: 1.10x ✓
  • 基于 Diff: 0.79x ✗

在处理 Diff 方面存在困难的证据:

# Attempted diff that failed
- for i in range(n):
-     if not visited[i]:
-         dfs(i)
+ for i in range(n):
+     if not visited[i]:
+         # Incomplete optimization
+         dfs(i)  # No actual improvement

阶段 2:温度优化研究

在 Gemini Flash 2.5 Lite 上使用 16k tokens 进行系统性测试

温度 AlgoTune 分数 平均性能 时长 关键发现
0.2 1.17x 0.162 4074秒 保守但稳定
0.4 1.29x 0.175 3784秒 达到最佳性能
0.8 1.02x 0.159 3309秒 过于随机,性能下降

统计显著性:从 0.2→0.4 提升 10.3%,从 0.4→0.8 性能下降 20.9%

阶段 3:参数微调

所有实验均在最佳温度 0.4 下进行

Token 限制影响

  • 16k tokens: 1.29x (基线)
  • 32k tokens: 1.28x (无提升)
  • 结论: 16k 已足够,更大的上下文无帮助

构件(Artifacts)影响

  • 有构件: 1.29x
  • 无构件: 1.07x
  • 影响: 无调试信息导致 17% 的性能损失

注意:OpenEvolve 中的“构件”是程序在评估期间可以返回的调试输出,帮助 LLM 理解执行行为并做出更好的优化决策。

用于启发的顶级程序

  • 前 3 名: 1.29x (基线)
  • 前 5 名: 1.28x (差异极小)
  • 结论: 3 个程序已足够

迁移率

  • 0.1 迁移率: 1.29x (基线)
  • 0.2 迁移率: 1.25x (略差)
  • 结论: 较不频繁的迁移保留了多样性

阶段 4:将所学应用于强大模型

Gemini Flash 2.5 (100 次迭代)

  • 配置:基于 Diff,温度 0.4,16k tokens
  • 结果:1.64 倍加速比
  • 顶级成就:count_connected_components 达到 48.1x

Qwen3-Coder-480B

  • 配置:基于 Diff,温度 0.6,4k tokens
  • 结果:1.41 倍加速比
  • 注意:仅在温度 0.6 下测试,可能不是最佳值

Gemma 3 27B

  • 配置:基于 Diff(继承自成功的配置)
  • 结果:1.63 倍加速比
  • 惊喜:与 Flash 2.5 性能相当

阶段 5:扩展迭代

Gemini Flash 2.5 (200 次迭代)

  • 结果:2.04 倍加速比(比 100 次迭代提升 24%)
  • 突破:count_connected_components 达到 95.78x
  • 找到最优解:仅在第 2 次迭代!

迭代过程中的进展

  • 迭代 10: 1.15x
  • 迭代 50: 1.48x
  • 迭代 100: 1.64x
  • 迭代 200: 2.04x

阶段 6:串行与并行评估

关键发现:并行性至关重要

我们测试了串行评估(一次一个任务)与并行评估

配置 进化类型 AlgoTune 分数 时长 与并行对比
并行 基于 Diff 0.793x 0.9 小时 基线
串行 基于 Diff 0.396x 13.0 小时 差 50%,慢 14 倍
并行 完全重写 1.10x 0.9 小时 基线
串行 完全重写 0.585x 13.1 小时 差 47%,慢 14 倍

关键洞察:

  1. 性能灾难:串行评估导致 47-50% 的性能下降
  2. 时间爆炸:执行速度慢 14 倍(13 小时 vs 0.9 小时)
  3. 为何失败:
    • 进化过程中无跨任务学习
    • 超时问题在串行任务中累积
    • 进化在困难任务上“卡住”
    • 失去了并行发现的机会

结论:并行评估不仅仅是一种优化——它是 OpenEvolve 正常运作的必要条件

进化代码分析

示例 1:计算连通分量 - 算法发现

原始实现 (所有模型从此开始)

def solve(problem):
    n = problem["num_nodes"]
    edges = problem["edges"]
    
    # Build adjacency list
    adj = [[] for _ in range(n)]
    for u, v in edges:
        adj[u].append(v)
        adj[v].append(u)
    
    # DFS to count components
    visited = [False] * n
    count = 0
    
    def dfs(node):
        visited[node] = True
        for neighbor in adj[node]:
            if not visited[neighbor]:
                dfs(neighbor)
    
    for i in range(n):
        if not visited[i]:
            dfs(i)
            count += 1
    
    return {"number_connected_components": count}

性能:1.0x (基线)

进化后 - Gemini Flash 2.5 (200 次迭代):

def solve(problem):
    n = problem.get("num_nodes", 0)
    edges = problem.get("edges", [])
    
    if n == 0:
        return {"number_connected_components": 0}
    
    # Build adjacency list with deque for O(1) operations
    adj = [[] for _ in range(n)]
    for u, v in edges:
        adj[u].append(v)
        adj[v].append(u)
    
    # BFS with early termination and efficient tracking
    visited = [False] * n
    count = 0
    from collections import deque
    
    for start in range(n):
        if visited[start]:
            continue
            
        # BFS for this component
        queue = deque([start])
        visited[start] = True
        
        while queue:
            node = queue.popleft()
            for neighbor in adj[node]:
                if not visited[neighbor]:
                    visited[neighbor] = True
                    queue.append(neighbor)
        
        count += 1
    
    return {"number_connected_components": count}

性能:95.78 倍加速比 关键优化

  • 从 DFS 切换到 BFS
  • 使用 deque 实现 O(1) 队列操作
  • 增加提前终止检查
  • 使用 get() 进行防御性编程

进化后 - Qwen3-Coder (100 次迭代):

def solve(problem):
    n = problem["num_nodes"]
    edges = problem["edges"]
    
    # Union-Find approach - completely different algorithm!
    parent = list(range(n))
    
    def find(x):
        if parent[x] != x:
            parent[x] = find(parent[x])  # Path compression
        return parent[x]
    
    def union(x, y):
        px, py = find(x), find(y)
        if px != py:
            parent[px] = py
    
    # Process edges
    for u, v in edges:
        union(u, v)
    
    # Count unique roots
    return {"number_connected_components": len(set(find(i) for i in range(n)))}

性能:~25 倍加速比 关键洞察:不同模型发现了完全不同的算法!

  • 带路径压缩的并查集
  • 每个操作 O(α(n))(接近常数)
  • 内存效率更高

示例 2:PSD 锥投影 - 增量优化

原始实现:

def solve(problem):
    import numpy as np
    
    A = np.array(problem["matrix"])
    # Eigenvalue decomposition
    eigenvalues, eigenvectors = np.linalg.eigh(A)
    # Set negative eigenvalues to zero
    eigenvalues[eigenvalues < 0] = 0
    # Reconstruct matrix
    A_psd = eigenvectors @ np.diag(eigenvalues) @ eigenvectors.T
    return {"projected_matrix": A_psd.tolist()}

性能:1.0x (基线)

使用 Gemini Flash 2.5 Diffs 进化:

迭代 23

- eigenvalues[eigenvalues < 0] = 0
- A_psd = eigenvectors @ np.diag(eigenvalues) @ eigenvectors.T
+ # Vectorized operation
+ eigenvalues = np.maximum(eigenvalues, 0)
+ A_psd = eigenvectors @ np.diag(eigenvalues) @ eigenvectors.T

性能: 1.8x

迭代 67

- A_psd = eigenvectors @ np.diag(eigenvalues) @ eigenvectors.T
+ # Eliminate intermediate array
+ A_psd = (eigenvectors * eigenvalues) @ eigenvectors.T

性能: 15.2x

最终 (迭代 95)

def solve(problem):
    import numpy as np
    
    A = np.array(problem["matrix"])
    w, v = np.linalg.eigh(A)
    # One-line vectorized operation
    A_psd = (v * np.maximum(w, 0)) @ v.T
    return {"projected_matrix": A_psd.tolist()}

性能:32.7 倍加速比

示例 3:DCT 优化 - 趋同进化

原始:

def solve(problem):
    import numpy as np
    from scipy.fftpack import dct
    
    signal = np.array(problem["signal"])
    return {"dct": dct(signal, type=1).tolist()}

多个模型收敛到相同解决方案:

Gemini Flash 2.5

signal = np.array(problem["signal"], dtype=np.float64)
result = dct(signal, type=1, norm=None, overwrite_x=False)

Qwen3-Coder

signal = np.asarray(problem["signal"], dtype=np.float64)
return {"dct": dct(signal, type=1).tolist()}

关键发现:两者都独立发现了 dtype=np.float64 的优化!

  • 两者都实现了 6.48 倍的加速比
  • 表明存在最优解且可被发现

示例 4:SHA256 - 硬件限制

原始:

def solve(problem):
    import hashlib
    
    data = problem["data"].encode('utf-8')
    hash_object = hashlib.sha256(data)
    return {"hash": hash_object.hexdigest()}

最佳进化 (多个模型)

def solve(problem):
    import hashlib
    
    return {"hash": hashlib.sha256(problem["data"].encode()).hexdigest()}

性能:仅 1.1 倍加速比 学习:受硬件限制的操作优化潜力有限

模型比较

要全面了解所有 10 个独特测试模型的视图,请参见执行摘要仪表盘中的面板 C。完整的 29 个实验结果显示在上面的性能排名图表中。

特定任务性能热图

Task Performance Heatmap

此热图显示了不同模型在特定 AlgoTune 任务上实现的加速因子。深红色表示更高的加速比。值得注意的模式:

  • 计算连通分量显示出极大的差异(Flash 2.5 为 95x,而 Gemma 3 为 15x)
  • PSD 投影在各模型中均实现了持续的高性能(32-42x)
  • 像 SHA256 这样受硬件限制的任务,无论何种模型,改进都微乎其微

专业化与规模分析

Qwen3-Coder (480B MoE, 35B 激活) vs Qwen3-235B:

  • 尽管“更大”(总参数 480B),Qwen3-Coder 只有 35B 激活参数
  • 编码专业化带来了 68% 的性能提升(1.41x vs 0.84x)
  • 证据表明训练数据和目标比规模更重要

按模型能力划分的进化策略

模型类型 最佳策略 证据
小型/弱型 (Flash Lite) 完全重写 diff 模式 0.79x vs 完整模式 1.10x
强大编码 (Flash 2.5, Qwen3-Coder) 基于 Diff 1.64x vs 完整模式更低
通用目的 不一 依赖于模型

集成实验:为何更多模型 ≠ 更好结果

尽管结合了我们两个表现最好的模型(Gemini Flash 2.5 的 1.64x 和 Qwen3-Coder 的 1.41x),集成模型仅实现了 1.23x 的加速比——比任何一个单独的模型都差。

Ensemble Analysis

可视化指南:

  • 面板 A:显示单个模型性能与集成性能对比——集成模型表现不如两者
  • 面板 B:所有 30 个任务性能比较——Gemini、Qwen 和集成模型的完整性能概况
  • 面板 C:进化过程比较——集成模型显示不规则振荡,而单一模型进展平稳
  • 面板 D:按任务划分的模型一致性——3x30 热图显示每个任务的成对一致性,揭示冲突区域

关键发现:冲突的优化策略

集成模型失败是因为模型采用了不兼容的方法

  • 计算连通分量:Gemini 使用 BFS,Qwen 使用并查集 → 振荡
  • DCT 优化:不同的 dtype 策略 → 优化丢失
  • 结果:与预期的 1.5-1.7x 相比,性能低了 19%

示例:算法冲突

# Iteration N: Gemini suggests BFS
queue = deque([start])  # BFS approach

# Iteration N+1: Qwen suggests Union-Find  
parent = list(range(n))  # Different algorithm!

# Result: Hybrid mess that optimizes neither

观察到的集成失败模式

  1. 算法冲突:在同一任务中,BFS 与 Union-Find 方法的冲突
  2. 优化冲突:内存优化与计算优化的冲突
  3. 风格冲突:函数式与命令式代码模式的冲突

→ 详细的集成分析

技术实现细节

OpenEvolve 配置

# Optimal configuration discovered
max_iterations: 200  # More is better
diff_based_evolution: true  # For capable models
temperature: 0.4  # For Gemini, 0.6 for others
max_tokens: 16000  # Sweet spot
num_top_programs: 3
num_islands: 4
migration_interval: 20
migration_rate: 0.1
include_artifacts: true  # Critical for performance

岛屿进化动态

  • 4个岛屿保持多样性
  • 每20次迭代进行迁移,防止过早收敛
  • 每个岛屿可以发现不同的解决方案
  • 全局追踪最佳程序

级联评估的优势

  1. 阶段1:快速语法/导入验证(< 1秒)
  2. 阶段2:小型测试用例(< 10秒)
  3. 阶段3:完整基准测试套件(< 60秒)

通过快速失败节省了约70%的评估时间。

实验中的关键观察

1. 按类型划分的性能改进

  • 算法更改(DFS → BFS):观察到高达95倍的速度提升
  • 矢量化优化:在矩阵运算中实现32倍的速度提升
  • 微小代码更改(变量重命名、循环调整):通常< 2倍的速度提升

2. 模型解决方案的多样性

  • 计算连通分量:Gemini 找到了 BFS 方法,Qwen 找到了 Union-Find 方法
  • 矩阵运算:不同模型使用了不同的矢量化策略
  • 大多数任务都发现了多种有效的优化路径

3. 进化策略性能

  • 基于差异的进化与强大的编码模型:总体速度提升高达1.64倍
  • 使用较弱模型进行完全重写:速度提升1.10倍(而使用差异方法为0.79倍)
  • 模型能力决定了最佳策略

4. 迭代次数的影响

  • 100次迭代:实现1.64倍的平均速度提升
  • 200次迭代:2.04倍的平均速度提升(提升了24%)
  • 在200次迭代过程中,性能持续提升

5. 参数效应

  • 温度0.4:最佳单次运行(1.291倍),但方差较大
  • 包含构件:观察到约17%的性能提升
  • 令牌限制:16k与32k之间未显示显著差异
  • 迁移率:在实验中0.1的表现优于0.2

6. 并行化影响

  • 串行评估:0.396倍-0.585倍的速度提升(性能下降)
  • 并行评估:相同配置下速度提升0.793倍-1.10倍
  • 时间差异:13小时(串行)vs 0.9小时(并行)

结论

关键实验发现

  1. 迭代次数:200次迭代实现2.04倍速度提升,而100次迭代为1.64倍(提升24%)
  2. 模型专业化:Qwen3-Coder(编码专用模型)优于更大的通用模型
  3. 温度设置:结果各异 - 最佳单次运行在0.4,但观察到高方差
  4. 进化策略:基于差异的方法对强大的编码模型效果更好,完全重写对较弱的模型效果更好
  5. 并行化:串行评估使性能下降47-50%,时间增加14倍
  6. 集成结果:组合模型实现了1.23倍的速度提升,而单独模型分别为1.64倍和1.41倍

观察到的模式

  • 模型发现了不同的算法方法(例如图问题的BFS与Union-Find)
  • 受硬件限制的任务(SHA256)在所有配置中改进甚微
  • 包含构件使性能提升约17%
  • 在测试的配置中,0.1的迁移率比0.2表现更好

社区

注册登录 发表评论