我一开始想做 LLM agent,最后先学会了怎么拆训练问题

6 阅读14分钟

这不是一篇“大模型训练教程”。

也不是说我做了一个《杀戮尖塔》小实验,就能解释大模型训练的全貌。

它更像一篇过程笔记:我原本想做一个 LLM + 记忆 + 游戏模拟器的 agent,让它自己玩、自己总结、自己变强。但真做下去以后,我发现自己其实先被迫补了一遍模型训练的基本问题:

  • 为什么要先有评估环境?
  • 为什么要拆任务和动作空间?
  • 为什么有些能力可以用小模型压缩?
  • 为什么有些能力不能直接从老师动作里蒸馏出来?
  • 为什么 learned guidance 不够好时,反而会伤害搜索?
  • 为什么负结果不是“没做成”,而是在告诉你下一阶段该怎么设计?

我现在觉得,这些问题比最后那个小模型本身更有价值。

因为它们不是从论文目录里读出来的,而是我在开发过程中一次次撞到的。

如果只想先抓主线,可以先看这张图:

从游戏实验拆出的训练问题路线图

图 1:这篇文章不是按术语讲,而是按开发中遇到的卡点讲。每个训练阶段,都是为了解决一个具体失败模式。

这篇文章可以当成一张入门路线图来读:

  • 先看为什么我没有直接做 LLM + 记忆。
  • 再看为什么要先拆环境、评估、动作空间。
  • 最后看为什么“判断”可以压缩,而“规划”需要展开。

如果你想先看实物,可以直接从这里进:

1. 最早的想法:让 LLM 读战报、写记忆、改策略

我一开始想做的不是一个 10 万参数的小 MLP。

最早的想法更像今天大家说的 agent:

  • 底层有一个很快的游戏模拟器,负责不断跑局。
  • 中间有执行策略,把“这局面该怎么行动”落成具体操作。
  • 上层有 LLM 和记忆系统,读失败过程、总结经验、提出下一轮改法。

这听起来很自然。

因为《杀戮尖塔》很像一个适合 agent 学习的封闭环境:目标清楚,反馈明确,长期规划重要,而且每局都能复盘。

但真正开始以后,我很快遇到第一个问题:

如果我一上来把 LLM、记忆、prompt、搜索、策略网络全部放进系统里,最后变强了,我怎么知道是哪一层起了作用?

反过来,如果它没有变强,我又该修哪里?

这是我第一次意识到:在做“会学习的系统”之前,先要有一个能归因的实验面。

这对应到模型训练里,就是最基础但最容易被低估的一层:评估环境和反馈闭环

没有固定评估,没有稳定环境,没有可复现的 seed,任何“它好像变聪明了”都很危险。你不知道那是能力提升,还是运气、提示词、搜索预算、评估集泄漏,或者某个隐藏启发式在起作用。

所以我第一步没有继续堆 LLM 和记忆,而是先退回去问:

我能不能先把底层环境和评估固定住?

2. 第二个决策:先选一个能反复试错的世界

这也是我后来选择 sts_lightspeed 的原因。

它不是最酷的环境,但它有几个关键好处:

  • 足够快,可以反复跑。
  • 足够封闭,结果主要来自系统自己的决策。
  • 有固定 seed,可以做 held-out 评估。
  • 有神经网络观测接口,能把游戏状态变成向量。
  • 有内置 MCTS,可以作为强基线。

这一步看起来像工程准备,但它其实回答了一个训练问题:

模型到底从哪里获得反馈?

很多时候我们讨论训练,会直接跳到模型结构、算法、参数量。但做起来以后我发现,模型之前还有一层更底层的东西:环境。

环境决定了什么是一次尝试,什么是一个动作,什么叫成功,什么叫失败,能不能重复,能不能比较。

如果没有这层,后面讲 RL、偏好模型、记忆、agent loop 都是悬空的。

所以我现在会把“找环境 / 建评估 / 固定反馈”看作训练系统的第 0 阶段。

它解决的不是“模型怎么学”,而是“学习有没有一个可以被测量的世界”。

3. 第三个决策:不要一上来让模型控制一切

有了环境以后,我最直觉的想法是:那就让模型从头到尾玩完整局。

但很快会发现,《杀戮尖塔》不是一种决策。

它里面至少有两类完全不同的问题。

第一类是非战斗决策:

  • 走哪条路线?
  • 选不选这张卡?
  • 商店买什么?
  • 篝火回血还是升级?
  • 事件选哪个选项?

第二类是战斗决策:

  • 这一回合先打哪张牌?
  • 能量怎么分配?
  • 要不要保留资源?
  • 这回合少防一点,后续抽牌能不能补回来?

这两类问题看起来都叫“决策”,但学习形态完全不同。

非战斗决策更像判断:候选项不多,局面相对稳定,好坏有可泛化模式。

战斗决策更像规划:动作之间强耦合,后果依赖未来抽牌、怪物行动、后续回合。

所以我做了一个很保守的切分:

  • 战斗继续交给内置 MCTS。
  • 非战斗交给学习出来的小网络。

这一步对应到模型训练里,其实是问题分解和动作空间设计

很多训练失败不是因为模型太小,而是因为一开始把不同形态的能力塞进了同一个学习目标里。

你让一个模型同时学“路线偏好”“卡牌价值”“商店购买”“战斗出牌序列”,它们表面上都是 action,内部却需要不同的表示、反馈和推理过程。

拆开以后,问题才变得可学。

4. 第四个决策:把策略写成“候选动作打分器”

我后来训练的非战斗模型也没有做得很复杂。

每次遇到一个非战斗决策点,我拿到当前游戏状态,再拿到所有合法候选动作。

然后对每个候选动作构造一个描述符:

  • 这是地图选择吗?
  • 目标房间是什么?
  • 后面一两层可能通向哪里?
  • 这是奖励选卡吗?
  • 候选卡是哪张?
  • 这是商店、篝火、事件里的哪个动作?

最后模型做的事很简单:

score = MLP(current_state + candidate_action)

对每个候选动作打一分,选分最高的那个。

候选动作打分器示意图

图 2:这一步把“策略”变成了一个状态-动作打分问题。模型不需要生成整局计划,只需要在当前候选项里排序。

这个设计对我很重要。

因为它让我第一次把“策略”从一个神秘概念降成了一个更具体的东西:在某个状态下,对候选动作排序。

这很像模型训练里的 reward model / preference model。

它不负责生成完整方案,也不负责长程规划。它解决的是:

在几个候选项里,哪个更像好选择?

很多判断型能力其实可以这样压缩。

比如人类说“这张卡现在不适合拿”,背后当然有经验,但落到模型形态上,它可以是一个状态-动作打分函数。

这也是我后来理解“偏好模型”时一个很有帮助的类比:它不是全能智能体,它只是把大量经验压成一个排序器。

5. 第五个决策:用最终楼层训练,但先接受它很粗

非战斗策略的训练信号其实很粗。

我没有给每一次选卡、每一次选路都写细粒度奖励,而是用整局最终楼层做反馈。

这意味着奖励很稀疏,也很延迟:

  • 你在 5 楼选了一张卡,可能 30 楼才体现价值。
  • 你早期贪了一个精英,可能直接死,也可能滚起雪球。
  • 你跳过一张牌,看起来什么都没发生,但可能让牌组更干净。

从训练角度看,这很不舒服。

但它也逼我理解了 RL 里一个很基础的问题:反馈不是天然写在每个动作旁边的。

很多时候我们只有最后结果,然后要把这个结果反推到前面的动作上。

这就是为什么训练里会出现 baseline、rollout、固定 eval seed、checkpoint、对照组这些东西。它们不是仪式感,而是在对抗一个现实问题:

单次反馈太吵了,你需要让系统知道自己到底是在变好,还是刚好这几局运气不错。

这也是我为什么后来很在意固定 50 个 held-out seed。

不是因为 50 个 seed 多么完美,而是至少它让比较有了同一个尺子。

6. 第六个节点:非战斗真的涨了,我才意识到“判断”可以被压缩

结果出来以后,最反直觉的是:只换非战斗策略,楼层涨了很多。

同样 MCTS 战斗、同样 50 个 held-out seed、A0 铁甲:

非战斗策略战斗平均楼层通关率
stock bot 启发式,地图接近随机MCTS @5000031.26%
学习型非战斗策略MCTS @5000042.514%

这件事改变了我对“学习”的理解。

我原来会下意识觉得,《杀戮尖塔》最难的是战斗出牌。但在这个基线里,短板反而是战斗之外:走哪条路线、什么时候贪、选不选卡、商店买什么。

这些东西不一定需要很深的展开推理。

它们更像经验判断。

而经验判断是可以被压缩进一个小模型里的。

这对应到大模型训练里,我会把它理解成:不是所有能力都需要生成式推理,有些能力更适合先做成偏好、价值、打分、过滤、路由。

也就是说,模型训练不是只有“让一个模型端到端做完所有事”这一种形态。

有些阶段的目标就是先学一个可靠的判断器。

7. 第七个节点:我试图学习战斗,然后连续失败

非战斗涨了以后,一个很自然的下一步是:那战斗能不能也学出来?

我试了几条路:

  • 行为克隆 MCTS。
  • DAgger。
  • REINFORCE 微调。
  • attention/token scorer。
  • value net 加一层 lookahead。
  • policy/value guided PUCT。

这部分对我反而更有教育意义。

因为它们基本都没有真正接近 MCTS。

最早我以为行为克隆会是一个合理起点:既然 MCTS 很强,那我收集 MCTS 在每个局面下选的动作,然后训练网络模仿它,不就行了吗?

结果不是。

问题在于,MCTS 的能力不只体现在最后那个动作上。

它强,是因为它在选择动作之前,在模拟器里展开了很多未来。它看到了很多“如果我先打这张牌,后面可能会怎样”的分支。

而我给学生看的,只是当前状态和老师最后选的动作。

这就像让学生只背答案,不给推导过程。

所以这里对应到模型训练里的问题是:蒸馏到底蒸馏的是什么?

如果老师的能力来自一个过程,比如搜索、工具调用、环境交互、多步验证,那你只蒸馏最终输出,可能蒸不到真正的能力来源。

这也是为什么现在很多训练会关心过程监督、思维链、verifier、搜索轨迹、工具调用轨迹。

它们本质上都在回答同一个问题:

老师做对,不只是因为答案对,而是因为中间那段计算有价值。

8. 第八个节点:半吊子的 guidance 会把搜索带偏

后来我又试过让网络不直接替代 MCTS,而是辅助搜索。

这听起来更合理:既然纯网络不够强,那让网络给搜索一点指导,应该会更好。

但结果也没有这么简单。

一个不够准的 policy/value,不一定是在帮搜索省时间,它可能是在把搜索预算集中到错误方向上。

这对我也很像大模型训练里的另一个问题:错误的奖励、错误的 verifier、错误的记忆,不是中性的。

它们会主动改变系统探索的方向。

如果 reward model 偏了,模型会学会迎合 reward model。

如果 verifier 弱了,模型会学会骗 verifier。

如果记忆层把错误经验总结成规则,agent 会越来越稳定地犯同一种错。

所以 learned guidance 不是“有总比没有好”。

它必须足够准,或者至少知道自己什么时候不该插手。

这也是我从战斗失败里学到的一个很重要的点:模型和搜索的组合,不是简单相加。模型如果没有达到足够质量,可能会伤害原来很强的搜索基线。

9. 我现在怎么理解模型训练里的这些阶段

如果把这次开发过程倒过来看,我会这样理解模型训练里那些看起来分散的阶段。

第一,评估环境不是附属品。

它解决的是“学习有没有世界、反馈和尺子”。没有它,agent 只是看起来会动。

第二,任务分解不是偷懒。

它解决的是“不同能力是不是被错误地塞进同一个目标”。判断、规划、记忆、搜索本来就可能需要不同结构。

第三,表示和动作空间设计不是细节。

它解决的是“模型看到的东西,是否对应它要学的东西”。我把非战斗做成候选动作打分器以后,问题才真正变得可学。

第四,偏好 / reward / value 模型不是完整智能。

它们解决的是“怎么把经验压成可复用判断”。它们很有用,但不能替代所有过程。

第五,模仿学习和蒸馏不是复制魔法。

它们解决的是“能不能从老师身上提取能力”。但如果老师的能力来自搜索过程,只看最终动作是不够的。

第六,搜索和规划不是旧时代方法。

它们解决的是“有些问题必须展开未来”。在这类问题上,一个单帧函数很难直接替代过程。

第七,记忆和反思应该在更后面接入。

它们解决的是“如何组织经验和下一轮训练任务”,但前提是底层评估、策略、反馈已经能被归因。否则记忆只会把混乱包装成经验。

训练系统分层图

图 3:我现在更倾向于把 agent 训练看成分层系统。越往上越像“反思”,但越依赖底层评估和反馈已经可靠。

10. 所以这篇文章不是在讲一个成功 demo

如果只看结果,这个项目并不夸张。

它没有做出完整 agent。

它没有让 LLM 自己玩游戏变强。

它也没有把战斗学出来。

但对我来说,它像一个入门指引:不是从概念开始,而是从一个真实小系统里不断遇到问题,然后被迫理解为什么训练系统会长成现在这样。

为什么要有 eval?

因为没有尺子就没有学习。

为什么要有 reward model / preference model?

因为很多判断可以先被压缩成排序函数。

为什么要有搜索和 verifier?

因为有些能力不是一眼看出来的,需要展开和检查。

为什么要有过程监督?

因为老师的答案不等于老师的计算。

为什么要有记忆和自我总结?

因为当系统能稳定评估和行动以后,才需要组织更长期的经验。

我现在更愿意把 agent 看成这些层的组合,而不是“LLM + 工具 + 记忆”三个词堆起来。

这次实验没有完成我最初的野心。

但它让我更清楚地知道,那个野心如果要继续往下做,下一步不应该是继续加 prompt 或加记忆,而是把判断、规划、搜索、价值、记忆分别放在能被验证的位置上。

这可能也是我想把这篇过程稿发出来的原因。

我不确定这些理解是否完全对,但我觉得它比“我训练了一个小模型”更接近我真正学到的东西。

如果你也在做 agent、RL、模型训练,或者只是刚开始理解这些词,我会很想知道:

你是在什么具体问题里,第一次理解“原来这个阶段是为了解决这个问题”的?

项目材料放在这里: