4.3 记忆、反思与重新规划:长程任务的闭环执行 机器人执行长程任务时一定会出错——杯子滑了、抽屉卡了、用户改主意了。区别优秀机器人与傻瓜机器人的,是出错后能否反思、纠偏、重新规划。 4.3.1 为什么开环规划必然失败 如果 LLM 规划器一次性生成完整动作链,然后机器人逐条执行不再修正,这就是开环规划。开环规划在真实世界几乎必然失败,原因有三: 失败原因 | 例子 | 后果 执行不确定性 | 抓杯子时滑了 | 后续「放下杯子」无意义 环境变化 | 用户中途移动了目标 | 整条规划作废 规划错误 | LLM 误判物体位置 | 执行不可能动作 💡 核心结论:真实世界的机器人必须是闭环规划——边执行边观测,根据反馈调整后续规划。这与第 1.
机器人执行长程任务时一定会出错——杯子滑了、抽屉卡了、用户改主意了。区别优秀机器人与傻瓜机器人的,是出错后能否反思、纠偏、重新规划。
如果 LLM 规划器一次性生成完整动作链,然后机器人逐条执行不再修正,这就是开环规划。开环规划在真实世界几乎必然失败,原因有三:
| 失败原因 | 例子 | 后果 |
|---|---|---|
| 执行不确定性 | 抓杯子时滑了 | 后续「放下杯子」无意义 |
| 环境变化 | 用户中途移动了目标 | 整条规划作废 |
| 规划错误 | LLM 误判物体位置 | 执行不可能动作 |
💡 核心结论:真实世界的机器人必须是闭环规划——边执行边观测,根据反馈调整后续规划。这与第 1.2 节「感知-决策-执行闭环」是同一个原则在规划层的体现。
闭环规划需要三个新组件:
下面分别讨论。
LLM 只能消化文本(或视觉 token),不能直接读传感器。观测提取(Observation Extraction) 把原始观测转为结构化状态描述:
| 原始数据 | 提取后 | 工具 |
|---|---|---|
| RGB 图像 | 「桌上有一个红色杯子和一个蓝色盘子」 | VLM 字幕 |
| 点云 | 「杯子在 (1.2, 0.5, 0.8)」 | 物体检测 + 3D 定位 |
| 关节角 | 「机械臂在 home 位置」 | 状态机描述 |
| 力觉 | 「末端接触力 5N,向下」 | 力阈值描述 |
| 历史动作 | 「已执行:抓杯子、移动到桌前」 | 行动日志 |
关键设计:观测描述要简洁而信息完整。太详细 LLM 抓不住重点,太简略 LLM 失去决策依据。一个常用模板:
当前状态: - 机器人位置: 厨房入口 - 桌上物体: 红色杯子(1.2, 0.5, 0.8), 蓝色盘子(1.5, 0.5, 0.8) - 机器人手中: 空 - 已完成步骤: 1.走到桌前 2.抓杯子(失败) - 当前子目标: 抓杯子
⚠️ 常见坑:观测描述里漏掉关键信息(比如没说杯子是否装了水),LLM 会做出错误规划。结构化状态模板要经过仔细设计,反复测试。
ReAct(Yao et al. 2022)是 LLM 闭环执行的经典范式,名字来自 Reasoning + Acting。它让 LLM 在每一步交替输出「思考」和「行动」,并接收「观察」:
任务: 把红色杯子端到厨房 [Thought 1] 我需要先找到红色杯子的位置。 [Action 1] find("red cup") [Observation 1] Red cup found at (1.2, 0.5, 0.8) [Thought 2] 杯子在桌上,我需要先走过去再抓。 [Action 2] goto(1.2, 0.5) [Observation 2] Robot at (1.2, 0.5) [Thought 3] 现在抓杯子。 [Action 3] grasp("red cup") [Observation 3] Grasp failed: cup slipped [Thought 4] 杯子滑了。我刚才抓得太靠上,应该抓杯子下部更稳。重试。 [Action 4] grasp_lower("red cup") [Observation 4] Grasp succeeded [Thought 5] 抓住了。现在走到厨房。 [Action 5] goto("kitchen") ...
ReAct 后来被广泛用于工具调用 Agent、机器人和自动化办公,是 LLM Agent 的基础范式。
Reflexion(Shinn et al. 2023)在 ReAct 基础上增加自我反思——失败后让 LLM 写一段「反思记忆」,存入上下文,避免重复犯错:
任务: 把红色杯子端到厨房 [Episode 1 - 失败] ... 抓杯子失败 ... [Self-Reflection] 我刚才抓杯子失败,因为抓得太靠杯口,导致杯子滑落。 下次应该抓杯子中部或下部,那里更稳。 记忆: 抓杯子要避开杯口,抓中下部。 [Episode 2 - 应用反思] ... 应用上次记忆 ... [Thought] 根据之前的经验,我应抓杯子中下部。 [Action] grasp_middle("red cup") [Observation] 成功 任务完成。
| 维度 | ReAct | Reflexion |
|---|---|---|
| 反思 | 单次 Thought | 跨 Episode 的反思记忆 |
| 学习 | 不学习 | 用自然语言记忆从失败中学习 |
| 适用 | 单次任务 | 多次尝试的复杂任务 |
| 上下文 | 当前任务 | 当前任务 + 反思记忆 |
💡 深刻意义:Reflexion 把「经验学习」引入 LLM Agent——LLM 通过语言反思从自己的失败中学习,类似人类的「复盘」。这种思路后来延伸到机器人:让机器人在多次任务尝试中积累「经验笔记」,提升长期表现。
ReAct 和 Reflexion 都依赖 LLM 的上下文窗口。但 LLM 上下文有限(即便 200K token 也装不下数小时任务的所有历史),长程任务需要外部记忆架构:
| 记忆类型 | 内容 | 实现方式 | 类比人类 |
|---|---|---|---|
| 工作记忆 | 当前状态 + 最近 N 步 | LLM 上下文窗口 | 短时记忆 |
| 情节记忆 | 本次任务完整历史 | 向量数据库检索 | 情节记忆 |
| 语义记忆 | 跨任务的常识、技能、反思笔记 | 知识图谱 / 文档库 | 知识记忆 |
| 程序记忆 | 技能执行代码 | 技能库(4.4 节) | 运动技能 |
情节记忆常用向量数据库(如 Chroma、Pinecone)+ 检索增强生成(RAG):
这是把「经验」变成机器人可调用的资源,是从零样本向少样本过渡的关键技术。
闭环规划的前提是知道是否出错。错误检测分三层:
| 层次 | 信号 | 检测方法 |
|---|---|---|
| 执行层 | 关节超限、力突变、超时 | 阈值规则 |
| 任务层 | 物体没抓起来、目标未达成 | VLM 验证 |
| 语义层 | 用户意图未满足 | LLM 推理判断 |
「抓杯子」是否成功?让 VLM 检查:
VLM 输入: 抓后的图像 + 问题 "Is the robot holding a cup?" VLM 输出: "Yes" 或 "No"
这是把 VLM 当作成功检测器,比传统力阈值鲁棒得多(因为不同物体重量、材质差异大)。
「把鸡蛋打到碗里」可能鸡蛋破了、可能没打到、可能打了一半——成功与否是连续的,不是二值。处理这种部分成功需要:
出错后如何重新规划?四种典型策略:
| 策略 | 思路 | 适用 |
|---|---|---|
| 重试 | 同一动作重试 N 次 | 偶然失败(抓滑了) |
| 微调 | 调整参数(更慢、力更大) | 参数不合适 |
| 替代 | 换一个等价动作 | 工具失效 |
| 回退 | 回到上一个稳定状态,重规划 | 大偏离 |
| 求助 | 报告失败,请求人类介入 | 无解情况 |
⚠️ 设计原则:重新规划要遵循「最小变更」——能局部修就别整体重做。整体重规划不仅耗时,还可能丢失已完成的进度,让任务不可收敛。
闭环执行有两种架构哲学:
把任务建模为状态机,每个状态有明确转移条件。LLM 只在关键决策点介入。
LLM 完全自主决定下一步,无预定义状态。
这是当前工业部署的主流架构——既享受 LLM 的灵活性,又有状态机的可控性兜底。
| 挑战 | 描述 | 当前进展 |
|---|---|---|
| 长程记忆 | 几小时任务的记忆管理 | 长上下文 LLM + RAG |
| 错误归因 | 准确诊断失败原因 | VLM 验证 + 因果推理 |
| 多步反思 | 避免反思振荡 | 约束反思次数 + 早停 |
| 代价权衡 | 反思重规划的延迟成本 | 关键步骤才反思 |
| 跨任务迁移 | 把经验迁移到新任务 | 语义记忆 + 跨任务学习 |
💡 趋势:当前研究方向是「世界模型引导的反思」——机器人不仅记录「我失败了」,还用世界模型预测「如果我当时换一种方式,结果会怎样」。这种反事实推理让反思更深入,第 8.4 节会展开。
下一节《4.4 技能库与工具调用》将讨论 LLM 规划器的「手」——抽象指令如何变成可执行动作。