use std::collections::HashMap;
use candle_core::DType;
use candle_core::Device;
use candle_nn::VarBuilder;
use super::*;
fn zeros(shape: impl Into<candle_core::Shape>) -> Tensor {
Tensor::zeros(shape, DType::F32, &Device::Cpu).unwrap()
}
fn tensor_map_without_a_position_table(config: &XlmRobertaFlashConfig) -> HashMap<String, Tensor> {
let h = config.hidden_size;
let inter = config.intermediate_size;
let mut map = HashMap::new();
map.insert(
"embeddings.word_embeddings.weight".to_string(),
zeros((config.vocab_size, h)),
);
map.insert(
"embeddings.token_type_embeddings.weight".to_string(),
zeros((config.type_vocab_size, h)),
);
map.insert("emb_ln.weight".to_string(), zeros(h));
map.insert("emb_ln.bias".to_string(), zeros(h));
for l in 0..config.num_hidden_layers {
let p = format!("encoder.layers.{l}");
map.insert(format!("{p}.mixer.Wqkv.weight"), zeros((3 * h, h)));
map.insert(format!("{p}.mixer.Wqkv.bias"), zeros(3 * h));
map.insert(format!("{p}.mixer.out_proj.weight"), zeros((h, h)));
map.insert(format!("{p}.mixer.out_proj.bias"), zeros(h));
map.insert(format!("{p}.norm1.weight"), zeros(h));
map.insert(format!("{p}.norm1.bias"), zeros(h));
map.insert(format!("{p}.mlp.fc1.weight"), zeros((inter, h)));
map.insert(format!("{p}.mlp.fc1.bias"), zeros(inter));
map.insert(format!("{p}.mlp.fc2.weight"), zeros((h, inter)));
map.insert(format!("{p}.mlp.fc2.bias"), zeros(h));
map.insert(format!("{p}.norm2.weight"), zeros(h));
map.insert(format!("{p}.norm2.bias"), zeros(h));
}
map
}
#[test]
fn loading_succeeds_from_tensors_that_include_no_position_table() {
let config = tiny_config();
let map = tensor_map_without_a_position_table(&config);
assert!(
!map.keys().any(|k| k.contains("position")),
"fixture must not smuggle in the thing this test proves absent"
);
let vb = VarBuilder::from_tensors(map, DType::F32, &Device::Cpu);
assert!(XlmRobertaFlashModel::load(config, vb, Some(PositionScheme::Rotary)).is_ok());
}
#[test]
fn rotary_positions_make_an_identical_token_diverge_by_position() {
let (_varmap, model) = tiny_model();
let out = run(&model, &[vec![5, 5, 9]]);
let shift = max_shift(&[vec![out[0][0].clone()]], &[vec![out[0][1].clone()]]);
assert!(
shift > 1e-3,
"token 5 at positions 0 and 1 produced the same output, so nothing is reading position: {shift}"
);
}