use crate::types::Embedder;
pub const BUNDLED_EMBEDDER_DIM: usize = 64;
const POTION_2M_MODEL: &[u8] = include_bytes!("../../assets/potion-base-2M/model.safetensors");
const POTION_2M_TOKENIZER: &[u8] = include_bytes!("../../assets/potion-base-2M/tokenizer.json");
const POTION_2M_CONFIG: &[u8] = include_bytes!("../../assets/potion-base-2M/config.json");
const POTION_2M_MODULES: &[u8] = include_bytes!("../../assets/potion-base-2M/modules.json");
#[derive(Clone)]
pub struct BundledEmbedder {
inner: std::sync::Arc<once_cell_lite::Lazy>,
}
mod once_cell_lite {
use model2vec_rs::model::StaticModel;
use std::sync::OnceLock;
static MODEL: OnceLock<Result<StaticModel, String>> = OnceLock::new();
pub struct Lazy;
impl Lazy {
pub fn new() -> Self {
Self
}
pub fn get(&self) -> Result<&'static StaticModel, &'static str> {
match MODEL.get_or_init(init_model) {
Ok(m) => Ok(m),
Err(e) => Err(e.as_str()),
}
}
}
fn init_model() -> Result<StaticModel, String> {
use std::io::Write;
let temp = std::env::temp_dir()
.join("yantrikdb")
.join(format!("potion-2M-{}", std::process::id()));
std::fs::create_dir_all(&temp)
.map_err(|e| format!("create temp dir {}: {e}", temp.display()))?;
for (name, bytes) in [
("model.safetensors", super::POTION_2M_MODEL),
("tokenizer.json", super::POTION_2M_TOKENIZER),
("config.json", super::POTION_2M_CONFIG),
("modules.json", super::POTION_2M_MODULES),
] {
let path = temp.join(name);
if matches!(std::fs::metadata(&path), Ok(m) if m.len() == bytes.len() as u64) {
continue;
}
let staging = temp.join(format!("{name}.{}.partial", std::process::id()));
{
let mut f = std::fs::File::create(&staging)
.map_err(|e| format!("create {}: {e}", staging.display()))?;
f.write_all(bytes)
.map_err(|e| format!("write {}: {e}", staging.display()))?;
f.sync_all()
.map_err(|e| format!("sync {}: {e}", staging.display()))?;
}
std::fs::rename(&staging, &path)
.map_err(|e| format!("publish {}: {e}", path.display()))?;
}
StaticModel::from_pretrained(&temp, None, None, None)
.map_err(|e| format!("model2vec_rs load: {e}"))
}
}
pub const BUNDLED_EMBEDDER_NAME: &str = "potion-base-2M";
pub fn bundled_embedder_fingerprint() -> &'static str {
static FP: std::sync::OnceLock<String> = std::sync::OnceLock::new();
FP.get_or_init(|| {
let mut h = blake3::Hasher::new();
h.update(b"yantrikdb.embedder.v1");
h.update(BUNDLED_EMBEDDER_NAME.as_bytes());
for bytes in [
POTION_2M_MODEL,
POTION_2M_TOKENIZER,
POTION_2M_CONFIG,
POTION_2M_MODULES,
] {
h.update(&(bytes.len() as u64).to_le_bytes());
h.update(bytes);
}
format!("blake3:{}", h.finalize().to_hex())
})
}
impl BundledEmbedder {
pub fn new() -> Self {
Self {
inner: std::sync::Arc::new(once_cell_lite::Lazy::new()),
}
}
}
impl Default for BundledEmbedder {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Debug for BundledEmbedder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BundledEmbedder")
.field("model", &"potion-base-2M")
.field("dim", &BUNDLED_EMBEDDER_DIM)
.finish()
}
}
impl Embedder for BundledEmbedder {
fn embed(
&self,
text: &str,
) -> std::result::Result<Vec<f32>, Box<dyn std::error::Error + Send + Sync>> {
let model = self
.inner
.get()
.map_err(|e| -> Box<dyn std::error::Error + Send + Sync> { e.to_string().into() })?;
Ok(model.encode_single(text))
}
fn embed_batch(
&self,
texts: &[&str],
) -> std::result::Result<Vec<Vec<f32>>, Box<dyn std::error::Error + Send + Sync>> {
let model = self
.inner
.get()
.map_err(|e| -> Box<dyn std::error::Error + Send + Sync> { e.to_string().into() })?;
let owned: Vec<String> = texts.iter().map(|s| (*s).to_string()).collect();
Ok(model.encode(&owned))
}
fn dim(&self) -> usize {
BUNDLED_EMBEDDER_DIM
}
fn fingerprint(&self) -> Option<String> {
Some(bundled_embedder_fingerprint().to_string())
}
fn name(&self) -> Option<String> {
Some(BUNDLED_EMBEDDER_NAME.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dim_is_64() {
assert_eq!(BundledEmbedder::new().dim(), BUNDLED_EMBEDDER_DIM);
assert_eq!(BUNDLED_EMBEDDER_DIM, 64);
}
#[test]
fn bundled_json_assets_have_no_crlf() {
for (name, bytes) in [
("tokenizer.json", POTION_2M_TOKENIZER),
("config.json", POTION_2M_CONFIG),
("modules.json", POTION_2M_MODULES),
] {
assert!(
!bytes.windows(2).any(|w| w == b"\r\n"),
"{name} was compiled in with CRLF line endings. The model still \
works, which is what makes this dangerous: the fingerprint \
changes, so packs built against a build of this crate on \
another platform will be refused at mount with \
PackEmbedderMismatch. Check that .gitattributes still marks \
crates/yantrikdb-core/assets/** as -text, then re-checkout."
);
}
}
#[test]
fn embed_returns_64_dim_vector() {
let e = BundledEmbedder::new();
let v = e.embed("Alice is the engineering lead at Acme").unwrap();
assert_eq!(v.len(), 64);
}
#[test]
fn embed_returns_l2_normalized_vector() {
let e = BundledEmbedder::new();
let v = e.embed("Project Atlas launches in March").unwrap();
let norm: f32 = v.iter().map(|x| x * x).sum::<f32>().sqrt();
assert!((norm - 1.0).abs() < 1e-3, "expected unit-norm; got {norm}");
}
#[test]
fn embed_is_deterministic_across_calls() {
let e = BundledEmbedder::new();
let a = e.embed("Acme Corporation").unwrap();
let b = e.embed("Acme Corporation").unwrap();
assert_eq!(a, b, "same input must yield same vector");
}
#[test]
fn concurrent_construction_loads_one_consistent_model() {
const THREADS: usize = 16;
let reference = BundledEmbedder::new().embed("consistency probe").unwrap();
let vectors: Vec<Vec<f32>> = std::thread::scope(|s| {
let handles: Vec<_> = (0..THREADS)
.map(|_| {
s.spawn(|| {
BundledEmbedder::new()
.embed("consistency probe")
.expect("concurrent construction must not tear the model load")
})
})
.collect();
handles.into_iter().map(|h| h.join().unwrap()).collect()
});
for (i, v) in vectors.iter().enumerate() {
assert_eq!(
v, &reference,
"thread {i} loaded a different model than the reference — torn extraction"
);
}
}
#[test]
fn embed_batch_matches_single() {
let e = BundledEmbedder::new();
let inputs = ["one fish", "two fish", "red fish"];
let single: Vec<Vec<f32>> = inputs.iter().map(|t| e.embed(t).unwrap()).collect();
let batch = e.embed_batch(&inputs).unwrap();
assert_eq!(single.len(), batch.len());
for (s, b) in single.iter().zip(batch.iter()) {
assert_eq!(s.len(), b.len(), "dim mismatch single vs batch");
for (x, y) in s.iter().zip(b.iter()) {
assert!(
(x - y).abs() < 1e-5,
"single vs batch divergence: {x} vs {y}"
);
}
}
}
#[test]
fn semantically_similar_texts_score_higher_than_unrelated() {
let e = BundledEmbedder::new();
let a = e.embed("Alice is the engineering lead").unwrap();
let b = e.embed("Alice runs the technical team").unwrap();
let c = e.embed("the lunch menu has pasta today").unwrap();
let cos =
|x: &[f32], y: &[f32]| -> f32 { x.iter().zip(y.iter()).map(|(a, b)| a * b).sum() };
let sim_ab = cos(&a, &b);
let sim_ac = cos(&a, &c);
assert!(
sim_ab > sim_ac,
"semantic match should beat unrelated; sim_ab={sim_ab} sim_ac={sim_ac}"
);
}
}