#[test]
fn test_transformer_from_gguf_tied_embeddings() {
use crate::gguf::GGUFTransformer;
let vocab = 8;
let hidden = 4;
let data = GGUFBuilder::new()
.architecture("llama")
.hidden_dim("llama", hidden as u32)
.num_layers("llama", 1)
.num_heads("llama", 1)
.num_kv_heads("llama", 1)
.context_length("llama", 32)
.rope_freq_base("llama", 10000.0)
.rms_epsilon("llama", 1e-5)
.ffn_hidden_dim("llama", 8)
.vocab_size("llama", vocab as u32)
.add_f32_tensor(
"token_embd.weight",
&[hidden as u64, vocab as u64],
&create_f32_embedding_data(vocab, hidden),
)
.add_f32_tensor(
"blk.0.attn_norm.weight",
&[hidden as u64],
&create_f32_norm_weights(hidden),
)
.add_f32_tensor(
"blk.0.attn_q.weight",
&[hidden as u64, hidden as u64],
&vec![0.01f32; hidden * hidden],
)
.add_f32_tensor(
"blk.0.attn_k.weight",
&[hidden as u64, hidden as u64],
&vec![0.01f32; hidden * hidden],
)
.add_f32_tensor(
"blk.0.attn_v.weight",
&[hidden as u64, hidden as u64],
&vec![0.01f32; hidden * hidden],
)
.add_f32_tensor(
"blk.0.attn_output.weight",
&[hidden as u64, hidden as u64],
&vec![0.01f32; hidden * hidden],
)
.add_f32_tensor(
"blk.0.ffn_gate.weight",
&[hidden as u64, 8],
&vec![0.01f32; hidden * 8],
)
.add_f32_tensor(
"blk.0.ffn_up.weight",
&[hidden as u64, 8],
&vec![0.01f32; hidden * 8],
)
.add_f32_tensor(
"blk.0.ffn_down.weight",
&[8, hidden as u64],
&vec![0.01f32; 8 * hidden],
)
.add_f32_tensor(
"blk.0.ffn_norm.weight",
&[hidden as u64],
&create_f32_norm_weights(hidden),
)
.add_f32_tensor(
"output_norm.weight",
&[hidden as u64],
&create_f32_norm_weights(hidden),
)
.build();
let model = GGUFModel::from_bytes(&data).expect("test value should be present");
let transformer = GGUFTransformer::from_gguf(&model, &data);
assert!(
transformer.is_ok(),
"Tied embeddings failed: {:?}",
transformer.err()
);
let t = transformer.expect("test value should be present");
assert_eq!(t.lm_head_weight.len(), t.token_embedding.len());
}
#[test]
fn test_transformer_from_gguf_two_layers() {
use crate::gguf::GGUFTransformer;
let vocab = 8;
let hidden = 4;
let mut builder = GGUFBuilder::new()
.architecture("llama")
.hidden_dim("llama", hidden as u32)
.num_layers("llama", 2)
.num_heads("llama", 1)
.num_kv_heads("llama", 1)
.context_length("llama", 32)
.rope_freq_base("llama", 10000.0)
.rms_epsilon("llama", 1e-5)
.ffn_hidden_dim("llama", 8)
.vocab_size("llama", vocab as u32)
.add_f32_tensor(
"token_embd.weight",
&[hidden as u64, vocab as u64],
&create_f32_embedding_data(vocab, hidden),
);
for layer_idx in 0..2 {
let prefix = format!("blk.{}", layer_idx);
builder = builder
.add_f32_tensor(
&format!("{}.attn_norm.weight", prefix),
&[hidden as u64],
&create_f32_norm_weights(hidden),
)
.add_f32_tensor(
&format!("{}.attn_q.weight", prefix),
&[hidden as u64, hidden as u64],
&vec![0.01f32; hidden * hidden],
)
.add_f32_tensor(
&format!("{}.attn_k.weight", prefix),
&[hidden as u64, hidden as u64],
&vec![0.01f32; hidden * hidden],
)
.add_f32_tensor(
&format!("{}.attn_v.weight", prefix),
&[hidden as u64, hidden as u64],
&vec![0.01f32; hidden * hidden],
)
.add_f32_tensor(
&format!("{}.attn_output.weight", prefix),
&[hidden as u64, hidden as u64],
&vec![0.01f32; hidden * hidden],
)
.add_f32_tensor(
&format!("{}.ffn_gate.weight", prefix),
&[hidden as u64, 8],
&vec![0.01f32; hidden * 8],
)
.add_f32_tensor(
&format!("{}.ffn_up.weight", prefix),
&[hidden as u64, 8],
&vec![0.01f32; hidden * 8],
)
.add_f32_tensor(
&format!("{}.ffn_down.weight", prefix),
&[8, hidden as u64],
&vec![0.01f32; 8 * hidden],
)
.add_f32_tensor(
&format!("{}.ffn_norm.weight", prefix),
&[hidden as u64],
&create_f32_norm_weights(hidden),
);
}
let data = builder
.add_f32_tensor(
"output_norm.weight",
&[hidden as u64],
&create_f32_norm_weights(hidden),
)
.add_f32_tensor(
"output.weight",
&[hidden as u64, vocab as u64],
&vec![0.01f32; hidden * vocab],
)
.build();
let model = GGUFModel::from_bytes(&data).expect("test value should be present");
let transformer = GGUFTransformer::from_gguf(&model, &data);
assert!(
transformer.is_ok(),
"2-layer failed: {:?}",
transformer.err()
);
let t = transformer.expect("test value should be present");
assert_eq!(t.layers.len(), 2);
assert_eq!(t.config.num_layers, 2);
}
#[test]
fn test_bos_eos_token_ids() {
let data = GGUFBuilder::new()
.architecture("llama")
.hidden_dim("llama", 32)
.num_layers("llama", 1)
.num_heads("llama", 4)
.add_u32("tokenizer.ggml.bos_token_id", 1)
.add_u32("tokenizer.ggml.eos_token_id", 2)
.build();
let model = GGUFModel::from_bytes(&data).expect("test value should be present");
assert_eq!(model.bos_token_id(), Some(1));
assert_eq!(model.eos_token_id(), Some(2));
}
#[test]
fn test_bos_eos_missing() {
let data = GGUFBuilder::new()
.architecture("llama")
.hidden_dim("llama", 32)
.num_layers("llama", 1)
.num_heads("llama", 4)
.build();
let model = GGUFModel::from_bytes(&data).expect("test value should be present");
let _ = model.bos_token_id();
let _ = model.eos_token_id();
}
#[test]
fn test_metadata_ffn_hidden_dim() {
let data = GGUFBuilder::new()
.architecture("llama")
.hidden_dim("llama", 64)
.num_layers("llama", 1)
.num_heads("llama", 4)
.ffn_hidden_dim("llama", 256)
.build();
let model = GGUFModel::from_bytes(&data).expect("test value should be present");
assert_eq!(model.header.version, 3);
}
#[test]
fn test_model_with_mixed_quantization() {
let data = GGUFBuilder::new()
.architecture("llama")
.hidden_dim("llama", 32)
.num_layers("llama", 1)
.num_heads("llama", 1)
.add_f32_tensor("norm.weight", &[32], &vec![1.0f32; 32])
.add_q4_0_tensor("layer.q4_0", &[32], &create_q4_0_data(32))
.add_q8_0_tensor("layer.q8_0", &[32], &create_q8_0_data(32))
.add_q4_k_tensor("layer.q4_k", &[256], &create_q4_k_data(256))
.add_q5_k_tensor("layer.q5_k", &[256], &create_q5_k_data(256))
.add_q6_k_tensor("layer.q6_k", &[256], &create_q6_k_data(256))
.build();
let model = GGUFModel::from_bytes(&data).expect("test value should be present");
assert_eq!(model.tensors.len(), 6);
let norm = model.get_tensor_f32("norm.weight", &data).expect("test value should be present");
assert_eq!(norm.len(), 32);
let q4_0 = model.get_tensor_f32("layer.q4_0", &data).expect("test value should be present");
assert_eq!(q4_0.len(), 32);
let q8_0 = model.get_tensor_f32("layer.q8_0", &data).expect("test value should be present");
assert_eq!(q8_0.len(), 32);
let q4_k = model.get_tensor_f32("layer.q4_k", &data).expect("test value should be present");
assert_eq!(q4_k.len(), 256);
let q5_k = model.get_tensor_f32("layer.q5_k", &data).expect("test value should be present");
assert_eq!(q5_k.len(), 256);
let q6_k = model.get_tensor_f32("layer.q6_k", &data).expect("test value should be present");
assert_eq!(q6_k.len(), 256);
}