本目录是 X-VLA-Libero (2toINF/X-VLA-Libero) 在华为 Ascend NPU 上的 PyTorch 推理适配版本,
通过 ascend-model-agent-plugin/adapt-agent
的 10 步 Playbook 完成模型分析 → 代码适配 → 双阶段验证 → 产物交付。
| 项目 | 说明 |
|---|---|
| 模型名 | X-VLA-Libero |
| 来源 | 2toINF/X-VLA-Libero |
| 任务类型 | Vision-Language-Action (机器人动作预测,Libero 基准) |
| 参数量 | 932 M (≈ 0.9 B) |
| 输入 | (1~3 张) PIL.Image + 自然语言指令 + proprio (20,) + domain_id int |
| 输出 | (1, num_actions=30, dim_action=20) 末端执行器动作(ee6d) |
| 框架 | PyTorch + torch_npu (Ascend910) + Transformers 5.x |
模型架构:
ee6d):末端执行器动作空间 + 预处理/后处理 + 损失函数训练范式:flow-matching — 迭代去噪 10 步生成 30 步动作轨迹。
完整 10 步流程见
assets/agent_workflow.png
Step 1 Collect Context ─┐
Step 2 Analyze Model │ 模型: 2toINF/X-VLA-Libero
Step 3 Operator Gate │ 权重: safetensors 3.5 GB
Step 4 Framework Analysis │ 设备: 16× Ascend910 NPU
Step 5 Adapt Strategy │ 框架: PyTorch + torch_npu + transformers 5.x
│
Step 6 Implement Code ─────┤
├─ xvla_models/ (remote code, NPU 适配补丁) │
├─ inference.py │ (服务化推理入口)
└─ test_xvla_libero_npu.py │
│
Step 7 Two-Stage Validate ─┤
├─ Stage A: dummy ──────┼─ OK
└─ Stage B: real weights ┼─ OK
│
Step 8 Feature Validate ──┤
├─ /health ────────────┼─ OK
└─ /act ────────────┼─ OK
│
Step 9 Backport & Artifacts ┤
Step 10 Handoff Report ──────┘NPU 注入:在所有 import torch 之前插入
import torch_npu
from torch_npu.contrib import transfer_to_nputransformers 5.x 兼容性补丁(针对官方 remote code):
Florence2PreTrainedModel._supports_sdpa = False / _supports_flash_attn_2 = False
(新版 transformers 不再从 PreTrainedModel 自动继承 GenerationMixin,
官方将 _supports_sdpa 写成访问 self.language_model 的 property 会触发 AttributeError)Florence2Config.florence_config.text_config.tie_word_embeddings = False
(XVLA 仅使用 encoder,关闭 lm_head/decoder 的自动绑定,避免加载阶段查找已删除的子模块)Florence2LanguageModel._tied_weights_keys / Florence2LanguageForConditionalGeneration._tied_weights_keys /
Florence2ForConditionalGeneration._tied_weights_keys 改为 dict 格式
(transformers 5.x 要求 {target: source} 而非 list)Florence2LanguageConfig.__init__ 中显式初始化 forced_bos_token_id
(新版 PretrainedConfig 不再自动初始化该字段)XVLA.__init__ 末尾增加 self.post_init()
(强制初始化 all_tied_weights_keys,否则 from_pretrained 会触发 AttributeError)XVLA.__init__ 中 del lm.model.decoder / lm.lm_head 移到 post_init() 之后
(避免加载阶段 _finalize_model_loading 找不到被删除的子模块)Tokenizer 修复:X-VLA 自带的 tokenizer 缺失 pad_token / eos_token / bos_token,
显式注册 <pad>=1 / </s>=2 / <s>=0(与官方 BART 配置一致)。
算子兼容:全部算子均为原生 PyTorch(Linear / Embedding / Matmul / Softmax / LayerNorm / Attention 等),无 CUDA-only / Triton-only 算子,可直接在 NPU 上运行。
CPU/NPU 一致性:通过 torch.manual_seed(7) 在每次推理前固定随机状态,
验证量级一致即可(浮点与算子编译差异导致 bit-equal 不可达)。
| 指标 | 实测值 |
|---|---|
| CPU/NPU 最大绝对误差(10 步 flow-matching) | 0.0003 |
| CPU/NPU 相对误差 | < 1% |
| 固定 seed 确定性 | max diff = 0.0(bit-exact) |
| 不同 domain_id 动作差异 | 0.1661(soft prompt 有效) |
| NPU 端到端推理(10 步) | ~140 ms |
| CPU 端到端推理(10 步) | ~42 s |
| 加速比 | ~300× |
X-VLA-Libero-npu/
├── README.md # 本文件
├── requirements.txt # 运行环境依赖
├── inference.py # 服务化推理入口(自测 + Flask)
├── test_xvla_libero_npu.py # 迁移测试用例(T1-T6, 共21项 PASS)
├── generate_screenshots.py # 三张截图生成脚本
├── xvla_models/ # 模型代码(NPU 适配补丁)
│ ├── __init__.py
│ ├── modeling_xvla.py # XVLA 主类(post_init + decoder 删除顺序)
│ ├── modeling_florence2.py # Florence2(_tied_weights_keys dict + 兼容补丁)
│ ├── configuration_xvla.py # XVLAConfig(tie_word_embeddings=False)
│ ├── configuration_florence2.py # Florence2Config(forced_bos_token_id 兼容)
│ ├── processing_xvla.py # XVLAProcessor
│ ├── transformer.py # SoftPromptedTransformer
│ ├── action_hub.py # 末端执行器动作空间
│ ├── config.json # 模型配置
│ ├── preprocessor_config.json # 图像预处理
│ ├── tokenizer.json / tokenizer_config.json
├── assets/
│ ├── npu_device_call.png # NPU 设备调用截图
│ ├── model_result.png # 测试结果截图(21 项 PASS)
│ └── agent_workflow.png # 适配过程截图
└── logs/
└── test_run.log # 完整测试日志
```bash
# 加载昇腾环境
source /usr/local/Ascend/ascend-toolkit/set_env.sh
# 进入交付目录
cd /mnt/old_data/whl/models/shipei-code/X-VLA-Libero-npu
# 安装依赖
pip install -r requirements.txt已验证的运行时环境:
- torch 2.9.0+cpu
- torch_npu 2.9.0.post1+gitee7ba04
- transformers 5.9.0(官方要求 ≤4.51.3,本适配已修复 5.x 兼容问题)
- Ascend910 × 16(
npu-smi info可见)
python3 inference.py --mode test输出示例:
============================================================
[test] device = npu
============================================================
[init] device = npu
[init] loaded XVLA-Libero from /mnt/old_data/whl/models/2toINF/X-VLA-Libero, params=932002392
[init] warmup done
[test] action shape = (1, 30, 20)
[test] NPU vs CPU max abs diff = 0.0003
[test] domain-change diff mean = 0.1661
[test] avg inference latency (steps=10) = 138.5 ms
[test] RESULT: PASSEDpython3 inference.py --mode serve --host 127.0.0.1 --port 8094服务接口:
| Method | Path | 说明 |
|---|---|---|
| GET | /health | 健康检查 |
| POST | /act | 动作预测:多视角图像 base64 + 指令 + proprio + domain_id |
POST /act 调用示例:
curl -s -X POST http://127.0.0.1:8094/act \
-H 'Content-Type: application/json' \
-d '{
"images": ["<base64-jpeg-1>", "<base64-jpeg-2>"],
"language_instruction": "move the object to the left",
"proprio": [0.0, 0.0, ...] // 20 维
"domain_id": 0,
"steps": 10
}'返回:
{
"action": [[[...30 行 × 20 列...]]],
"steps": 10,
"num_views": 2,
"latency_ms": 137.06
}python3 test_xvla_libero_npu.py| 用例 | 覆盖 | 期望 |
|---|---|---|
| T1 | NPU 环境与设备调用 | torch / torch_npu 可用;NPU tensor 算子通过 |
| T2 | 模型加载 | XVLA 在 NPU 上加载,932M 参数量 |
| T3 | 端到端推理 | action shape (1, 30, 20),有限,量级合理 |
| T4 | CPU/NPU 一致性 | 固定 seed 下,max abs diff < 0.05 |
| T5 | 多 domain 区分 | 不同 domain_id 产生不同动作;固定 seed 确定性 |
| T6 | 服务化接口 | /health + /act 接口返回正确 |
实测结果:PASS=21 FAIL=0,详见
assets/model_result.png与logs/test_run.log。
assets/npu_device_call.png)展示 npu-smi info 的 16 张 Ascend910 卡 + torch.npu.is_available() == True、
npu_count == 16、以及 tensor @ tensor 算子在 NPU 上的设备判定。
assets/model_result.png)21 项测试用例全部 PASSED,含 CPU/NPU 对比(0.0003)、多 domain 区分(0.1661)、
服务化 GET /health + POST /act 验证。
assets/agent_workflow.png)依据 ascend-model-agent-plugin/adapt-agent 的 10-Step Playbook,从
Collect Context → Handoff Report 的完整流程图。
| 现象 | 原因 | 解决 |
|---|---|---|
torch.npu.is_available() == False | 未加载 Ascend toolkit | source /usr/local/Ascend/ascend-toolkit/set_env.sh |
from torch_npu.contrib import transfer_to_npu 报警告 | 注入位置不对 | 必须在所有 import torch 之前 |
MISSING: encoder.embed_tokens.weight | transformers 5.x 自动 binding 与 XVLA 不兼容 | 已通过 tie_word_embeddings=False + _tied_weights_keys 字典化修复,可忽略 |
ValueError: tokenizer.pad_token is None | X-VLA tokenizer 缺失特殊 token | 已显式注册 <pad>=1 / </s>=2 / <s>=0 |
Florence2LanguageModel has no attribute decoder | transformers 5.x _finalize_model_loading 找不到被删除的子模块 | 已将 del decoder / lm_head 移到 post_init() 之后 |
Florence2LanguageForConditionalGeneration has no attribute encoder | _tied_weights_keys 路径错 | 已修正为 model.encoder.embed_tokens.weight: model.shared.weight |
AttributeError: 'Florence2LanguageConfig' object has no attribute 'forced_bos_token_id' | 新版 PretrainedConfig 不自动初始化 | 已显式 self.forced_bos_token_id = kwargs.get("forced_bos_token_id", None) |
AttributeError: 'list' object has no attribute 'keys' | _tied_weights_keys 旧版为 list | 已改为 dict 格式 {target: source} |
| 场景 | 设备 | 耗时 (steps=10, 2 views, 224×224) |
|---|---|---|
| 端到端推理 | Ascend910 | ~140 ms |
| 端到端推理 | CPU | ~42 000 ms |
NPU 相对 CPU 加速 ~300×。