use std::collections::HashMap;
use std::path::Path;
use anyhow::{anyhow, Result};
use rten::Value as RtenValue;
use rten::{Model as RtenGraph, NodeId};
use rten_tensor::{AsView, Layout};
use super::{Model, Runtime, Tensor};
pub struct RtenRuntime;
impl Runtime for RtenRuntime {
type Model = RtenModel;
fn load_model(&self, path: &Path) -> Result<RtenModel> {
let model = RtenGraph::load_file(path)?;
let input_map: HashMap<String, NodeId> = model
.input_ids()
.iter()
.filter_map(|&id| {
let info = model.node_info(id)?;
let name = info.name()?;
Some((name.to_string(), id))
})
.collect();
let output_names: Vec<(NodeId, String)> = model
.output_ids()
.iter()
.filter_map(|&id| {
let info = model.node_info(id)?;
let name = info.name()?;
Some((id, name.to_string()))
})
.collect();
let output_ids: Vec<NodeId> = model.output_ids().to_vec();
Ok(RtenModel {
model,
input_map,
output_names,
output_ids,
})
}
}
pub struct RtenModel {
model: RtenGraph,
input_map: HashMap<String, NodeId>,
output_names: Vec<(NodeId, String)>,
output_ids: Vec<NodeId>,
}
impl Model for RtenModel {
fn run(&mut self, inputs: &[(&str, &Tensor)]) -> Result<HashMap<String, Tensor>> {
let rten_inputs: Vec<(NodeId, RtenValue)> = inputs
.iter()
.map(|(name, tensor)| {
let node_id = self
.input_map
.get(*name)
.ok_or_else(|| anyhow!("rten: unknown input name '{}'", name))?;
let value = RtenValue::from_shape(tensor.shape.as_slice(), tensor.data.clone())
.map_err(|e| {
anyhow!("rten: failed to create input tensor '{}': {}", name, e)
})?;
Ok((*node_id, value))
})
.collect::<Result<Vec<_>>>()?;
let inputs_with_views: Vec<_> = rten_inputs
.iter()
.map(|(id, val)| (*id, val.into()))
.collect();
let outputs = self.model.run(inputs_with_views, &self.output_ids, None)?;
let mut result = HashMap::new();
for (&id, value) in self.output_ids.iter().zip(outputs.into_iter()) {
let name = self
.output_names
.iter()
.find(|(nid, _)| *nid == id)
.map(|(_, n)| n.clone())
.unwrap_or_else(|| format!("output_{:?}", id));
let rten_tensor = value
.into_tensor::<f32>()
.ok_or_else(|| anyhow!("rten: output '{}' is not f32", name))?;
let shape: Vec<usize> = rten_tensor.shape().to_vec();
let data: Vec<f32> = rten_tensor.to_vec();
result.insert(name, Tensor { shape, data });
}
Ok(result)
}
}