☰
GEPA 实战:用反射式优化自动演化出能解 ARC-AGI 谜题的 Python Agent 代码
2026/10/9 1:35:07 网站建设 项目流程
  • AI Agent
  • 提示工程
  • 模型优化

【免费下载链接】gepa

Optimize prompts, code, and more with AI-powered Reflective Optimization

项目地址:https://gitcode.com/gh_mirrors/ge/gepa
点击查看免费下载

本指南围绕仓库中的 examples/arc_agi 示例展开,讲解如何用 GEPA 的反射式优化(Reflective Optimization)把"能解 ARC-AGI 谜题"的Agent Python 代码(而非提示词)当作优化对象,通过训练样本反复评估、反思并演化,最终得到一个可部署的求解程序。读完本文你将掌握:ARC-AGI 示例的数据切分与评估口径、从种子 Agent 到优化循环的完整代码脉络、GEPAConfig/EngineConfig/ReflectionConfig各字段的实战含义,以及如何复现"优化后自动在测试集上对比基线准确率"的完整流程。

ARC-AGI 示例在做什么:优化代码,而不是提示词

ARC-AGI(Abstraction and Reasoning Corpus)是经典的抽象推理基准:每个任务给出若干训练输入/输出网格对,Agent 需要推断出背后的变换规则,并预测测试输入的输出网格。传统做法通常是手写提示词来"提示"大模型推理;而本示例走的是另一条路线——GEPA 直接把 Agent 的 Python 程序作为优化对象,让大模型(反射模型)依据每次评估的反馈反复改写这段代码,直到它在验证集上拿到更好的分数。

该设计的关键约束记录在 main.py 与 utils.py 的BACKGROUND说明中:

  • 每个问题最多允许10 次 LLM 调用(max_llm_calls=10);
  • 每个测试输入最多提交2 个输出尝试,任一正确即算该例通过(与 ARC-AGI 竞赛规则一致);
  • 每问题 LLM 成本目标控制在约$0.8~1.0;
  • 允许 Agent 自由探索多样策略:多 Agent 系统、集成、投票等。

也就是说,示例中的solve()不是被优化者,而是被优化对象——GEPA 的反射循环会基于评估结果持续生成它的改进版本。

数据集与评估口径

README 明确给出了数据来源与划分:

集合内容
来源HuggingFacedataartist/arc-agi
Train训练 split 中的 200 个问题,用于优化过程中的训练评估
Val从训练 split 中留出的 200 个问题,用于候选选择
Test完整的 evaluation split,用于优化结束后的最终对比

对应实现见 utils.py:load_arc_dataset()加载dataartist/arc-agi,把每条记录转成dspy.Example(字段为problem_id / train_in / train_out / test_in / test_out),用固定seed=0打乱训练集后,取最后 200 条作为val_set,其余作为train_set,evaluation split 全部作为test_set。

需要留意的是 ARC-AGI 的计分口径(utils.py):测试评估时每个输入允许最多 2 次尝试,只要任意一次与标准输出网格完全一致即算通过;而一个问题只有全部测试样例都通过才算"解决"(all_correct为真时该问题得 1.0,否则 0.0)。这一二元计分在优化时会被当作评估分数反馈给反射模型,是驱动代码演化的核心信号。

环境准备与安装

在仓库根目录(gepa/)下按 README 的顺序执行:

uv venv uv pip install datasets dspy litellm uv pip install -e . # must come after dspy to avoid PyPI overwrite

uv venv创建虚拟环境,然后依次安装数据加载(datasets)、DSPy(dspy,示例用它的Example承载训练样例)、LiteLLM(litellm,统一各类 LLM 后端);最后以可编辑模式安装当前仓库。README 特别强调-e .必须放在dspy之后,以避免 PyPI 上同名的旧包覆盖本地源码——这是本示例可复现运行的前提。

运行优化

配置好模型 API Key 后从仓库根目录运行:

export OPENAI_API_KEY=... uv run python -m examples.arc_agi.main

示例默认使用openrouter/google/gemini-3-flash-preview作为反射模型(main.py)。运行流程(main.py):

  1. 加载数据集得到train_set / val_set / test_set;
  2. 构造GEPAConfig调用optimize_anything(),以种子 Agent 代码为起点,在训练集上评估、在验证集上选择候选,反复迭代;
  3. 优化结束后把最优 Agent 代码写入outputs/arc_agi/best_agent.py;
  4. 分别在测试集上评估种子 Agent(基线)与最优 Agent,打印两者准确率与提升幅度。
Best score (on val): 0.1234 Evaluating Baseline (Seed Agent)... Evaluating Best Agent... Baseline accuracy: 5.0% Optimized accuracy: 15.0% Improvement: +10.0%

关键代码脉络:种子、评估器与 SideInfo

种子 Agent:一段可被exec的solve()函数

优化起点是一段普通 Python 源码字符串(main.py)。它定义一个solve(train_inputs, train_outputs, test_inputs, llm):把训练样例与测试输入拼进提示词,调用llm得到 JSON 网格列表,再解析并按数量切分为训练预测与测试预测(测试部分以[[g], ...]形式容纳最多 2 个尝试)。这段代码本身可运行,但表现平平——这正是 GEPA 演化的起点。

评估器:返回(score, SideInfo)

optimize_anything的评估器签名是evaluator(candidate, example) -> (score, side_info)。本示例的实现(main.py):

  • 调用run_agent()真正执行 Agent:动态exec(agent_code)后调用solve(),并在内部用TrackedLLM包装模型调用(utils.py);
  • score = test_score - 0.1 * (cost > 1.0):当单个问题 LLM 成本超过 1 美元时扣 0.1 分,形成对"烧钱方案"的经济惩罚,引导反射模型在精度与成本之间做权衡;
  • SideInfo(本示例中为dict[str, Any])携带problem_id、agent_code、training_score、test_score、cost、error、train_examples、test_examples以及llms.get_traces()返回的调用轨迹(每次 LLM 调用的 prompt、response、cost、reasoning,超过 10 次时随机抽样并标注)。

在 GEPA 中,这种结构化反馈被称为 Actionable Side Information(ASI)——官方文档定位它是"文本优化的梯度":梯度告诉数值优化器往哪个方向移动,ASI 则告诉反射 LLM 候选为什么失败、如何修复(见 gepa_launcher.py)。本例中compare_grid生成的"矩阵形状不符 / 第 (i,j) 元素值错误 / 期望网格为..."等细粒度诊断(utils.py)正是这类可操作反馈的来源。

成本与调用追踪:TrackedLLM

TrackedLLM(utils.py)是一个带预算闸门的模型封装:

  • 每次调用前检查已用次数,超过max_llm_calls(示例为 10)直接抛RuntimeError,从机制上保证 Agent 不超过 LLM 调用配额;
  • 通过 LiteLLM 的completion()发请求,支持以extra_body={"reasoning": {"effort": ...}}传递 OpenRouter 风格推理强度参数;
  • 逐次记录prompt / response / cost / duration / reasoning,get_traces()再把轨迹整理为 GEPA 反射可读的字典(含llm_calls、llm_budget、total_cost、trajectory),最终并入SideInfo。

这套追踪使得"最多 10 次调用、单问题成本约 $0.8~1.0"的约束不仅是提示词里的口头约定,而是被代码强制执行并进入反射反馈的硬指标。

GEPA 配置详解:从 GEPAConfig 到三层组件

示例只用了两层配置(main.py),却是理解 GEPA 控制面的最佳入口:

config = GEPAConfig( engine=EngineConfig( run_dir=log_dir, max_metric_calls=3000, parallel=True, max_workers=64, cache_evaluation=True, track_best_outputs=True, ), reflection=ReflectionConfig( reflection_lm=LLM_MODEL, # We use Gemini 3 Flash, but a stronger model will do better results ), )

GEPAConfig是顶层配置(gepa_launcher.py),把设置分组为嵌套组件:engine、reflection、tracking,以及可选的merge/refiner/callbacks/stop_callbacks;它支持从 dict 构造(__post_init__会把传入的 dict 展开为对应 dataclass),因此很容易从 JSON/YAML 读取配置。

EngineConfig:优化循环的预算、并行与缓存

本示例用到的字段及其含义(gepa_launcher.py):

字段示例值含义
run_dir"outputs/arc_agi"引擎工作目录,状态文件、迭代产物写在这里
max_metric_calls3000评估预算上限(最关键字段),达到后停止优化
parallel/max_workersTrue/64并行评估开关与线程池大小;默认parallel=True、max_workers=os.cpu_count() or 32
cache_evaluationTrue评估缓存(默认关闭),按(candidate, split, example_id)为键,避免重复评估
track_best_outputsTrue追踪并保存每个样例上的最优输出,可用于热启动后续优化

此外EngineConfig还提供max_candidate_proposals、max_reflection_cost、stop_at_score(验证集达到阈值即停)、candidate_selection_strategy(默认pareto)、acceptance_criterion(默认strict_improvement)、capture_stdio(自动把评估器中的print()捕获进 ASI)等更多旋钮,供按需开启。

ReflectionConfig:反射 LLM 与反思节奏

本示例只覆盖了reflection_lm(反射模型,默认为openai/gpt-5.1)。完整的反思配置(gepa_launcher.py)还包含:

  • reflection_minibatch_size:每次反思展示的样本数(单任务默认 1、多任务默认 3),用小批量而非全部样例换取聚焦的定向改进;
  • batch_sampler:默认epoch_shuffled,保证不同迭代覆盖不同样例;
  • module_selector:多组件优化时每轮选择改哪个组件(默认round_robin);
  • reflection_lm_kwargs:透传给litellm.completion的额外参数(如reasoning_effort、temperature);
  • reflection_prompt_template/custom_candidate_proposer:自定义反思提示词或完全替换提议器(例如接 Claude Code 作为候选生成器)。

optimize_anything 调用语义

完整调用(main.py)将任务拆成三个部分(对应 optimize_anything.py 的签名):

result = optimize_anything( seed_candidate=SEED_AGENT_CODE, # 优化对象:Agent 源码 evaluator=evaluate, # 如何打分:(candidate, example) -> (score, side_info) dataset=train_set, # 优化中用到的训练样例 valset=val_set, # 候选选择用的验证样例 config=config, # 引擎、预算、反射配置 objective=OBJECTIVE, # 短目标陈述 background=BACKGROUND, # 长上下文:任务格式、约束、成本说明 )

objective("Build an ARC-AGI agent program that maximizes a test score.")与background(任务格式、2 次尝试规则、10 次 LLM 调用与成本预算)会被逐字注入反思提示词(见 gepa_launcher.py 的动态模板构建逻辑),也就是说约束说明要尽量写进background,反射模型才会在每一轮都看到它们。

运行后result.best_candidate即最优 Agent 代码,result.val_aggregate_scores[result.best_idx]是其在验证集上的聚合分数;示例随后把最优代码落盘到outputs/arc_agi/best_agent.py,并用evaluate_on_testset()(utils.py,基于ThreadPoolExecutor并行评估,默认 32 线程)对比种子与最优 Agent 在测试集上的解决率。

实战要点与延伸建议

  • 约束要可执行,也要可反馈:10 次调用上限由TrackedLLM强制执行,成本超限由评分函数扣分惩罚——优化目标里写不进去的东西,要靠代码闸门兜住。
  • 反馈要细粒度:compare_grid输出的结构/形状/逐格错误信息直接进入 ASI,是反射模型能"看懂为什么失败"的关键;如果换用只回 0/1 的评估器,演化会退化为随机盲搜。
  • 评估口径要与目标一致:ARC-AGI 的"全对才得分"二元计分是刻意为之——若改成平均逐格正确率,演化出的 Agent 可能擅长"部分正确"而偏离竞赛目标。
  • 预算与并行按资源调:示例max_metric_calls=3000、max_workers=64是针对并行评估设计的;预算不足时优先调小验证集或开启cache_evaluation,避免同一候选被重复评估。
  • 看更多:GEPAConfig的merge(Pareto 前沿候选交叉)、refiner(每次评估后即时精修)与tracking(W&B / MLflow 实验追踪)可在仓库 src/gepa/gepa_launcher.py 中进一步查阅;官方还提供OptimizeAnythingConfig(src/gepa/oa/config.py)这一扁平化配置入口,支持max_evals/max_token_cost预算与gepa/autoresearch/meta_harness等引擎切换。

总而言之,本示例是"GEPA 优化一段可执行程序而非一段提示词"的完整范式:数据集、种子程序、评估器、SideInfo 与引擎配置五块拼图共同构成一个可复现、可扩展的 Agent 代码演化流水线——把它换成其他编程任务,你只需要替换solve()的输入/输出约定、评估器与数据集,GEPA 的反射循环无需任何改动。

  • AI Agent
  • 提示工程
  • 模型优化

【免费下载链接】gepa

Optimize prompts, code, and more with AI-powered Reflective Optimization

项目地址:https://gitcode.com/gh_mirrors/ge/gepa
点击查看免费下载

相关推荐

上一篇:Pwn2Own2018提权秘籍:XNU内核漏洞实现从普通用户到root的终极突破
下一篇:提升远程开发体验:GitHub_Trending/au/autocomplete与SSH/Mosh集成方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询