一句话定位

不训练任何机器人专用模型,直接用现成的代码生成 LLM(OpenAI Codex)把自然语言指令写成一段 Python 策略代码——调用感知 API 取物体位置、调用控制 API 参数化动作、用 if/while/for 表达反应式逻辑、用 NumPy/Shapely 做空间几何推理,并能递归生成自己调用但尚未定义的函数(hierarchical code-gen),让同一套 few-shot prompt 在积木搭建、白板画图、移动机械臂厨房操作等多个真实机器人平台上零训练泛化。

背景与定位

Code as Policies(CaP)出自 Robotics at Google(Jacky Liang、Wenlong Huang、Fei Xia、Peng Xu、Karol Hausman、Brian Ichter、Pete Florence、Andy Zeng),2022-09 首发 arXiv,2023 中 ICRA 收录。它直接承接同组的 saycan:SayCan 用 LLM 打分选一个预训练好的固定技能(“pick up the can”),CaP 则让 LLM 直接生成代码去操作感知输出和控制原语,因此不再受限于一个预先枚举的技能集合——同样是”移动可乐罐往右一点”,SayCan 只能挑一个”移动物体”技能去执行,CaP 能直接写出带反馈循环的位置计算代码(while not obj_in_gripper(...): ...),把规划、策略逻辑和控制三层用一段程序捏合在一起。

它也与同期 Huang et al.《Language Models as Zero-Shot Planners》(纯 prompt 出计划、无世界落地)、Socratic Models(视觉语言模型把感知代入 prompt 再出计划)、Inner Monologue(引入成功检测器闭环重规划)同属”LLM + 现成感知/控制模块、零训练做机器人”这一脉络,但落地方式不同:前三者输出自然语言计划再映射到固定技能,CaP 输出可执行代码,因而能表达精确数值(“快一点”→具体速度)、条件分支和循环这些语言计划无法直接表达的东西。CaP 的方法论(LMP:language model program,即语言模型生成、在真实系统上执行的程序)后续影响了机器人领域”用代码做接口”这一支路线。

模型架构

CaP 不是一个训练出来的网络,而是”现成代码生成 LLM + 一组感知/控制 API + 递归代码生成机制”的系统性方法。

  • 语言模型:默认用 OpenAI Codex code-davinci-002,温度设为 0(确定性贪心解码)。RoboCodeGen 消融额外测试了 GPT-3 6.7B、InstructGPT 175B、Codex cushman(更小)与 davinci(更大,两个 Codex 模型的具体参数量未公开)。
  • Language Model Program (LMP):论文提出的核心抽象——任何由语言模型生成、直接在系统上执行的程序。Prompt 由两部分组成:Hints(import 语句,告知有哪些可用 API 及类型提示)+ Examples(指令-代码 few-shot 示例对,指令写成注释)。输入新指令(同样格式为注释)后模型续写代码。
  • 执行沙箱:生成代码先做安全检查(无 import 语句、无 __ 开头的特殊变量、不调用 exec/eval),再用 Python exec() 执行,传入两个字典作用域:globals(预置全部可调用 API)和 locals(执行期间填充的新变量/新函数)。若 LMP 需要返回值,从 locals 里取。
  • 多 LMP 组合架构(以 tabletop 域为例,四个 LMP 协同):(i) High-Level LMP——解析用户指令、维护多轮会话、调用动作 API;(ii) Parse Object Names——把语言描述(“the bowls”、“sea-colored block”、“the other block”)解析成具体物体名;(iii) Parse Positions / Parse Waypoints——把语言描述解析成坐标或轨迹点;(iv) Function Generation LMP——专门负责补写未定义函数。不同任务域(画图、移动导航)复用相同框架,只替换动作原语相关的 prompt。
  • 层级代码生成(Hierarchical code-gen):解析生成代码的抽象语法树,定位其中调用但尚未定义的函数,用专门的 Function Generation LMP 补写这些函数并加入作用域;该过程在新生成的函数体内递归执行(深度优先)。效果上相当于借”显式变量命名”实现的一种 functional-programming 版思维链——prompt 不需要把全部实现细节铺平(flatten),只给”代码逻辑草图”即可。
  • 感知 API:不同实验域接入不同开放词表检测器——桌面/移动机械臂用 MDETR(modulated detection)取物体位置与包围盒,或 ViLD(open-vocabulary object detection)。这些是现成的第三方感知模型,CaP 本身不训练感知。
  • 动作/控制 API:随机器人平台不同而不同——UR5e 机械臂用末端轨迹跟随 API(画图域)或抓取放置脚本原语 pick_place(桌面操作域,吸盘夹爪+腕部 Intel RealSense D435);移动机械臂(Everyday Robots 平台)用导航到指定位置、按名称/坐标抓取的 API。CaP 论文强调这是”在感知-控制分解式系统里、特定一层的泛化”,不改变底层控制器本身。

数据

CaP 不需要任何针对机器人的训练数据——这是它区别于 rt-1saycan 等需要示范数据训练底层策略/价值函数工作的核心特征。所谓”数据”仅体现在两处:

  • Few-shot prompt 示例:每个 LMP 的 prompt 由人工撰写少量指令-代码对(数量因 LMP 而异,论文未给统一计数,Appendix 收录了各域完整 prompt),用来教会 LLM 该 API 的调用惯例、变量命名风格。
  • RoboCodeGen 基准:论文新构造的 37 道函数生成题(评测用,非训练数据),覆盖空间推理(找点集里最近的点)、几何推理(一个包围盒是否被另一个包含)、控制(PD 控制);允许并鼓励用第三方库(如 NumPy);给出的函数签名不带 docstring、不带类型提示(要求模型靠命名惯例推断语义);允许调用尚未定义的函数(考察 hierarchical code-gen)。
  • LLM 本身用的预训练语料(Codex 训练用的公开代码语料、GPT-3/InstructGPT 训练语料)是现成的,论文未涉及、也不重新披露其规模或配比。

训练方法

CaP 不训练任何新模型,全部能力来自现成 LLM 的 few-shot in-context learning,“训练方法”实质是prompt 工程 + 系统设计

  • Prompt 组成:Hints(import 语句 + 类型提示)+ Examples(指令注释 + 对应代码,few-shot)。可维护 LMP 会话(session)——增量地把新指令和响应追加进 prompt,使后续指令能引用先前上下文(如”undo the last action”)。
  • 递归函数生成:解析生成代码的 AST,找出调用了但未在当前作用域定义的函数名,交给专门的 Function-Generation LMP 写出函数体(同样通过 few-shot prompting,无需训练),并将新函数并入作用域供后续代码调用;该过程对新函数体递归展开。
  • LMP 组合方式:既可以嵌套函数调用(parse_obj 被 High-Level LMP 调用,各自维护独立 prompt 与作用域,避免单个 prompt 塞进所有 few-shot 示例而超出 token 限制),也可以在同一层用控制流(if/else、while/for)表达反应式策略。
  • 关键超参:Codex 解码温度=0(确定性贪心);RoboCodeGen/HumanEval 的 P@N 指标额外在 temperature=0.8 下采样评测生成多样性(P@10、P@100)。

Infra(训练 / 推理工程)

  • 无训练,无 GPU 集群——全部推理走 OpenAI API 远程调用(Codex code-davinci-002 等),本地只做安全检查 + exec() 执行 + 机器人控制接口对接。
  • 论文明确提到:真机视频演示里”命令和响应之间的长暂停主要由 OpenAI API 查询耗时和限流导致”,说明系统未做实时性优化,推理延迟、控制频率 Hz、端到端时延均未披露
  • 真机平台:UR5e 机械臂(画图域、桌面操作域,吸盘夹爪 + 腕部 Intel RealSense D435);Everyday Robots 移动机械臂(7-DoF 手臂,导航+抓取域)。感知侧接入现成的 MDETR / ViLD 检测器(推理算力未披露,视为外部服务)。

评测 benchmark

RoboCodeGen(论文新提出的机器人主题代码生成基准,37 题,% pass rate):

方法GPT-3 6.7BInstructGPT 175BCodex cushmanCodex davinci
Flat3685481
Hierarchical5845795

层级代码生成在四个模型上全面优于扁平生成;模型越大表现越好(符合 scaling law);层级生成对”Productivity”这一类泛化(需要比示例更长/更多逻辑层的代码)改善最明显,但这一改善只在两个 davinci 级模型上出现,cushman 上没有,说明层级代码生成要建立在模型已具备一定代码生成能力之上才有增益。

HumanEval(通用代码生成基准,非机器人专用):

方法GreedyP@1P@10P@100
Flat45.734.975.190.9
Hierarchical53.039.880.695.7

层级代码生成把 HumanEval P@1 从 34.9% 提到 39.8%(论文称高于同期 Codex/GPT-3 相关工作报告的数字),证明该方法对通用代码生成同样有效,不只是机器人场景专用技巧。

桌面操作仿真评测(沿用 saycan/Inner Monologue 同款环境:UR5e + Robotiq 2F85 + 10 色积木 + 10 色碗;8 个继承的长程任务 + 6 个新增的空间几何任务;50 trials/task):

Train/Test任务族CLIPortNL PlannerCaP(本文)
SA SILong-Horizon78.8086.4097.20
SA SISpatial-Geometric97.33N/A89.30
UA SILong-Horizon36.8088.0097.60
UA SISpatial-Geometric0.00N/A73.33
UA UILong-Horizon0.0064.0080.00
UA UISpatial-Geometric0.01N/A62.00

(SA/UA = seen/unseen attributes,SI/UI = seen/unseen instructions;CLIPort 为在 3万条示范上有监督训练的基线,NL Planner 为纯自然语言 few-shot 规划器基线,不涉及代码/精确数值,故 Spatial-Geometric 任务无 N/A 之外的结果。)在 seen 设定下 CaP 已能与有监督训练的 CLIPort 相竞争;一旦切到 unseen attributes/instructions,CLIPort 性能骤降至 0% 附近,CaP 保持在 60-97% 区间,且 NL Planner 完全无法处理需要精确数值空间推理的任务。

代码推理 vs 自然语言推理(Appendix C,物体选择 28 题 + 位置选择 23 题,坐标误差需在 1cm 内才算对):

方法物体选择位置选择总计
Vanilla NL393035
Chain-of-Thought684858
LMP(代码,本文)9610098

用代码做空间几何推理(LMP)显著优于直接自然语言问答(Vanilla)和思维链(CoT):CoT 能处理相对关系但在精确多步数值计算上仍会出错,而 LMP 直接用 Python(借助 NumPy 等库)做计算,准确率达到 96-100%。

真实机器人域(画图、桌面操作、移动机械臂厨房导航+操作)仅做定性演示,论文明确说明”由于开放式任务难以评测、且缺乏可比基线,量化评测局限于表 III 这组仿真任务”。

创新点与影响

  1. 把”用 LLM 选技能”升级为”用 LLM 写代码”:从 SayCan 式的固定技能打分选择,跳到直接生成可执行策略代码,突破了预定义技能集合对表达力的限制,能处理”再快一点""往左挪一点”这类需要精确数值参数化、而非离散技能切换的指令。
  2. 层级代码生成(hierarchical code-gen):递归补写未定义函数,既提升机器人代码生成正确率(RoboCodeGen),也提升通用代码生成正确率(HumanEval pass@1 到 39.8%),说明这一 prompt 技巧的收益不局限于机器人领域。
  3. 提出 RoboCodeGen 基准:填补”机器人主题代码生成评测”的空白,供后续 LLM 在这一细分领域对比。
  4. 零训练、多平台复用:同一套方法在桌面机械臂、白板画图、移动机械臂厨房场景复用,只需替换 Hints/Examples 里的 API 定义,不需要重新采集数据或训练模型。
  5. 跨具身(cross-embodiment)表达潜力:同一指令在不同机器人(不同可用 API)下可生成不同但语义等价的代码,论文认为这对机器人基础模型是重要属性,但也承认”以现有 LLM 而言这一能力较脆弱,可能需要更大、专门在领域代码上训练的模型”。

作者自陈局限:① CaP 的泛化被”感知 API 能描述什么”和”有哪些控制原语可用”这两层卡死——例如当前视觉语言模型无法描述轨迹”颠簸”或”更像 C 形”;② 能塞进 prompt 的具名控制参数数量有限,塞太多会 prompt 过载;③ 无法处理明显超出 Examples 抽象层级或复杂度的指令(如桌面积木域里让 LMP “用积木搭一栋房子”,因为没有搭建复杂 3D 结构的示例);④ 假设所有给定指令都可行,无法先验判断生成代码是否会成功;⑤ 官方博客额外指出安全风险——生成程序若未逐次人工检查,在物理硬件上可能产生意外行为,需要靠限定控制原语访问范围等内建安全检查来缓解,但新的原语组合方式是否同样安全仍需更多工作。

原始链接

一手源存档(sources/)

  • code-as-policies—blog — Google Research 官方博客快照(方法概述、RoboCodeGen 图示说明、限制、开源发布说明、安全风险讨论)
  • code-as-policies—project-page — code-as-policies.github.io 项目页快照(ICRA 2023、六大真机演示域指令列表、引用信息、各域 prompt 文件链接)
  • code-as-policies—github-readme — 开源 Colab 集合 README 快照
  • arXiv 原文 PDF(2209.07753,含 Appendix A-M:prompt 工程细节、代码执行安全检查、各域完整 prompt、多语言/emoji 案例、跨具身案例、cartpole/阻抗控制补充实验)——arXiv 原文 PDF,不入 git,见上方 PDF 链接