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
use super::*;

#[test]
fn phase_two_has_its_eighteen_entries_in_registration_order() {
  let phase2 = by_phase(2);
  assert_eq!(
    phase2.iter().map(|d| d.id.as_str()).collect::<Vec<_>>(),
    vec![
      "intfloat/multilingual-e5-small",
      "intfloat/multilingual-e5-base",
      "intfloat/multilingual-e5-large",
      "BAAI/bge-m3",
      "sentence-transformers/paraphrase-multilingual-mpnet-base-v2",
      "sentence-transformers/all-mpnet-base-v2",
      "jinaai/jina-embeddings-v2-small-en",
      "jinaai/jina-embeddings-v2-base-en",
      "jinaai/jina-embeddings-v2-base-de",
      "jinaai/jina-embeddings-v2-base-zh",
      "jinaai/jina-embeddings-v2-base-es",
      "jinaai/jina-embeddings-v2-base-code",
      "nomic-ai/nomic-embed-text-v1",
      "nomic-ai/nomic-embed-text-v1.5",
      "Snowflake/snowflake-arctic-embed-m-long",
      "Alibaba-NLP/gte-modernbert-base",
      "Alibaba-NLP/gte-multilingual-base",
      "Alibaba-NLP/gte-base-en-v1.5",
    ]
  );
  assert_eq!(phase2.len(), 18);
  assert_eq!(all().len(), 35, "13 phase 0 + 4 phase 1 + 18 phase 2");
  assert_eq!(
    lookup("intfloat/multilingual-e5-small").unwrap().family,
    Family::Bert
  );
  let e5: Vec<_> = phase2
    .iter()
    .filter(|d| d.id.starts_with("intfloat/"))
    .collect();
  assert_eq!(e5.len(), 3);
  for d in &e5 {
    assert_eq!(d.pooling, Pooling::Mean, "{}", d.id);
    assert_eq!(d.default_max_length, 512, "{}", d.id);
    assert_eq!(
      d.query_template.as_deref(),
      Some("query: {text}"),
      "{}",
      d.id
    );
    assert_eq!(
      d.passage_template.as_deref(),
      Some("passage: {text}"),
      "{}",
      d.id
    );
    assert_eq!(d.default_dtype, DType::F32, "{}", d.id);
    assert!(
      d.default_instruction.is_none() && !d.mrl && !d.gated,
      "{}",
      d.id
    );
    assert!(d.dense_dirs.is_empty() && d.normalize, "{}", d.id);
  }
  let xlm: Vec<_> = phase2
    .iter()
    .filter(|d| d.family == Family::XlmRoberta)
    .collect();
  assert_eq!(
    xlm.iter().map(|d| d.dim).collect::<Vec<_>>(),
    vec![768, 1024, 1024, 768]
  );
}

#[test]
fn phase_two_has_bge_m3() {
  let d = lookup("BAAI/bge-m3").expect("registered");
  assert_eq!(d.family, Family::XlmRoberta);
  assert_eq!((d.dim, d.default_max_length), (1024, 8192));
  assert_eq!(d.pooling, Pooling::Cls);
  assert!(d.query_template.is_none() && d.passage_template.is_none());
  assert!(d.default_instruction.is_none() && !d.mrl && !d.gated);
  assert!(d.dense_dirs.is_empty() && d.normalize);
  assert_eq!(d.default_dtype, DType::F32);
  assert_eq!(weights_format("BAAI/bge-m3"), WeightsFormat::Pickle);
}

#[test]
fn weights_format_resolves_a_sparse_only_id_too() {
  let id = "prithivida/Splade_PP_en_v1";
  assert_eq!(weights_format(id), WeightsFormat::Pickle);
}

/// Named like an MPNet, but its `config.json` and tensors are XLM-RoBERTa's; the config decides the family.
#[test]
fn phase_two_has_paraphrase_multilingual_mpnet() {
  let d =
    lookup("sentence-transformers/paraphrase-multilingual-mpnet-base-v2").expect("registered");
  assert_eq!(d.family, Family::XlmRoberta);
  assert_eq!((d.dim, d.default_max_length), (768, 128));
  assert_eq!(d.pooling, Pooling::Mean);
  assert_eq!(d.default_dtype, DType::F32);
  assert_eq!(d.license, "Apache-2.0");
  assert_eq!(d.backends.cuda, Support::Verified);
  assert!(d.query_template.is_none() && d.passage_template.is_none());
  assert!(d.default_instruction.is_none() && !d.mrl && !d.gated);
  assert!(d.dense_dirs.is_empty());
  assert!(
    d.normalize,
    "its modules.json has no Normalize module, yet every catalog entry normalizes"
  );
  assert_eq!(weights_format(&d.id), WeightsFormat::Safetensors);
}

/// Its repository publishes a 384 default length against a 512-position table.
#[test]
fn phase_two_has_all_mpnet_base_v2() {
  let d = lookup("sentence-transformers/all-mpnet-base-v2").expect("registered");
  assert_eq!(d.family, Family::Mpnet);
  assert_eq!((d.dim, d.default_max_length), (768, 384));
  assert_eq!(d.pooling, Pooling::Mean);
  assert_eq!(d.default_dtype, DType::F32);
  assert_eq!(d.license, "Apache-2.0");
  assert_eq!(d.backends.cuda, Support::Verified);
  assert!(d.query_template.is_none() && d.passage_template.is_none());
  assert!(d.default_instruction.is_none() && !d.mrl && !d.gated);
  assert!(d.dense_dirs.is_empty() && d.normalize);
  assert_eq!(weights_format(&d.id), WeightsFormat::Safetensors);
}