use super::*;
#[test]
fn keeps_cls_row_true_keeps_the_classification_row() {
let weight = Tensor::eye(2, DType::F32, &Device::Cpu).unwrap();
let bias = Tensor::zeros(2, DType::F32, &Device::Cpu).unwrap();
let model = head(weight, bias, 2, true);
let hidden = Tensor::new(
&[[[1f32, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, -1.0]]],
&Device::Cpu,
)
.unwrap();
let rows = model.project_rows(&hidden, &[4]).unwrap();
assert_eq!(
rows[0].row_count(),
4,
"keeps_cls_row true must keep all 4 positions, CLS included"
);
let root2 = 2f32.sqrt();
let expected = [
vec![1.0f32, 0.0],
vec![0.0, 1.0],
vec![1.0 / root2, 1.0 / root2],
vec![1.0 / root2, -1.0 / root2],
];
for (got, want) in rows[0].rows().zip(expected.iter()) {
for (g, w) in got.iter().zip(want) {
assert!(
(g - w).abs() < 1e-6,
"{:?} vs {expected:?}",
rows[0].rows().collect::<Vec<_>>()
);
}
}
}
#[test]
fn normalize_false_and_no_bias_leave_the_raw_projection_unchanged() {
let weight = Tensor::new(&[[3f32, 0.0], [0.0, 4.0]], &Device::Cpu).unwrap();
let model = M3Colbert {
encoder: dummy_encoder(2),
weight,
bias: None,
dim: 2,
normalize: false,
keeps_cls_row: true,
};
let hidden = Tensor::new(&[[[1f32, 1.0]]], &Device::Cpu).unwrap();
let rows = model.project_rows(&hidden, &[1]).unwrap();
let row: Vec<f32> = rows[0].rows().next().unwrap().to_vec();
assert!(
(row[0] - 3.0).abs() < 1e-6 && (row[1] - 4.0).abs() < 1e-6,
"with normalize:false and no bias, [1,1] through diag(3,4) must stay [3,4]: {row:?}"
);
}