candding 0.1.0

Pure candle embeddings for Rust with no ONNX: dense, sparse, multi-vector and rerank models today, image models on the roadmap
Documentation
//! The multi-vector catalog: `all`, `lookup` and `by_phase` over its entries, each a `MultiVectorDescriptor`.

mod answerai_colbert_small;
mod bge_m3;
mod colbertv2;
mod conventions;
mod entry;
mod jina_colbert_v2;

use answerai_colbert_small::ANSWERAI_COLBERT_SMALL_MULTI_VECTOR;
use bge_m3::BGE_M3_MULTI_VECTOR;
use candle_core::DType;
use colbertv2::COLBERTV2_MULTI_VECTOR;
pub use entry::MultiVectorDescriptor;
pub(super) use entry::MultiVectorEntry;
use jina_colbert_v2::JINA_COLBERT_V2_MULTI_VECTOR;

/// Entries land already proven: `registry::tests::verified` fails for an entry with no `Verified` cell.
pub(super) const ENTRIES: &[MultiVectorEntry] = &[
  BGE_M3_MULTI_VECTOR,
  COLBERTV2_MULTI_VECTOR,
  ANSWERAI_COLBERT_SMALL_MULTI_VECTOR,
  JINA_COLBERT_V2_MULTI_VECTOR,
];

/// Every registered multi-vector entry, in registration order.
pub fn all() -> Vec<MultiVectorDescriptor> {
  ENTRIES.iter().map(MultiVectorEntry::descriptor).collect()
}

fn entry_for(id: &str) -> Option<&'static MultiVectorEntry> {
  ENTRIES
    .iter()
    .find(|entry| entry.id.eq_ignore_ascii_case(id))
}

/// This registry's own spelling of an id it carries, for `registry::canonical_id`.
pub(crate) fn canonical_id(id: &str) -> Option<&'static str> {
  entry_for(id).map(|entry| entry.id)
}

/// Case-insensitive lookup by repository id.
pub fn lookup(id: &str) -> Option<MultiVectorDescriptor> {
  entry_for(id).map(MultiVectorEntry::descriptor)
}

/// Every registered multi-vector entry for a phase, in registration order.
pub fn by_phase(phase: u8) -> Vec<MultiVectorDescriptor> {
  ENTRIES
    .iter()
    .filter(|entry| entry.phase == phase)
    .map(MultiVectorEntry::descriptor)
    .collect()
}

/// Whether a registered multi-vector id computes `dtype` correctly only on an accelerator, read from the row its
/// builder refuses from; `false` for an id outside the multi-vector catalog.
pub fn dtype_needs_accelerator(id: &str, dtype: DType) -> bool {
  entry_for(id).is_some_and(|entry| {
    entry
      .descriptor()
      .dtype_backends
      .row(dtype)
      .needs_accelerator()
  })
}

#[cfg(test)]
mod tests;