mecha10-models 0.9.0

Mecha10 model services — ML model management and Minio download support
Documentation
//! INT8 quantization (shells out to an embedded Python + onnxruntime script)

use super::catalog::QuantizeConfig;
use super::ModelService;
use anyhow::Result;
use indicatif::ProgressBar;
use std::path::{Path, PathBuf};
use tokio::fs;

impl ModelService {
    /// Quantize a model to INT8 (calls embedded Python script)
    #[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)
    }

    /// Perform dynamic INT8 quantization using ONNX Runtime tools
    #[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(())
    }
}