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。它需要:
- 探索环境。
- 学会采集资源。
- 合成工具。
- 完成越来越复杂的任务。
关键是它不是每次从零开始,而是把学到的技能保存下来。
方法框架与核心机制
核心结构
三个关键模块
1. Automatic Curriculum
自动决定下一步学什么。
就像游戏里先学砍树,再学做木镐,再学挖矿。
2. Skill Library
成功的代码技能会保存下来。
这就是程序性记忆:不是记住一句话,而是记住“怎么做”。
3. Iterative Prompting
失败后让模型根据错误反馈修改代码,直到成功。
为什么它也是 Memory
很多人以为 memory 只是“事实记忆”。Voyager 告诉我们还有一种记忆:
代码块收起展开
我会做什么这叫 procedural memory,程序性记忆。
例子:
- 如何运行测试。
- 如何修复某类 bug。
- 如何生成周计划。
- 如何调用某个 API。
概念校准
你刚学 Java 时,每次写文件上传都要查资料。后来你写多了,就形成“技能模板”。以后遇到类似任务,直接复用。这就是技能库记忆。
工程映射与实践启发
工程落地方案
Agent CLI 可以做一个 Skill Memory:
| 模块 | 作用 |
|---|---|
SkillExtractor | 从成功任务中提取可复用步骤 |
SkillStore | 保存技能名称、描述、代码/流程 |
SkillRetriever | 新任务检索相关技能 |
SkillExecutor | 将技能作为 prompt 或工具调用策略 |
SkillEvaluator | 验证技能是否仍有效 |
技能表:
代码块收起展开
agent_skill(id, name, description, task_type, steps, success_count, last_used_at)相关工作与方法对比
和 Reflexion 的关系
| 维度 | Voyager | Reflexion |
|---|---|---|
| 保存内容 | 成功技能/代码 | 失败后的语言反馈 |
| 记忆类型 | 程序性记忆 | 经验性反思记忆 |
| 适用 | 可重复执行任务 | 需要自我改进的任务 |
局限、对比与阅读检查
局限与边界
- 技能在环境变化后可能失效。
- 自动生成代码有安全风险。
- 技能库太大后需要检索和去重。
- Minecraft 场景和普通软件开发不完全一样。
阅读重点
- 它如何自动选择任务。
- 它如何生成和修正代码。
- 它如何保存技能。
- 它如何检索旧技能解决新任务。
- 程序性记忆和事实记忆有什么不同。
实践启发
你后续做 Agent 工程时,可以让 Agent 不只记住“用户喜欢什么”,还记住“成功做事的方法”:
- 某项目怎么启动。
- 某框架怎么测试。
- 某类 bug 怎么排查。
- 某种笔记怎么生成。
这会让 Agent 越用越顺手。
原文精读补充
1. Voyager 的三件套
Voyager 不是单纯“让 GPT 玩 Minecraft”。它的核心是三件套:
| 模块 | 作用 |
|---|---|
| Automatic Curriculum | 自动决定下一个探索目标 |
| Skill Library | 保存成功代码技能 |
| Iterative Prompting | 根据反馈修正代码 |
这三个模块组合起来,才形成“越玩越会”的效果。
2. Automatic Curriculum 怎么理解
人学游戏不会一开始打最终 Boss,而是:
代码块收起展开
砍树 -> 做工作台 -> 做木镐 -> 挖石头 -> 做石镐 -> 挖铁Automatic Curriculum 就是让 Agent 根据当前状态自动选择合适目标。它解决的是:
代码块收起展开
下一步学什么,既不要太简单,也不要太难。这对学习 Agent 很有启发:你也需要自动安排下一篇论文、下一个项目、下一段练习。
3. Skill Library 为什么是记忆
很多人把记忆理解成“记住事实”。Voyager 证明了另一类更重要的记忆:
代码块收起展开
记住如何做事。技能库里的内容通常是可执行代码或步骤。它不是“铁矿在哪里”,而是“如何挖矿并制作工具”。
4. Iterative Prompting 的闭环
Voyager 生成代码后,会在环境里执行。如果失败,就拿环境反馈继续修改。
flowchart TD
A[生成技能代码] --> B[执行]
B --> C{成功吗}
C -->|成功| D[保存技能]
C -->|失败| E[读取错误反馈]
E --> F[修改代码]
F --> B
这和编程 Agent 的测试循环几乎一样:
代码块收起展开
写代码 -> 跑测试 -> 看错误 -> 改代码 -> 测试通过 -> 保存经验5. 技能检索怎么发挥作用
当新任务出现时,Voyager 会从技能库检索相似技能,复用已有代码。
这带来两个好处:
- 不必每次从零写。
- 复杂技能可以由简单技能组合而来。
这就是“能力滚雪球”。
6. 实验怎么看
原文实验会比较探索能力、技能树解锁、获得物品数量等。你读时重点问:
- 没有 skill library 是否会重复试错。
- 没有 curriculum 是否目标选择混乱。
- 没有 feedback loop 是否代码失败率高。
- 技能是否真的能跨任务复用。
7. 工程落地提醒
你未来做 Agent 工程,不要只存事实记忆,也要存成功流程:
代码块收起展开
{
"skill": "生成论文精读笔记",
"trigger": "用户给论文列表并要求入门可读拆解",
"steps": [
"下载 PDF",
"嵌入本地原文",
"按 Abstract/Method/Experiment 拆",
"补工程落地和工程类比",
"更新 history"
],
"evidence": "本次 Agent Memory 21 篇论文笔记"
}这就是把一次成功任务沉淀成 procedural memory。
深度精读:Voyager 的记忆是“可执行技能”,不是文本事实
1. Voyager 解决的是开放式持续学习
Minecraft 环境没有固定题目列表。Agent 必须自己探索、发现目标、积累能力。这和普通问答不同:
代码块收起展开
问答 Agent:回答当前问题。
Voyager:在开放世界里持续变强。所以它需要的记忆不是“事实库”,而是“技能库”。
2. 三模块缺一不可
| 模块 | 没有它会怎样 |
|---|---|
| Automatic Curriculum | 不知道下一步该学什么 |
| Skill Library | 每次从零开始,能力不能累积 |
| Iterative Prompting | 代码失败后不会修正 |
这三个模块共同形成:
代码块收起展开
选目标 -> 写代码 -> 执行 -> 反馈 -> 修正 -> 成功后存技能 -> 下个目标复用技能3. Skill Library 为什么是程序性记忆
人类记忆分很多类。Voyager 对应的是 procedural memory:
代码块收起展开
不是“知道什么”,而是“知道怎么做”。在编程 Agent 中,程序性记忆可以是:
- 怎么启动项目。
- 怎么跑测试。
- 怎么定位某类 bug。
- 怎么生成某类笔记。
- 怎么处理 Git 冲突。
这些比事实记忆更接近“能力”。
4. 技能保存必须有成功验证
Voyager 不应该把任何生成代码都存技能库。只有执行成功的代码才值得保存。
这给工程一个原则:
代码块收起展开
技能记忆必须有验证信号。比如:
| 技能 | 验证 |
|---|---|
| 修复 bug | 测试通过 |
| 生成笔记 | 文件存在且结构合格 |
| 调用 API | 返回 200 且数据正确 |
| 数据迁移 | 校验行数/哈希一致 |
没有验证的“技能”只是模型猜测。
5. 技能检索不只是相似搜索
新任务来了,检索技能要看:
- 任务描述相似。
- 前置条件满足。
- 环境版本兼容。
- 技能成功率高。
- 最近是否还有效。
一个技能库字段可以是:
代码块收起展开
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 可以迁移到你的学习路线:
代码块收起展开
当前基础:Java 后端
目标:AI Agent 工程
下一步:不是直接啃所有模型论文,而是先做 Memory/RAG/MCP 小闭环一个学习 Agent 应该能根据:
- 你已经会什么。
- 你卡在哪里。
- 下个目标需要什么前置。
- 哪个任务最能形成闭环。
自动安排下一步。
7. Iterative Prompting 和 Reflexion 的关系
Voyager 和 Reflexion 都有试错,但保存内容不同:
| 论文 | 失败后做什么 | 成功后存什么 |
|---|---|---|
| Reflexion | 写语言反思 | 经验教训 |
| Voyager | 根据错误改代码 | 可执行技能 |
你做编程 Agent 时最好两个都要:
代码块收起展开
失败 -> 反思为什么错
成功 -> 保存怎么做8. 对你当前笔记任务的直接启发
这次任务本身就能沉淀一个技能:
代码块收起展开
技能名:论文精读笔记生成
前置:已下载 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 解决任务,成功后把代码封装为技能并写入库。后续遇到相似任务时检索技能,组合或改写后执行。
方法部分按数据流读:任务成功后总结代码技能,生成描述和 embedding,后续任务检索相似技能并改写执行。每一步都要能标出输入、输出、控制点和失败后该记录的日志。
4. 技术细节
Skill Library 是程序性记忆。技能必须有名称、描述、代码、前置条件、使用示例和成功验证。没有执行验证的代码不能进库,否则会把失败经验固化成技能。
代码块收起展开
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());
}
}字段检查重点是 skillName、description、precondition、code、testEvidence、usageCount 是技能记忆核心。这些字段不是装饰,它们决定后续能否检索、审计、回滚、限权和做离线评测。
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),检索时返回 whyMatched 和 requiredInputs。执行前再次跑沙箱或单元测试。
代码验收门槛:技能入库前必须有成功证据;没有测试或可验证结果的代码只能进草稿,不进正式 skill library。这条门槛应写进测试或 trace 字段里,避免实现只停留在 demo。
10. 相关论文对比
Voyager 保存成功技能,Reflexion 保存失败教训;CoALA 会把它归入 procedural memory;Mem0 可以管理技能描述的更新,但技能执行还需要测试系统。
横向比较时抓这个角度:Voyager 存成功程序,Reflexion 存失败教训,CoALA 把它们都归入 procedural/episodic 的组合。比较对象不是谁“更先进”,而是谁负责哪一层失败。
11. 批判性思考
Voyager 的强大依赖 Minecraft 这种可执行反馈环境。迁移到学习笔记时,必须把“成功”定义清楚,例如验证 Markdown 结构、链接、标题和内容覆盖,而不是模型觉得写得好。
批判边界:技能复用可能固化旧错误;技能库越强,越需要版本、适用边界和自动回归测试。这不是否定论文,而是把论文结论放回真实系统的成本、权限和恢复约束里。