xpuenabler/OpenVLA-OFT-LIBERO-130-QNN-CPU
By xpuenabler · ↓ 0 · ♥ 0 · Updated 2026-03-03
What's in this repo
This page lists the files in xpuenabler/OpenVLA-OFT-LIBERO-130-QNN-CPU, including action_head.onnx, llm_backbone_v7.onnx, llm_backbone_v9.onnx and more.
- 4 ONNX models (.onnx files)
- 21 files, including 6 .sh, 4 .py, 4 .onnx, 3 .so, 2 .json, 1 .md
- Last updated 2026-03-03
ONNX files
| File | Size | Download |
|---|---|---|
| onnx/action_head.onnx | — | Download |
| onnx/llm_backbone_v7.onnx | — | Download |
| onnx/llm_backbone_v9.onnx | — | Download |
| onnx/vision_encoder.onnx | — | Download |
How to use
These ONNX files can be loaded with ONNX Runtime. To inspect a model graph, upload the file to the Netron viewer. Download links point to the original files on Hugging Face.
README
OpenVLA-OFT LIBERO-10 — QNN FP32 CPU Inference
This repository contains QNN FP32 CPU models and inference scripts for running OpenVLA-OFT on the LIBERO-10 benchmark using Qualcomm AI Engine Direct (QNN SDK).
All inference runs on CPU using libQnnCpu.so.
Benchmark Results
| Model | Episodes | Success | Rate |
|---|---|---|---|
| ONNX (ORT CPU) | 30 | 21/30 | 70% |
| QNN v9 FP32 CPU | 30 | 17/30 | 57% |
Evaluated on LIBERO-10 tasks 0–9, 3 trials each, max 300 steps.
| Task | Description | ONNX | QNN v9 |
|---|---|---|---|
| 0 | put both alphabet soup and tomato sauce in basket | 3/3 100% | 3/3 100% |
| 1 | put both cream cheese box and butter in basket | 3/3 100% | 2/3 67% |
| 2 | turn on stove and put moka pot on it | 1/3 33% | 1/3 33% |
| 3 | put black bowl in bottom drawer of cabinet | 3/3 100% | 2/3 67% |
| 4 | put white mug on left plate and yellow mug on right plate | 3/3 100% | 3/3 100% |
| 5 | pick up book and place in back compartment of caddy | 3/3 100% | 3/3 100% |
| 6 | put white mug on plate and chocolate pudding to right | 2/3 67% | 2/3 67% |
| 7 | put both alphabet soup and cream cheese box in basket | 3/3 100% | 1/3 33% |
| 8 | put both moka pots on stove | 0/3 0% | 0/3 0% |
| 9 | put yellow and white mug in microwave | 0/3 0% | 0/3 0% |
Repository Structure
.
├── README.md
├── inference/
│ ├── infer_libero_episode_qnn_fp32_cpu_v9.py # QNN single-episode inference
│ ├── infer_libero_episode_onnx_cpu.py # ONNX single-episode inference
│ └── eval_libero_batch.py # Batch evaluation (ONNX + QNN)
├── conversion/
│ ├── make_llm_v9.py # Generate LLM backbone v9 ONNX (ScatterND+Trilu fix)
│ ├── convert_llm_v9.sh # Convert LLM v9 ONNX → QNN
│ ├── convert_ve.sh # Convert Vision Encoder ONNX → QNN
│ └── convert_ah.sh # Convert Action Head ONNX → QNN
├── onnx/
│ ├── vision_encoder.onnx # Vision Encoder ONNX model (894 KB)
│ └── action_head.onnx # Action Head ONNX model (3.9 KB)
├── qnn_models/ # Compiled QNN shared libraries (LFS)
│ ├── libvision_encoder_sliced.so # Vision Encoder QNN (2.9 GB)
│ ├── libaction_head.so # Action Head QNN (502 MB)
│ └── libllm_backbone.so # LLM Backbone QNN (25 GB)
└── eval_results/
├── onnx_results.json # ONNX batch evaluation results
└── qnn_v9_results.json # QNN v9 batch evaluation results
Prerequisites
Software
- QNN SDK: Qualcomm AI Engine Direct 2.43.0 (
qairt/2.43.0.260128) - Python 3.10 (for QNN conversion):
miniforge3/envs/qnn - Python 3.11 (for inference):
miniforge3/envs/openvla-oft - LIBERO installed in the inference environment
- OpenVLA-OFT RLinf codebase at
/home/work/nota-data/gmkim/RLinf
Base Model
Download the original OpenVLA-OFT LIBERO-130 checkpoint from HuggingFace:
huggingface-cli download xpuenabler/RLinf-OpenVLAOFT-LIBERO-130 \
--local-dir /path/to/models/RLinf-OpenVLAOFT-LIBERO-130
Update MODEL_PATH in all scripts to point to this directory.
QNN Model Libraries
The compiled .so files are stored in qnn_models/ via Git LFS:
git lfs install
git lfs pull
Place them as follows:
qnn_workspace/
├── vision_encoder_sliced_fp32/model_lib_x86/x86_64-linux-clang/libvision_encoder_sliced.so
├── llm_backbone_fp32_v9/model_lib_x86_bfd/libs/x86_64-linux-clang/libllm_backbone.so
└── ah_transpose_fix/model_lib_x86/x86_64-linux-clang/libaction_head.so
Or update MODEL_LIBS paths in infer_libero_episode_qnn_fp32_cpu_v9.py to point directly to the downloaded .so files.
Reproducing a Success Episode
The following reproduces Task 1 (cream cheese + butter → basket), Trial 38 which was verified as SUCCESS.
Step 1: Set up environment variables
export TMPDIR=/path/to/tmp_py # Required: /tmp may be full
export PYTHONNOUSERSITE=1 # Required: prevent sys-Python conflicts
export PYTHONPATH=/path/to/RLinf:/path/to/RLinf/venv-openvla-oft/lib/python3.11/site-packages:/path/to/RLinf/venv-openvla-oft/libero
Step 2: Run QNN inference
TMPDIR=/home/work/nota-data/gmkim/tmp_py \
PYTHONNOUSERSITE=1 \
PYTHONPATH=/home/work/nota-data/gmkim/RLinf:\
/home/work/nota-data/gmkim/RLinf/venv-openvla-oft/lib/python3.11/site-packages:\
/home/work/nota-data/gmkim/RLinf/venv-openvla-oft/libero \
/home/work/nota-data/gmkim/miniforge3/envs/openvla-oft/bin/python3.11 \
inference/infer_libero_episode_qnn_fp32_cpu_v9.py \
--task-id 1 \
--trial-id 38 \
--max-steps 300
Expected output:
EPISODE SUMMARY (QNN FP32 CPU v9)
Task [1]: put both the cream cheese box and the butter in the basket
Result: SUCCESS
Steps: 231 / 300
Running with ONNX (reference)
TMPDIR=/home/work/nota-data/gmkim/tmp_py \
PYTHONNOUSERSITE=1 \
PYTHONPATH=/home/work/nota-data/gmkim/RLinf:\
/home/work/nota-data/gmkim/RLinf/venv-openvla-oft/lib/python3.11/site-packages:\
/home/work/nota-data/gmkim/RLinf/venv-openvla-oft/libero \
/home/work/nota-data/gmkim/miniforge3/envs/openvla-oft/bin/python3.11 \
inference/infer_libero_episode_onnx_cpu.py \
--task-id 1 \
--trial-id 38 \
--max-steps 300
Batch Evaluation
# Evaluate ONNX (30 episodes, tasks 0-9, trials 0-2)
python inference/eval_libero_batch.py --model onnx
# Evaluate QNN v9 (same episodes)
python inference/eval_libero_batch.py --model qnn
# Compare results
python inference/eval_libero_batch.py --compare
Checkpoint files are saved automatically to eval_results/ so interrupted runs can be resumed.
ONNX → QNN Conversion
If you want to re-convert the models from ONNX:
Vision Encoder
bash conversion/convert_ve.sh
Action Head
bash conversion/convert_ah.sh
LLM Backbone (v9)
The LLM backbone requires two steps:
Step 1: Generate v9 ONNX (replaces ScatterND+Trilu with QNN-compatible ops):
# make_llm_v9.py reads onnx/llm_backbone_v7.onnx (included in this repo, 785KB header)
# External weight data (~25 GB) must be present in the same directory,
# exported from the original OpenVLA-OFT checkpoint.
TMPDIR=/home/work/nota-data/gmkim/tmp_py \
PYTHONNOUSERSITE=1 \
/home/work/nota-data/gmkim/miniforge3/envs/qnn/bin/python3.10 \
conversion/make_llm_v9.py
Note on external data:
llm_backbone_v7.onnxstores model weights as external data files (embed_tokens.weight,onnx__MatMul_*, etc., ~25 GB total).make_llm_v9.pyusesload_external_data=False(modifies graph structure only), so the 785KB.onnxheader in this repo is sufficient for graph transformation. However,qnn-onnx-converter(Step 2) requires the full weights — export them first from the original model checkpoint usingconversion/make_llm_v9.pyafter a full ONNX export.
Step 2: Convert to QNN + compile .so:
bash conversion/convert_llm_v9.sh
Note:
convert_llm_v9.shhandles the full pipeline:
qnn-onnx-converter→llm_backbone.cpp+llm_backbone.bin(~25 GB tar)- Build directory setup from QNN SDK templates
- Patches Makefile:
-fuse-ld=lld→-fuse-ld=bfd -nostartfiles(required for >2 GB data)make→libllm_backbone.so(~25 GB, takes ~1 hour)
Technical Notes
v9 LLM Backbone
The original ONNX LLM backbone contains ScatterND and Trilu ops that QNN's CPU backend cannot execute. v9 replaces them with a static subgraph:
- ScatterND → Replaced with
Cast + Concat + Sub + Mul + Reshape + Addusing precomputed causal mask - Trilu → Replaced with
Identityon a precomputed upper-triangular constant
Cosine similarity between v9 QNN output and original ONNX: cos = 0.962
Tensor Layout Differences (ONNX vs QNN)
| Component | ONNX input | QNN input |
|---|---|---|
Vision Encoder pixel_values |
[1, 6, 224, 224] NCHW |
[1, 224, 224, 6] NHWC |
LLM patch_features |
[1, 256, 4096] |
[1, 4096, 256] NCF |
Action Head hidden_states |
[1, 440, 4096] |
[1, 4096, 440] NCF |
All transpositions are handled automatically in the inference scripts.
LLM Backbone Input Specification (v9)
| Tensor | Shape | Dtype | Notes |
|---|---|---|---|
input_ids_no_stop |
[1, 184] |
int32 | Native int (no cast) |
patch_features |
[1, 4096, 256] |
float32 | NCF layout |
attention_mask |
[1, 184] |
int32 | Native int (no cast) |
output hidden_states |
[1, 440, 4096] |
float32 |
Citation
@article{kim2024openvla,
title={OpenVLA-OFT: Efficient Fine-Tuning of Open-Source Vision-Language-Action Models},
author={Kim, Moojin and others},
year={2024}
}
Files (21)
Related models
More from xpuenabler
More models
No task type declared.