#![allow(dead_code)]
use crate::error::{IoError, Result};
use crate::ml_framework::converters::MLFrameworkConverter;
use crate::ml_framework::types::{MLFramework, MLModel, MLTensor};
use scirs2_core::ndarray::{ArrayD, IxDyn};
use std::fs::File;
use std::path::Path;
pub struct JAXConverter;
impl MLFrameworkConverter for JAXConverter {
fn save_model(&self, model: &MLModel, path: &Path) -> Result<()> {
let jax_model = serde_json::json!({
"format": "jax",
"version": "0.4.0",
"pytree": {
"params": model.weights.iter().map(|(name, tensor)| {
(name.clone(), serde_json::json!({
"shape": tensor.metadata.shape,
"dtype": format!("{:?}", tensor.metadata.dtype),
"data": tensor.data.as_slice().expect("Operation failed").to_vec()
}))
}).collect::<serde_json::Map<String, serde_json::Value>>(),
"config": model.config
},
"metadata": model.metadata
});
let file = File::create(path).map_err(IoError::Io)?;
serde_json::to_writer_pretty(file, &jax_model)
.map_err(|e| IoError::SerializationError(e.to_string()))
}
fn load_model(&self, path: &Path) -> Result<MLModel> {
let file = File::open(path).map_err(IoError::Io)?;
let jax_model: serde_json::Value = serde_json::from_reader(file)
.map_err(|e| IoError::SerializationError(e.to_string()))?;
let mut model = MLModel::new(MLFramework::JAX);
if let Some(metadata) = jax_model.get("metadata") {
model.metadata = serde_json::from_value(metadata.clone())
.map_err(|e| IoError::SerializationError(e.to_string()))?;
}
if let Some(pytree) = jax_model.get("pytree") {
if let Some(params) = pytree.get("params").and_then(|v| v.as_object()) {
for (name, param_data) in params {
let shape: Vec<usize> = serde_json::from_value(param_data["shape"].clone())
.map_err(|e| IoError::SerializationError(e.to_string()))?;
let data: Vec<f32> = serde_json::from_value(param_data["data"].clone())
.map_err(|e| IoError::SerializationError(e.to_string()))?;
let array = ArrayD::from_shape_vec(IxDyn(&shape), data)
.map_err(|e| IoError::Other(e.to_string()))?;
model
.weights
.insert(name.clone(), MLTensor::new(array, Some(name.clone())));
}
}
if let Some(config) = pytree.get("config") {
model.config = serde_json::from_value(config.clone())
.map_err(|e| IoError::SerializationError(e.to_string()))?;
}
}
Ok(model)
}
fn save_tensor(&self, tensor: &MLTensor, path: &Path) -> Result<()> {
let tensor_data = serde_json::json!({
"jax_array": {
"shape": tensor.metadata.shape,
"dtype": format!("{:?}", tensor.metadata.dtype),
"data": tensor.data.as_slice().expect("Operation failed").to_vec(),
"weak_type": false
}
});
let file = File::create(path).map_err(IoError::Io)?;
serde_json::to_writer_pretty(file, &tensor_data)
.map_err(|e| IoError::SerializationError(e.to_string()))
}
fn load_tensor(&self, path: &Path) -> Result<MLTensor> {
let file = File::open(path).map_err(IoError::Io)?;
let tensor_data: serde_json::Value = serde_json::from_reader(file)
.map_err(|e| IoError::SerializationError(e.to_string()))?;
if let Some(jax_array) = tensor_data.get("jax_array") {
let shape: Vec<usize> = serde_json::from_value(jax_array["shape"].clone())
.map_err(|e| IoError::SerializationError(e.to_string()))?;
let data: Vec<f32> = serde_json::from_value(jax_array["data"].clone())
.map_err(|e| IoError::SerializationError(e.to_string()))?;
let array = ArrayD::from_shape_vec(IxDyn(&shape), data)
.map_err(|e| IoError::Other(e.to_string()))?;
return Ok(MLTensor::new(array, None));
}
Err(IoError::Other("Invalid JAX tensor format".to_string()))
}
}