4.1 大语言模型作为任务规划器:任务分解与技能链 大语言模型读了互联网上所有的食谱、说明书、对话,它「知道」做三明治要先拿面包。把这种常识性任务分解能力装到机器人身上,就是 LLM 作为任务规划器的起点。 4.1.1 为什么 LLM 适合做任务规划 传统机器人任务规划用符号规划(如 STRIPS、PDDL),需要人工定义: 状态空间(谓词集合) 动作集合(前置条件 + 效果) 目标条件 这种方法在小规模、封闭任务上有效,但面对开放世界(家庭、办公室)暴露致命缺陷: 状态空间爆炸:真实世界的状态无穷无尽,无法枚举。 动作定义困难:每个动作的前置/效果都要手工写。 无语义理解:无法理解「把杯子放在桌子靠窗那侧」这种自然语言指令。
大语言模型读了互联网上所有的食谱、说明书、对话,它「知道」做三明治要先拿面包。把这种常识性任务分解能力装到机器人身上,就是 LLM 作为任务规划器的起点。
传统机器人任务规划用符号规划(如 STRIPS、PDDL),需要人工定义:
这种方法在小规模、封闭任务上有效,但面对开放世界(家庭、办公室)暴露致命缺陷:
LLM 的优势恰好互补:
| 维度 | 符号规划 | LLM 规划 |
|---|---|---|
| 知识来源 | 人工编码 | 互联网语料自学 |
| 自然语言指令 | 需解析为符号 | 直接消化 |
| 开放性 | 封闭世界假设 | 开放世界 |
| 推理 | 演绎(保证正确) | 启发式(不保证正确) |
| 计算成本 | 低 | 高 |
💡 关键洞察:LLM 不是替代传统规划,而是替代「传统规划里的人工建模部分」。LLM 把自然语言任务翻译成一系列子目标,传统规划(或学习型策略)再把这些子目标落地为动作。
LLM 规划器处于最上层,承担三类工作:
下面分别讲三类典型范式。
最朴素也最直接的用法,是让 LLM 像「思考过程」一样一步步分解任务:
Prompt: 你是一个机器人助手。请把以下任务分解为子步骤: "做一杯拿铁" LLM 输出(Chain-of-Thought): 1. 走到咖啡机前 2. 把杯子放在咖啡机出水口下 3. 按下制作拿铁的按钮 4. 等待制作完成 5. 把杯子端给用户
优点:实现极简,零样本可用,LLM 直接给出步骤。
问题:
CoT 任务分解是后续所有范式的起点,但单独使用不够——必须配合技能库(4.4 节)和 affordance 评估(下面 SayCan)。
Google 2022 年的 SayCan 是 LLM 机器人规划的里程碑。它解决了 CoT 的两个问题:怎么把语言步骤变成可执行动作?怎么避免规划当前不可行的步骤?
SayCan 把每个候选动作 a 的得分定义为:
两者相乘,选出当前最优的下一步动作。然后执行,更新历史,再选下一步——贪心式的逐步规划。
⚠️ SayCan 的局限:(1) 需要预先定义的候选动作集合(不能凭空创造新动作);(2) affordance 模型需要训练数据;(3) 贪心策略可能陷入局部最优。但作为 LLM 规划的开山之作,它的「Language × Affordance」思想影响了后续无数工作。
如果说 SayCan 是「LLM 选动作」,那么 Code-as-Policies(Google 2022)就是「LLM 写代码」。它让 LLM 直接生成调用机器人 API 的 Python 代码:
Prompt: 你有一个机器人,可用 API: - goto(x, y):移动到坐标 - grasp(obj):抓取物体 - place(obj, location):放置物体 - find(obj_name):返回物体坐标 任务:把可乐罐扔进垃圾桶,把其他东西放回原位 LLM 输出(生成的 Python 代码): cokes = find("coke can") trash = find("trash can") others = find_all_except("coke can") original_positions = get_positions(others) grasp(cokes) goto(trash) release(cokes) for obj in others: goto(obj) grasp(obj) goto(original_positions[obj]) release(obj)
为了让 LLM 知道物体在哪,Code-as-Policies 把感知模型(如 CLIP、开放词汇检测)包装成 API:
def find(obj_name): # 内部调用 CLIP/Grounding-DINO 定位物体 return obj_position
LLM 在生成代码时把这些函数当作黑盒,调用即可。这是「LLM 大脑 + 感知模块」协作的典型设计。
ProgPrompt(AWS 2022)进一步系统化了「LLM 写程序」的思路,强调结构化提示:
assert has_object("cup") 在放杯动作前)。这让 LLM 的输出更可控、可验证、可恢复(assert 失败时触发重新规划)。
| 范式 | LLM 输出 | 优点 | 缺点 | 复杂度 |
|---|---|---|---|---|
| CoT 任务分解 | 自然语言步骤 | 零样本、简单 | 不可直接执行 | 极低 |
| SayCan | 选下一个动作(语言×affordance) | 闭环可行、职责分离 | 候选动作有限、贪心 | 中 |
| Code-as-Policies | 可执行 Python 代码 | 表达力强、组合性 | 代码可能错误 | 中 |
| ProgPrompt | 带约束的程序 | 可验证、可恢复 | 需要状态建模 | 中高 |
💡 选型建议:探索性场景用 SayCan(贪心安全),工程化场景用 Code-as-Policies(表达力强、可调试),高可靠性场景用 ProgPrompt(带约束可验证)。当前工业部署更倾向后两者。
LLM 规划器虽然强大,但有三个典型失败模式:
| 失败模式 | 表现 | 原因 | 缓解 |
|---|---|---|---|
| 幻觉规划 | 规划出不可能的动作 | LLM 不知道物理约束 | affordance 过滤 + 技能库约束 |
| 长程遗忘 | 任务进行到一半忘记目标 | LLM 上下文有限 | 外部记忆(4.3 节) |
| 错误累积 | 早期小错误导致后续大偏离 | 无反馈修正 | ReAct 闭环 + 反思 |
这三个问题正是第 4.3 节「记忆、反思与重新规划」要解决的。
一个值得思考的问题:既然 LLM 能规划,为什么还要第 5 章的端到端 VLA?两者关系如下:
| 维度 | LLM 规划(本章) | VLA 端到端(第 5 章) |
|---|---|---|
| 处理层 | 高层认知 | 高层 + 底层融合 |
| 输出 | 离散技能/子目标 | 连续动作 |
| 数据需求 | 少(LLM 已预训练) | 多(需大量机器人数据) |
| 泛化 | 强(语言泛化) | 取决于数据 |
| 精细操作 | 弱(依赖底层技能) | 强(端到端学动作) |
💡 当前共识:两者不互斥,而是互补。LLM 规划擅长长程语义任务("做早餐"),VLA 擅长短程精细操作("把鸡蛋翻一面")。分层架构(LLM 上层 + VLA 下层)是 2024-2026 年的主流方向,第 5 章会展开。
下一节《4.2 VLM 与场景-指令对齐》将讨论 LLM 的「眼睛」——视觉-语言模型如何把「红色杯子」这种语言指令对齐到场景中的具体物体。