22 端侧部署与打包洞察
- 章节编号:22
- 所属层:D 部署与服务层(承接 12 Runtime、20 前端、21 模型)
- 关联 ADR:ADR-075(端侧制品形态:vmfb+manifest bundle)、ADR-076(打包工具链与依赖)、ADR-077(版本/回滚与 A/B)、ADR-078(与 Yocto/rootfs 集成)
- 上游依赖:10(Yocto/rootfs)、12(IREE VM)、18(tuning spec)、20(manifest)、21(模型验收)
学习目标
- 前置知识:读过 21 章(具身模型族与 INT4 内存画像:π0/GR00T 的权重量级与 chunk 延迟靶标)、12 章(IREE VM 与运行时依赖)、18 章(tuning spec 的产出形态)。知道「编译产物 = vmfb + 常量」这条链路的输出是什么,以及「端侧不是一台云服务器」——它没有 Docker daemon、磁盘按 GB 计、每次刷机都要过安全启动。无需 Yocto 实战经验,但要理解「制品(artifact)」与「运行时(runtime)」是两件事。
- 学完产出:① 能说清一个端侧 bundle 里到底装了什么(manifest / vmfb / 权重 / tuning spec / 签名),以及为什么它要「自描述 + 可校验」;② 能对标 TensorRT engine、QNN context binary、CANN OM 三种闭源制品,讲清「可 git diff 的 spec + manifest」这条差异化护城河的工程价值;③ 能亲手把「bundle 目标 ≤8GB、典型 4GB」这条硬指标算一遍——用模型权重 + runtime + 依赖的实际字节数反推,而不是背一个区间;④ 能在「Yocto 原生集成」与「容器化部署」之间做取舍,说清端侧为什么倾向前者、边缘侧为什么容忍后者;⑤ 能设计一套「版本回滚 + 固件 ABI 契约」机制,理解为什么「回滚 bundle」和「回滚固件」是两个不同量级的操作。
- 阅读姿势:盯住一条主线——「端侧制品的一切设计,都是为了让一次刷机既能跑得动、又能安全回退」。云上部署可以「重新 build 一个镜像重启」,端侧不行:板子在客户现场、模型有 GB 级权重、刷坏了要人上门。所以本章所有的「自描述 manifest」「A/B 分区」「N-1 保留」「ABI 契约」,本质都在回答同一个问题:当新版本跑挂了,怎么在一次 reboot 内退回上一个能跑的状态。
1. 范围与目标
本章定义 编译产物如何打包为端侧可部署单元,含 vmfb、权重、tuning spec、manifest、Runtime 依赖,以及与 rootfs/Yocto 的安装布局。不含 Fleet OTA(23 章)。
核心问题
- 端侧 制品(bundle)里有什么?
- 对标 TensorRT engine / QNN context binary / CANN OM 我们的等价物?
- GR00T 混合部署(PyTorch + AOT)如何打包?
- 版本、回滚、多模型并存如何组织?
- Demo 部署路径?
2. 需求洞察(具身驱动)
2.1 具体场景
| 场景 | 打包诉求 | 来源 |
|---|---|---|
| π0 单模型部署 | vmfb + INT4 weights + spec + manifest | 21 章 |
| GR00T 双系统 | VLM bundle + DiT bundle + link.yaml | 17 章 |
| 客户 POC | 一条命令 deploy 到 Thor 类板 | 26 章 |
| OTA 增量 | delta weights/spec | 23 章 |
| 多模型 | 目录隔离 + MIG context(09) | 12/09 |
2.2 硬性指标
- bundle 自描述(manifest+json);Runtime 校验 hash。
- 单 VLA bundle 目标 ≤8GB,典型 4GB(INT4,21 章)——见 §2.4 的字节级拆解。
deploy install≤5min 到目标板。- 回滚 ≤1 reboot。
2.3 端 / 边 / 中心
| 形态 | 打包 |
|---|---|
| 端侧 | .dsa-bundle (概念名) |
| 边缘 | 同 bundle + 多 robot 索引 |
| 中心 | container/VM;规模化阶段 |
2.4 bundle 容量为何 ≤8GB:一次字节级拆解
「bundle ≤8GB」不是拍脑袋的区间,而是从端侧存储预算倒推出来的硬约束。一块典型的具身 SoC 板(Thor 类 / IQ10 类)eMMC/UFS 容量在 64–128GB 量级,扣掉 rootfs、内核、Yocto 系统层、日志、A/B 双分区冗余后,留给「一个 robot profile 的模型制品」的空间通常只剩 十几 GB。而 A/B 回滚要求同时保留 N 与 N-1 两份 bundle——单份的预算就被再砍一半。于是「典型 4GB / 上限 8GB」这条线自然浮现。
我们把一个 π0 级 INT4 单 VLA 的 bundle 逐项算一遍(数量级估算,权重口径对齐 21 章 §2.2):
| 组成 | 内容 | 典型体积 | 备注 |
|---|---|---|---|
| 模型权重 | VLM(PaliGemma 3B / Gemma3 4B)INT4 + 300M 动作专家 | ~2.0–2.6GB | 4B 参数 × 0.5 byte(INT4)≈ 2GB;动作专家 300M INT4 ≈ 0.15GB |
| 编译产物 vmfb | VLM.vmfb + action_head.vmfb(纯代码,不含权重) | ~50–150MB | vmfb 只装 kernel 序列,权重外置 mmap |
| tuning spec | *.tuning.spec.mlir(18 章调优决策) | ~1–10MB | 文本 IR,可 gzip |
| Runtime 依赖 | IREE runtime + HAL backend 库 | ~200–500MB | 若随 bundle 附带;走 rootfs 共享则趋近 0 |
| manifest + 签名 | manifest.yaml + signature.json(hash 列表) | <1MB | 自描述元数据 |
| 感知/控制小网 + 缓冲 | ViT stub + 控制小网 | ~0.3–0.8GB | 21 章「感知前端 + 控制小网」 |
| 合计(典型) | ~3–4GB | 落在「典型 4GB」 | |
| 合计(带满配 FP8 VLM + 双系统) | ~6–8GB | 逼近「上限 8GB」 |
结论口径:典型 π0 INT4 单 VLA 落在 ~4GB;当 VLM 用 FP8(不减半)、或 GR00T 式双系统(VLM + DiT 两份权重共存)时,才逼近 8GB 上限。一旦某个 bundle 超过 8GB,A/B 双份就吃不下端侧存储预算——这就是把上限钉在 8GB 的物理根因。规避手段:权重外置 + mmap(见 §5)、delta OTA(23 章)、多 bundle 间共享 runtime 层(不重复打包)。