#![cfg(feature = "onnx")]
use crate::{BundleIo, BundleMeta};
use anyhow::{Context, Result};
use rlx_ir::hir::HirModule;
use std::collections::HashMap;
use std::path::Path;
pub fn import_onnx(
path: &Path,
) -> Result<(
HirModule,
HashMap<String, Vec<f32>>,
rlx_onnx_import::BundleManifest,
)> {
let opts = rlx_onnx_import::ImportOptions {
strict: false,
..Default::default()
};
let (hir, params, _report, manifest) = rlx_onnx_import::build_hir_from_onnx_file(path, opts)
.with_context(|| format!("importing ONNX {}", path.display()))?;
Ok((hir, params, manifest))
}
fn write_safetensors_f32(path: &Path, params: &HashMap<String, Vec<f32>>) -> Result<()> {
use safetensors::tensor::{Dtype, TensorView};
let bufs: Vec<(String, Vec<u8>)> = params
.iter()
.map(|(k, d)| {
(
k.clone(),
d.iter().flat_map(|f| f.to_le_bytes()).collect::<Vec<u8>>(),
)
})
.collect();
let mut views: Vec<(String, TensorView)> = Vec::with_capacity(bufs.len());
for (k, b) in &bufs {
views.push((
k.clone(),
TensorView::new(Dtype::F32, vec![b.len() / 4], b)?,
));
}
safetensors::serialize_to_file(views, None, path)?;
Ok(())
}
fn dims_of(meta: &rlx_onnx_import::IoMeta) -> Vec<usize> {
meta.meta
.shape
.iter()
.map(|v| v.as_i64().unwrap_or(1).max(0) as usize)
.collect()
}
pub fn emit_onnx_bundle(onnx_path: &Path, bundle_dir: &Path) -> Result<BundleMeta> {
std::fs::create_dir_all(bundle_dir)?;
let (hir, params, manifest) = import_onnx(onnx_path)?;
let json = rlx_ir::hir_to_json(&hir).context("serializing HIR")?;
std::fs::write(bundle_dir.join("model.hir.json"), json)?;
write_safetensors_f32(&bundle_dir.join("weights.safetensors"), ¶ms)?;
let meta = BundleMeta {
name: onnx_path
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("onnx_model")
.to_string(),
inputs: manifest
.inputs
.iter()
.map(|io| BundleIo {
name: io.name.clone(),
shape: dims_of(io),
dtype: io.meta.dtype.to_lowercase(),
})
.collect(),
output_count: manifest.outputs.len(),
zero_params: Vec::new(),
};
std::fs::write(
bundle_dir.join("meta.json"),
serde_json::to_string_pretty(&meta)?,
)?;
Ok(meta)
}