use super::*;
fn ramp_bias(heads: usize, seq: usize) -> Tensor {
let mut values = Vec::with_capacity(heads * seq * seq);
for h in 0..heads {
for i in 0..seq {
for j in 0..seq {
values.push((h * 100 + i * 10 + j) as f32);
}
}
}
Tensor::from_vec(values, (1, heads, seq, seq), &Device::Cpu).unwrap()
}
fn floor_in(dtype: DType) -> f32 {
Tensor::new(&[mask_min(dtype) as f32], &Device::Cpu)
.unwrap()
.to_dtype(dtype)
.unwrap()
.to_dtype(DType::F32)
.unwrap()
.to_vec1::<f32>()
.unwrap()[0]
}
#[test]
fn padding_with_bias_keeps_the_bias_and_floors_the_padded_keys() {
let attention_mask = Tensor::new(&[[1u32, 1, 0], [1, 1, 1]], &Device::Cpu).unwrap();
let bias = ramp_bias(2, 3);
let mask =
AttentionMask::padding_with_bias(&attention_mask, &[2, 3], &bias, 2, 64, DType::F32).unwrap();
let additive = mask
.additive()
.expect("padding_with_bias never returns none()");
assert_eq!(additive.dims(), &[2, 2, 3, 3]);
assert!(!mask.is_causal());
let values = additive.flatten_all().unwrap().to_vec1::<f32>().unwrap();
let at = |b: usize, h: usize, i: usize, j: usize| values[((b * 2 + h) * 3 + i) * 3 + j];
let floor = floor_in(DType::F32);
for h in 0..2 {
for i in 0..3 {
for j in 0..3 {
let expected = (h * 100 + i * 10 + j) as f32;
assert_eq!(at(1, h, i, j), expected, "row 1 ({h}, {i}, {j})");
let expected0 = if j == 2 { floor } else { expected };
assert_eq!(at(0, h, i, j), expected0, "row 0 ({h}, {i}, {j})");
}
}
}
}
#[test]
fn padding_with_bias_keeps_one_row_when_nothing_is_padded() {
let attention_mask = Tensor::new(&[[1u32, 1], [1, 1]], &Device::Cpu).unwrap();
let bias = ramp_bias(3, 2);
let mask =
AttentionMask::padding_with_bias(&attention_mask, &[2, 2], &bias, 3, 64, DType::F32).unwrap();
let additive = mask
.additive()
.expect("padding_with_bias never returns none()");
assert_eq!(additive.dims(), &[1, 3, 2, 2]);
assert_eq!(
additive.flatten_all().unwrap().to_vec1::<f32>().unwrap(),
bias.flatten_all().unwrap().to_vec1::<f32>().unwrap()
);
assert!(!mask.is_causal());
}
#[test]
fn padding_with_bias_casts_once_at_the_end_in_every_dtype() {
let attention_mask = Tensor::new(&[[1u32, 0]], &Device::Cpu).unwrap();
let bias = ramp_bias(1, 2);
for dtype in [DType::F32, DType::F16, DType::BF16] {
let mask =
AttentionMask::padding_with_bias(&attention_mask, &[1], &bias, 1, 64, dtype).unwrap();
let additive = mask
.additive()
.expect("padding_with_bias never returns none()");
assert_eq!(additive.dtype(), dtype, "{dtype:?}");
let values = additive
.to_dtype(DType::F32)
.unwrap()
.flatten_all()
.unwrap()
.to_vec1::<f32>()
.unwrap();
assert_eq!(values[0], 0.0, "{dtype:?} real key, bias 0");
assert_eq!(values[1], floor_in(dtype), "{dtype:?} padded key");
assert_eq!(values[2], 10.0, "{dtype:?} real key, bias 10");
assert_eq!(values[3], floor_in(dtype), "{dtype:?} padded key");
}
}
#[test]
fn a_large_negative_bias_never_pushes_a_padded_key_past_the_floor() {
let attention_mask = Tensor::new(&[[1u32, 0]], &Device::Cpu).unwrap();
let bias = Tensor::from_vec(
vec![-24.0f32, -24.0, -24.0, -24.0],
(1, 1, 2, 2),
&Device::Cpu,
)
.unwrap();
for dtype in [DType::F16, DType::BF16] {
let mask =
AttentionMask::padding_with_bias(&attention_mask, &[1], &bias, 1, 64, dtype).unwrap();
let values = mask
.additive()
.unwrap()
.to_dtype(DType::F32)
.unwrap()
.flatten_all()
.unwrap()
.to_vec1::<f32>()
.unwrap();
assert!(
values.iter().all(|v| v.is_finite()),
"{dtype:?}: {values:?}"
);
assert_eq!(values[1], floor_in(dtype), "{dtype:?} padded key");
assert!(
(values[0] + 24.0).abs() < 0.2,
"{dtype:?} real key kept the bias: {}",
values[0]
);
}
}