1use crate::config::Config;
2use anyhow::{Context, Result};
3use sha2::{Digest, Sha256};
4use std::path::PathBuf;
5
6pub async fn install_vector(
7 config: &Config,
8 from_file: Option<PathBuf>,
9 force: bool,
10) -> Result<()> {
11 let default_path = crate::config::get_data_dir().join("models/bge-micro-v2.onnx");
12 let model_path = config
13 .vector
14 .model_path
15 .as_ref()
16 .map(PathBuf::from)
17 .unwrap_or(default_path);
18
19 if let Some(parent) = model_path.parent() {
20 std::fs::create_dir_all(parent)?;
21 }
22
23 if let Some(src_path) = from_file {
24 println!("Copying model from {:?} to {:?}...", src_path, model_path);
25 std::fs::copy(&src_path, &model_path).context("Failed to copy custom model file")?;
26 } else {
27 let url = config
28 .vector
29 .model_url
30 .as_deref()
31 .unwrap_or("https://cdn.cmdhub.xyz/models/bge-micro-v2.onnx");
32 println!("Downloading model from {}...", url);
33 let response = reqwest::get(url).await?.bytes().await?;
34 std::fs::write(&model_path, response)?;
35 }
36
37 if !force {
39 let file_bytes = std::fs::read(&model_path)?;
40 let mut hasher = Sha256::new();
41 hasher.update(&file_bytes);
42 let hash_str = format!("{:x}", hasher.finalize());
43 let target_hash = config
44 .vector
45 .model_sha256
46 .as_deref()
47 .unwrap_or("d3b07384d113edec49eaa6238ad5ff00b192e2ad47a8a6cf23bdc1048b292e2a");
48 if hash_str != target_hash {
49 std::fs::remove_file(&model_path)?;
50 anyhow::bail!(
51 "SHA-256 verification failed. Expected {}, got {}",
52 target_hash,
53 hash_str
54 );
55 }
56 }
57 println!("Model installed successfully to {:?}", model_path);
58 Ok(())
59}