faiss-next 0.6.0

Rust bindings for Faiss (Facebook AI Similarity Search)
Documentation
use std::ffi::CString;
use std::ptr;

use faiss_next_sys;

use crate::error::{check_return_code, Result};
use crate::index::{Index, IndexImpl};
use crate::metric::MetricType;

pub fn index_factory(d: u32, description: &str, metric: MetricType) -> Result<IndexImpl> {
    let c_description = CString::new(description)?;
    let mut inner = ptr::null_mut();

    unsafe {
        check_return_code(faiss_next_sys::faiss_index_factory(
            &mut inner,
            d as i32,
            c_description.as_ptr(),
            metric.as_native(),
        ))?;

        IndexImpl::from_raw(inner)
    }
}

pub struct IndexBuilder {
    d: u32,
    description: String,
    metric: MetricType,
    nprobe: Option<usize>,
    verbose: bool,
}

impl IndexBuilder {
    pub fn new(d: u32) -> Self {
        Self {
            d,
            description: "Flat".to_string(),
            metric: MetricType::L2,
            nprobe: None,
            verbose: false,
        }
    }

    pub fn description(mut self, desc: impl Into<String>) -> Self {
        self.description = desc.into();
        self
    }

    pub fn flat(self) -> Self {
        self.description("Flat")
    }

    pub fn ivf_flat(self, nlist: usize) -> Self {
        self.description(format!("IVF{},Flat", nlist))
    }

    pub fn ivf_pq(self, nlist: usize, m: usize, nbits: usize) -> Self {
        self.description(format!("IVF{},PQ{}x{}", nlist, m, nbits))
    }

    pub fn pq(self, m: usize, nbits: usize) -> Self {
        self.description(format!("PQ{}x{}", m, nbits))
    }

    pub fn hnsw(self, m: usize) -> Self {
        self.description(format!("HNSW{}", m))
    }

    pub fn lsh(self, nbits: usize) -> Self {
        self.description(format!("LSH{}", nbits))
    }

    pub fn metric(mut self, metric: MetricType) -> Self {
        self.metric = metric;
        self
    }

    pub fn l2(self) -> Self {
        self.metric(MetricType::L2)
    }

    pub fn ip(self) -> Self {
        self.metric(MetricType::InnerProduct)
    }

    pub fn nprobe(mut self, nprobe: usize) -> Self {
        self.nprobe = Some(nprobe);
        self
    }

    pub fn verbose(mut self, verbose: bool) -> Self {
        self.verbose = verbose;
        self
    }

    pub fn build(self) -> Result<IndexImpl> {
        let mut index = index_factory(self.d, &self.description, self.metric)?;

        if self.verbose {
            index.set_verbose(true);
        }

        Ok(index)
    }
}