Download shapequant/arch.py from Angshul/Shapequant: direct link, hf CLI and curl.
- Browser
- Download file 5.28 kB
-
https://huggingface.co/Angshul/Shapequant/resolve/main/shapequant/arch.py
- Command line
-
hf download hf://Angshul/Shapequant/shapequant/arch.py
-
curl -L -o arch.py https://huggingface.co/Angshul/Shapequant/resolve/main/shapequant/arch.py
5.28 kB
| """Architecture adapters: tensor names and structure for the supported Hugging Face causal LMs. | |
| Supported model_type: llama, mistral, qwen2 (incl. Llama-2/3/3.1/3.3-70B, Qwen2.5-72B), opt (pre-LN), gpt2. | |
| A linear module is described by (module_name, input_key, role): | |
| input_key in {"ln1", "attn_out", "ln2", "act"} - which activation it reads | |
| role in {"q","k","v","qkv","o","gate","up","down"} | |
| Weights are returned in torch Linear layout (out, in); GPT-2 Conv1D weights are transposed on read. | |
| """ | |
| from dataclasses import dataclass, field | |
| from typing import List, Optional, Tuple | |
| class Linear: | |
| name: str # module path, e.g. "model.layers.3.self_attn.q_proj" | |
| input_key: str | |
| role: str | |
| conv1d: bool = False # stored (in, out) | |
| class Arch: | |
| model_type: str | |
| n_layer: int | |
| d: int | |
| n_head: int | |
| n_kv: int | |
| head_dim: int | |
| inter: int | |
| norm: str # "rms" | "ln" | |
| norm_eps: float | |
| act: str # "swiglu" | "relu" | "gelu_new" | "gelu" | |
| embed: str | |
| pos_embed: Optional[str] | |
| pos_offset: int | |
| final_norm: str | |
| lm_head: Optional[str] | |
| vocab: int | |
| max_pos: int | |
| layers: List[List[Linear]] = field(default_factory=list) | |
| norms: List[Tuple[str, str]] = field(default_factory=list) # per layer: (ln1 prefix, ln2 prefix) | |
| def norm_names(self, L, which): | |
| p = self.norms[L][0 if which == "ln1" else 1] | |
| return p + ".weight", (p + ".bias" if self.norm == "ln" else None) | |
| def from_config(cfg: dict) -> Arch: | |
| mt = cfg.get("model_type") | |
| if mt in ("llama", "mistral", "qwen2"): | |
| d, H = cfg["hidden_size"], cfg["num_attention_heads"] | |
| act = cfg.get("hidden_act", "silu") | |
| if act != "silu": | |
| raise NotImplementedError(f"{mt} with hidden_act={act}") | |
| a = Arch(mt, cfg["num_hidden_layers"], d, H, cfg.get("num_key_value_heads", H), cfg.get("head_dim") or d // H, | |
| cfg["intermediate_size"], "rms", cfg.get("rms_norm_eps", 1e-6), "swiglu", | |
| "model.embed_tokens.weight", None, 0, "model.norm.weight", | |
| None if cfg.get("tie_word_embeddings", False) else "lm_head.weight", | |
| cfg["vocab_size"], cfg.get("max_position_embeddings", 4096)) | |
| for L in range(a.n_layer): | |
| p = f"model.layers.{L}." | |
| a.layers.append([Linear(p + "self_attn.q_proj", "ln1", "q"), Linear(p + "self_attn.k_proj", "ln1", "k"), | |
| Linear(p + "self_attn.v_proj", "ln1", "v"), Linear(p + "self_attn.o_proj", "attn_out", "o"), | |
| Linear(p + "mlp.gate_proj", "ln2", "gate"), Linear(p + "mlp.up_proj", "ln2", "up"), | |
| Linear(p + "mlp.down_proj", "act", "down")]) | |
| a.norms.append((p + "input_layernorm", p + "post_attention_layernorm")) | |
| return a | |
| if mt == "opt": | |
| if not cfg.get("do_layer_norm_before", True): | |
| raise NotImplementedError("post-LN OPT (opt-350m) is not supported") | |
| if cfg.get("word_embed_proj_dim", cfg["hidden_size"]) != cfg["hidden_size"]: | |
| raise NotImplementedError("OPT with project_in/out is not supported") | |
| d, H = cfg["hidden_size"], cfg["num_attention_heads"] | |
| a = Arch(mt, cfg["num_hidden_layers"], d, H, H, d // H, cfg["ffn_dim"], "ln", 1e-5, | |
| {"relu": "relu"}.get(cfg.get("activation_function", "relu"), cfg.get("activation_function")), | |
| "model.decoder.embed_tokens.weight", "model.decoder.embed_positions.weight", 2, | |
| "model.decoder.final_layer_norm.weight", None if cfg.get("tie_word_embeddings", True) else "lm_head.weight", | |
| cfg["vocab_size"], cfg.get("max_position_embeddings", 2048)) | |
| for L in range(a.n_layer): | |
| p = f"model.decoder.layers.{L}." | |
| a.layers.append([Linear(p + "self_attn.q_proj", "ln1", "q"), Linear(p + "self_attn.k_proj", "ln1", "k"), | |
| Linear(p + "self_attn.v_proj", "ln1", "v"), Linear(p + "self_attn.out_proj", "attn_out", "o"), | |
| Linear(p + "fc1", "ln2", "up"), Linear(p + "fc2", "act", "down")]) | |
| a.norms.append((p + "self_attn_layer_norm", p + "final_layer_norm")) | |
| return a | |
| if mt == "gpt2": | |
| d, H = cfg["n_embd"], cfg["n_head"] | |
| a = Arch(mt, cfg["n_layer"], d, H, H, d // H, cfg.get("n_inner") or 4 * d, "ln", cfg.get("layer_norm_epsilon", 1e-5), | |
| {"gelu_new": "gelu_new"}.get(cfg.get("activation_function", "gelu_new"), cfg.get("activation_function")), | |
| "transformer.wte.weight", "transformer.wpe.weight", 0, "transformer.ln_f.weight", None, | |
| cfg["vocab_size"], cfg.get("n_positions", 1024)) | |
| for L in range(a.n_layer): | |
| p = f"transformer.h.{L}." | |
| a.layers.append([Linear(p + "attn.c_attn", "ln1", "qkv", True), Linear(p + "attn.c_proj", "attn_out", "o", True), | |
| Linear(p + "mlp.c_fc", "ln2", "up", True), Linear(p + "mlp.c_proj", "act", "down", True)]) | |
| a.norms.append((p + "ln_1", p + "ln_2")) | |
| return a | |
| raise NotImplementedError(f"model_type={mt!r} is not supported (supported: llama, mistral, qwen2, opt, gpt2)") | |