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 facts a multi-vector head decides, as every registered checkpoint with that head states them;
//! `MultiVectorDescriptor::new` takes its defaults from here rather than from one head's convention.

use crate::models::MultiVectorHead;
use crate::multi_vector::MaskedRowFill;
use crate::multi_vector::ScoreReduction;
use crate::registry::WeightsFormat;

pub(super) struct HeadConventions {
  pub keeps_cls_row: bool,
  pub projection_bias: bool,
  pub score_reduction: ScoreReduction,
  pub masked_document_row_fill: MaskedRowFill,
  pub query_marker: Option<&'static str>,
  pub document_marker: Option<&'static str>,
  pub query_length: Option<usize>,
  pub attends_to_mask_tokens: bool,
  pub weights: WeightsFormat,
}

impl HeadConventions {
  pub(super) fn of(head: MultiVectorHead) -> Self {
    match head {
      MultiVectorHead::M3Colbert => Self {
        keeps_cls_row: false,
        projection_bias: true,
        score_reduction: ScoreReduction::MeanByQueryLength,
        masked_document_row_fill: MaskedRowFill::Zero,
        query_marker: None,
        document_marker: None,
        query_length: None,
        attends_to_mask_tokens: false,
        weights: WeightsFormat::Pickle,
      },
      MultiVectorHead::StanfordColbert => Self {
        keeps_cls_row: true,
        projection_bias: false,
        score_reduction: ScoreReduction::Sum,
        masked_document_row_fill: MaskedRowFill::DtypeMinimum,
        query_marker: Some("[unused0] "),
        document_marker: Some("[unused1] "),
        query_length: Some(32),
        attends_to_mask_tokens: false,
        weights: WeightsFormat::Safetensors,
      },
      MultiVectorHead::JinaColbert => Self {
        keeps_cls_row: true,
        projection_bias: false,
        score_reduction: ScoreReduction::Sum,
        masked_document_row_fill: MaskedRowFill::DtypeMinimum,
        query_marker: Some("[QueryMarker] "),
        document_marker: Some("[DocumentMarker] "),
        query_length: Some(32),
        attends_to_mask_tokens: true,
        weights: WeightsFormat::Safetensors,
      },
    }
  }
}