Voyager - Skill Library as Memory · essay

10. Voyager:技能库作为程序性记忆

论文:Voyager: An Open-Ended Embodied Agent with Large Language Models
链接:https://arxiv.org/abs/2305.16291
代码:https://github.com/MineDojo/Voyager

本地原文:

![[papers/10-Voyager-2305.16291.pdf]]

论文定位与阅读路径

核心定位

Voyager 不是主要研究“对话记忆”,而是证明 Agent 可以把成功经验沉淀成技能库,让未来任务复用。这是程序性记忆的代表。

原文结构导读

原文章节读法你要抓住的工程问题
Abstract / Introduction看开放式学习目标为什么 Minecraft 适合测试持续探索 Agent
2 Method精读,论文核心curriculum、skill library、iterative prompting 如何互相喂数据
2.1 Automatic Curriculum重点Agent 如何决定下一个该学的任务
2.2 Skill Library重点成功代码怎样变成可检索、可复用技能
2.3 Iterative Prompting重点失败反馈如何驱动修正和重试
3 Experiments看 baseline / ablation技能库和课程机制分别贡献什么
3.5 Multimodal Feedback from Humans快读人类反馈如何补环境自动反馈不足
4 Limitations and Future Work必读泛化、环境依赖、技能污染的边界
5-7 Related / Conclusion / Impact快读把 Voyager 放到 embodied agent 脉络里

Voyager 要按“经验如何变成程序”来读。它和 Reflexion 的差别在于:Reflexion 存下次策略,Voyager 存可执行函数;前者像错题本,后者像经过测试的工具库。

证据链阅读

证据类型看什么工程含义
Evaluation results探索范围、任务完成、技能增长技能库是否真的扩大能力边界
Ablation studies去掉 curriculum / skill library / iterative prompting三模块各自是否必要
Skill reuse examples旧技能是否被新任务调用程序性记忆必须能复用,不只是存代码
Limitation技能错误、环境绑定、人工反馈技能入库前必须验证、命名、版本化

研究背景与问题定义

论文场景

Voyager 是 Minecraft 里的开放式 Agent。它需要:

  • 探索环境。
  • 学会采集资源。
  • 合成工具。
  • 完成越来越复杂的任务。

关键是它不是每次从零开始,而是把学到的技能保存下来。

方法框架与核心机制

核心结构

Voyager:技能库就是程序化记忆 环境观察 自动课程 代码生成 执行技能 成功? 自我纠错 技能库

三个关键模块

1. Automatic Curriculum

自动决定下一步学什么。
就像游戏里先学砍树,再学做木镐,再学挖矿。

2. Skill Library

成功的代码技能会保存下来。
这就是程序性记忆:不是记住一句话,而是记住“怎么做”。

3. Iterative Prompting

失败后让模型根据错误反馈修改代码,直到成功。

为什么它也是 Memory

很多人以为 memory 只是“事实记忆”。Voyager 告诉我们还有一种记忆:

代码块TEXT · 1 行收起展开
我会做什么

这叫 procedural memory,程序性记忆。

例子:

  • 如何运行测试。
  • 如何修复某类 bug。
  • 如何生成周计划。
  • 如何调用某个 API。

概念校准

你刚学 Java 时,每次写文件上传都要查资料。后来你写多了,就形成“技能模板”。以后遇到类似任务,直接复用。这就是技能库记忆。

工程映射与实践启发

工程落地方案

Agent CLI 可以做一个 Skill Memory:

模块作用
SkillExtractor从成功任务中提取可复用步骤
SkillStore保存技能名称、描述、代码/流程
SkillRetriever新任务检索相关技能
SkillExecutor将技能作为 prompt 或工具调用策略
SkillEvaluator验证技能是否仍有效

技能表:

代码块SQL · 1 行收起展开
agent_skill(id, name, description, task_type, steps, success_count, last_used_at)

相关工作与方法对比

和 Reflexion 的关系

维度VoyagerReflexion
保存内容成功技能/代码失败后的语言反馈
记忆类型程序性记忆经验性反思记忆
适用可重复执行任务需要自我改进的任务

局限、对比与阅读检查

局限与边界

  • 技能在环境变化后可能失效。
  • 自动生成代码有安全风险。
  • 技能库太大后需要检索和去重。
  • Minecraft 场景和普通软件开发不完全一样。

阅读重点

  1. 它如何自动选择任务。
  2. 它如何生成和修正代码。
  3. 它如何保存技能。
  4. 它如何检索旧技能解决新任务。
  5. 程序性记忆和事实记忆有什么不同。

实践启发

你后续做 Agent 工程时,可以让 Agent 不只记住“用户喜欢什么”,还记住“成功做事的方法”:

  • 某项目怎么启动。
  • 某框架怎么测试。
  • 某类 bug 怎么排查。
  • 某种笔记怎么生成。

这会让 Agent 越用越顺手。

原文精读补充

1. Voyager 的三件套

Voyager 不是单纯“让 GPT 玩 Minecraft”。它的核心是三件套:

模块作用
Automatic Curriculum自动决定下一个探索目标
Skill Library保存成功代码技能
Iterative Prompting根据反馈修正代码

这三个模块组合起来,才形成“越玩越会”的效果。

2. Automatic Curriculum 怎么理解

人学游戏不会一开始打最终 Boss,而是:

代码块TEXT · 1 行收起展开
砍树 -> 做工作台 -> 做木镐 -> 挖石头 -> 做石镐 -> 挖铁

Automatic Curriculum 就是让 Agent 根据当前状态自动选择合适目标。它解决的是:

代码块TEXT · 1 行收起展开
下一步学什么,既不要太简单,也不要太难。

这对学习 Agent 很有启发:你也需要自动安排下一篇论文、下一个项目、下一段练习。

3. Skill Library 为什么是记忆

很多人把记忆理解成“记住事实”。Voyager 证明了另一类更重要的记忆:

代码块TEXT · 1 行收起展开
记住如何做事。

技能库里的内容通常是可执行代码或步骤。它不是“铁矿在哪里”,而是“如何挖矿并制作工具”。

4. Iterative Prompting 的闭环

Voyager 生成代码后,会在环境里执行。如果失败,就拿环境反馈继续修改。

flowchart TD
    A[生成技能代码] --> B[执行]
    B --> C{成功吗}
    C -->|成功| D[保存技能]
    C -->|失败| E[读取错误反馈]
    E --> F[修改代码]
    F --> B

这和编程 Agent 的测试循环几乎一样:

代码块TEXT · 1 行收起展开
写代码 -> 跑测试 -> 看错误 -> 改代码 -> 测试通过 -> 保存经验

5. 技能检索怎么发挥作用

当新任务出现时,Voyager 会从技能库检索相似技能,复用已有代码。

这带来两个好处:

  1. 不必每次从零写。
  2. 复杂技能可以由简单技能组合而来。

这就是“能力滚雪球”。

6. 实验怎么看

原文实验会比较探索能力、技能树解锁、获得物品数量等。你读时重点问:

  1. 没有 skill library 是否会重复试错。
  2. 没有 curriculum 是否目标选择混乱。
  3. 没有 feedback loop 是否代码失败率高。
  4. 技能是否真的能跨任务复用。

7. 工程落地提醒

你未来做 Agent 工程,不要只存事实记忆,也要存成功流程:

代码块JSON · 12 行收起展开
{
  "skill": "生成论文精读笔记",
  "trigger": "用户给论文列表并要求入门可读拆解",
  "steps": [
    "下载 PDF",
    "嵌入本地原文",
    "按 Abstract/Method/Experiment 拆",
    "补工程落地和工程类比",
    "更新 history"
  ],
  "evidence": "本次 Agent Memory 21 篇论文笔记"
}

这就是把一次成功任务沉淀成 procedural memory。

深度精读:Voyager 的记忆是“可执行技能”,不是文本事实

1. Voyager 解决的是开放式持续学习

Minecraft 环境没有固定题目列表。Agent 必须自己探索、发现目标、积累能力。这和普通问答不同:

代码块TEXT · 2 行收起展开
问答 Agent:回答当前问题。
Voyager:在开放世界里持续变强。

所以它需要的记忆不是“事实库”,而是“技能库”。

2. 三模块缺一不可

模块没有它会怎样
Automatic Curriculum不知道下一步该学什么
Skill Library每次从零开始,能力不能累积
Iterative Prompting代码失败后不会修正

这三个模块共同形成:

代码块TEXT · 1 行收起展开
选目标 -> 写代码 -> 执行 -> 反馈 -> 修正 -> 成功后存技能 -> 下个目标复用技能

3. Skill Library 为什么是程序性记忆

人类记忆分很多类。Voyager 对应的是 procedural memory:

代码块TEXT · 1 行收起展开
不是“知道什么”,而是“知道怎么做”。

在编程 Agent 中,程序性记忆可以是:

  1. 怎么启动项目。
  2. 怎么跑测试。
  3. 怎么定位某类 bug。
  4. 怎么生成某类笔记。
  5. 怎么处理 Git 冲突。

这些比事实记忆更接近“能力”。

4. 技能保存必须有成功验证

Voyager 不应该把任何生成代码都存技能库。只有执行成功的代码才值得保存。

这给工程一个原则:

代码块TEXT · 1 行收起展开
技能记忆必须有验证信号。

比如:

技能验证
修复 bug测试通过
生成笔记文件存在且结构合格
调用 API返回 200 且数据正确
数据迁移校验行数/哈希一致

没有验证的“技能”只是模型猜测。

5. 技能检索不只是相似搜索

新任务来了,检索技能要看:

  1. 任务描述相似。
  2. 前置条件满足。
  3. 环境版本兼容。
  4. 技能成功率高。
  5. 最近是否还有效。

一个技能库字段可以是:

代码块SQL · 11 行收起展开
agent_skill(
  id,               -- 技能 ID。
  name,             -- 技能名,检索和调用时使用。
  description,      -- 自然语言说明,帮助模型判断何时使用。
  preconditions,    -- 使用前提,例如需要哪些物品、状态或权限。
  steps,            -- 人类可读步骤,便于审计和复盘。
  code_ref,         -- 可执行代码或脚本引用。
  success_count,    -- 成功次数,用于估计可靠性。
  failure_count,    -- 失败次数,用于降权或触发重写。
  last_verified_at  -- 最近一次验证时间,过旧技能需要重新测试。
);

这比只存 skill_text + embedding 更可靠。

6. Curriculum 对学习 Agent 的启发

Automatic Curriculum 可以迁移到你的学习路线:

代码块TEXT · 3 行收起展开
当前基础:Java 后端
目标:AI Agent 工程
下一步:不是直接啃所有模型论文,而是先做 Memory/RAG/MCP 小闭环

一个学习 Agent 应该能根据:

  1. 你已经会什么。
  2. 你卡在哪里。
  3. 下个目标需要什么前置。
  4. 哪个任务最能形成闭环。

自动安排下一步。

7. Iterative Prompting 和 Reflexion 的关系

Voyager 和 Reflexion 都有试错,但保存内容不同:

论文失败后做什么成功后存什么
Reflexion写语言反思经验教训
Voyager根据错误改代码可执行技能

你做编程 Agent 时最好两个都要:

代码块TEXT · 2 行收起展开
失败 -> 反思为什么错
成功 -> 保存怎么做

8. 对你当前笔记任务的直接启发

这次任务本身就能沉淀一个技能:

代码块TEXT · 10 行收起展开
技能名:论文精读笔记生成
前置:已下载 PDF,已提取章节结构
步骤:
  1. 嵌入本地 PDF
  2. 拆 Abstract/Introduction/Method/Experiments
  3. 写工程类比
  4. 写工程落地表/伪代码
  5. 校验嵌入和本地文件
  6. 更新 history/CodexRules
验证:用户反馈不再认为浅

这就是 Voyager 思想在当前工作里的真实应用。

论文精读主线:问题-方法-验证-局限-启发

1. 核心结论

Voyager 把成功代码技能保存成可检索 Skill Library,使 Agent 在开放式环境中复用程序性记忆,而不是每次从零推理。

本篇的阅读重心是:成功经验可以沉淀为可检索、可执行、可复用的技能,而不只是文本事实。读完后要能说清它改变的是 runtime、存储、检索、更新还是评测层;否则只是记住了论文名。

2. 问题背景

开放式任务的难点不是单次解题,而是持续学习。普通文本记忆能告诉 Agent 发生过什么,却不能直接复用“怎么做”。如果成功经验不能沉淀成可执行技能,Agent 会反复试错。

把问题具体化为失败样例:Agent 每次遇到相似任务都重新推理和试错,无法把上次成功代码变成下次可调用能力。用这个样例反推论文动机,比泛泛说“上下文不够”或“记忆不准”更有判断力。

3. 核心方法

Voyager 由 automatic curriculum 产生新目标,iterative prompting 解决任务,成功后把代码封装为技能并写入库。后续遇到相似任务时检索技能,组合或改写后执行。

Skill Loop 成功经验进入技能库,失败反馈继续重试。 Curriculum Try Task Success? Save Skill Library Reuse Feedback yes no

方法部分按数据流读:任务成功后总结代码技能,生成描述和 embedding,后续任务检索相似技能并改写执行。每一步都要能标出输入、输出、控制点和失败后该记录的日志。

4. 技术细节

Skill Library 是程序性记忆。技能必须有名称、描述、代码、前置条件、使用示例和成功验证。没有执行验证的代码不能进库,否则会把失败经验固化成技能。

代码块JAVA · 15 行收起展开
final class SkillMemoryService {
    private final SkillVerifier verifier; // 只有通过环境执行或测试的代码才能保存为技能
    private final SkillIndexer indexer; // 用描述、标签、输入输出建立检索索引
    private final SkillRetriever retriever; // 按当前任务检索可复用技能,并返回适用条件
    private final SkillComposer composer; // 把多个技能组合成新解决方案,并记录来源

    MemoryResult handle(MemoryInput input) {
        // 1. 只有通过环境执行或测试的代码才能保存为技能
        // 2. 用描述、标签、输入输出建立检索索引
        // 3. 按当前任务检索可复用技能,并返回适用条件
        // 4. 把多个技能组合成新解决方案,并记录来源
        // 返回前附带 evidenceIds、scoreBreakdown、traceId,避免只看到答案看不到记忆来源。
        return MemoryResult.withTrace(input.traceId());
    }
}

字段检查重点是 skillNamedescriptionpreconditioncodetestEvidenceusageCount 是技能记忆核心。这些字段不是装饰,它们决定后续能否检索、审计、回滚、限权和做离线评测。

5. 实验验证

实验应看开放式探索能力和技能复用率。消融 automatic curriculum、skill library、iterative prompting 后如果明显下降,说明三件套都重要。还要看技能数量增长是否带来更好覆盖,而不是检索噪声。

实验阅读重点:看新任务覆盖率、技能复用率、失败技能污染率;技能库增长后还要看检索是否变慢或变噪。如果论文没有直接给出这层证据,复现时就要自己补机制级指标。

6. 局限与启发

适合可执行、可验证的环境;不适合没有明确反馈的纯聊天任务。启发是你的 Agent 可以把成功的笔记处理流程、检索流程、论文拆解流程保存为技能,但必须有验收条件。

迁移到你的项目时,结论是:你的 Agent 工程学习可以把成功流程沉淀成 skill,而不是只保存“我学过什么”的笔记。先把边界做对,再追求更复杂的模型或更大的记忆规模。

7. 关键术语表

术语在论文里的意思工程落地时要看什么
Skill library可执行技能库函数/脚本 + 描述 + 测试
Automatic curriculum自动生成逐步目标让 Agent 持续探索而非等用户给任务
Iterative prompting失败反馈驱动重试错误日志进入下一轮 prompt
Procedural memory关于怎么做的记忆可执行流程或代码

8. 复现难点

最大风险是把不可靠代码存成技能。技能检索也不能只按语义相似,还要检查环境、输入输出、依赖和权限。技能库膨胀后需要版本和淘汰。

复现入口应从失败集开始:准备一组相似但参数不同的编程任务,验证系统是否复用旧技能并通过测试,而不是复制错误代码。只有先证明旧方案会坏,才知道新机制是否真的解决了问题。

9. 代码框架建议

保存 skill(id,name,description,code,preconditions,test_result,version),检索时返回 whyMatchedrequiredInputs。执行前再次跑沙箱或单元测试。

代码验收门槛:技能入库前必须有成功证据;没有测试或可验证结果的代码只能进草稿,不进正式 skill library。这条门槛应写进测试或 trace 字段里,避免实现只停留在 demo。

10. 相关论文对比

Voyager 保存成功技能,Reflexion 保存失败教训;CoALA 会把它归入 procedural memory;Mem0 可以管理技能描述的更新,但技能执行还需要测试系统。

横向比较时抓这个角度:Voyager 存成功程序,Reflexion 存失败教训,CoALA 把它们都归入 procedural/episodic 的组合。比较对象不是谁“更先进”,而是谁负责哪一层失败。

11. 批判性思考

Voyager 的强大依赖 Minecraft 这种可执行反馈环境。迁移到学习笔记时,必须把“成功”定义清楚,例如验证 Markdown 结构、链接、标题和内容覆盖,而不是模型觉得写得好。

批判边界:技能复用可能固化旧错误;技能库越强,越需要版本、适用边界和自动回归测试。这不是否定论文,而是把论文结论放回真实系统的成本、权限和恢复约束里。