use super::*;
use crate::embed::builder::reject_unsupported_dtype;
use crate::models::xlm_roberta_flash::PositionScheme;
use crate::registry::Backend;
fn row(cpu: Support, metal: Support, cuda: Support) -> BackendSupport {
BackendSupport { cpu, metal, cuda }
}
fn axis() -> DtypeBackendSupport {
DtypeBackendSupport {
f32: row(Support::Verified, Support::Verified, Support::Untested),
f16: row(Support::Unsupported, Support::Verified, Support::Untested),
bf16: row(
Support::Unsupported,
Support::Unsupported,
Support::Unsupported,
),
}
}
#[test]
fn a_cpu_only_unsupported_cell_is_refused_on_the_cpu_as_accelerator_only() {
let err = reject_unsupported_dtype("m", DType::F16, axis(), &Device::Cpu).unwrap_err();
assert!(
matches!(&err, CanddingError::UnsupportedOnDevice { model, backend: Backend::Cpu, dtype: DType::F16 } if model == "m"),
"{err}"
);
let message = err.to_string();
assert!(message.contains("accelerator-only"), "{message}");
assert!(!message.contains("NaN"), "{message}");
}
#[test]
fn a_dtype_unsupported_on_every_device_is_refused_as_unsupported() {
let err = reject_unsupported_dtype("m", DType::BF16, axis(), &Device::Cpu).unwrap_err();
assert!(
matches!(&err, CanddingError::UnsupportedDtype { model, dtype: DType::BF16 } if model == "m"),
"{err}"
);
assert!(err.to_string().contains("bf16"), "{err}");
}
#[test]
fn a_verified_cell_passes() {
assert!(reject_unsupported_dtype("m", DType::F32, axis(), &Device::Cpu).is_ok());
}
#[test]
fn bge_m3_multi_vector_f16_is_refused_everywhere_through_its_registered_row() {
let descriptor = crate::registry::multi_vector::lookup("BAAI/bge-m3").expect("registered");
let err = reject_unsupported_dtype(
"BAAI/bge-m3",
DType::F16,
descriptor.dtype_backends,
&Device::Cpu,
)
.unwrap_err();
assert!(
matches!(
err,
CanddingError::UnsupportedDtype {
dtype: DType::F16,
..
}
),
"{err}"
);
}
#[test]
fn conventions_from_descriptor_carries_every_field_without_swapping_or_hardcoding_one() {
let mut descriptor = stub_descriptor();
descriptor.keeps_cls_row = true;
descriptor.projection_in = 7;
descriptor.projection_out = 5;
descriptor.projection_bias = true;
descriptor.normalize = true;
descriptor.attends_to_mask_tokens = true;
descriptor.position_scheme = Some(PositionScheme::Absolute);
let conventions = build::conventions_from_descriptor(&descriptor);
assert!(
conventions.keeps_cls_row,
"keeps_cls_row must carry through"
);
assert_eq!(
conventions.projection_in, 7,
"projection_in must not be swapped with projection_out"
);
assert_eq!(
conventions.projection_out, 5,
"projection_out must not be swapped with projection_in"
);
assert!(
conventions.projection_bias,
"projection_bias must carry through"
);
assert!(conventions.normalize, "normalize must carry through");
assert!(
conventions.attends_to_mask_tokens,
"attends_to_mask_tokens must carry through"
);
assert_eq!(
conventions.position_scheme,
Some(PositionScheme::Absolute),
"position_scheme must carry through"
);
}
#[test]
fn the_registered_flash_entry_maps_onto_its_rotary_scheme() {
let descriptor =
crate::registry::multi_vector::lookup("jinaai/jina-colbert-v2").expect("registered");
assert_eq!(
build::conventions_from_descriptor(&descriptor).position_scheme,
Some(PositionScheme::Rotary)
);
}
#[test]
fn a_stanford_colbert_descriptor_with_no_query_length_is_refused() {
let mut descriptor = stub_descriptor();
descriptor.head = MultiVectorHead::StanfordColbert;
let err = build::require_fixed_query_length("m", &descriptor).unwrap_err();
assert!(
matches!(err, CanddingError::MissingQueryLength { .. }),
"{err}"
);
}
#[test]
fn a_stanford_colbert_descriptor_with_a_query_length_is_accepted() {
let mut descriptor = stub_descriptor();
descriptor.head = MultiVectorHead::StanfordColbert;
descriptor.query_length = Some(32);
assert!(build::require_fixed_query_length("m", &descriptor).is_ok());
}
#[test]
fn an_m3_colbert_descriptor_with_no_query_length_is_unaffected() {
let descriptor = stub_descriptor();
assert!(build::require_fixed_query_length("m", &descriptor).is_ok());
}