use super::catalog::QuantizeConfig;
use super::ModelService;
use anyhow::Result;
use indicatif::ProgressBar;
use std::path::{Path, PathBuf};
use tokio::fs;
impl ModelService {
#[cfg(feature = "model-download")]
pub(super) async fn quantize_model(
&self,
model_path: &Path,
config: &QuantizeConfig,
progress: Option<&ProgressBar>,
) -> Result<PathBuf> {
let int8_path = model_path.with_file_name("model-int8.onnx");
if int8_path.exists() {
if let Some(pb) = progress {
pb.set_message("INT8 model already cached");
}
return Ok(int8_path);
}
if let Some(pb) = progress {
pb.set_message("Quantizing model to INT8...");
}
match config.method.as_str() {
"dynamic_int8" => {
self.quantize_dynamic_int8(model_path, &int8_path).await?;
}
_ => {
anyhow::bail!("Unsupported quantization method: {}", config.method);
}
}
if let Some(pb) = progress {
pb.set_message("✅ INT8 model ready");
}
Ok(int8_path)
}
#[cfg(feature = "model-download")]
async fn quantize_dynamic_int8(&self, input: &Path, output: &Path) -> Result<()> {
let python = self.find_python()?;
let script = include_str!("../../../scripts/quantize_int8.py");
let script_path = std::env::temp_dir().join("mecha10_quantize_int8.py");
fs::write(&script_path, script).await?;
let output_result = tokio::process::Command::new(&python)
.arg(&script_path)
.arg(input)
.arg(output)
.output()
.await?;
let _ = fs::remove_file(&script_path).await;
if !output_result.status.success() {
let stderr = String::from_utf8_lossy(&output_result.stderr);
anyhow::bail!(
"Quantization failed: {}\n\nTip: Install with 'pip install onnx onnxruntime'",
stderr
);
}
Ok(())
}
}