use crate::hnsw::HnswParams;
#[derive(Debug, Clone, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum IndexType {
#[default]
Hnsw,
HnswPq,
IvfPq,
}
impl IndexType {
pub fn parse(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"hnsw" | "" => Some(Self::Hnsw),
"hnsw_pq" => Some(Self::HnswPq),
"ivf_pq" | "ivfpq" => Some(Self::IvfPq),
_ => None,
}
}
}
#[derive(Debug, Clone)]
pub struct IndexConfig {
pub hnsw: HnswParams,
pub index_type: IndexType,
pub pq_m: usize,
pub ivf_cells: usize,
pub ivf_nprobe: usize,
}
pub const DEFAULT_PQ_M: usize = 8;
pub const DEFAULT_IVF_CELLS: usize = 256;
pub const DEFAULT_IVF_NPROBE: usize = 16;
impl Default for IndexConfig {
fn default() -> Self {
Self {
hnsw: HnswParams::default(),
index_type: IndexType::Hnsw,
pq_m: DEFAULT_PQ_M,
ivf_cells: DEFAULT_IVF_CELLS,
ivf_nprobe: DEFAULT_IVF_NPROBE,
}
}
}
impl IndexConfig {
#[cfg(feature = "ivf")]
pub fn to_ivf_params(&self) -> crate::ivf::IvfPqParams {
crate::ivf::IvfPqParams {
n_cells: self.ivf_cells,
pq_m: self.pq_m,
pq_k: 256,
nprobe: self.ivf_nprobe,
metric: self.hnsw.metric,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_index_type() {
assert_eq!(IndexType::parse("hnsw"), Some(IndexType::Hnsw));
assert_eq!(IndexType::parse(""), Some(IndexType::Hnsw));
assert_eq!(IndexType::parse("hnsw_pq"), Some(IndexType::HnswPq));
assert_eq!(IndexType::parse("ivf_pq"), Some(IndexType::IvfPq));
assert_eq!(IndexType::parse("ivfpq"), Some(IndexType::IvfPq));
assert_eq!(IndexType::parse("unknown"), None);
}
#[test]
fn default_is_hnsw() {
let cfg = IndexConfig::default();
assert_eq!(cfg.index_type, IndexType::Hnsw);
}
}