面向具身智能端侧部署态的统一编译框架Lamp,智元创新助力复杂机器人算法从原型走向端侧产品交付

问AI · 具身智能编译对象为何从模型转向完整流水线?
图片

转载请联系本公众号获得授权,并标明来源


在 HyperAI 主办的 Meet AI Compiler 技术沙龙第 9 期中,智元创新 Genie 业务部 AI 引擎负责人孟通和智元创新 Genie 业务部 AI 编译器负责人尹艳鹏以「面向具身智能领域的通用 AI 编译器」为题,分享了最新产业洞察和公司的研究进展。


8 月 1 日,由 HyperAI 主办的 Meet AI Compiler 技术沙龙第 9 期在北京圆满落幕,多位 AI 编译器领域的专家与学者齐聚北京中关村,围绕技术创新、落地经验带来了精彩分享,力图呈现 AI 编译器在语言表达、算子计算、推理执行与场景应用等多个层面上的协同演进图景。


其中,智元创新 Genie 业务部 AI 引擎负责人孟通和智元创新 Genie 业务部 AI 编译器负责人尹艳鹏以「面向具身智能领域的通用 AI 编译器」为题,分享了最新产业洞察和公司的研究进展。


图片

孟通老师出席 Meet AI Compiler 第 9 期


图片

尹艳鹏老师出席 Meet AI Compiler 第 9 期


图片

两位老师与现场观众深度交流


图片

两位老师与现场观众深度交流


HyperAI 在不违原意的前提下,对两位嘉宾的分享进行了整理汇总。


为什么传统模型部署链路在具身领域失效


AI Compiler 其实并不是一个特别新的技术,实际上,在智能驾驶领域以及互联网芯片等一些方向,已经存在比较成熟的编译器解决方案和完整工具链。但为什么这些方案到了具身智能领域就不完全适用了?其实具身领域使用的模型本身可能并没有发生特别大的变化,甚至可能更加标准。但具身智能领域最大的一个问题在于——目前整个算法结构还没有形成统一范式。


现在具身智能领域的解决方案非常多,比较常见的主要有三种路线:


图片


第一种是 VLA(Vision-Language-Action)路线:它的核心思路是,希望通过视觉语言模型(VLM)和大语言模型(LLM)的能力,再加入 Action 模块,让模型能够理解物理世界,并直接输出机器人的执行动作。


第二种是大小脑协同方案(LLM/VLM Planner+Skill/Control):也就是把机器人的智能拆分成两个部分,「大脑」负责思考和规划,「小脑」负责执行。


第三种是 Workflow(工作流)方案:完全抛弃大脑思考,可能完全就用一种拼接的方式,把各种 AI 的原子能力和一些非 AI 的原子能力给串成一个工作流。


① VLA路线的问题:资源和数据限制


VLA 路线一开始看起来是一个非常美好的解决方案,因为过去 VLM 和 LLM 已经取得了非常大的成功,所以大家会思考:能不能直接把视觉语言模型和大语言模型结合起来,再增加一个 Action Head让它直接解决泛化物理世界中的机器人执行问题?但真正落地之后,会发现它存在很多限制,其中最重要的两个问题:第一是资源限制;第二是数据限制。


先看资源问题。VLM 和 LLM 的成功,很大程度上依赖云端资源。云上的计算资源相对充足,没有太多限制,但是 VLA 的执行策略,最终需要部署到机器人端,而机器人端的计算资源天然有限。这就决定了机器人的大脑不可能无限扩大。因此,它的智能能力本身会受到计算资源限制。


第二个更加严重的问题是数据。现在大家经常讨论,具身智能什么时候能够迎来类似 GPT-3.5 的突破时刻?但 GPT-3.5 爆发的一个重要前提是训练数据规模的大幅增长。而目前具身领域采集的数据量,距离达到类似规模还有很大差距。按照目前的发展情况来看,至少可能还需要两个到三个数量级的数据增长,这甚至还是比较保守的估计。


②从端到端模型转向「大脑+小脑」架构


VLA 路线虽然非常理想,但真正落地时会遇到各种问题。因此,就产生了第二种路线:既然 VLA 很难完全端到端解决问题,那么能不能把思考和执行拆开?也就是「大脑」负责 Planning,「小脑」负责 Execution。这个思路其实有点类似 Agentic 解决方案,大脑部分可以使用当前大模型提供的各种 API 服务,小脑部分可以是 VLA,也可以是一些前 LLM 时代已经存在的基础模型。整体流程就是:由大模型完成任务理解和规划,然后调用各种原子能力,把整个任务串起来。


③Workflow 路线:工业场景中的确定性方案


这种方案在工业场景中应用比较多,它的思路是不完全依赖「大脑」进行自主思考,而是把各种 AI 原子能力,以及一些非 AI 的原子能力组合起来,形成一个固定工作流。这种方案更加白盒化,需要更多人工维护和工程理解,但一旦 Workflow 确定之后,机器人可以直接按照既定流程执行。换言之,机器人不需要思考,只需要按照规定好的 Workflow 工作。某种程度上,就是拥有了一个「硅基劳动力」。


所以,整个具身智能领域给 AI Compiler 带来的第一个挑战就是:各种算法方案正在同时发展,目前我们并不知道哪一种方案最终会成为主流,这导致编译器需要面对的模型和 Pipeline 非常复杂。进一步带来的问题是:具身智能领域的编译对象到底是什么?也就是说,AI Compiler 到底需要解决什么问题?


过去在智能驾驶或者互联网领域,我们通常解决的是一个模型的编译问题,模型结构确定之后,再不断通过 HPC、算子优化等方式持续提升性能。但是具身领域无法完全按照这个方式发展,这是因为:第一,算法路线还没有确定,我们甚至不知道最终哪一种模型结构会成为主流;第二,具身智能当前最重要的需求是先把机器人部署出去,让它快速运行起来,采集数据,形成数据飞轮,然后不断提升模型能力。因此,经常会遇到这样的情况:一个新的算法原型出来之后,要求在非常短时间内把完整 Pipeline 交付出去。这里交付的不是一个模型,而是一个完整的端到端 Pipeline,目标是尽快让机器人在真实环境中运行,快速收集数据。


在这种情况下,没有足够时间去仔细打磨模型和系统之间的连接部分,比如前处理、后处理、不同模型之间的数据转换、Runtime 之间的衔接。 因此,整个行业对于 AI Compiler 的需求,也从过去的模型编译逐渐转向 Pipeline 编译。


以目前比较常见的 VLA 类模型为例,一个完整 Pipeline 至少包含六个模块:


图片


比如,一个通用模型通常会有 Prompt 输入,那么这里可能需要一个 Tokenizer 模块;之后,它还会有图像输入,因此需要一些图像预处理模块;再往后,至少包含几个核心部分——第一部分是 Vision 模块,比如常见的 ViT,或者其他视觉识别类模型,由于这类模型相对比较标准,所以可能采用 TensorRT 或其他现有的标准化解决方案;第二部分是 LLM 模块,这一部分可能采用类似 MLC-LLM 的解决方案;第三部分是 Diffusion 模块。所以从模型层面来看,至少会存在三类不同 Case,以及对应三种不同的解决方案。


但这里面最复杂的问题,其实是:模型和模型之间的 Glue Layer(胶水层)因为现在很多基于 HuggingFace 生态的模型,本质上并不是一个单独模型,而更像是一个 Pipeline。它像搭积木一样,把不同模块组合在一起,所以最大的问题就是:能不能通过一套体系,把这些不同模块融合起来?这需要同时面对不同的 Runtime、不同的算法表达方式、不同的模型框架,然后在这个基础上,实现高效、敏捷的交付。这实际上是我们现在面临最大的一个问题。


我们预期未来的情况可能会像图中展示的一样,算法在最开始阶段可能会非常混乱。它可能由各种不同模块,以及不同逻辑表达方式组合而成,但是最终交付的时候,我们希望能够对这些模块进行一定程度的分组和 Fusion,然后基于拓扑结构把整个 Runtime 组合起来,最终形成一个整包交付。



落地实践:高性能 VLA 推理


接下来我简单介绍一下智元创新的解决方案。这个工作实际上已经 Release 了,大概是在今年 1 月份左右。我们在真机上对 π-0.5 的推理性能进行了优化,将推理频率从原来的 1.4 Hz 提升到了 22 Hz,22 Hz 基本已经接近一个实时可用的端侧「小脑」。


图片


这里简单介绍一下我们的整体思路。一个原始算法 Pipeline,首先会通过一些 Dynamic Trace(动态追踪) 的方式,对整个链路进行分析和分类标记。为什么要做标记?因为我们希望追踪整个链路里面每一个环节对应的表达形式、不同模块之间的拓扑结构,以及整个执行过程中的拓扑顺序。 在完成分析之后,我们会通过一些融合(Fusion)和翻译(Translation)策略,把不同部分转换成不同的 Group 或者 Scope,然后再进一步做融合。


实际上,在融合之后,才进入传统编译器擅长解决的问题。无论是 TensorRT 方案,还是 TVM 方案,至少当 Scope 被拆分清楚之后,每一个 Scope 都可以对应一套标准编译方案。最后,会有不同的引擎或者 Runtime 负责组合整个系统。


比如 Tokenizer 这种模块,本身可能并不需要编译,它只需要通过 Runtime 把不同模块连接起来即可。因此,整个流程就是:从最开始一个非常分散、复杂的算法 Pipeline,经过 Dynamic Trace 分析,再进行模块融合,最后完成 Runtime 拼接。这样才能从整体上达到更优的性能和更高效的交付效率。


我们在 Release 的时候,实际上把能够使用的优化手段都进行了尝试。在第二层方案,我们使用了原生 Triton,但是没有继续做进一步优化。这个方案可以把性能从原来的 1.4 Hz 提升到约 3.5 Hz。整体来看,使用 Triton 和 Compiler 方法,相比原始算法确实能够带来明显提升。但是如果目标是从整体达到 22 Hz,我们会发现如果考虑从算法到硬件的端到端协同优化,还有一些性价比更高的方法,比如图级别(Graph Level)的编译优化。通过这种方式,性能可以提升到大约 8 Hz,从投入产出来看,它的性价比会更高。


所以这里也带来了一些反思:在现在这种追求端到端性能极限的情况下,编译器到底应该承担什么样的责任?我们的感觉是:未来编译器可能不仅仅是解决 IR 层面的表达问题,更重要的是如何把每一层的优化能力沉淀成 Skill,然后通过一套 Harness 机制,把这些 Skill 快速组合起来。最终通过这些能力的组合,实现端到端完整方案的快速交付。



Lamp 编译器核心原理


接下来详细介绍一下我们的具体方案。首先介绍一下 Lamp 的定位,它可以从三个方面来理解:


图片


首先,LAMP 服务的是机器人算法从 Python 原型阶段走向端侧产品交付阶段的关键过程。大家都知道,在算法原型阶段,通常是算法人员在比如 NVIDIA 4090、5090 等边缘计算卡上,直接使用 Python 进行算法验证,然后连接机器人进行测试。这个阶段最关注的是迭代速度,算法人员希望能够快速修改、快速验证。但是到了产品阶段,要求就完全不同,产品阶段更加关注稳定性、性能、可维护性和出现问题之后的可回归能力。 所以 Lamp 并不是要求算法从一开始就放弃 Python 侧的灵活性,也不是要求开发阶段完全按照产品方式进行。它解决的是在交付阶段,把这种灵活表达的算法形式,逐步收敛成一个明确、可交付的部署契约。


第二,Lamp 纳管的是整条业务 Pipeline,这和过去传统算法编译有比较大的区别。以前很多算法优化,核心对象是单个模型,但是现在具身智能场景下我们管理的是完整业务 Pipeline。更直白一点——从机器人传感器产生的 raw data(原始数据),一直到机器人最终执行 Action 的整个过程,都属于 Pipeline 的范围。其中包括图像预处理、文本处理、一个或者多个模型推理、不同模型推理之间的胶水代码、后处理、自定义 Kernel 以及最终 Runtime 执行。 整个业务 Pipeline 都可以通过 Lamp 构建成为一个可构建、可检查并且可以持续优化的端侧制品。


第三,它的目标架构是跨平台、跨来源的。具体而言,是跨 NVIDIA GPU 与国产芯片双平台,灵活组合手写高性能 Kernel、模型专属加速引擎与厂商原生后端,结合统一 Runtime 高效执行,逼近硬件性能上限。

接下来详细介绍一下 Lamp 所具备的五项能力:


图片


第一个能力是端到端的 DAG,它回答的是到底编译什么的问题。刚才也提到,具身智能场景下,编译对象已经不再是单个模型,而是完整的业务 Pipeline。Lamp 通过端到端 DAG,把从机器人传感器产生的数据,到最终机器人执行动作这一整套数据链路全部纳入管理范围,也就是覆盖整个业务流程。


第二个能力是分组编译以及多后端协同,它回答的是每一部分由谁来实现,以及如何完成的问题。硬件是横向维度,Kernel 和 Backend 是纵向维度。在具体构建过程中,不同模块采用什么样的实现方式,都会在构建计划中被显式确定。


第三个能力是统一 Runtime 的高效执行,它回答的是这些经过分组编译之后的组件,如何在端侧统一管理和协同执行的问题。通过统一接口和统一配置,不同组件可以按照共同约定进行协同运行,从而实现整个业务 Pipeline 的最优执行效果。


第四个能力是全链路闭环交付,它回答的是如何让开发结果真正进入产品流程的问题。目前 Lamp 的核心闭环已经覆盖到最终编译产物(Artifacts)构建,包括整个检查、加载和运行流程。后续生产和发布环节,可以由上层发布系统承担,而 Lamp 主要负责向发布系统提供版本化的制品,以及对应的可验证证据,确保交付过程具备可追踪性和可靠性。


第五个能力是白盒可控、深度可调,它回答的是当正确性或者性能出现问题时,能不能快速定位并继续优化的问题。其实刚才也提到,业界使用比较广泛的 TensorRT,虽然性能非常强,但在 AI Compiler 领域也经常被讨论的一个问题就是它的黑盒属性。用户通常只能拿到最终结果,但如果出现性能瓶颈或者精度问题,很难进一步分析和优化。而 Lamp 的设计理念是实现整个流程的白盒化,当发现性能或者精度问题时,我们可以快速定位到具体是哪一层出现问题。同时,在生产阶段,我们可以保留整个 Pipeline 中间过程的结果,并且对每一层进行对应分析,从而快速判断问题来源,并针对性进行优化。


这五项能力并不是彼此独立的卖点,而是一条完整的链路。首先,需要有端到端的图(Graph),明确整个 Pipeline 的结构;然后基于这个图进行切分,确定每个模块适合采用什么方式解决;切分之后,再通过统一 Runtime 对不同编译后的组件进行统一调度和执行;最终执行结果进入发布系统,而发布之后产生的数据,又可以继续反馈回来,用于下一轮优化。


接下来详细展开介绍每一个能力,以及我们具体是如何实现的。首先是端到端部署 DAG,这也是整个 Lamp 框架的核心所在。


图片


它的核心思路是:把传统的业务 Pipeline 转换成一个类似神经网络的 DAG 图。我们可以看到,在这个图里面,每一个节点可以是一个普通算子,也可以是一个 Tokenizer,也可以是一个图像预处理函数,也可以是一个后处理函数,比如 Action Trunk 或者做动作 smoothing 的函数。同时,图里面每一条边也不再像传统网络或者 IR 表达中,只表示这里有数据经过。我们的边里面还会携带更多信息,比如数据类型、Shape、Device 信息、量化相关信息、混合精度情况下具体采用什么精度,以及部分有状态的信息。


因为从机器人的角度来看,很多时候系统本身是有状态的。比如每一次初始化的时候,机器人可能需要保持一个初始动作,然后根据后续 Action 的变化继续执行。这种状态信息在机器人或者具身智能领域会是一个比较重要,也比较麻烦的问题。所以我们的边里面,也会包含一些状态属性以及生命周期约束。


这样做主要可以减少两类成本——第一类是手工改写成本。按照以前传统的方式,算法人员通常是在 Python 层面,先在大规模计算卡上验证算法和模型效果。验证完成之后,再由集成人员去查看算法代码,把 Python 代码转写成 C++。而在这个转移过程中,除了需要保证语义一致性,还需要考虑很多部署侧优化问题。


比如:能不能使用 CUDA 加速?图像处理是不是可以使用 OpenCV 进行加速?甚至包括传感器编解码、图像编解码等问题。这些能力在大规模计算卡上可能并不存在,但是在端侧部署时,比如部署到专用 SoC 上,实际上可能会有专门的硬件解码能力。所以这实际上体现的是研发态和部署态之间的区别。在部署态,我们可以做更加深入和极致的优化。通过构建统一的 DAG,就可以避免大量手工改写工作。同时,也不需要再让各种算法模块之间通过 Python 胶水代码进行分散连接。而是形成一个统一的业务图,把整个 Pipeline 的全貌展示出来。


第二类是回归成本。当图、权重或者算子的实现发生变化的时候,我们可以快速定位到具体是哪一部分发生了变化,而不是需要重新检查整个图。因为在实际 Pipeline 中,某一个模块可能并不是由同一个组件完成的,甚至可能由其他组件替代实现。这个时候有一个全局的业务图,就可以帮助我们快速定位到底是哪一个组件发生了变化,是哪一个部分产生了影响。


接下来把分组编译和统一 Runtime放在一起讲:


图片


先看分组编译。刚才提到了它实际上包含横向和纵向两个维度的实现——横向来看,我们需要支持算法研发态和部署态的不同环境,比如算法研发阶段可能是在 4090、5090 这样的 GPU 环境下进行验证,而部署阶段可能面对 Thor、Orin 以及国产芯片等不同硬件平台;纵向来看,则是 Kernel 的来源,比如手写 CUDA、CuTeDSL、CUTLASS,以及厂商自定义的一些 Kernel 实现,这些都属于我们整个交付范围内支持的内容。不同模块可以实现自由派发。在编译阶段,可以通过 Model Spec 进行声明,然后完成注册和应用,这样可以快速构建出一个可解释的、能够明确知道每一个模块具体实现方式,并且可以进行回归验证的制品。


然后再看统一 Runtime。它加载的是最终编译生成的制品,也就是 Artifacts。Runtime 会读取 ABI 和 Manifest,然后完成权重绑定、资源分配、算子 Kernel 加载以及调度。其中内存规划也包含在整个流程里面,无论是在编译阶段还是执行阶段,都会涉及相关处理。


到这里,整个流程就是:图已经完成切分;不同模块已经完成编译;并且可以通过统一 Runtime 进行调度和执行。但是如果真正进入产品阶段,还需要继续回答几个问题:包括版本发布、回归,以及出现问题之后如何进行定位。


最后回归到上面提到的最后两项能力,即全链路的闭环交付和白盒逼近硬件极限的这种问题。


图片


先看全链路闭环交付。模型完成接入之后,首先需要进行权重转换和校验。随后根据目标平台,比如 Thor 或 Orin,完成编译构建,之后再将接口 ABI、权重、Kernel 实现等内容统一打包成制品(Artifacts)。这些制品经过上层平台发布之后,会在端侧,也就是机器人本体上进行加载和运行。运行之后,我们可以进一步进行正确性和性能回归。


任何一个环节出现失败或者问题,都可以依靠具体证据进行定位,包括明确的版本信息,以及对应的输入和验证证据。而不是最后交付之后,仅仅通过评测人员观察:「这一次机器人抓到了这个瓶子,下次没有抓到。」这种方式无法定位问题。我们需要的是实实在在的 Profile 数据,能够明确:这一次运行结果是什么,以及对应的动作以及数值表现是什么。


我为什么要强调整条链路?因为机器人,尤其是在端侧部署的时候,遇到的问题很多时候并不是模型发生变化,或者模型效果变差。更多情况下,一个性能回归可能包含很多因素,比如:可能是预处理发生了变化;可能是传感器配置发生变化,比如 Camera 输出从 4K 变成了 2K;甚至可能是因为内存资源紧张,系统在资源规划的时候分配给模型推理的资源变少了。所以权重格式变化、资源分配变化,都可能最终影响端到端效果。


然后再看白盒能力。在开发阶段,我们可以检查高层 Graph,也就是整个业务 DAG,然后一直向下追踪到编译过程,包括整个构建流程以及构建计划,其中包括:功能选择,Memory Planning 的最终结果,以及对应的分析过程,最后最关键的是运行时 Profile。正式运行时,默认保存的是关键运行信息、对齐接口以及构建信息,而不是把所有中间表示全部塞进最终制品里面。


当出现问题的时候,我们可以沿着版本和证据进行追溯。比如:图是不是发生变化?图里面每一个节点的信息有没有变化?每一个算子的具体信息有没有变化?内存复用策略有没有变化?最后性能瓶颈热点到底集中在哪一个 Kernel 上?这些问题都可以比较清晰地定位。


所以最终达到硬件性能极限,并不是我们现在已经完成的目标,而是代表一种可持续的方法。我们首先建立基础设施,然后不断观察、部署;当发现问题之后,再进行定位、修改和优化,持续迭代;最终,在相同模型权重和业务约束条件下,可以一步一步提升性能,并且保证——每一次优化都有对应的证据,每一次重新发布都依然能够满足业务约束,同时明确优化带来的影响边界。


最后总结一下,Lamp 是面向具身智能端侧部署态的统一编译框架,让复杂机器人算法从 Python 原型走向端侧产品交付时,既能自动化构建统一部署制品,又能以白盒可控、深度可调的方式持续逼近硬件性能上限。