ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

REFACTOR-VLA:无监督类型化运动程序库如何重构机器人动作生成

REFACTOR-VLA:无监督类型化运动程序库如何重构机器人动作生成 这次我们先看 Apple 公开的 REFACTOR-VLA。项目名很长拆开其实好理解REFACTOR VLA。“VLA” 在机器人方向通常指 Vision-Language-Action也就是视觉、语言、动作三条信息流一起建模的大模型“REFACTOR” 在这里更接近“重构运动表达”的意思。它真正想做的事情是把零散的、随时序变化的动作数据重构为一个“类型化运动程序库”并且让库的形成尽量不依赖人工标注。先说结论这个方向的价值不在“又做了一个大号动作生成网络”而在它对运动数据的表达做了分层。常见做法是让模型在视觉特征、语言描述和动作序列之间做端到端映射结果往往是换一个场景、换一个物体朝向就失效。REFACTOR-VLA 这类思路强调先形成一套稳定、可复用、有类型约束的动作原语集再由模型去检索、组合、调度。这篇文章会按“怎么看懂它”而不是“照着跑 demo”来展开。因为公开信息更偏向框架和方法验证直接给出完整一键包或精确显存占用反而不严谨。我会说明项目核心能力、类型化运动库和价值无监督学习的切入点、与主流 VLA 方法的区别、复用和验证时可以设计的实验以及容易踩的坑。如果你是做机器人决策、运动生成、具身智能或多模态控制方向这篇文章可以直接收藏。1. REFACTOR-VLA 核心能力速览下面用表格先建立一个整体判断。部分字段受公开材料限制我会明确写“需按实际发布说明确认”不做无依据推测。能力项说明项目类型视觉-语言-动作VLA研究型框架重点在运动程序表达发布方Apple 公开研究与工程方向的工作核心关键词REFACTOR-VLA、无监督学习、类型化运动程序库主要解决把杂散动作轨迹重构为类型化运动程序提高复用性和组合性关键输入视觉观测、语言任务描述、本体感觉/运动轨迹核心输出对运动程序库的检索、调用、执行或直接输出类型化行动计划训练方式包含无监督学习机制目标是减少对人工动作标签的依赖硬件门槛训练端通常需要较高级别 GPU 或集群推理端需按最终模型规模测试显存占用未给到可复用的固定数字需要以模型版本和输入分辨率为准启动方式当前更像研究方案是否有完整一键启动有待官方说明接口 API没有统一公开说明建议以发布仓库或论文代码为准批量任务适配批处理但对象不是“视频素材批处理”而是运动程序批量评估最适合的场景具身智能策略预训练、机器人操作原语抽取、可控动作生成、技能库构建重点要区分一点这里说的“程序库”不是传统软件开发里pip install下来的包而是把“拿起杯子”“把物体放平”“绕开障碍”这类运动用类似函数签名和前后置条件的结构化方式表示起来。库是模型内或模型外的一个运动资产集类型化则给每一项动作补充约束比如需要什么起始状态、结束会改变什么状态、轨迹需要满足什么限制。从训练与推理的视角看这是一个比较重的框架。如果你只有一张消费级显卡想直接从头训练是不可能的更合理的方式是使用预训练模型做只读推理或者用小规模数据做运动库热启动。这个项目更适合团队预研和高校实验室复现而不是个人电脑上的“即装即用”工具。2. 为什么需要类型化运动程序库很多端到端模型的问题不是生成能力弱而是运动语义不稳定。你输入“把杯子拿到桌面”模型能输出一条轨迹换一个杯子颜色或者换一个桌面高度同样一句话可能指向完全不同的轨迹模式。原因是模型没有一个内部抽象层它一直在字符、图像特征、关节坐标之间走短路。类型化运动程序库就是要补上这一层抽象。它把运动拆成“可调用的程序”每个程序带类型信息。例如# 概念示意不代表 REFACTOR-VLA 的真实 API def pick_and_place( object_id: str, start_pose: Pose, target_pose: Pose, gripper_policy: str vertical, ) - MotionProgram: 返回一段可执行的运动程序而不是直接输出末端轨迹点。这段代码看着简单含义却不小。“类型信息”让策略知道pick_and_place需要哪些输入、会改变什么世界状态。模型不再是自由造句它需要在已知程序库里做选择再把具体参数填进去。输出也随之变成两段结构程序调用 参数列表。从工程角度看这是把连续动作控制问题部分转成离散程序调用问题。离散调用的好处是更容易验证。执行完一段程序我们检查起始姿态是否符合前置条件、结束姿态是否满足后置条件。如果不符合就可以判定失败并回滚。无监督学习和类型化程序库放一起还解决了一个数据矛盾。真实动作数据里没有统一标签“把物体放好”在不同人看来可能是不同的动作序列。与其用人工标准去强行统一还不如用运动本身的状态变化自动归类。REFACTOR-VLA 真正让人觉得有延展性的一点就在这里它不要求人类事先定义好每一个动作的教科书标签而是让算法从海量轨迹里发现“有哪些可复用的运动程序”再做类型抽象。这样可以缓解标签不一致、动作长尾、场景跨域问题让模型学到更稳定的运动词汇表。3. “无监督 类型化”的关键设计拆解“无监督学习”在这个项目里不是指完全不看任何标签而是指运动程序的类型发现过程可以自动完成。要理解这一点可以把它解成三个层次。第一层是运动分割。输入是一段连续的动作序列比如机器人从抓取到转移再到放下的完整轨迹。算法需要自动切分出若干子段段与段之间存在明显的状态变化。状态变化不一定是语言可以描述的它可能表现为力的变化、物体相对位置变化、速度曲线突变。第二层是程序归纳。切分后的每个子段被归纳成一个候选运动程序候选程序带着可观察的前置状态和后置状态。这里不需要人告诉它“这段叫拿取”只需要确认这段运动开始前世界是什么状态结束后世界变成什么状态。第三层是类型合并。多个候选程序如果满足相同或近似的前后置条件在运动约束上可以归并就合并为同一个类型化程序。这个过程类似我们做代码重构时把重复逻辑提炼成公共函数。3.1 用无监督信号代替人工标签可以这样比喻传统训练要告诉模型“这是抓取动作”无监督方法更倾向于让模型自己发现“一系列视频都包含同一类状态转移物体从不接触变成接触”。状态转移比语义词更稳定。因为“抓”这个词在不同语境下可以对应不同物理过程而“接触点形成、重力转移、物体位置改变”这个模式更通用。无监督学习的核心难点也在这里如何定义什么是重要的运动状态。如果只用关节速度做聚类很容易把噪声当成动作边界。更稳妥的做法是多模态信号结合比如视觉帧差、物体位姿、接触状态、力的变化一起构成状态描述子再对状态描述子做边界检测。3.2 程序库的类型系统设计类型系统决定了这个库能覆盖多少动作、泛化能力有多强。类型定义太细库会爆炸难以检索类型定义太粗库虽然小但每一步都需要在线微调适应又失去复用意义。合理的做法是做分层类型。最底层是物理原语比如“移动关节”“施加力”“夹取”中间层是任务原语比如“抓取物体”“放稳物体”“旋转到目标角度”高层是复合程序比如“把零件从 A 处组装到 B 处”它内部会调度多个中间层原语。每一层都要有类型签名约束输入输出。这样模型在遇到新任务时不需要从零生成轨迹而是先在高层程序里搜索合适的组合再逐层向下实例化。整个过程很像“程序合成 轨迹优化”的混合体。4. REFACTOR-VLA 与常见 VLA 的区别主流的 VLA 做法是输入视觉 token 和语言 token经过多模态 Transformer直接回归出动作 token。这种方式表达能力强但动作空间是连续的语义空间和动作空间之间没有中间表示。模型像一个巨大的查表函数输入变了输出轨迹往往整体漂移。REFACTOR-VLA 的潜在改动在于动作空间设计。它把动作从“连续坐标序列”提升为“离散程序调用”。我们可以用下面的表做对照维度常规 VLA 方法REFACTOR-VLA 风格设计动作粒度帧级动作或短轨迹运动程序级调用表达结构视觉特征直接映射到动作视觉特征先映射到程序槽位泛化方式依靠训练数据覆盖依靠程序库组合复用对数据标注依赖较高句子要对应动作运动类型可通过无监督发现验证难度难只能看执行结果相对容易可检查前后置状态训练成本极高程序归纳阶段成本高下游策略可更轻这个对比能解释为什么“类型化运动程序库”不是锦上添花。程序库相当于给模型一个候选动作集合。模型的任务变成“判断当前场景匹配哪个程序签名”而不是在几乎没有约束的连续空间里猜。这种设计的代价也很明显。第一程序库以外的动作很难被处理第二类型归纳一旦不准会放大执行误差第三程序检索本身就是新的长尾问题库太大时检索延迟和质量都会下降。所以严格说它不是要替代所有 VLA而是在探索一条更模块化、更可解释的路线。5. 这个方向适合解决什么问题把 REFACTOR-VLA 放在实际业务场景里最有价值的是以下四类问题。第一机器人操作技能复用。仓库里的场景是抓取、移动、放置但物体的形状、位置、环境光照不断变化。只要运动库能把“抓取圆柱体”“放置到托盘”这类任务原语抽象出来模型每到一个新点位只需要更新抓取参数而不需要重新学习整条动作链。第二数字人和可控运动生成。游戏动画、影视预演、工业仿真里经常要求角色执行动作。程序化的运动库可以给动画生成提供更多约束防止生成出不符合物理规律的姿态。第三高风险任务中的动作验证。医疗、精密装配这类场景要求动作可解释、可审计不能接受策略自己“编”轨迹。类型签名允许我们在执行前做静态检查在执行后做状态核对这对合规部署非常关键。第四多设备迁移。不同机器人本体结构不同但高层任务语义相似。只要运动库把“抓取”定义为接触点与夹持方向的状态变化新机械臂可以复用同一个高层程序再通过底层的运动学适配完成迁移。反过来看不适合的情况也很清楚。如果任务本身非常简单只有固定几个动作不需要复杂的运动抽象如果任务极其开放动作空间难以枚举强制类型化反而会限制灵活性。REFACTOR-VLA 更适合中等复杂度、重复度高、要求可解释的连续任务不适合完全自由式的动作探索。6. 功能验证与实验设计建议由于当前没有可以直接下载的一键包说明我们就按“方法复现和效果验证”的思路来设计实验。建议按下面几个模块推进。6.1 先验证无监督运动分割准备数据可以是机器人操作视频也可以是动捕数据。用一个较小规模的子集跑运动分割判断能不能把“伸手、抓取、拿起、移动、放下”这类流程自动切成若干段。没有明显边界时要检查是否缺少视觉以外的状态信号。# 伪代码验证一段轨迹是否具备运动类型边界 from typing import List def detect_segments(states: List[State]) - List[Segment]: segments [] previous_state states[0] start_index 0 for idx, state in enumerate(states[1:], start1): delta state.key_signal() - previous_state.key_signal() if abs(delta) threshold: segments.append(Segment(startstart_index, endidx)) start_index idx previous_state state if start_index len(states) - 1: segments.append(Segment(startstart_index, endlen(states) - 1)) return segments上面只是一个判断逻辑示例。真实项目要接入状态估计、滤波和多模态融合不是直接看单个差值。6.2 验证程序库的复用性把运动库固定住然后做两个级别的测试同域复用、跨域迁移。同域复用指同样的机器人在新物体上能否完成任务跨域迁移指不同机械结构或场景能否完成任务。评估时可以建立下面的 JSON 描述文件把任务参数和期望状态分离{ task: pick_and_place, instances: [ { scene: desk_small, object: mug_red, start_pose: { x: 0.2, y: 0.1, z: 0.0 }, target_pose: { x: 0.5, y: 0.4, z: 0.1 } }, { scene: shelf_high, object: box_blue, start_pose: { x: 0.3, y: 0.2, z: 0.3 }, target_pose: { x: 0.1, y: 0.8, z: 0.6 } } ] }这种文件的好处是可以批量跑任务。每完成一次任务判断起止状态是否满足类型签名要求然后把成功率记到同一个 csv 或 jsonl 里。判断标准不能只看末端是否到达目标还要看是否所有程序的前置条件都被满足。6.3 对比实验要怎么做对比对象不是“能不能生成像不像”而是“在未见场景下单位训练数据的成功率”。同时记录三类指标执行成功率、平均任务耗时、程序库命中率。程序库命中率最有代表性。它统计的是面对新任务时模型能不能在已有程序库里找到正确的候选程序。如果命中率低说明库的抽象还不够完善如果命中率高但执行失败率高说明程序内部的参数化或者底层轨迹优化还需要调整。6.4 一个最低成本的最小验证在没有整条机器人流水线的条件下可以先做一个简化版验证把输入限制为“状态序列 目标状态”。目标是看模型能不能从状态序列中学习到“状态 A 到状态 B 的转换规律”并在新的状态组合上复用。这一步能在普通 Python 环境里实现不涉及真实机器人也有助于把问题定位在程序归纳层面。整体验证逻辑是先选一个运动类型库小一点场景数量少一点手动检查结果确认能跑通后再增加类型数量再加大场景差异。不要一开始就追求大规模通用性容易把类型归纳和轨迹控制的问题混在一起排错成本很高。7. 资源占用与性能观察方法端到端 VLA 通常很吃显存因为输入包含图像、文本和长序列动作。REFACTOR-VLA 这类方法如果按训练阶段看视觉编码器和策略网络都会消耗大量显存如果只做推理和调用显存占用会明显下降。实际占用取决于图像分辨率、上下文长度、运动序列长度和 Transformer 层数。观察性能时可以关注五件事。第一推理是否做成两步先做程序检索再执行动作。如果两步分离第一步的低命中率会浪费大量算力因为检索失败后要重新生成或在线搜索程序。第二运动库规模。库越大检索阶段需要遍历的候选越多。可以用向量索引对程序缓存做加速把文本和状态描述投影到同一个 embedding 空间排序时只需要算一次相似度。第三是否使用缓存。一次任务中同一段程序往往要被调用多次比如“拿起”和“放下”。把程序实例的求值结果缓存起来可以显著降低重复计算。第四避免程序级别的重复生成。每次被执行失败后都重新调用大模型做全局搜索会很慢。更稳的方式是先缩小候选范围再在候选程序内做参数修正。第五小批量并行。如果你的部署环境是为了评测而不是实机实时控制可以并行评估多个运动程序但要注意不要同时执行多个强交互物理任务否则会相互干扰。要拿到准确显存占用最好的办法不是参考别人的显卡数据而是用nvidia-smi和 PyTorch Profiler 记录。先固定住 batch size、图像尺度和序列长度再逐项改变变量。你会发现尺度对显存的影响往往超过模型参数本身。8. 常见问题与排查方法下面这套排查表更多是工程层面的建议用来帮助做“无监督运动类型化 程序库调度”实验的人避开常见坑。问题现象可能原因排查方式解决方案运动分割把所有片段切成一段没有区分目标物体与机械臂的状态检查状态信号是否包含物体级变化加入接触、力或物体位姿特征两个完全不同语义的动作被合并成同一类型只用了关节运动特征缺少视觉场景表征对比不同类型视频的状态转移增加视觉特征和语义特征做联合判断程序库命中率低类型粒度偏大搜索难匹配统计失败任务的相似度分布对程序库做分层增加中间粒度候选新场景执行失败率高程序调用正确但底层轨迹未适配区分“程序选择错误”与“轨迹执行失败”为程序内层增加参数化控制器训练显存溢出图像序列和动作序列过长看 step 数与 batch 数降低帧率、切短上下文、做序列采样无监督训练崩溃状态变化尺度不平衡检查不同状态信号的量纲做归一化和滤波让各信号同量级推理结果每次不一样采样温度过高或程序检索策略不稳定固定随机种子检查是否有随机采样降低温度或改为确定性 top-k 调用API 调用超时运动模型服务拖住了检索接口分阶段压测检索和运动服务分开部署检索服务与执行服务解耦如果你是自己搭工程而不是直接使用官方仓建议从一开始就区分“动作生成失败”和“程序调度失败”。在日志里至少要记三件事当前任务描述、模型选择的程序编号、程序执行后的状态差异。没有这三项出现问题几乎无法定位。9. 使用边界、数据授权与安全提醒REFACTOR-VLA 处理的是运动数据实际采集经常涉及人体动作、真实机器人操作和环境录像。做实验前一定要控制好三方面问题。第一数据授权。动捕数据、动画资产、真实机器人录制数据如果来自第三方要确认是否有再训练、再发布和商业使用授权。不要把一套带人脸或可辨识个体的视频直接丢进无监督学习流程也不要把自己获取到的内部数据随意上传到外部平台。第二隐私保护。如果动作数据来自真实场景画面里可能包含人、办公室布局或敏感设备。原始视频要先做匿名化处理。姿态传感器数据如果不加脱敏同样可能通过步态或操作习惯识别人。第三物理安全。带类型签名的运动程序在仿真环境里表现再稳定也要经过充分验证才能部署到真实执行器。前置条件的自动检查不能替代安全回路。执行器碰到新物体、新接触状态时必须有外部急停或力控保护不能只依赖模型判断。这类研究方法的边界也不是单靠算法解决。程序库再完整也很难覆盖极端的长尾情况。所以部署时建议设一个“低置信度保护”当程序检索结果置信度偏低马上交给人工决策或切换到保守控制策略而不是让模型在连续空间里自由发挥。10. 接下来可以继续做什么如果 REFACTOR-VLA 的公开代码或完整技术报告后续放出我建议第一步先复现它的运动分割和类型归纳模块而不是立刻端到端训练。原因是这两个模块直接决定程序库质量也只有它们跑通了才能谈上层策略复用。最容易踩的坑有三个一是忽视程序库检索规模测试任务一多就出现高延迟二是只看文本语义聚类不看物理状态转移导致合并出错误类型三是把轨迹生成质量的指标直接拿来评价程序调用没有做执行态验证。只要避开这三个坑框架的理解和验证都能省很多时间。从后续方向看这类“类型化运动程序库”和基于大模型的技能规划很互补。VLA 负责把视觉和语言信号解析成任务意图运动程序库负责把任务意图落成可执行、可检查的动作计划。如果硬件条件允许值得在仿真环境里先跑一套开放物体操作任务验证在物体分布变化时程序调用能否比端到端动作回归更稳定。也建议把这套思路和传统的机器人行为树、状态机做对比看类型化程序到底在哪些任务上真正降低开发成本。最后整理一句话先用小数据集验证运动类型分割再构建分层运动程序最后再套大模型检索和调用这是最稳的推进顺序。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进