use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt::Debug;
use crate::error::Result;
use crate::hyperdim::HVec10240;
use crate::singularity::Concept;
pub mod brute_force;
#[cfg(feature = "ann-hnsw")]
pub mod hnsw;
#[cfg(feature = "ann-lsh")]
pub mod lsh;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct IndexStats {
pub backend: String,
pub count: usize,
pub memory_usage_bytes: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
pub enum IndexBackend {
#[default]
BruteForce,
#[cfg(feature = "ann-hnsw")]
Hnsw {
m: usize,
ef_construction: usize,
ef_search: usize,
},
#[cfg(feature = "ann-lsh")]
Lsh {
num_tables: usize,
hash_bits: usize,
},
}
pub trait AnnIndex: Send + Sync + Debug {
fn insert(&mut self, id: String, vec: &HVec10240) -> Result<()>;
fn delete(&mut self, id: &str) -> Result<()>;
fn search(&self, query: &HVec10240, top_k: usize) -> Result<Vec<(String, f32)>>;
fn search_filtered(
&self,
query: &HVec10240,
top_k: usize,
filter: &crate::metadata_filter::MetadataFilter,
concepts: &std::collections::HashMap<String, crate::singularity::Concept>,
) -> Result<Vec<(String, f32)>>;
fn rebuild(&mut self, concepts: &HashMap<String, Concept>) -> Result<()>;
fn stats(&self) -> IndexStats;
fn serialize(&self) -> Result<Vec<u8>>;
fn deserialize(&mut self, data: &[u8]) -> Result<()>;
}
pub fn create_index(backend: &IndexBackend) -> Result<Box<dyn AnnIndex>> {
let index: Box<dyn AnnIndex> = match backend {
IndexBackend::BruteForce => Box::new(brute_force::BruteForce::new()),
#[cfg(feature = "ann-hnsw")]
IndexBackend::Hnsw {
m,
ef_construction,
ef_search,
} => Box::new(hnsw::HnswIndex::new(*m, *ef_construction, *ef_search)?),
#[cfg(feature = "ann-lsh")]
IndexBackend::Lsh {
num_tables,
hash_bits,
} => Box::new(lsh::LshIndex::new(*num_tables, *hash_bits)?),
#[allow(unreachable_patterns)]
_ => Box::new(brute_force::BruteForce::new()),
};
Ok(index)
}