Instructions to use LocalWisdom/Penny-Alpha with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use LocalWisdom/Penny-Alpha with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="LocalWisdom/Penny-Alpha", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("LocalWisdom/Penny-Alpha", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use LocalWisdom/Penny-Alpha with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "LocalWisdom/Penny-Alpha" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "LocalWisdom/Penny-Alpha", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/LocalWisdom/Penny-Alpha
- SGLang
How to use LocalWisdom/Penny-Alpha with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "LocalWisdom/Penny-Alpha" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "LocalWisdom/Penny-Alpha", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "LocalWisdom/Penny-Alpha" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "LocalWisdom/Penny-Alpha", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use LocalWisdom/Penny-Alpha with Docker Model Runner:
docker model run hf.co/LocalWisdom/Penny-Alpha
Download model.py from LocalWisdom/Penny-Alpha: direct link, hf CLI and curl.
- Browser
- Download file 31.3 kB
-
https://huggingface.co/LocalWisdom/Penny-Alpha/resolve/main/model.py
- Command line
-
hf download hf://LocalWisdom/Penny-Alpha/model.py
-
curl -L -o model.py https://huggingface.co/LocalWisdom/Penny-Alpha/resolve/main/model.py
31.3 kB
| """Penny (DeepSeek-V4.1-Flash port) for Hugging Face transformers, via trust_remote_code. | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| tok = AutoTokenizer.from_pretrained("LocalWisdom/Penny-Alpha") | |
| model = AutoModelForCausalLM.from_pretrained("LocalWisdom/Penny-Alpha", trust_remote_code=True, dtype="float32") | |
| ids = tok(tok.eos_token + "The history of the bicycle begins", add_special_tokens=False, return_tensors="pt") | |
| out = model.generate(**ids, max_new_tokens=200, do_sample=True, temperature=0.8, top_k=50, use_cache=False) | |
| print(tok.decode(out[0])) | |
| Inference-only port of the training model (no KV cache: every step re-runs the whole sequence, which is | |
| fine at this size). Weights use the official DeepSeek-V4.1 tensor names, so `model.safetensors` loads as is. | |
| Penny is a base model (no chat template). Prompts must start with EOS (marks a fresh document); the tokenizer does not add it, so prepend tok.eos_token. | |
| """ | |
| import math | |
| from dataclasses import dataclass | |
| import numpy as np | |
| import torch | |
| import torch.nn.functional as F | |
| from torch import nn | |
| from transformers import AutoTokenizer, GenerationMixin, PretrainedConfig, PreTrainedModel | |
| from transformers.modeling_outputs import CausalLMOutput | |
| # --------------------------------------------------------------------------------------------- | |
| # config | |
| class DeepseekV41Config(PretrainedConfig): | |
| """Wraps the nested config.json: top-level HF fields + `text_config` (the architecture) + `penny`.""" | |
| model_type = "deepseek_v41" | |
| def __init__(self, text_config=None, penny=None, **kwargs): | |
| super().__init__(**kwargs) | |
| # kept as `arch`, not `text_config`: transformers treats a `text_config` attribute as a sub-config object | |
| self.arch = dict(text_config or {}) | |
| self.penny = dict(penny or {}) | |
| def to_dict(self): | |
| d = super().to_dict() | |
| d["text_config"] = d.pop("arch", self.arch) | |
| return d | |
| class Args: | |
| vocab_size: int | |
| dim: int | |
| moe_inter_dim: int | |
| n_layers: int | |
| n_heads: int | |
| n_routed_experts: int | |
| n_shared_experts: int | |
| n_activated_experts: int | |
| score_func: str | |
| norm_topk_prob: bool | |
| route_scale: float | |
| swiglu_limit: float | |
| q_lora_rank: int | |
| head_dim: int | |
| rope_head_dim: int | |
| norm_eps: float | |
| o_groups: int | |
| o_lora_rank: int | |
| window_size: int | |
| compress_ratios: tuple | |
| kv_source_layers: tuple | |
| index_source_layers: tuple | |
| compress_rope_theta: float | |
| original_seq_len: int | |
| rope_theta: float | |
| rope_factor: float | |
| beta_fast: int | |
| beta_slow: int | |
| index_n_heads: int | |
| index_head_dim: int | |
| index_topk: int | |
| candidate_source_layer: int | |
| candidate_topk_blocks: int | |
| candidate_block_size: int | |
| hc_mult: int | |
| hc_sinkhorn_iters: int | |
| hc_eps: float | |
| engram_layer_ids: tuple | |
| engram_num_embeddings: tuple | |
| engram_max_ngram_size: int | |
| engram_vocab_size: int | |
| engram_n_heads: int | |
| engram_head_dim: int | |
| engram_pad_id: int | |
| engram_compressed_vocab_size: int | |
| max_seq_len: int | |
| attn_chunk: int = 256 | |
| def from_config(cls, cfg: DeepseekV41Config) -> "Args": | |
| t = cfg.arch | |
| rs = t.get("rope_scaling") or {} | |
| n = t["num_hidden_layers"] | |
| return cls( | |
| vocab_size=t["vocab_size"], dim=t["hidden_size"], moe_inter_dim=t["moe_intermediate_size"], | |
| n_layers=n, n_heads=t["num_attention_heads"], n_routed_experts=t["n_routed_experts"], | |
| n_shared_experts=t["n_shared_experts"], n_activated_experts=t["num_experts_per_tok"], | |
| score_func=t["scoring_func"], norm_topk_prob=t["norm_topk_prob"], | |
| route_scale=t["routed_scaling_factor"], swiglu_limit=t["swiglu_limit"], | |
| q_lora_rank=t["q_lora_rank"], head_dim=t["head_dim"], rope_head_dim=t["qk_rope_head_dim"], | |
| norm_eps=t["rms_norm_eps"], o_groups=t["o_groups"], o_lora_rank=t["o_lora_rank"], | |
| window_size=t["sliding_window"], compress_ratios=tuple(t["compress_ratios"][:n]), | |
| kv_source_layers=tuple(t["kv_source_layer_ids"]), index_source_layers=tuple(t["index_source_layer_ids"]), | |
| compress_rope_theta=t["compress_rope_theta"], | |
| original_seq_len=rs.get("original_max_position_embeddings", 0), rope_theta=t["rope_theta"], | |
| rope_factor=rs.get("factor", 1), beta_fast=rs.get("beta_fast", 32), beta_slow=rs.get("beta_slow", 1), | |
| index_n_heads=t["index_n_heads"], index_head_dim=t["index_head_dim"], index_topk=t["index_topk"], | |
| candidate_source_layer=t["candidate_source_layer_id"], candidate_topk_blocks=t["candidate_topk_blocks"], | |
| candidate_block_size=t["candidate_block_size"], hc_mult=t["hc_mult"], | |
| hc_sinkhorn_iters=t["hc_sinkhorn_iters"], hc_eps=t["hc_eps"], | |
| engram_layer_ids=tuple(t["engram_layer_ids"]), engram_num_embeddings=tuple(t["engram_num_embeddings"]), | |
| engram_max_ngram_size=t["engram_max_ngram_size"], engram_vocab_size=t["engram_vocab_size"], | |
| engram_n_heads=t["engram_n_heads"], engram_head_dim=t["engram_head_dim"], | |
| engram_pad_id=t["engram_pad_token_id"], engram_compressed_vocab_size=t["engram_compressed_vocab_size"], | |
| max_seq_len=cfg.penny.get("trained_seq_len", 8192), | |
| ) | |
| # --------------------------------------------------------------------------------------------- | |
| # Engram n-gram hashing (hash ids match the DeepSeek reference exactly) | |
| def _is_prime(n: int) -> bool: | |
| if n < 2: | |
| return False | |
| i = 2 | |
| while i * i <= n: | |
| if n % i == 0: | |
| return False | |
| i += 1 | |
| return True | |
| def _next_prime(start: int, seen: set) -> int: | |
| c = start + 1 | |
| while not _is_prime(c) or c in seen: | |
| c += 1 | |
| return c | |
| def _compressed_token_map(tokenizer): | |
| """Collapse tokens that normalize alike (" The", "the", "THE") onto one compressed id.""" | |
| from tokenizers import Regex, normalizers | |
| sentinel = "\ue000" # private-use char, as in the reference | |
| normalizer = normalizers.Sequence([ | |
| normalizers.NFKC(), normalizers.NFD(), normalizers.StripAccents(), normalizers.Lowercase(), | |
| normalizers.Replace(Regex(r"[ \t\r\n]+"), " "), normalizers.Replace(Regex(r"^ $"), sentinel), | |
| normalizers.Strip(), normalizers.Replace(sentinel, " "), | |
| ]) | |
| backend = tokenizer.backend_tokenizer | |
| key_to_new, lookup = {}, [0] * len(tokenizer) | |
| for token_id in range(len(tokenizer)): | |
| text = backend.decode([token_id], skip_special_tokens=False) | |
| if "\ufffd" in text: | |
| key = backend.id_to_token(token_id) | |
| else: | |
| normalized = normalizer.normalize_str(text) | |
| key = normalized if normalized else text | |
| new_id = key_to_new.get(key) | |
| if new_id is None: | |
| new_id = len(key_to_new) | |
| key_to_new[key] = new_id | |
| lookup[token_id] = new_id | |
| return lookup, len(key_to_new) | |
| class NgramHash: | |
| """input_ids [B, L] -> hash ids [B, L, n_engram_layers, (max_ngram_size-1) * n_heads]. Built lazily | |
| (needs the tokenizer) and not an nn.Module, so it never touches the weights.""" | |
| def __init__(self, a: Args, tokenizer): | |
| layer_ids = tuple(a.engram_layer_ids) | |
| self.max_n = a.engram_max_ngram_size | |
| primes, seen = [], set() | |
| for _ in layer_ids: | |
| per_ngram = [] | |
| for _ in range(self.max_n - 1): | |
| sizes, current = [], a.engram_vocab_size - 1 | |
| for _ in range(a.engram_n_heads): | |
| current = _next_prime(current, seen) | |
| seen.add(current) | |
| sizes.append(current) | |
| per_ngram.append(sizes) | |
| primes.append(per_ngram) | |
| token_map, vocab_size = _compressed_token_map(tokenizer) | |
| assert vocab_size == a.engram_compressed_vocab_size, (vocab_size, a.engram_compressed_vocab_size) | |
| self.pad_id = token_map[a.engram_pad_id] | |
| flat = [[p for per_ngram in layer for p in per_ngram] for layer in primes] | |
| offsets = [np.cumsum([0, *sizes[:-1]]) for sizes in flat] | |
| max_long = np.iinfo(np.int64).max | |
| bound = max(1, (max_long // vocab_size) // 2) | |
| mult = [] | |
| for layer_id in layer_ids: | |
| g = np.random.default_rng(10007 * layer_id) | |
| mult.append(torch.tensor(g.integers(low=0, high=bound, size=(self.max_n,), dtype=np.int64) * 2 + 1)) | |
| self.primes = torch.tensor(primes) | |
| self.offsets = torch.tensor(np.array(offsets)) | |
| self.multipliers = torch.stack(mult) | |
| self.token_map = torch.tensor(token_map) | |
| def __call__(self, input_ids: torch.Tensor) -> torch.Tensor: | |
| dev = input_ids.device | |
| primes, offsets, multipliers, token_map = ( | |
| self.primes.to(dev), self.offsets.to(dev), self.multipliers.to(dev), self.token_map.to(dev)) | |
| compressed = token_map[input_ids] | |
| tokens = [compressed] | |
| for shift in range(1, self.max_n): | |
| shifted = torch.full_like(compressed, self.pad_id) | |
| shifted[:, shift:] = compressed[:, :-shift] | |
| tokens.append(shifted) | |
| tokens = torch.stack(tokens, dim=-1) | |
| products = tokens.unsqueeze(2) * multipliers | |
| rolling, hashes = products[..., 0], [] | |
| for i in range(1, self.max_n): | |
| rolling = torch.bitwise_xor(rolling, products[..., i]) | |
| hashes.append(rolling.unsqueeze(-1) % primes[:, i - 1]) | |
| return torch.cat(hashes, dim=-1) + offsets | |
| # --------------------------------------------------------------------------------------------- | |
| # primitives | |
| class RMSNorm(nn.Module): | |
| def __init__(self, dim: int, eps: float): | |
| super().__init__() | |
| self.eps = eps | |
| self.weight = nn.Parameter(torch.ones(dim)) | |
| def forward(self, x): | |
| dtype = x.dtype | |
| x = x.float() | |
| x = x * torch.rsqrt(x.square().mean(-1, keepdim=True) + self.eps) | |
| return (self.weight.float() * x).to(dtype) | |
| def precompute_freqs_cis(dim, seqlen, original_seq_len, base, factor, beta_fast, beta_slow, device): | |
| freqs = 1.0 / (base ** (torch.arange(0, dim, 2, dtype=torch.float32) / dim)) | |
| if original_seq_len > 0: | |
| def corrected_dim(rotations): | |
| return dim * math.log(original_seq_len / (rotations * 2 * math.pi)) / (2 * math.log(base)) | |
| low = max(math.floor(corrected_dim(beta_fast)), 0) | |
| high = min(math.ceil(corrected_dim(beta_slow)), dim - 1) | |
| ramp = ((torch.arange(dim // 2, dtype=torch.float32) - low) / max(high - low, 1e-3)).clamp(0, 1) | |
| smooth = 1 - ramp | |
| freqs = freqs / factor * (1 - smooth) + freqs * smooth | |
| freqs = torch.outer(torch.arange(seqlen), freqs) | |
| return torch.polar(torch.ones_like(freqs), freqs).to(device) | |
| def rope(x, freqs_cis, rd, inverse=False): | |
| """Rotate the last `rd` dims of x (adjacent pairs as complex numbers). x: [b,s,d] or [b,s,h,d].""" | |
| nope, pe = x[..., :-rd], x[..., -rd:] | |
| z = torch.view_as_complex(pe.float().unflatten(-1, (-1, 2)).contiguous()) | |
| f = freqs_cis.conj() if inverse else freqs_cis | |
| f = f.view(1, z.size(1), *([1] * (z.ndim - 3)), z.size(-1)) | |
| pe = torch.view_as_real(z * f).flatten(-2).to(x.dtype) | |
| return torch.cat([nope, pe], dim=-1) | |
| def idxs_to_mask(idxs, n): | |
| """[b,m,k] int indices (-1 = empty) -> [b,m,n] bool mask.""" | |
| mask = torch.zeros(*idxs.shape[:2], n + 1, dtype=torch.bool, device=idxs.device) | |
| mask.scatter_(-1, torch.where(idxs < 0, n, idxs).long(), True) | |
| return mask[..., :n] | |
| def chunked_sink_attention(q, kv, attn_sink, window, scale, comp_kv=None, comp_idxs=None, chunk=256): | |
| """Sliding-window attention over raw KV plus top-k compressed KV, with a learned sink logit. | |
| q [b,L,h,d]; kv [b,L,d]; comp_kv [b,T,d]; comp_idxs [b,L,k] into comp_kv (-1 = empty).""" | |
| L = q.size(1) | |
| outs = [] | |
| for s0 in range(0, L, chunk): | |
| s1 = min(s0 + chunk, L) | |
| k0 = max(0, s0 - window + 1) | |
| qpos = torch.arange(s0, s1, device=q.device).unsqueeze(1) | |
| kpos = torch.arange(k0, s1, device=q.device) | |
| wmask = (kpos <= qpos) & (kpos > qpos - window) | |
| qc, kw = q[:, s0:s1], kv[:, k0:s1] | |
| s = torch.einsum("bmhd,bnd->bhmn", qc, kw).float() * scale | |
| s = s.masked_fill(~wmask, -torch.inf) | |
| vals = kw | |
| if comp_kv is not None: | |
| cmask = idxs_to_mask(comp_idxs[:, s0:s1], comp_kv.size(1)) | |
| sc = torch.einsum("bmhd,bnd->bhmn", qc, comp_kv).float() * scale | |
| s = torch.cat([s, sc.masked_fill(~cmask.unsqueeze(1), -torch.inf)], dim=-1) | |
| vals = torch.cat([kw, comp_kv], dim=1) | |
| sink = attn_sink.float().view(1, -1, 1, 1).expand(*s.shape[:3], 1) | |
| lse = torch.logsumexp(torch.cat([s, sink], dim=-1), dim=-1) | |
| p = torch.exp(s - lse.unsqueeze(-1)) | |
| outs.append(torch.einsum("bhmn,bnd->bmhd", p.to(vals.dtype), vals)) | |
| return torch.cat(outs, dim=1) | |
| def hc_split_sinkhorn(mixes, hc_scale, hc_base, hc, iters, eps): | |
| pre = torch.sigmoid(mixes[..., :hc] * hc_scale[0] + hc_base[:hc]) + eps | |
| post = 2 * torch.sigmoid(mixes[..., hc : 2 * hc] * hc_scale[1] + hc_base[hc : 2 * hc]) | |
| comb = mixes[..., 2 * hc :] * hc_scale[2] + hc_base[2 * hc :] | |
| comb = comb.unflatten(-1, (hc, hc)).softmax(-1) + eps | |
| comb = comb / (comb.sum(-2, keepdim=True) + eps) | |
| for _ in range(iters - 1): | |
| comb = comb / (comb.sum(-1, keepdim=True) + eps) | |
| comb = comb / (comb.sum(-2, keepdim=True) + eps) | |
| return pre, post, comb | |
| # --------------------------------------------------------------------------------------------- | |
| # attention | |
| class Shared: | |
| """Per-forward hand-off between source layers and the layers that reuse their results.""" | |
| def __init__(self): | |
| self.compress_kv = None | |
| self.index_k = None | |
| self.topk_idxs = None | |
| self.candidates = None | |
| class Compressor(nn.Module): | |
| """Pools `ratio` consecutive tokens into one KV latent with a learned softmax gate (pre-RoPE).""" | |
| def __init__(self, a: Args, layer_id: int): | |
| super().__init__() | |
| self.ratio = a.compress_ratios[layer_id] | |
| self.norm = RMSNorm(a.head_dim, a.norm_eps) | |
| self.wkv = nn.Linear(a.dim, a.head_dim, bias=False) | |
| self.wgate = nn.Linear(a.dim, a.head_dim, bias=False) if self.ratio > 1 else None | |
| def forward(self, x): | |
| if self.ratio == 1: | |
| return self.norm(self.wkv(x)) | |
| cutoff = x.size(1) - x.size(1) % self.ratio # trailing partial group is not visible yet | |
| xf = x[:, :cutoff].float() # the reference pools in fp32 | |
| kv = F.linear(xf, self.wkv.weight.float()).unflatten(1, (-1, self.ratio)) | |
| score = F.linear(xf, self.wgate.weight.float()).unflatten(1, (-1, self.ratio)) | |
| kv = (kv * score.softmax(dim=2)).sum(dim=2) | |
| return self.norm(kv.to(x.dtype)) | |
| def select_candidate_blocks(logits, compress_lens, topk_blocks, block_size): | |
| width = logits.size(-1) | |
| scores = F.pad(logits, (0, -width % block_size), value=-torch.inf) | |
| scores = scores.unflatten(-1, (-1, block_size)).amax(dim=-1) | |
| num_blocks = scores.size(-1) | |
| last = (compress_lens - 1) // block_size | |
| scores = scores.masked_fill(torch.arange(num_blocks, device=logits.device) == last, torch.inf) | |
| top = scores.topk(min(topk_blocks, num_blocks), dim=-1) | |
| keep = torch.zeros_like(scores, dtype=torch.bool).scatter_(-1, top.indices, top.values > -torch.inf) | |
| return keep.repeat_interleave(block_size, dim=-1)[..., :width] | |
| class Indexer(nn.Module): | |
| """Scores compressed positions and keeps the `index_topk` best per query.""" | |
| def __init__(self, a: Args, layer_id: int): | |
| super().__init__() | |
| self.owns_k = layer_id in a.kv_source_layers | |
| self.ratio = a.compress_ratios[layer_id] | |
| self.is_candidate_source = layer_id == a.candidate_source_layer | |
| self.uses_candidates = 0 <= a.candidate_source_layer < layer_id | |
| self.candidate_topk_blocks = a.candidate_topk_blocks | |
| self.candidate_block_size = a.candidate_block_size | |
| self.n_heads = a.index_n_heads | |
| self.index_head_dim = a.index_head_dim | |
| self.rd = a.rope_head_dim | |
| self.index_topk = a.index_topk | |
| self.softmax_scale = self.index_head_dim**-0.5 | |
| self.wq_b = nn.Linear(a.q_lora_rank, self.n_heads * self.index_head_dim, bias=False) | |
| self.weights_proj = nn.Linear(a.dim, self.n_heads, bias=False) | |
| if self.owns_k: | |
| self.wk = nn.Linear(a.head_dim, self.index_head_dim, bias=False) | |
| self.k_norm = RMSNorm(self.index_head_dim, a.norm_eps) | |
| def forward(self, x, qr, latent, freqs_cis, shared: Shared, chunk: int): | |
| """Returns selected compressed indices [b,s,k] (-1 = empty).""" | |
| seqlen, ratio = x.size(1), self.ratio | |
| if self.owns_k: | |
| k = self.k_norm(self.wk(latent)) | |
| shared.index_k = rope(k, freqs_cis[: seqlen - seqlen % ratio : ratio], self.rd) | |
| q = rope(self.wq_b(qr).unflatten(-1, (self.n_heads, self.index_head_dim)), freqs_cis[:seqlen], self.rd) | |
| index_k = shared.index_k | |
| weights = self.weights_proj(x) * (self.softmax_scale * self.n_heads**-0.5) | |
| T = index_k.size(1) | |
| topk = min(self.index_topk, T) | |
| idx_chunks, cand_chunks = [], [] | |
| for s0 in range(0, seqlen, chunk): | |
| s1 = min(s0 + chunk, seqlen) | |
| score = torch.einsum("bshd,btd->bsht", q[:, s0:s1], index_k) | |
| score = (score.relu() * weights[:, s0:s1].unsqueeze(-1)).sum(dim=2).float() | |
| lens = (torch.arange(s0 + 1, s1 + 1, device=x.device) // ratio).unsqueeze(-1) | |
| score = score.masked_fill(torch.arange(T, device=x.device) >= lens, -torch.inf) | |
| if self.is_candidate_source: | |
| cand_chunks.append(select_candidate_blocks( | |
| score, lens, self.candidate_topk_blocks, self.candidate_block_size)) | |
| elif self.uses_candidates and shared.candidates is not None: | |
| score = score.masked_fill(~shared.candidates[:, s0:s1], -torch.inf) | |
| idxs = score.topk(topk, dim=-1, sorted=False).indices | |
| idx_chunks.append(torch.where(idxs < lens, idxs, -1)) | |
| if self.is_candidate_source: | |
| shared.candidates = torch.cat(cand_chunks, dim=1) | |
| return torch.cat(idx_chunks, dim=1) | |
| class Attention(nn.Module): | |
| """Sliding window over raw KV, plus (compress_ratio > 0) top-k compressed KV further back. | |
| Low-rank Q; grouped low-rank output projection; shared K=V latent (MQA).""" | |
| def __init__(self, layer_id: int, a: Args): | |
| super().__init__() | |
| self.n_heads, self.head_dim, self.rd = a.n_heads, a.head_dim, a.rope_head_dim | |
| self.n_groups, self.o_lora_rank, self.window = a.o_groups, a.o_lora_rank, a.window_size | |
| self.ratio = a.compress_ratios[layer_id] | |
| self.softmax_scale = self.head_dim**-0.5 | |
| self.attn_chunk = a.attn_chunk | |
| self.attn_sink = nn.Parameter(torch.zeros(self.n_heads)) | |
| self.wq_a = nn.Linear(a.dim, a.q_lora_rank, bias=False) | |
| self.q_norm = RMSNorm(a.q_lora_rank, a.norm_eps) | |
| self.wq_b = nn.Linear(a.q_lora_rank, self.n_heads * self.head_dim, bias=False) | |
| self.wkv = nn.Linear(a.dim, self.head_dim, bias=False) | |
| self.kv_norm = RMSNorm(self.head_dim, a.norm_eps) | |
| self.wo_a = nn.Linear(self.n_heads * self.head_dim // self.n_groups, self.n_groups * self.o_lora_rank, bias=False) | |
| self.wo_b = nn.Linear(self.n_groups * self.o_lora_rank, a.dim, bias=False) | |
| self.is_kv_source = layer_id in a.kv_source_layers | |
| self.is_index_source = layer_id in a.index_source_layers | |
| self.compressor = Compressor(a, layer_id) if self.is_kv_source else None | |
| self.indexer = Indexer(a, layer_id) if self.is_index_source else None | |
| # RoPE table: built lazily on the right device (never part of the checkpoint) | |
| if self.ratio: | |
| self._rope = (a.original_seq_len, a.compress_rope_theta) | |
| else: | |
| self._rope = (0, a.rope_theta) # pure sliding window: no YaRN, base theta | |
| self._rope_args = (a.rope_factor, a.beta_fast, a.beta_slow, a.max_seq_len) | |
| self._fc = None | |
| def freqs(self, seqlen, device): | |
| if self._fc is None or self._fc.size(0) < seqlen or self._fc.device != device: | |
| factor, bf, bs, max_len = self._rope_args | |
| self._fc = precompute_freqs_cis(self.rd, max(seqlen, max_len), self._rope[0], self._rope[1], | |
| factor, bf, bs, device) | |
| return self._fc[:seqlen] | |
| def forward(self, x, shared: Shared): | |
| bsz, seqlen, _ = x.shape | |
| fc = self.freqs(seqlen, x.device) | |
| qr = self.q_norm(self.wq_a(x)) | |
| q = rope(self.wq_b(qr).unflatten(-1, (self.n_heads, self.head_dim)), fc, self.rd) | |
| kv = rope(self.kv_norm(self.wkv(x)), fc, self.rd) | |
| comp_kv, cidx = None, None | |
| if self.ratio: | |
| latent = self.compressor(x) if self.is_kv_source else None | |
| if self.is_index_source: | |
| shared.topk_idxs = self.indexer(x, qr, latent, fc, shared, chunk=self.attn_chunk) | |
| cidx = shared.topk_idxs | |
| if latent is not None: # group j sits at the position of its first token, j * ratio | |
| shared.compress_kv = rope(latent, fc[: seqlen - seqlen % self.ratio : self.ratio], self.rd) | |
| comp_kv = shared.compress_kv | |
| o = chunked_sink_attention(q, kv, self.attn_sink, self.window, self.softmax_scale, comp_kv, cidx, | |
| chunk=self.attn_chunk) | |
| o = rope(o, fc, self.rd, inverse=True) # remove the query rotation from the output | |
| o = o.reshape(bsz, seqlen, self.n_groups, -1) | |
| wo_a = self.wo_a.weight.view(self.n_groups, self.o_lora_rank, -1) | |
| o = torch.einsum("bsgd,grd->bsgr", o, wo_a.to(o.dtype)) | |
| return self.wo_b(o.flatten(2)) | |
| # --------------------------------------------------------------------------------------------- | |
| # MoE | |
| class Gate(nn.Module): | |
| """sqrtsoftplus scores; a bias picks experts, weights come from the unbiased scores.""" | |
| def __init__(self, a: Args): | |
| super().__init__() | |
| self.topk, self.score_func = a.n_activated_experts, a.score_func | |
| self.norm_topk_prob, self.route_scale = a.norm_topk_prob, a.route_scale | |
| self.weight = nn.Parameter(torch.empty(a.n_routed_experts, a.dim)) | |
| self.register_buffer("bias", torch.zeros(a.n_routed_experts)) | |
| def forward(self, x): | |
| scores = F.linear(x.float(), self.weight.float()) | |
| if self.score_func == "softmax": | |
| scores = scores.softmax(dim=-1) | |
| elif self.score_func == "sigmoid": | |
| scores = scores.sigmoid() | |
| else: | |
| scores = F.softplus(scores).sqrt() | |
| indices = (scores + self.bias.float()).topk(self.topk, dim=-1)[1] | |
| weights = scores.gather(1, indices) | |
| if self.norm_topk_prob and self.topk > 1: | |
| weights = weights / (weights.sum(dim=-1, keepdim=True) + 1e-20) | |
| return weights * self.route_scale, indices | |
| class Expert(nn.Module): | |
| def __init__(self, dim, inter_dim, swiglu_limit): | |
| super().__init__() | |
| self.w1 = nn.Linear(dim, inter_dim, bias=False) | |
| self.w2 = nn.Linear(inter_dim, dim, bias=False) | |
| self.w3 = nn.Linear(dim, inter_dim, bias=False) | |
| self.swiglu_limit = swiglu_limit | |
| def forward(self, x, weights=None): | |
| dtype = x.dtype | |
| gate, up = self.w1(x).float(), self.w3(x).float() | |
| if self.swiglu_limit > 0: | |
| up = up.clamp(-self.swiglu_limit, self.swiglu_limit) | |
| gate = gate.clamp(max=self.swiglu_limit) | |
| h = F.silu(gate) * up | |
| if weights is not None: | |
| h = weights * h | |
| return self.w2(h.to(dtype)) | |
| class MoE(nn.Module): | |
| def __init__(self, a: Args): | |
| super().__init__() | |
| self.dim = a.dim | |
| self.gate = Gate(a) | |
| self.experts = nn.ModuleList([Expert(a.dim, a.moe_inter_dim, a.swiglu_limit) for _ in range(a.n_routed_experts)]) | |
| assert a.n_shared_experts == 1 | |
| self.shared_experts = Expert(a.dim, a.moe_inter_dim, a.swiglu_limit) | |
| def forward(self, x): | |
| shape = x.shape | |
| x = x.reshape(-1, self.dim) | |
| weights, indices = self.gate(x) | |
| y = torch.zeros_like(x, dtype=torch.float32) | |
| counts = torch.bincount(indices.flatten(), minlength=len(self.experts)).tolist() | |
| for i, expert in enumerate(self.experts): | |
| if counts[i] == 0: | |
| continue | |
| idx, top = torch.where(indices == i) | |
| y = y.index_add(0, idx, expert(x[idx], weights[idx, top, None]).float()) | |
| y = y + self.shared_experts(x).float() | |
| return y.to(x.dtype).view(shape) | |
| # --------------------------------------------------------------------------------------------- | |
| # Engram, blocks, model | |
| class Engram(nn.Module): | |
| """Gated n-gram lookup written into each hc copy of the residual stream.""" | |
| def __init__(self, a: Args, layer_id: int): | |
| super().__init__() | |
| self.layer_hash_index = tuple(a.engram_layer_ids).index(layer_id) | |
| self.dim, self.hc_mult, self.eps = a.dim, a.hc_mult, a.norm_eps | |
| self.embed = nn.Embedding(a.engram_num_embeddings[self.layer_hash_index], a.engram_head_dim) | |
| n_hash_cols = (a.engram_max_ngram_size - 1) * a.engram_n_heads | |
| self.wkv = nn.Linear(n_hash_cols * a.engram_head_dim, a.dim * (a.hc_mult + 1), bias=False) | |
| self.q_weight = nn.Parameter(torch.ones(a.hc_mult, a.dim)) | |
| self.k_weight = nn.Parameter(torch.ones(a.hc_mult, a.dim)) | |
| def forward(self, x, hash_ids): | |
| kv = self.wkv(self.embed(hash_ids).flatten(-2)) | |
| key, value = kv.split([self.hc_mult * self.dim, self.dim], dim=-1) | |
| key = key.float().unflatten(-1, (self.hc_mult, self.dim)) | |
| h = x.float() | |
| rstd = torch.rsqrt(h.square().mean(-1) + self.eps) * torch.rsqrt(key.square().mean(-1) + self.eps) | |
| dot = (h * (self.q_weight.float() * self.k_weight.float()) * key).sum(-1) * rstd * self.dim**-0.5 | |
| gate = torch.sigmoid(torch.copysign(dot.abs().clamp_min(1e-6).sqrt(), dot)) | |
| return (h + gate.unsqueeze(-1) * value.float().unsqueeze(-2)).to(x.dtype) | |
| class Block(nn.Module): | |
| """Hyper-Connections block: the residual stream is carried as hc_mult copies.""" | |
| def __init__(self, layer_id: int, a: Args): | |
| super().__init__() | |
| self.norm_eps = a.norm_eps | |
| self.attn = Attention(layer_id, a) | |
| self.ffn = MoE(a) | |
| self.engram = Engram(a, layer_id) if layer_id in a.engram_layer_ids else None | |
| self.attn_norm = RMSNorm(a.dim, a.norm_eps) | |
| self.ffn_norm = RMSNorm(a.dim, a.norm_eps) | |
| self.hc, self.hc_iters, self.hc_eps = a.hc_mult, a.hc_sinkhorn_iters, a.hc_eps | |
| mix_hc = (2 + self.hc) * self.hc | |
| self.hc_attn_fn = nn.Parameter(torch.empty(mix_hc, self.hc * a.dim)) | |
| self.hc_ffn_fn = nn.Parameter(torch.empty(mix_hc, self.hc * a.dim)) | |
| self.hc_attn_base = nn.Parameter(torch.empty(mix_hc)) | |
| self.hc_ffn_base = nn.Parameter(torch.empty(mix_hc)) | |
| self.hc_attn_scale = nn.Parameter(torch.ones(3)) | |
| self.hc_ffn_scale = nn.Parameter(torch.ones(3)) | |
| def hc_mixes(self, x, fn, scale, base): | |
| x = x.flatten(2).float() | |
| mixes = F.linear(x, fn.float()) * torch.rsqrt(x.square().mean(-1, keepdim=True) + self.norm_eps) | |
| return hc_split_sinkhorn(mixes, scale.float(), base.float(), self.hc, self.hc_iters, self.hc_eps) | |
| def hc_pre(x, pre_mix): | |
| return torch.sum(pre_mix.unsqueeze(-1) * x.float(), dim=2).to(x.dtype) | |
| def hc_post(x, residual, post, comb): | |
| y = post.unsqueeze(-1) * x.unsqueeze(-2) + torch.sum(comb.unsqueeze(-1) * residual.unsqueeze(-2), dim=2) | |
| return y.to(residual.dtype) | |
| def forward(self, x, pre_mix, shared: Shared): | |
| residual = x | |
| attn_pre, attn_post, attn_comb = self.hc_mixes(x, self.hc_attn_fn, self.hc_attn_scale, self.hc_attn_base) | |
| h = self.attn(self.attn_norm(self.hc_pre(x, pre_mix)), shared) | |
| x = self.hc_post(h, residual, attn_post, attn_comb) | |
| residual = x | |
| ffn_pre, ffn_post, ffn_comb = self.hc_mixes(x, self.hc_ffn_fn, self.hc_ffn_scale, self.hc_ffn_base) | |
| h = self.ffn(self.ffn_norm(self.hc_pre(x, attn_pre))) | |
| x = self.hc_post(h, residual, ffn_post, ffn_comb) | |
| return x, ffn_pre | |
| class DeepseekV41PreTrainedModel(PreTrainedModel): | |
| config_class = DeepseekV41Config | |
| base_model_prefix = "" | |
| supports_gradient_checkpointing = False | |
| def _init_weights(self, module): | |
| pass # every parameter comes from model.safetensors | |
| class DeepseekV41ForCausalLM(DeepseekV41PreTrainedModel, GenerationMixin): | |
| """Submodule names (embed, layers, norm, head) match the checkpoint's tensor names directly.""" | |
| def __init__(self, config: DeepseekV41Config): | |
| super().__init__(config) | |
| a = Args.from_config(config) | |
| self.args = a | |
| self.embed = nn.Embedding(a.vocab_size, a.dim) | |
| self.layers = nn.ModuleList([Block(i, a) for i in range(a.n_layers)]) | |
| self.norm = RMSNorm(a.dim, a.norm_eps) | |
| self.head = nn.Linear(a.dim, a.vocab_size, bias=False) | |
| self.hc = a.hc_mult | |
| self._engram_hash = None | |
| self.post_init() | |
| def get_input_embeddings(self): | |
| return self.embed | |
| def set_input_embeddings(self, value): | |
| self.embed = value | |
| def get_output_embeddings(self): | |
| return self.head | |
| def set_output_embeddings(self, value): | |
| self.head = value | |
| def _engram(self): | |
| if self._engram_hash is None: # needs the tokenizer shipped in the same repo / folder | |
| src = getattr(self.config, "_name_or_path", None) or self.config.name_or_path | |
| self._engram_hash = NgramHash(self.args, AutoTokenizer.from_pretrained(src)) | |
| return self._engram_hash | |
| def forward(self, input_ids=None, attention_mask=None, labels=None, logits_to_keep=0, **kwargs): | |
| """No KV cache; attention_mask is ignored (use one unpadded sequence per row, i.e. batch of equal | |
| lengths or batch size 1). logits_to_keep=N returns logits for the last N positions only.""" | |
| bsz, seqlen = input_ids.shape | |
| hashes = self._engram()(input_ids) | |
| h = self.embed(input_ids).unsqueeze(2).repeat(1, 1, self.hc, 1) | |
| pre_mix = torch.zeros(bsz, seqlen, self.hc, device=h.device) | |
| pre_mix[..., 0] = 1.0 | |
| shared = Shared() | |
| for layer in self.layers: | |
| if layer.engram is not None: | |
| h = layer.engram(h, hashes[:, :, layer.engram.layer_hash_index]) | |
| h, pre_mix = layer(h, pre_mix, shared) | |
| h = self.norm(Block.hc_pre(h, pre_mix)) | |
| logits = self.head(h[:, -logits_to_keep:] if logits_to_keep else h) | |
| loss = None | |
| if labels is not None: | |
| loss = F.cross_entropy(logits[:, :-1].float().flatten(0, 1), labels[:, 1:].flatten(), ignore_index=-100) | |
| return CausalLMOutput(loss=loss, logits=logits) | |