☰
IB_Robot 跨主机 OM 精度验证工作流:Torch 基线目标的生成、封包与 Ascend 部署对齐实战指南
2026/10/15 17:07:47 网站建设 项目流程
  • 具身智能
  • 机器人
  • 人工智能
  • 大模型
  • 模型推理服务
  • 本地部署
  • 计算机视觉
  • ROS

【免费下载链接】IB_Robot

Save the code of IB-Robot, an AI robot execution framework developed by openEuler Embedded for embodied intelligence scenarios. It includes references to the forked version of tensormsg, references to lerobot fork, code references to the lerobot_ros2:ros2_ws branch, as well as some code related to development usability.

项目地址:https://gitcode.com/openeuler/IB_Robot
点击查看免费下载

本指南面向 IB_Robot(openEuler Embedded 面向具身智能场景的 AI 机器人执行框架)中「LeRobot 策略模型 → Ascend OM 转换」的精度验证环节,讲解一套可跨机器复现、可审计、可交接的多主机精度对齐方法。核心思路是:Torch 目标生成、ONNX/OM 转换与昇腾部署可能发生在三台不同的机器上,因此必须用一份「不可变的规范化验证包」把基线输入、权威动作目标与随机噪声固定下来,再通过哈希校验保证每一次 Torch-vs-OM 对比都基于完全相同的输入。读完本文,你将掌握hosts.json拓扑记录、validation-inputs验证包封包、loss_compare.py目标生成与计算损失、SHA256SUMS 校验、跨主机传输与交接报告的一整套可落地流程,并理解 IB_Robot 仓库中相关源码的设计意图。

本文的主体是仓库中.agents/skills/om-convert/references/multi-host-validation.md(IB_Robot 统一的 Ascend OM 转换入口om-convert的内部参考文档),源码与测试仅用于佐证和深化。所有命令均以仓库当前实现为准。

一、适用场景与三条核心原则

在 IB_Robot 的 Ascend OM 转换链路(统一入口见 .agents/skills/om-convert/SKILL.md)中,一条完整链路包含三个角色:

角色职责
Torch 主机运行原始 LeRobot/Torch 部署,生成权威动作目标(target)与持久化噪声
转换主机执行 ONNX 导出与 ATC 编译,产出 OM 候选
Ascend 主机加载 OM 部署,对同一批观测计算损失,与 Torch 目标对比

多主机精度工作流建立在三条硬性原则上:

  1. 绝不假设路径或环境是共享的。Torch 目标生成、转换、昇腾部署可能运行在不同的机器上,同一绝对路径在另一台机器上可能不存在,install/setup.sh、venv、CANN 环境也各不相同。
  2. 每个固定参考契约只生成一次权威目标。所有 ONNX、OM、编译器和语义保持型优化候选都必须与同一份目标包对比;导出器修复、宿主预处理变体、dtype 实验、ONNX/OM 候选、优化阶段都不允许生成新的target.json包。
  3. 每一次跨主机对比前都必须验证输入一致性。观测、目标、raw 目标、噪声必须来自同一权威包目录,并校验其记录在案的哈希值。

关于远程执行:仅询问一次是否允许远程执行;复用用户已有的 SSH 配置,绝不索取密码、私钥、访问令牌或密钥文件内容。如果直接传输不可用,给出精确命令并在明确的交接点停下。许多实验室主机禁用了密码认证,跨主机运行前应先在控制机上准备好基于密钥的访问:

ssh-copy-id "RESOLVED_USER@RESOLVED_HOST" ssh -o BatchMode=yes "RESOLVED_USER@RESOLVED_HOST" true

若策略禁止ssh-copy-id,请用户改用组织批准的密钥提供方式。不得修改sshd_config或启用密码认证。

二、拓扑记录:reports/hosts.json

在动手之前,先创建不含任何机密信息的reports/hosts.json,把三台主机的关键信息固化下来:

{ "torch": { "location": "local-or-user@ip", "workspace": "/absolute/IB_Robot", "bundle": "/absolute/policy", "deployment": "torch-device", "device": "cpu|cuda|npu" }, "conversion": { "location": "local-or-user@ip", "workspace": "/absolute/IB_Robot", "bundle": "/absolute/policy", "experiment": "/absolute/experiment" }, "ascend": { "location": "local-or-user@ip", "workspace": "/absolute/IB_Robot", "bundle": "/absolute/policy", "deployment": "ascend-name", "device_id": 0 } }

字段语义要点:

  • location:本机写local,远程写user@ip;
  • workspace:每台机器上 IB_Robot 仓库的绝对路径;
  • bundle:策略 bundle 的绝对路径(需含config.json、model.safetensors、policy_preprocessor.json、policy_postprocessor.json);
  • deployment:bundle 内inference_manifest.json中的命名部署;
  • device:Torch 侧的cpu|cuda|npu;Ascend 侧用device_id指定 ACL 设备号。

这与om-convert前置信息采集(.agents/skills/om-convert/SKILL.md 的 Upfront Intake 一节)一一对应:Torch 主机、转换主机、Ascend 主机各自的 SSH 目标、IB_Robot 路径、bundle 路径、部署名与设备都必须显式采集。若三个角色都在同一台机器上,只问一次并记录"拓扑共享",但主机的路径仍然相互独立,绝不假定同一绝对路径在两台机器上都存在。

三、规范化验证包:唯一权威的对比输入

跨主机精度验证只认一份「规范化验证包」——一组不可变的对比输入。目录结构如下:

validation-inputs/ ├── observations.safetensors ├── target.json ├── target_raw.json ├── noises/ ├── validation.json └── SHA256SUMS

其中:

  • observations.safetensors:带版本号的观测批次(Safetensors 格式);
  • target.json:Torch 部署生成的动作目标(反归一化/物理空间);
  • target_raw.json:归一化(pre-postprocessor)空间的原始动作目标;
  • noises/:为随机策略持久化的逐样本控制噪声;
  • validation.json:记录参考契约全部关键元数据;
  • SHA256SUMS:除自身外所有文件的 SHA-256 校验和清单。

validation.json记录的内容包括:策略类型(policy type)、源 bundle、Torch 部署、观测来源(provenance)、任务(task)、随机种子(seed)、样本数、目标生成命令、IB-Robot 修订号(SHA)与 LeRobot 修订号(SHA)。哈希应在目标生成后立即计算,并在每次传输后重新校验。

这份验证包是其记录的参考契约下唯一权威的动作目标包。导出器修复、宿主预处理变体、dtype 实验、ONNX/OM 候选、优化阶段的产物只能存到reports/或候选目录,命名如candidate_output.json、metrics.json、stage_reference/,绝不能作为另一个可消费的target.json包。

如果仓库里已存在多个历史 target 目录,不要按名字或时间新旧来选:应根据 manifest 与哈希识别权威包,并通过重跑被接受的基线产物、复现其记录的指标来证明其权威性;其余目录标记为历史诊断快照(记入实验台账),严禁跨包混用文件。

四、观测批次:优先真实本地 LeRobot 数据集

4.1 生成与检查命令

优先使用真实本地 LeRobot 数据集生成观测批次。在 IB_Robot 工作区中执行(.shrc_local负责加载 ROS 2 Humble、venv、libs/lerobot/src的 PYTHONPATH 以及已安装的 CANN 环境,见 .shrc_local):

source .shrc_local source install/setup.sh ros2 run model_utils observation-batch dataset \ --dataset-root "RESOLVED_DATASET_ROOT" \ --policy-path "RESOLVED_TORCH_BUNDLE" \ --output "RESOLVED_INPUT_DIR/observations.safetensors" \ --samples "RESOLVED_SAMPLE_COUNT" \ --sampling episode-stratified \ --seed "RESOLVED_SEED"

检查生成结果:

ros2 run model_utils observation-batch inspect \ "RESOLVED_INPUT_DIR/observations.safetensors"

已经存在且带版本号的批次同样有效。仅当用户完全没有数据时,才允许用确定性随机观测做 smoke 转换,且结果必须标注为非代表性;随机观测永远不能作为校准输入。

4.2 源码级实现佐证

observation-batch命令的实现位于 src/model_utils/model_utils/observation_batch_cli.py,底层由 src/model_utils/model_utils/observation_batch.py 支撑。从源码可以确认:

  • 格式规范:Safetensors 文件携带__ibrobot.format=ibrobot-observation-batch与__ibrobot.schema_version=1元数据,加载时严格校验格式与版本(load_observation_batch);
  • 采样策略:CLI 支持episode-stratified、global-random、global-uniform三种策略,默认episode-stratified(按 episode 分层,见select_dataset_indices);--samples必须落在[1, 数据集帧数]区间;
  • 字段约束:策略 bundle 的config.json中input_features定义字段形状与类型,VISUAL特征强制为图像语义(CHW 布局),数字字段必须显式声明 FieldSpec(NAME=SHAPE,DTYPE,MIN,MAX[,SEMANTIC,LAYOUT]);
  • 任务文本编码:字符串型task字段被编码为task-index张量 + 字符串表,供 VLA 策略的语言条件推理使用;
  • 来源追踪:批次元数据记录source/root/policy_path/repo_id/sampling_strategy/seed/selected_indices/video_backend,且带dataset_index/episode_index/frame_index逐样本溯源张量;
  • 原子写入:save_observation_batch通过临时文件 +os.replace原子落盘,且默认拒绝覆盖已存在文件(--force除外)。

loss_compare.py加载观测时还会做关键预处理:图像从 HWC 转 NCHW 并归一化到[0,1](若最大值 >1 则除以 255,见_prepare_image),并把task作为自然语言提示透传给 VLA 预处理器(src/model_utils/model_utils/loss_compare.py)。

五、Torch 目标生成

5.1 前置条件

在 Torch 主机上,首先要证明 IB-Robot 能加载并执行原始 Torch 部署,然后才运行目标生成。目标生成使用loss_compare.py的--generate-target模式,该模式只应运行一次(除非用户明确批准替换基线,否则不要加--force)。

5.2 生成命令

source .shrc_local source install/setup.sh python3 src/model_utils/model_utils/loss_compare.py \ --policy_path "RESOLVED_TORCH_BUNDLE" \ --deployment "RESOLVED_TORCH_DEPLOYMENT" \ --batch_path "RESOLVED_INPUT_DIR/observations.safetensors" \ --task "RESOLVED_TASK" \ --seed "RESOLVED_SEED" \ --exp-dir "RESOLVED_INPUT_DIR" \ --generate-target

要点:

  • 使用新的实验目录:--exp-dir会自动派生三条长路径——target.json、target_raw.json、noises/(见 src/model_utils/model_utils/loss_compare_cli.py 的apply_exp_dir_derivation);
  • 覆盖保护:generate-target模式下,若目标文件已存在或noises/非空,CLI 会拒绝覆盖并要求换新目录或显式加--force(check_overwrite_guard);
  • 噪声必须持久化:对随机策略,目标生成必须持久化noises/;缺失噪声在跨机对比中属于硬失败;
  • 任务与种子必须与后续计算损失完全一致;
  • 每个参考契约版本只生成一次目标。封包后,所有后续诊断与优化候选都复用同一份目标;候选失败不得触发重新生成目标。

5.3 噪声自检与确定性证明(源码级)

对随机策略,--generate-target在写出任何目标前会先执行噪声自检_assert_noise_effective(src/model_utils/model_utils/loss_compare.py),对批次 0 做 3 次前向:

  • A1、A2 使用noise=zeros,B 使用noise=3*ones;
  • 确定性检查:A1 ≈ A2(否则说明存在 RNG 泄漏或 dropout 未关闭,拒绝生成不可复现目标);
  • 有效性检查:A1 ≠ B(否则说明噪声被忽略,终止并报告)。

该自检把「manifest 噪声绑定缺失或被忽略」这类问题在写出坏目标之前变成硬失败。loss_compare的统一推理管线通过PureInferenceEngine.control_inputs把噪声绑定到选定的 PI05 codec,并捕获 pre-postprocessor 的raw_action(capture_raw_action=True),从而同时产出target.json(物理空间)与target_raw.json(归一化空间)。

从源码结构可以推断,这套流程面向 PI0、PI05、SmolVLA、Diffusion Policy 以及任何生产推理接受随机噪声或随机控制输入的新策略。但需要注意一个明确的边界:当前loss_compare只为 PI05 实现了持久化噪声(_resolve_noise与_pi05_noise_shape均以policy_type == "pi05"为前置条件,噪声形状(1, chunk_size, max_action_dim)从引擎声明的nominal_chunk_size与max_action_dimension推导)。在验证其他随机家族之前,必须为其扩展 codec/运行时与对比工具(家族特定的控制输入生成、版本化存储、回放、形状/dtype 校验与有效性测试)。不要假设仅靠--seed就能复现某个后端内部随机状态。

相关测试覆盖在 src/model_utils/test/test_loss_compare.py:包括噪声确定性、generate-target必须持久化噪声(RuntimeError匹配noise-dir)、噪声自检 3 次 reset、target.json/target_raw.json同时写出等。

六、封包:写入validation.json与计算 SHA256SUMS

6.1 生成validation.json

目标生成完成后,用解析后的真实值生成validation.json(用排序 JSON 保证记录稳定;所有占位符必须先替换再执行,数值保持数值类型):

python3 - "RESOLVED_INPUT_DIR/validation.json" "RESOLVED_SEED" "RESOLVED_SAMPLE_COUNT" <<'PY' import json import sys from pathlib import Path payload = { "format": "ibrobot-om-validation-v1", "policy_type": "RESOLVED_POLICY_TYPE", "source_bundle": "RESOLVED_TORCH_BUNDLE", "torch_deployment": "RESOLVED_TORCH_DEPLOYMENT", "observation_batch": "observations.safetensors", "observation_provenance": "RESOLVED_PROVENANCE", "task": "RESOLVED_TASK", "seed": int(sys.argv[2]), "sample_count": int(sys.argv[3]), "generation_command": "RESOLVED_GENERATION_COMMAND", "ibrobot_revision": "RESOLVED_IBROBOT_SHA", "lerobot_revision": "RESOLVED_LEROBOT_SHA", } Path(sys.argv[1]).write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8") PY

6.2 计算校验和清单

然后对包内除校验和清单本身外的每个文件计算 SHA-256:

python3 - "RESOLVED_INPUT_DIR" <<'PY' import hashlib import sys from pathlib import Path root = Path(sys.argv[1]).resolve(strict=True) files = sorted(path for path in root.rglob("*") if path.is_file() and path.name != "SHA256SUMS") lines = [] for path in files: digest = hashlib.sha256(path.read_bytes()).hexdigest() lines.append(f"{digest} {path.relative_to(root)}") (root / "SHA256SUMS").write_text("\n".join(lines) + "\n", encoding="utf-8") PY

这两段脚本分别对应文档规定的「目标生成后计算哈希、每次传输后验证哈希」纪律。封包完成即视为「seal」:此后所有诊断与优化候选复用此包,任何候选不得触发目标重生成。

七、跨主机传输:整体搬运,逐项校验

7.1 传输命令

传输的是完整验证包,而不是选中的若干文件。示例(使用已批准的 SSH 目标):

rsync -a --checksum "RESOLVED_INPUT_DIR/" \ "RESOLVED_ASCEND_SSH:RESOLVED_ASCEND_INPUT_DIR/"

要点:

  • 路径必须加引号;
  • 在目标机验证SHA256SUMS;
  • 若rsync不可用,改用scp -r并单独校验哈希;
  • 绝不允许在另一台主机上静默重新生成观测、目标、raw 目标或噪声。

7.2 校验命令

可用系统自带的:

sha256sum -c SHA256SUMS

若系统没有sha256sum,用解析每个 digest 与相对路径的 Python 等价实现。校验清单不得包含SHA256SUMS自身。

7.3 可部署 bundle 的单独传输

可部署 bundle(或托管生成产物)需要单独传输,并保留inference_manifest.json、其引用的全部构件、processor 资产以及相对路径。bundle 的加载契约见 inference_manifest 模块 与 loss_compare_cli.py 中--policy_path的说明("bundle 目录必须包含config.json与inference_manifest.json")。PI05 转换的产物布局为<policy-path>/artifacts/ascend/<deployment>/...(见 .agents/skills/om-convert/references/pi05.md)。

八、Ascend 计算损失:Torch-vs-OM 对齐

8.1 计算命令

在 Ascend 主机上使用传输过来的包(注意此时不带--generate-target):

source .shrc_local source install/setup.sh python3 src/model_utils/model_utils/loss_compare.py \ --policy_path "RESOLVED_ASCEND_BUNDLE" \ --deployment "RESOLVED_ASCEND_DEPLOYMENT" \ --batch_path "RESOLVED_ASCEND_INPUT_DIR/observations.safetensors" \ --task "RESOLVED_TASK" \ --seed "RESOLVED_SEED" \ --exp-dir "RESOLVED_ASCEND_INPUT_DIR" \ --metrics-json "RESOLVED_REPORT_DIR/torch-vs-om.json"

硬性约束:

  • 严禁对被测 Ascend 部署使用--generate-target——目标只能来自原始 Torch 部署;
  • --task与--seed必须与目标生成时完全一致;
  • 执行前必须确认--batch_path、--exp-dir,以及任何显式的 target、raw-target、noise 路径,全部解析到同一个传输包目录;严禁从不同目录里按相似文件名手动拼装对比。

8.2 指标输出(源码级)

loss_compare.py的compute_loss(src/model_utils/model_utils/loss_compare.py)对每个样本计算:

  • unnormalized(物理空间):L1 loss 与余弦相似度,并按批次打印汇总表与Avg;
  • normalized(pre-postprocessor 空间):若存在 raw 预测与target_raw.json,额外比较归一化空间的 L1 与余弦,用于隔离「真实模型漂移」与「反归一化放大」;
  • batch 0 诊断:预测/目标的 shape、dtype、范围、均值、标准差、逐 action 维 L1/Linf;
  • PI05 专属分布度量:见下文;
  • --metrics-json:以loss-compare-metrics-v1格式写出结构化 JSON(sample_count、inference、unnormalized、normalized、pi05_distribution、aggregates),aggregates 汇总raw_l1/raw_cos/unnorm_l1/unnorm_cos、归一化空间平均 W1/std 与首帧余弦。

从 .agents/skills/om-convert/references/accuracy.md 可知,整个工作流只设置两道数值门:Torch vs ONNX 与 Torch vs Ascend OM。Torch-vs-OM 的契约是mean_l1_max与cosine_min;当前工具不输出全局 max-abs 指标,因此除非扩展实现,不得声称存在 Torch-vs-OM 的 max-abs 判定。

8.3 PI05 的混沌鲁棒分布度量

对于 PI05(10 步 Euler 积分 flow-matching ODE),逐点余弦相似度会被 ODE 的混沌放大效应破坏:即使实现数学上正确,微小扰动(如 fp16 KV-cache 漂移 1-cos ~ 2e-5)也会随步数指数放大,导致逐样本余弦塌缩到 0。因此 src/model_utils/model_utils/pi05_dist_metrics.py 提供了两种混沌鲁棒指标:

  • Method A — 逐 action 维边际 Wasserstein-1(W1/std):比较每个动作维的值分布而非逐点对齐,尺度不变;mean_ratio ≤ 0.05为 EXCELLENT(可部署),≤ 0.15GOOD,≤ 0.30MARGINAL,更大为 POOR;
  • Method C — 首帧余弦:滚动时域控制真正执行的是chunk[:, 0, :],该帧受混沌影响最小且唯一驱动物理运动;mean_cos ≥ 0.95EXCELLENT,≥ 0.80GOOD,≥ 0.50MARGINAL,更低为 POOR。

evaluate_pi05会同时对归一化与物理空间输出 W1/首帧余弦报告。最终部署验证仍建议在仿真或真机上做任务级成功率评估(模块注释中明确提示)。

九、交接报告:可审计的实验记录

跨主机检查结束后,记录以下内容,形成交接报告:

  • 执行的命令(含各主机上的实际参数);
  • 源/目标路径;
  • 各文件哈希;
  • 各主机工作区路径;
  • IB-Robot / LeRobot 修订号(SHA);
  • 每次传输由 Agent 还是用户执行;
  • 被测部署的soc_version、NPU、驱动、CANN、ATC、ACL、deployment 指纹与 ABI 哈希(若 OM 哈希变化,旧 OM 的精度结论失效)。

文档明确规定:输入不匹配的跨主机检查无效。换句话说,精度结论只有在「观测、目标、raw 目标、噪声全部来自同一封包且哈希一致」的前提下才成立。

十、落地到完整 OM 转换链路的衔接

multi-host-validation.md是om-convert工作流中「生成 Torch 目标后再测试 OM 精度」这一环节的专项规范,它与其他环节的衔接关系如下:

环节依据文档/实现与本工作流的衔接
前置信息采集om-convert/SKILL.md一次性采集三主机拓扑、bundle、部署、设备、远程执行许可
观测批次observation_batch.py本工作流第四节
目标生成loss_compare.py本工作流第五、六节
精度门限accuracy.md两道数值门;单一权威目标规则;精度预检
PI05 专项pi05.md目标仅从原 Torch 部署生成,噪声包按本文封包传输
性能基线benchmark.md精度通过后,每个 OM 跑ais_bench --loop 20,按角色调用次数加权计算total_mean_ms

对随机策略而言,「持久化噪声 + 逐主机消费同一噪声」是本工作流正确性的命门:验证「相同持久化噪声复现相同 Torch 动作、不同噪声产生不同动作、Ascend 运行消费的是传输过来的噪声而不是重新生成」,是每个随机策略家族通过精度验证前必须证明的三件事。谨记当前实现仅覆盖 PI05,其他家族需先扩展 codec/运行时与对比工具,再谈精度结论。

  • 具身智能
  • 机器人
  • 人工智能
  • 大模型
  • 模型推理服务
  • 本地部署
  • 计算机视觉
  • ROS

【免费下载链接】IB_Robot

Save the code of IB-Robot, an AI robot execution framework developed by openEuler Embedded for embodied intelligence scenarios. It includes references to the forked version of tensormsg, references to lerobot fork, code references to the lerobot_ros2:ros2_ws branch, as well as some code related to development usability.

项目地址:https://gitcode.com/openeuler/IB_Robot
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询