#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NameMapResult {
pub gguf_name: String,
pub is_norm: bool,
}
pub fn hf_to_gguf_name(hf_name: &str) -> Option<NameMapResult> {
if hf_name == "model.embed_tokens.weight" {
return Some(NameMapResult {
gguf_name: "token_embd.weight".to_string(),
is_norm: false,
});
}
if hf_name == "model.norm.weight" {
return Some(NameMapResult {
gguf_name: "output_norm.weight".to_string(),
is_norm: true,
});
}
if hf_name == "lm_head.weight" {
return Some(NameMapResult {
gguf_name: "output.weight".to_string(),
is_norm: false,
});
}
let layer_prefix = "model.layers.";
if let Some(rest) = hf_name.strip_prefix(layer_prefix) {
let dot_pos = rest.find('.')?;
let (layer_str, suffix_with_dot) = rest.split_at(dot_pos);
let layer_idx: usize = layer_str.parse().ok()?;
let suffix = suffix_with_dot.strip_prefix('.')?;
let (gguf_suffix, is_norm) = match suffix {
"input_layernorm.weight" => ("attn_norm.weight", true),
"post_attention_layernorm.weight" => ("ffn_norm.weight", true),
"self_attn.q_proj.weight" => ("attn_q.weight", false),
"self_attn.k_proj.weight" => ("attn_k.weight", false),
"self_attn.v_proj.weight" => ("attn_v.weight", false),
"self_attn.o_proj.weight" => ("attn_output.weight", false),
"mlp.gate_proj.weight" => ("ffn_gate.weight", false),
"mlp.up_proj.weight" => ("ffn_up.weight", false),
"mlp.down_proj.weight" => ("ffn_down.weight", false),
"self_attn.q_norm.weight" => ("attn_q_norm.weight", true),
"self_attn.k_norm.weight" => ("attn_k_norm.weight", true),
_ => return None,
};
return Some(NameMapResult {
gguf_name: format!("blk.{layer_idx}.{gguf_suffix}"),
is_norm,
});
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn convert_name_maps_correctly() {
let r = hf_to_gguf_name("model.embed_tokens.weight").expect("known tensor name must map");
assert_eq!(r.gguf_name, "token_embd.weight");
assert!(!r.is_norm);
let r = hf_to_gguf_name("lm_head.weight").expect("known tensor name must map");
assert_eq!(r.gguf_name, "output.weight");
assert!(!r.is_norm);
let r = hf_to_gguf_name("model.norm.weight").expect("known tensor name must map");
assert_eq!(r.gguf_name, "output_norm.weight");
assert!(r.is_norm);
let r = hf_to_gguf_name("model.layers.0.self_attn.q_proj.weight")
.expect("known tensor name must map");
assert_eq!(r.gguf_name, "blk.0.attn_q.weight");
assert!(!r.is_norm);
let r = hf_to_gguf_name("model.layers.27.mlp.gate_proj.weight")
.expect("known tensor name must map");
assert_eq!(r.gguf_name, "blk.27.ffn_gate.weight");
assert!(!r.is_norm);
let r = hf_to_gguf_name("model.layers.3.input_layernorm.weight")
.expect("known tensor name must map");
assert_eq!(r.gguf_name, "blk.3.attn_norm.weight");
assert!(r.is_norm);
let r = hf_to_gguf_name("model.layers.5.self_attn.k_norm.weight")
.expect("known tensor name must map");
assert_eq!(r.gguf_name, "blk.5.attn_k_norm.weight");
assert!(r.is_norm);
assert!(hf_to_gguf_name("some.unknown.tensor").is_none());
}
}