GEPA 算法概述
b1babo
2026年4月19日
2026年4月19日
GEPA 算法概述
GEPA (Genetic-Pareto) 是一个用于优化文本组件(如 AI prompts、代码片段、配置参数等)的进化算法框架。它通过 LLM 的反思能力和 Pareto 高效搜索来迭代改进候选者。
为什么叫 "Genetic"(遗传)?
GEPA 的名称体现了它与遗传算法的深刻联系:
| 遗传算法概念 | GEPA 对应机制 | 说明 |
|---|---|---|
| 种群 | Pareto 前沿候选者集合 | 维护多个候选者,不是单一最优解 |
| 选择 | 从 Pareto 前沿采样 | 选择表现好的候选者作为父代 |
| 变异 Mutation | 反思突变 | LLM 基于反馈修改 prompt |
| 交叉 Crossover | 系统感知合并 | 组合两个候选者的优势模块 |
| 适应度 | 分数 Score | 衡量候选者质量的指标 |
| 继承 | 祖先累积改进 | 新候选者继承所有祖先的改进 |
遗传算法:
种群 → 选择 → 交叉/变异 → 评估 → 新种群 → 重复
GEPA:
前沿 → 选择 → 合并/反思 → 评估 → 新前沿 → 重复
↓ ↓
Pareto LLM 智能变异1. 种群: Pareto 前沿作为种群
# 遗传算法: population = [individual1, individual2, ...]
# GEPA: Pareto 前沿作为种群
pareto_front = {
"sample_0": {candidate_1, candidate_3}, # 在样本0上最好
"sample_1": {candidate_2}, # 在样本1上最好
}2. 选择: 从前沿选择父代
# 遗传算法: 根据适应度概率选择
# GEPA: 从 Pareto 前沿选择
selector = ParetoCandidateSelector(rng=random.Random(0))
parent_idx = selector.select_candidate_idx(state)3. 变异: 反思突变
# 遗传算法: 随机扰动基因
# GEPA: LLM 智能反思修改
# 反思突变: 基于反馈修改
new_candidate = propose_by_reflection(
parent_candidate,
reflective_dataset # 失败案例 + 成功案例
)
# LLM 生成:
# "基于以下反馈,将 prompt 从 X 改为 Y 以提高准确率"4. 交叉: 系统感知合并(无 LLM)
# 遗传算法: 交换两个个体的基因片段
# GEPA: 合并两个候选者的组件(纯规则,无 LLM)
# src/gepa/proposer/merge.py
child_candidate = merge_candidates(
candidate_a, # 擅长数学题
candidate_b # 擅长语文题
)
# ⚠️ 重要:合并不调用 LLM!
# 只是字符串比较和复制操作具体示例:
# 进化历史
候选者 0 (祖先): {
"system_prompt": "You are helpful.",
"user_prompt": "Answer:"
}
↓ 反思改进
候选者 5 (候选A): {
"system_prompt": "You are a math expert.", # ← 改进了
"user_prompt": "Answer the math:" # ← 改进了
}
↓ 不同路径反思改进
候选者 8 (候选B): {
"system_prompt": "You are helpful.", # ← 未变
"user_prompt": "Please provide reasoning:" # ← 改进了
}
# 合并候选5和候选8
候选者 12 (合并结果): {
"system_prompt": "You are a math expert.", # 来自候选5 (改进了)
"user_prompt": "Please provide reasoning:" # 来自候选8 (改进了)
}合并逻辑 (核心代码):
# 从共同祖先开始
new_candidate = deepcopy(ancestor_candidate)
# 逐组件决定从哪个后代选择
for component_name in ["system_prompt", "user_prompt"]:
ancestor_val = ancestor[component_name]
id1_val = candidate_a[component_name]
id2_val = candidate_b[component_name]
if ancestor_val == id1_val and ancestor_val != id2_val:
# A未改进,B改进了 → 选择B
new_candidate[component_name] = id2_val
elif ancestor_val == id2_val and ancestor_val != id1_val:
# B未改进,A改进了 → 选择A
new_candidate[component_name] = id1_val
elif ancestor_val != id1_val and ancestor_val != id2_val:
# 两者都改进了 → 选择分数更高的
new_candidate[component_name] = (
id1_val if score_a > score_b else id2_val
)
else:
# 两者都一样 → 任选
new_candidate[component_name] = id1_val5. 继承: 祖史累积
# 每个候选者记录其进化历史
candidate = {
"system_prompt": "...",
"ancestry": [0, 1, 5, 12] # 祖先索引
}
# 反思时可以看到所有祖先的改进历史
reflective_dataset = build_from_ancestry(candidate.ancestry)核心概念
候选者 (Candidate)
候选者是 GEPA 优化过程中的基本单位,表示为 dict[str, str]:
candidate = {
"system_prompt": "You are a helpful assistant...",
"user_prompt": "Please answer the following question:",
# 可以包含更多组件
}类比神经网络:
- 候选者 ≈ 权重参数
W - 优化目标 ≈ 找到最优的 prompt 文本
评分 (Score)
分数衡量候选者的性能:
- 范围:
[0.0, 1.0] - 越高越好(与神经网络的 loss 相反)
- 在验证集上计算平均分数
类比神经网络:
- Score ≈ 负 Loss 或 准确率
- GEPA 最大化 score,神经网络最小化 loss
算法流程
┌─────────────────────────────────────────────────────────────────────────┐
│ GEPA 进化算法主循环 │
│ (Genetic-Pareto Evolutionary Loop) │
└─────────────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────┐
│ 初始化种群 │
│ seed_candidate│
└───────┬───────┘
│
▼
┌───────────────┐ ┌─────────────┐
│ 选择 Selection│──────→│ 适应度评估 │
│ 从前沿选择父代│ │ 更新前沿 │
└───────┬───────┘ └──────┬──────┘
│ │
▼ │
┌──────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 进化循环 (双策略) │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ 策略 A: 反思变异 (Mutation) │ │
│ │ │ │
│ │ 1. 选择父代 ← 从 Pareto 前沿 │ │
│ │ 2. 评估父代 ← 在 minibatch 上测试 │ │
│ │ 3. 反思分析 ← LLM 分析失败原因 │ │
│ │ 4. 变异生成 ← LLM 生成改进版本 │ │
│ │ 5. 适应度测试 ← 比较 minibatch 分数 │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ 策略 B: 系统合并 (Crossover) │ │
│ │ │ │
│ │ 1. 选择两个父代 ← 从 Pareto 前沿 │ │
│ │ 2. 分析进化史 ← 比较组件改进记录 │ │
│ │ 3. 智能合并 ← 组合优势组件 │ │
│ │ 4. 适应度测试 ← 在验证集上评估 │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ 接受 → 验证集评估 → 更新 Pareto 前沿 (新一代种群) │
│ │
│ 重复直到达到停止条件 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌───────────────┐
│ 返回最优候选者 │
│ (种群中最适应) │
└───────────────┘训练集 vs 验证集
| 用途 | 训练集 | 验证集 |
|---|---|---|
| 反思数据 | ✅ 提供失败案例学习 | ❌ 不用于反思 |
| 接受测试 | ✅ 快速迭代 | ❌ 不用于接受 |
| 最终评估 | ❌ 防止过拟合 | ✅ 真实性能 |
| 候选选择 | ❌ 避免局部最优 | ✅ Pareto 选择 |
result = gepa.optimize(
seed_candidate={"prompt": "..."},
trainset=train_data, # 用于反思和接受测试
valset=val_data, # 用于 Pareto 前沿跟踪
max_metric_calls=150
)数据集格式
默认格式 (DefaultAdapter)
trainset = [
{
"input": "法国的首都是哪里?",
"additional_context": {}, # 可选
"answer": "巴黎"
},
{
"input": "中国的首都是哪里?",
"additional_context": {},
"answer": "北京"
}
]自定义格式
DataInst 是泛型类型,可以根据需要自定义:
from gepa.adapters.generic_rag_adapter import RAGDataInst
trainset = [
{
"query": "What is machine learning?",
"ground_truth_answer": "Machine learning is...",
"relevant_doc_ids": ["doc_001", "doc_042"],
"metadata": {"category": "AI"}
}
]停止条件
GEPA 支持多种停止条件:
# 方式 1: 最大评估次数
max_metric_calls=150
# 方式 2: 最大反思成本
max_reflection_cost=10.0 # USD
# 方式 3: 自定义停止条件
from gepa.utils import FileStopper, NoImprovementStopper
stop_callbacks = [
FileStopper("gepa.stop"), # 检测停止文件
NoImprovementStopper(patience=10) # 10 次无改进
]两种 LLM 调用
每次迭代中,GEPA 会调用 LLM 两次:
1. Task LLM (评估/前向传播)
task_lm = "openai/gpt-4o-mini" # 较小的模型用于:
- 生成预测值
- 计算分数
2. Reflection LLM (反思/反向传播)
reflection_lm = "openai/gpt-4o" # 更强的模型用于:
- 分析失败原因
- 生成改进的 prompt
核心优势
| 特性 | GEPA | 传统方法 |
|---|---|---|
| 评估次数 | 100-500 | 10,000+ (RL) |
| 可微性 | 无需可微 | 需要梯度 |
| 优化目标 | 任何文本组件 | 主要用于 prompts |
| 可解释性 | 人类可读的优化轨迹 | 黑盒优化 |
下一步
- 评估流程详解 - 了解 GEPA 如何评估候选者
- 反思流程详解 - 了解 LLM 如何反思和改进
- Pareto 前沿 - 了解多目标优化机制
- 与神经网络对比 - 深入类比理解
评论