model.rs (1912B)
1 use anyhow::Result; 2 use serde::Serialize; 3 use std::path::Path; 4 use tch::{autocast, no_grad, CModule, Device, Tensor}; 5 6 #[derive(Debug, Clone, Copy, Serialize)] 7 pub enum Label { 8 Speech, 9 Music, 10 Noise, 11 } 12 13 pub struct Model { 14 model: CModule, 15 } 16 17 impl Model { 18 pub fn new<T>(model_path: T) -> Result<Model> 19 where 20 T: AsRef<Path>, 21 { 22 let device = Device::cuda_if_available(); 23 println!("Running model on {:?}", device); 24 Ok(Self { 25 model: CModule::load_on_device(model_path, device)?, 26 }) 27 } 28 29 pub fn label(&self, tensor: &Tensor) -> Result<Box<[Label]>> { 30 let raw_output = Vec::try_from( 31 no_grad(|| autocast(true, || tensor.apply(&self.model))) 32 .f_sigmoid()? 33 .flatten(0, -1), 34 )?; 35 36 let labels = raw_output 37 .chunks(527) 38 .map(|chunk| { 39 if chunk.len() != 527 { 40 return Ok(Label::Noise); 41 } 42 let output: [f32; 527] = chunk 43 .try_into() 44 .map_err(|_| anyhow::anyhow!("Failed to convert chunk to fixed-size array"))?; 45 46 let results = [ 47 (Label::Speech, output[0]), 48 (Label::Music, output[137]), 49 (Label::Noise, output[513]), 50 ]; 51 52 let label = if results[0].1 < 0.5 && results[1].1 < 0.5 { 53 Label::Noise 54 } else { 55 results 56 .iter() 57 .max_by(|a, b| a.1.total_cmp(&b.1)) 58 .map(|(label, _)| *label) 59 .unwrap_or(Label::Noise) 60 }; 61 62 Ok::<_, anyhow::Error>(label) 63 }) 64 .collect::<Result<Vec<_>>>()? 65 .into_boxed_slice(); 66 67 Ok(labels) 68 } 69 }