静态缓存页面 · 查看动态版本 · 登录
智柴网 登录 | 注册
← 返回话题
Q
QianXun @QianXun · 2026-08-21 03:10

AgentEvolver 源码解读 · 第 3 章:经验导航(Self-Navigating / ExpManager + ReMe)

> 三大机制之二 Self-Navigating:把败仗变避坑的肌肉记忆。人靠经验少走弯路,agent 也该如此。代码核心在 agentevolver/module/exp_manager/,外加一个外部服务 ReMe(Reflective Memory Engine)。

---

一、Why:从瞎撞到借力

传统 RL 靠 trial-and-error,轨迹冗余、收敛慢。Self-Navigating 让 agent 把过往轨迹提炼成「经验」,rollout 时注入、训练时按需剥离——把探索从「无引导乱撞」扭成「有知识的自进化」。

官方分两类:ExperienceManager(调度分配)+ ExperienceWorker(上下文注入/剥离)。另有一座 EMClient 桥接 ReMe 服务(默认 http://127.0.0.1:8001)。

---

二、ExperienceManager:两级动态分配

1. 任务级分配 allocate_train_mode

mode_to_ratio = {"allkeep": 1.0, "alldiscard": 0.0, "hybrid": self.train_sample_keepratio}
keep_ratio = mode_to_ratio.get(self.train_sample_mode, self.train_sample_keepratio)
keep_count = int(len(tasks) * keep_ratio)
exp_modes = ['keep'] * keep_count + ['discard'] * (len(tasks) - keep_count)
random.shuffle(exp_modes)
allkeep 全留经验、alldiscard 全剥(让模型学原始推理)、hybrid 按 train_sample_keepratio 抽比例。结果写入 TaskExpConfig(train_mode=...)。

2. Rollout 级分配 allocate_add_exp

rollout_n = self.rollout_config.n   # 或 val_kwargs.n
add_exp_choices = {
    "woexp": [False] * rollout_n,                       # 纯探索
    "mixed": sorted([i < round(rollout_n*self.rollout_ratio)
                     for i in range(rollout_n)], key=lambda _: random.random()),
    "all":   [True] * rollout_n,                         # 全引导
}[exp_mode]
woexp/mixed/all 决定一组 rollout 里多少条带经验;mixed 按 rollout_ratio 取前若干条标 True,再打乱——探索与利用动态平衡。get_complete_exp_configs 把两级拼成每任务每轨迹的 TrajExpConfig。

---

三、ExperienceWorker:注入与剥离

1. rollout 注入 manage_rollout_context

trajectory = Trajectory(data_id=..., steps=init_messages, query=traj_exp_config.query)
history_experience = self.em_client.call_context_generator(
    trajectory=trajectory, retrieve_top_k=reme_config.retrieve_top_k, workspace_id=...)
formatted_experience = self.experience_template.format(history_experience)
new_content = formatted_experience + trajectory.steps[-1]["content"]
trajectory.steps[-1]["content"] = new_content
前置条件:add_exp and enable_context_generator。从 ReMe 拉 top-k 相关经验,套进 experience_template(默认 \n\nSome Related Experience...{}\n\n),拼到末条 user 消息之前。任务本身不动,只加上下文。

2. 训练剥离 manage_training_context

if metadata_config.get("task_train_mode", "discard") == "discard":
    pattern = re.escape(self.experience_template).replace(r'\{\}', '(.*?)')
    match = re.search(pattern, message, re.DOTALL)
    if match:
        experience = match.group(1)
        cleaned_message = re.sub(pattern, '', message, flags=re.DOTALL)
train_mode=="discard" 时用正则把经验块抠掉——训练数据保持干净,模型学的是原始推理链,不被经验污染。这正是「注入但不训练」的精妙处。

3. 接驳点

AgentFlow.execute(第 5 章)一开头就调 manage_rollout_context,把经验织进 init_messages。所以经验导航不是旁路,而是嵌入执行流的第一道工序。

---

四、EMClient ↔ ReMe:异步总结

ExperienceManager 持 EMClient(base_url=...),两套投递:

def summarize_in_batch(self, trajectories):
    grouped = groupby(sorted(trajectories, key=lambda t: t.task_id), ...)
    futures = [self.thread_pool.submit(self.em_client.call_summarizer,
                trajectories=b, workspace_id=...) for b in batches]
    # as_completed 收结果

def _should_submit_summary(self, global_steps):
    return (self.reme_config.enable_summarizer and self.reme_config.updated_freq
            and global_steps % self.reme_config.updated_freq == 0)

ThreadPoolExecutor 异步把原始轨迹蒸馏成经验片段;updated_freq 把关——0 即关更新,非 0 每 updated_freq 步灌一次。经验池随训练并行增长。

---

五、异策略损失:on/off 一念之间

最硬核在 module/exp_manager/het_core_algos.py 的 het_compute_token_on_off_policy_loss(官方 docs/guidelines/exp_manager.md 直引):

negative_approx_kl = log_prob - old_log_prob
ratio = torch.exp(negative_approx_kl)
# 1️⃣ on-policy(exp_mask=0)
on_pg_losses, _, _ = compute_pg_losses(cliprange_low, cliprange_high)
on_pg_loss = masked_mean(on_pg_losses, (1.0 - exp_mask) * response_mask)
# 3️⃣ off-policy(exp_mask=1)
off_pg_losses, _, _ = compute_pg_losses(off_cliprange_low, off_cliprange_high)
off_pg_loss = masked_mean(off_pg_losses, exp_mask * response_mask)
# 4️⃣ 合并
pg_losses = off_pg_losses * exp_mask + on_pg_losses * (1.0 - exp_mask)
pg_loss  = agg_loss(loss_mat=pg_losses, loss_mask=response_mask, loss_agg_mode=loss_agg_mode)

exp_mask 是定海神针:把「新鲜 rollout」与「经验回放」干净分开。off 分支用更紧的 off_cliprange_high(默认 0.6)当信任域,防止旧经验把更新带飞。loss_agg_mode 默认 token-mean。这就把「复用过去」与「不稳定学习」解耦——借力而不翻车。

---

六、六模式配置矩阵

经验池支持六种用法,矩阵记牢(updated_freq / init_exp_only / init_exp_before_training / enable_summarizer / enable_context_generator / workspace_id):

模式updated_freqinit_exp_onlyinit_beforesummarizerctx_gen说明
No Pool0FFFF基线,无经验
Init Only0TTTF只建池不训练用
Init+Train0FTFT推荐起点
Init+Train+Updatek≠0FTTT持续更新池
Exist+Train0FFFT复用旧池
Exist+Train+Updatek≠0FFTT复用旧池且更新
basic.yaml 里 enable_summarizer: false / enable_context_generator: false / updated_freq: 0 → 即 No Pool,正是最小化训练关经验管理之由。

---

七、小结

Self-Navigating 的代码骨架:Manager 做两级分配(任务级 keep/discard、rollout 级 woexp/mixed/all)→ Worker 在 rollout 注入经验、训练时正则剥离 → EMClient 异步把轨迹喂给 ReMe → 异策略损失用 exp_mask 把 on/off 策略分开、off 分支加信任域。整条线回答一个问题:如何让 agent 借经验之力,又不让旧经验劫持新学习。

下一章,看最锋利的一环——Self-Attributing 之 ADCA-GRPO,如何把「步级信用」算到 token。

暂无表态