use cactus_rs::needle::{Needle, Weights};
fn cosine(left: &[f32], right: &[f32]) -> f32 {
let dot: f32 = left.iter().zip(right).map(|(a, b)| a * b).sum();
let left_norm = left.iter().map(|a| a * a).sum::<f32>().sqrt();
let right_norm = right.iter().map(|b| b * b).sum::<f32>().sqrt();
if left_norm == 0.0 || right_norm == 0.0 {
return 0.0;
}
dot / (left_norm * right_norm)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut needle = Needle::builder(Weights::fetch()?).build()?;
println!("dimension {}", needle.embedding_dimension()?);
let phrases = [
"send an email to Ada",
"email Ada a message",
"close the bedroom blinds",
];
let vectors = phrases
.iter()
.map(|phrase| needle.embed(phrase))
.collect::<Result<Vec<_>, _>>()?;
for (i, left) in phrases.iter().enumerate() {
for (j, right) in phrases.iter().enumerate().skip(i + 1) {
println!(
"{:.3} {left} <-> {right}",
cosine(&vectors[i], &vectors[j])
);
}
}
let related = cosine(&vectors[0], &vectors[1]);
let unrelated = cosine(&vectors[0], &vectors[2]).max(cosine(&vectors[1], &vectors[2]));
println!(
"related beats the closest unrelated pair by {:.3}",
related - unrelated
);
Ok(())
}