跳到主要内容

自演化引擎:评测闭环与优化器家族

30 秒导读: EvoAgentX 最大的卖点不是"跑一个多智能体工作流",而是自动把它改得更好。 做法是:把工作流里的每个 prompt / 代码块暴露成一个"可读写的目标",然后拿一个数据集(benchmark) 反复给这套工作流打分,让某种搜索算法根据分数去改这些目标——像给 prompt 做梯度下降。本章讲清 这套"评测闭环 + 优化器家族"是怎么搭起来的。

前几章已讲过工作流本体:03-workflow-execution.md(WorkFlowGraph 与执行引擎)、 04-auto-construction.md(从一句话目标自动生成工作流)。本章不重复图/agent 的结构, 只聚焦一件事:一个已经能跑的工作流,如何用分数反向迭代改进自己。


1. 这是什么(零基础也能懂)

  • 一句话定义: 一台"自动调优机"——把工作流当成待优化对象,拿测试集分数当反馈, 反复改工作流里的 prompt(有时也改结构/代码),让分数越来越高。

  • 它解决什么问题: 你手搓了一个多智能体工作流去做数学题,准确率 62%。你怀疑 某个节点的 prompt 写得不好,但不知道怎么改、也不想一条条手试。自演化引擎替你干这件事: 你只要给它一个能打分的数据集,它自己去搜更好的 prompt,最后还给你一个准确率更高的工作流。

  • 它给谁用: 想让 agentic workflow "自己进化"、而不是永远停在人工初版的研究者和工程师。

  • 一句话直觉/类比: 把工作流当成一个有很多旋钮的机器,每个 prompt 就是一个旋钮; benchmark 就是一台打分仪。优化器不断拧旋钮、看打分仪读数、往读数变高的方向拧。 区别只在于"怎么拧":有的随机试(蒙特卡洛)、有的让 LLM 讲"哪里错了该怎么改"(文本梯度)、 有的用进化算法(交叉+变异)、有的用贝叶斯搜索。

  • 用起来什么样: 下面这段(改编自 examples/optimization/textgrad/math_textgrad.py)是最小骨架—— 三步:建评测器 → 建优化器 → optimize()

    # 示意,非源码:自演化的最小三步
    evaluator = Evaluator(llm=executor_llm, num_workers=5) # 1. 谁来打分
    optimizer = TextGradOptimizer( # 2. 谁来改
    graph=math_graph, evaluator=evaluator,
    optimizer_llm=optim_llm, max_steps=20,
    )
    optimizer.optimize(dataset=gsm8k) # 3. 拿数据集反复改进

本节不出现底层细节。记住一句:优化 = 评测闭环(打分)+ 搜索策略(改),两块拼起来。


2. 顶层全景(它大概怎么转)

整个子系统分两层:下层是评测闭环(把工作流在数据集上跑一遍、打出分数), 上层是优化器(拿这个分数当信号去改工作流)。所有优化器共用同一个下层。

怎么读这张图: 从上到下是一个优化步(step)的数据流;虚线是"分数反馈"回到优化器。

┌──────────────────────────────────────────┐
│ Optimizer(某个优化器) │
│ 持有 graph + 一套"怎么改"的策略 │
└───────────────┬──────────────────────────┘
① 提出一个改法(改某些 prompt / 代码块 / 结构)

┌──────────────────────────────────────────┐
│ 可优化字段抽象(OptimizableField/Registry)│
│ 把改法写回 graph 里真实的 prompt 属性 │
└───────────────┬──────────────────────────┘
② 改后的 graph

┌───────────────────────── 评测闭环 ───────────────────────────┐
│ Evaluator │
│ · 从 Benchmark 取一批数据(train/dev/test 三分) │
│ · 并行地把每条样本喂进 graph 执行,拿到预测 │
│ · 调 Benchmark.evaluate(预测, 标签) 打分 │
│ · 求平均 → 一个 metrics 字典 {acc: 0.71, ...} │
└───────────────┬──────────────────────────────────────────────┘
③ 分数
╎ (虚线反馈)
└╌╌╌╌╌╌╌╌╌╌╌╌╌╌► 回到 Optimizer:据此决定下一个改法

各部件一句话职责:

部件干什么在哪个文件
Benchmark数据源 + 打分器抽象:管 train/dev/test 三分,定义 evaluate(预测,标签)evoagentx/benchmark/benchmark.py:13
Evaluator评测执行器:并行把一批样本跑过 graph、逐条打分、求平均evoagentx/evaluators/evaluator.py:20
Optimizer(抽象)优化契约:optimize / step / evaluate / convergence_checkevoagentx/optimizers/optimizer.py:12
OptimizableField / ParamRegistry把 graph 里任意 prompt/代码块暴露成可读写目标evoagentx/optimizers/optimizer_core.py:17engine/registry.py:20
优化器家族各家不同的"怎么改"策略(AFlow/TextGrad/MIPRO/EvoPrompt/SEW/MAP-Elites)evoagentx/optimizers/*_optimizer.py

主线走一遍(高层): 优化器提出改法 → 通过"可优化字段"写回工作流 → 评测闭环在数据集上打分 → 分数回到优化器 → 决定下一步怎么改 → 循环,直到收敛或用完步数。


3. 核心机制之一:评测闭环(打分是一切的前提)

优化的第一性原理:没有可信的分数,就没有优化。 所以先讲这层。

3.1 Benchmark —— 数据源 + 打分器

Benchmark 是抽象基类(benchmark/benchmark.py:13)。它同时管两件事:

  1. 数据的三分供给:_train_data / _dev_data / _test_data 三个切片,以及取数接口 get_train_data / get_dev_data / get_test_data(benchmark.py:199-224),都支持 indices / sample_k / seed 抽样。这让"训练集搜、验证集调、测试集报"这套规范流程成为可能。

  2. 打分:每个子类必须实现三个抽象方法——_get_id(样本唯一 id)、_get_label(取标准答案)、 evaluate(prediction, label) -> dict(benchmark.py:73-85,返回如 {"em": 1.0, "f1": 0.8})。 注意返回的是字典(可以多指标),不是单个数。

编码任务是特例。 CodingBenchmark(benchmark.py:227)在打分时不能只比字符串,而要 真的执行代码跑单元测试。它的 check_solution(benchmark.py:254)把模型生成的解答 exec 进一个受限命名空间,再 exec 测试代码,在 timeout 内调用 check 函数,返回 (SUCCESS/FAILED/TIMEOUT, 信息);还提供 compute_pass_at_k(benchmark.py:302)算 pass@k。

具体数据集就是这些抽象的实现,充当现成数据源:

数据集类任务文件
GSM8K小学数学应用题benchmark/gsm8k.py:39
HotPotQA多跳问答benchmark/hotpotqa.py:23
HumanEval代码生成(继承 CodingBenchmark)benchmark/humaneval.py:32

还有 math_benchmark.pymbpp.pylivecodebench.pybigbenchhard.pynq.py 等, 套路一致:_load_data 灌数据、evaluate 定义指标。

3.2 Evaluator —— 并行地"跑 + 打分 + 求平均"

Evaluator(evaluators/evaluator.py:20)是把 benchmark 和 graph 接起来的执行器。 它要解决的小问题:给我一个 graph 和一个数据集,吐出一个平均分。 核心是 evaluate 方法 (evaluator.py:74),内部管线如下:

怎么读: 一条样本从取出到变成分数,要过四道加工。

一条样本 example
│ collate_func(example) # 把样本整理成 graph 的输入 dict

inputs ──► 执行 graph ──► raw output
│ (ActionGraph 直接 execute;WorkFlowGraph 包一层 WorkFlow 再跑)

output_postprocess_func(output) # 抽取/清洗成可比对的形式


benchmark.evaluate(预测, 标签) # 打分 → {指标: 值}

三个关键设计:

  • 两种 graph 都支持。 _evaluate_single_example(evaluator.py:158)里判断: ActionGraph 直接 execute;WorkFlowGraph 则新建一份拷贝、reset_graph()、 包进一个 WorkFlow 实例跑(_execute_workflow_graph,evaluator.py:113), 并额外记录执行轨迹 trajectory

  • 可插拔的前后处理。 collate_func(样本 → 工作流输入)和 output_postprocess_func (工作流输出 → 可打分形式)都是构造时传入的回调(evaluator.py:56-57), 默认是恒等函数。这让"benchmark 的数据格式"和"工作流的 I/O 格式"解耦。

  • 并行 + 线程隔离。 num_workers > 1 时走 _parallel_evaluate(evaluator.py:274), 用 ThreadPoolExecutor + contextvars.copy_context().run 隔离上下文;每个线程还会拿到 各自的 AgentManager 副本(_get_thread_agent_manager,evaluator.py:248),避免多线程 共享 agent 状态出错。另有一套 async_evaluate(evaluator.py:376)用信号量限并发。

最后 _calculate_average_score(evaluator.py:304)对每个指标求平均——注意分母是 样本总数(失败置 None 的样本也计入分母),所以"跑挂"会实打实拉低分数,而不是被悄悄丢掉。


4. 核心机制之二:统一的"可优化字段"抽象

这是让"优化器"和"工作流本体"解耦的关键。要解决的小问题:优化器怎么才能在不知道 你 graph 长啥样的前提下,读写你 graph 里任意深处的某个 prompt?

4.1 思路:把"一个可改的目标"封装成 getter/setter 对

OptimizableField(optimizers/optimizer_core.py:17,以及更完善的 optimizers/engine/registry.py:20)就是一个极简封装:一个 name(别名)+ 一对读写闭包。

```python
# 示意,非源码:可优化字段的本质
class OptimizableField:
def __init__(self, name, getter, setter):
self.name, self._get, self._set = name, getter, setter
def get(self): return self._get() # 读当前值
def set(self, v): self._set(v) # 写新值
```

优化器只跟 nameget/set 打交道,完全不关心这个 prompt 藏在对象树的哪一层

4.2 ParamRegistry:用字符串路径一键注册任意深处的字段

手写 getter/setter 太累,所以有 ParamRegistry.track(engine/registry.py:154): 给它一个根对象 + 一个路径字符串,它自己解析出该改哪里。

```python
# 示意,非源码:把 graph 里的 prompt 暴露成可优化目标
registry = ParamRegistry()
registry.track(program, "prompt.template") # 嵌套属性
registry.track(program, "metadata['style']", name="style")# 字典键 + 起别名
registry.track(program, "components[2].prefix") # 列表下标
# 之后优化器就能:registry.get("style") / registry.set("style", 新值)
```

路径解析靠一个正则 _PATH_RE(engine/registry.py:14)拆出"属性名 / 列表下标 / 字典键", _walk(engine/registry.py:243)一路走到叶子的父容器,再据类型用 getattr/setattr[] 读写(_track_path,engine/registry.py:213)。

一个巧处:快照 + 回滚。 注册时 register_field 会调 init_snapshot() 深拷一份初值 (engine/registry.py:121),safe_deepcopy(engine/registry.py:331)对拷不动的对象有多级 降级兜底;之后 reset() 能把字段(乃至整个 registry)还原(engine/registry.py:85,145)。 优化搜坏了,能一键回到原点。

4.3 CodeBlock 与 EntryPoint:把"整段工作流跑一次"也包成可调用对象

CodeBlock(optimizer_core.py:97)把一个"输入 cfg → 输出"的函数包一层,配合 registry 就能构成"改配置 → 跑一次 → 得结果"的最小实验单元;BaseCodeBlockOptimizer.run (optimizer_core.py:175)演示了这个循环:sample_cfg → _apply_cfg → code_block.run → evaluator → update。 基于 registry 的那批优化器(EvoPrompt/MAP-Elites/MIPRO)都建在 engine/base.py:6BaseOptimizer 之上,共享 apply_cfg / get_current_cfg 等(engine/base.py:44-52)。

两套并存,别混淆。 代码里有两份 OptimizableField/Registry:一份在 optimizer_core.py(早期/演示,文件底部还留着 main() demo),一份在 engine/registry.py(带快照回滚,更完善,被 EvoPrompt/MAP-Elites/MIPRO 实际使用)。 二者概念相同,engine/ 那版是主力。


5. 核心机制之三:两套优化器契约

优化器不止一种基类,分两支——这是读代码时最容易懵的地方,先分清:

契约基类谁继承核心方法graph 类型
Optimizer(optimizers/optimizer.py:12)SEW、TextGrad(部分对齐)optimize / step / evaluate / convergence_checkWorkFlowGraph / ActionGraph
BaseOptimizer(engine/base.py:6)EvoPrompt、MAP-Elites、MIPRO、Exampleoptimize(+ registry 读写)任意"program"可调用
(独立) BaseModuleAFlow、TextGrad各自的 optimize()AFlow 用磁盘上的 graph.py

Optimizer 抽象(optimizer.py)定义了最规整的四段式契约,每个方法默认抛 NotImplementedError,由子类实现:

  • optimize(dataset) —— 主循环入口。
  • step() —— 走一步(提一个改法并应用)。
  • evaluate(dataset, ...) —— 用 Evaluator 打分。
  • convergence_check() —— 判断是否该停(连续 N 步没进步)。

它还统一了几个超参:max_stepseval_every_n_stepseval_roundsconvergence_threshold(optimizer.py:18-21)。SEW 是这套契约最标准的实现。


6. 优化器家族(各家"怎么改"的不同思路)

这是本章的重头。所有优化器目标一致(让分数变高),区别只在"怎么提出下一个改法"。 先给一张全景对比表,再逐个一句直觉 + 改写对象 + 关键 file:line

优化器改什么搜索策略(直觉)典型场景
AFlow工作流的 graph.py + prompt.py(整个结构+算子)蒙特卡洛式:从历史高分轮采样一个,让 LLM 改写,存为新一"轮",按分数收敛想连结构一起搜(加/删节点、换算子)
TextGrad各 agent 的 system prompt / instruction"文本梯度":让 LLM 生成"哪里错、该怎么改"的自然语言梯度,反向传播多智能体工作流的 prompt 精修
MIPROprompt 指令 + few-shot 示例贝叶斯优化(基于 DSPy MIPROv2):bootstrap 示例 + 提案指令,用 Optuna 搜配置想同时优化指令示例,要正统 TPE 搜索
EvoPrompt各节点的 prompt(种群)进化算法:GA(交叉+变异+选择)或 DE(差分进化)一次维护一群候选 prompt、择优
SEW工作流表示(结构)+ prompt自我进化改写:把 graph 转成某种"方案"表示,用 mutation prompt 让 LLM 改想切换工作流表示(python/yaml/bpmn…)并进化
MAP-Elites任意 registry 字段(cfg)质量-多样性:按"特征维度"分格,每格只留最优,兼顾多样性想要一档多样的高质量解,而非单个最优

6.1 AFlow —— 蒙特卡洛式搜图,连结构一起改

一句直觉: 把每一轮优化的工作流存成一个目录 round_N/(里面是 graph.py + prompt.py), 从历史高分轮里采样,让 LLM 改写出新一轮,谁分高留谁——像蒙特卡洛树搜索在"工作流空间"里探路。

改写对象: 磁盘上的 graph.py(ActionGraph 的结构)与 prompt.py。这是唯一一个 直接改代码文件、能动结构(而非只改 prompt)的优化器。

关键实现:

  • AFlowOptimizer.optimize(aflow_optimizer.py:96):跑 max_rounds 轮,每轮起一个新事件循环 跑 _optimize_graph,轮后 _check_convergence
  • _handle_optimization_round(aflow_optimizer.py:185):_get_optimization_sample 从 top 轮里采一个(get_top_rounds),读该轮的 graph/prompt + 历史经验 + 算子说明 + 日志, 拼出 create_graph_optimize_prompt,让 optimizer_llm 生成改写。
  • 输出解析成 GraphOptimizeOutput(aflow_optimizer.py:23,字段 modification/graph/prompt, 优先 XML 解析,失败退回正则 _parse_optimizer_llm_output,aflow_optimizer.py:222)。
  • 收敛判定外包给 ConvergenceUtils.check_convergence(top_k=3)(utils/aflow_utils/convergence_utils.py:65)。
  • 算子表 OPERATOR_MAP 与图文件读写在 utils/aflow_utils/graph_utils.py

AFlow 改编自 MetaGPT 的 AFlow(见 aflow_optimizer.py:1 致谢)。

6.2 TextGrad —— 用 LLM 生成"文本梯度"反向传播

一句直觉: 把 prompt 当成神经网络里的可训练参数,把"这次答错了"当成 loss; 让一个 LLM 用自然语言说清"输出哪里不对、该怎么改 prompt"——这段自然语言就是"文本梯度"; 再沿工作流反向传播、更新每个 agent 的 prompt。是"给 prompt 做梯度下降"最字面的实现。

改写对象: 每个 agent 的 system_promptinstruction(optimize_modeall / system_prompt / instruction,textgrad_optimizer.py:166)。

关键实现(基于 textgrad 库):

  • 每个 agent 被包成 TextGradAgent(textgrad_optimizer.py:108):把它的 system prompt / instruction 包成 textgrad.Variable(requires_grad=...)——这就是"可训练参数"。
  • optimize(textgrad_optimizer.py:236):按 epoch 洗数据、切 batch,逐 batch 调 step
  • step(textgrad_optimizer.py:309):对每条样本 forward 跑工作流拿输出,用 loss_fn (MultiFieldEvaluation / TextLoss)算文本 loss,total_loss.backward(engine) 生成梯度, textgrad_optimizer.step() 据梯度改 prompt,再 _update_workflow_graph 写回。
  • forward(textgrad_optimizer.py:356)从终点节点递归 _compute_node(:503)串起整图, 让梯度能沿工作流反传。
  • LLM 后端封装成 TextGradEngine(textgrad_optimizer.py:62),把 EvoAgentX 的 BaseLLM 适配成 textgrad 的 EngineLM

改编自 zou-group 的 TextGrad(textgrad_optimizer.py:1-8)。

6.3 MIPRO —— 基于 DSPy 的贝叶斯优化(指令 + 示例一起搜)

一句直觉: 不只改指令,还自动挑few-shot 示例;用贝叶斯优化(Optuna 的 TPE)在 "指令候选 × 示例候选"的组合空间里搜最优配置。

改写对象: prompt 指令 + bootstrap 出来的少样本示例。

关键实现(直接复用 DSPy):

  • MiproOptimizer 多继承 BaseOptimizer 和 DSPy 的 MIPROv2(mipro_optimizer.py:309), 把 EvoAgentX 的 program/registry 转成 DSPy module(_convert_to_dspy_module,:578), 把 BaseLLM 包成 MiproLMWrapper(LM)(:75),把 benchmark 打分包成 MiproEvaluator(:140)。
  • optimize(mipro_optimizer.py:590):先 _bootstrap_fewshot_examples 造示例候选, 再让 GroundedProposer 提指令候选,最后用 Optuna 搜组合。
  • 另有 WorkFlowMiproOptimizer(同文件)专门优化 WorkFlowGraph
  • 可选依赖 optuna:没装会在 optimizers/__init__.py:31 给出明确报错。

改编自 Stanford DSPy(mipro_optimizer.py:2-4)。

6.4 EvoPrompt —— 进化算法改 prompt(GA / DE 两支)

一句直觉: 给每个节点维护一"群"候选 prompt(population),像生物进化一样反复 变异 + 交叉 + 选择,一代代淘汰劣者、保留优者。

改写对象: 各节点的 prompt(以种群形式,node_populations,evoprompt_optimizer.py:95)。

关键实现:

  • 基类 EvopromptOptimizer(evoprompt_optimizer.py:38)管种群、并发信号量、早停 (early_stopping_patience)、日志与性能曲线绘图;初始种群靠一个 paraphrase_agent (:103)对初始 prompt 做同义改写来扩充。
  • 两个具体算法:
    • GAOptimizer(:665):遗传算法——交叉/变异/选择,optimize:737
    • DEOptimizer(:945):差分进化——_evolve_and_select_one(:998)对每个 prompt 做 DE 式变异+交叉,optimize:1053,专门配 BIGBenchHard
  • 组合评估:_generate_combinations(:471)把各节点种群组合成整体候选再打分。

6.5 SEW —— 切换工作流"表示",再进化改写

一句直觉: SEW(Self-Evolving Workflow)先把工作流转成某种方案表示 (python / yaml / code / core / bpmn 五选一,VALID_SCHEMES,sew_optimizer.py:20), 再用 mutation prompt 让 LLM 改写这份表示——既能改结构,也能改 prompt。

改写对象: 工作流表示(optimize_mode = structure / prompt / all,sew_optimizer.py:660)。

关键实现(最贴合 Optimizer 四段式契约):

  • SEWWorkFlowScheme(sew_optimizer.py:22):convert_to_scheme / parse_from_schemeSequentialWorkFlowGraph 与五种文本表示之间来回转换。
  • optimize(sew_optimizer.py:675):初评一次 → 循环 step + 定期 evaluate + convergence_check,末尾 restore_best_graph 还原历史最优。
  • step(sew_optimizer.py:713):选当前最高分的 graph,_workflow_graph_step(:862)按 optimize_mode 决定改结构(_wfg_structure_optimization_step)还是改 prompt。
  • SimplePromptBreeder(sew_optimizer.py:603)生成变异 prompt:zero-order 用随机 "thinking style" 现造 hyper-mutation prompt,first-order 从固定 mutation prompt 里选 (get_mutation_prompt,:622)。
  • convergence_check(sew_optimizer.py:901):连续多步没超过 _best_score 就停。

6.6 MAP-Elites —— 质量-多样性存档

一句直觉: 别只求"单个最高分"。按几个特征维度(如 prompt 长度、成本)把解空间切成 网格,每格只保留该格里最优的一个——最后得到一整档"各具特色的高质量解",而非一个孤峰。

改写对象: 任意 registry 里的 cfg 字段(search_space 给出每个字段的候选值)。

关键实现:

  • MapElitesOptimizer(map_elites_optimizer.py:25),存档单元是 ArchiveEntry (cfg / fitness / metrics / cell,:17)。
  • optimize(map_elites_optimizer.py:61)主循环:按 exploration_ratio 决定 从存档挑父代变异(_mutate_cfg,:164)还是全随机采样(_random_cfg,:161); 跑一次拿 metrics → _cell_from_metrics(:131)按特征维度算出落在哪个格子 → 若该格空或 更优则替换(:87)。
  • 特征维度必须给范围:缺 feature_ranges 会直接报错(:54),_bin_index(:147) 把连续特征值离散成格子下标。

7. 巧妙之处(可借鉴的技术)

  • "可优化字段"是整个设计的枢纽。 用一对 getter/setter + 路径字符串,就把"优化器"和 "工作流内部结构"彻底解耦——优化器不需要知道你的 graph 长什么样,只要报得出 name 就能改。 见 engine/registry.py:154(track)。

  • 注册即快照,搜坏能回滚。 注册字段时自动深拷初值(register_field → init_snapshot, engine/registry.py:121),safe_deepcopy(:331)对不可拷贝对象有三级降级兜底。 这让"大胆探索、随时还原"成为安全操作。

  • 失败样本计入分母。 _calculate_average_score(evaluator.py:327)对跑挂的样本记 None不缩小分母——优化器因此能感知"改法让工作流更容易崩",而不是被幸存者偏差骗到。

  • 多线程各持一份 AgentManager。 并行评测时每个线程克隆独立的 agent 管理器 (evaluator.py:248),用 contextvars 隔离,避免共享可变 agent 状态导致的串扰。

  • 一个抽象,多种搜索哲学。 同一套"改字段 + benchmark 打分"的骨架下,能装进蒙特卡洛 (AFlow)、梯度式(TextGrad)、贝叶斯(MIPRO)、进化(EvoPrompt)、质量-多样性(MAP-Elites) 五种完全不同的搜索范式——这正是"框架"价值的体现。


8. 边界与局限(诚实)

  • 优化很贵。 每一步都要在数据集上把整个工作流跑一遍(常常还 eval_rounds 多次求平均), 每次执行都是真实 LLM 调用。步数 × 样本数 × 轮数 × 每次多个 agent 调用 = 成本迅速膨胀。

  • 两套 registry / 多条继承链,认知负担不小。 optimizer_core.pyengine/registry.py 各有一份可优化字段抽象;优化器又分挂在 Optimizer / BaseOptimizer / BaseModule 三种基类下。 代码里还留着 demo(optimizer_core.py:285main())和标注 "Unused" 的类 (engine/registry.py:282,395)。初读需要先分清哪套是主力。

  • 可选依赖。 MIPRO 需要 optuna + dspy,TextGrad 需要 textgrad 库;缺了会导入失败 (MIPRO 的缺失在 optimizers/__init__.py:31 有友好报错,其余按普通 ImportError)。

  • 各优化器的 graph 适配面不同。 例如 SEW 的结构优化针对 SequentialWorkFlowGraph, 对 ActionGraph 只支持 prompt 优化(sew_optimizer.py:668-673);AFlow 直接操作磁盘上的 graph.py。选优化器前要先确认它吃哪种工作流。


9. 代码地图(导航索引)

用符号名 grep 比行号更抗漂移;下表给"主题 | 文件 | 符号"。

主题文件符号
数据源+打分抽象evoagentx/benchmark/benchmark.pyBenchmarkCodingBenchmarkcheck_solutioncompute_pass_at_k
具体数据集evoagentx/benchmark/{gsm8k,hotpotqa,humaneval}.pyGSM8KHotPotQAHumanEval
评测执行器evoagentx/evaluators/evaluator.pyEvaluator_evaluate_single_example_parallel_evaluate_calculate_average_score
优化器契约(四段式)evoagentx/optimizers/optimizer.pyOptimizer(optimize/step/evaluate/convergence_check)
可优化字段(演示版)evoagentx/optimizers/optimizer_core.pyOptimizableFieldPromptRegistryCodeBlockBaseCodeBlockOptimizer
可优化字段(主力版)evoagentx/optimizers/engine/registry.pyOptimizableFieldParamRegistry.tracksafe_deepcopy
registry 优化器基类evoagentx/optimizers/engine/base.pyBaseOptimizerapply_cfg
AFlow(蒙特卡洛搜图)evoagentx/optimizers/aflow_optimizer.pyAFlowOptimizerGraphOptimizeOutput_handle_optimization_round
AFlow 收敛/图工具evoagentx/utils/aflow_utils/{convergence_utils,graph_utils}.pyConvergenceUtils.check_convergenceOPERATOR_MAP
TextGrad(文本梯度)evoagentx/optimizers/textgrad_optimizer.pyTextGradOptimizerTextGradAgentTextGradEnginestepforward
MIPRO(DSPy/贝叶斯)evoagentx/optimizers/mipro_optimizer.pyMiproOptimizerWorkFlowMiproOptimizerMiproEvaluatorMiproLMWrapper
EvoPrompt(进化)evoagentx/optimizers/evoprompt_optimizer.pyEvopromptOptimizerGAOptimizerDEOptimizer
SEW(表示进化)evoagentx/optimizers/sew_optimizer.pySEWOptimizerSEWWorkFlowSchemeSimplePromptBreederVALID_SCHEMES
MAP-Elites(质量-多样性)evoagentx/optimizers/map_elites_optimizer.pyMapElitesOptimizerArchiveEntry
优化器统一出口evoagentx/optimizers/__init__.py_EXPORTS(懒加载)
端到端示例examples/optimization/{aflow,textgrad,mipro,evoprompt}/examples/sew_optimizer.pyexamples/optimization/map_elites_demo.py

相邻章节: 工作流本体见 03-workflow-execution.md;自动构建 工作流见 04-auto-construction.md;顶层全景与阅读地图见 index.md。本章的评测闭环也是评估任何 EvoAgentX 工作流质量的通用工具, 不止服务于优化。