CompressedGemma commited on
Commit
ca34b06
·
verified ·
1 Parent(s): da342e1

Upload slimshard.py

Browse files
Files changed (1) hide show
  1. slimshard.py +306 -0
slimshard.py CHANGED
@@ -941,6 +941,312 @@ def _run_generic_transformer_forward(
941
  return outputs
942
 
943
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
944
  def _synthesize_embed_tokens_checkfree(
945
  f_handle,
946
  present: set[str],
 
941
  return outputs
942
 
943
 
944
+ _FP4_LUT_CPU = [0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 0.0, -0.5, -1.0, -1.5, -2.0, -3.0, -4.0, -6.0]
945
+
946
+
947
+ def _ds4_dequant_fp8_32x32(w_fp8: "torch.Tensor", s_u8: "torch.Tensor") -> "torch.Tensor":
948
+ out_d, in_d = w_fp8.shape
949
+ s = torch.exp2(s_u8.view(torch.uint8).float() - 127.0)
950
+ b0, b1 = s.shape
951
+ g0, g1 = out_d // b0, in_d // b1
952
+ return (w_fp8.float().view(b0, g0, b1, g1) * s[:, None, :, None]).reshape(out_d, in_d)
953
+
954
+
955
+ def _ds4_dequant_fp4_1x32(w_i8: "torch.Tensor", s_u8: "torch.Tensor", lut: "torch.Tensor") -> "torch.Tensor":
956
+ out_d, half_in = w_i8.shape
957
+ in_d = half_in * 2
958
+ u = w_i8.view(torch.uint8)
959
+ low = (u & 0x0F).long()
960
+ high = ((u >> 4) & 0x0F).long()
961
+ vals = torch.stack([lut[low], lut[high]], dim=-1).reshape(out_d, in_d // 32, 32)
962
+ s = torch.exp2(s_u8.view(torch.uint8).float() - 127.0).unsqueeze(-1)
963
+ return (vals * s).reshape(out_d, in_d)
964
+
965
+
966
+ def _ds4_hc_mixes(
967
+ x: "torch.Tensor",
968
+ hc_fn: "torch.Tensor",
969
+ hc_scale: "torch.Tensor",
970
+ hc_base: "torch.Tensor",
971
+ hc_mult: int = 4,
972
+ sinkhorn_iters: int = 20,
973
+ norm_eps: float = 1.0e-20,
974
+ hc_eps: float = 1.0e-6,
975
+ ) -> tuple["torch.Tensor", "torch.Tensor", "torch.Tensor"]:
976
+ xf = x.flatten(2).float()
977
+ rsqrt = torch.rsqrt(xf.square().mean(-1, keepdim=True) + norm_eps)
978
+ mixes = F.linear(xf, hc_fn.float()) * rsqrt
979
+ s0, s1, s2 = hc_scale.float()[0], hc_scale.float()[1], hc_scale.float()[2]
980
+ b_f = hc_base.float()
981
+ pre = torch.sigmoid(mixes[..., :hc_mult] * s0 + b_f[:hc_mult]) + hc_eps
982
+ post = 2.0 * torch.sigmoid(mixes[..., hc_mult : 2 * hc_mult] * s1 + b_f[hc_mult : 2 * hc_mult])
983
+ comb = (mixes[..., 2 * hc_mult :] * s2 + b_f[2 * hc_mult :]).reshape(*mixes.shape[:-1], hc_mult, hc_mult)
984
+ comb = torch.softmax(comb, dim=-1) + hc_eps
985
+ comb = comb / (comb.sum(dim=-2, keepdim=True) + hc_eps)
986
+ for _ in range(sinkhorn_iters - 1):
987
+ comb = comb / (comb.sum(dim=-1, keepdim=True) + hc_eps)
988
+ comb = comb / (comb.sum(dim=-2, keepdim=True) + hc_eps)
989
+ return pre, post, comb
990
+
991
+
992
+ def _ds4_apply_rope(x: "torch.Tensor", freqs_cis: "torch.Tensor", inverse: bool = False) -> "torch.Tensor":
993
+ rd = freqs_cis.shape[-1] * 2
994
+ tail = x[..., -rd:].float().unflatten(-1, (-1, 2))
995
+ c = torch.view_as_complex(tail)
996
+ fc = freqs_cis.conj() if inverse else freqs_cis
997
+ if x.ndim == 3:
998
+ fc = fc.view(1, x.size(1), -1)
999
+ else:
1000
+ fc = fc.view(1, x.size(1), 1, -1)
1001
+ rot = torch.view_as_real(c * fc).flatten(-2).to(x.dtype)
1002
+ if rd == x.shape[-1]:
1003
+ return rot
1004
+ return torch.cat([x[..., :-rd], rot], dim=-1)
1005
+
1006
+
1007
+ def _run_deepseek_v41_forward(
1008
+ read_fn,
1009
+ has_key_fn,
1010
+ token_seqs: list[list[int]],
1011
+ coords: np.ndarray | None,
1012
+ basis_in: "torch.Tensor | None",
1013
+ scale_in: float,
1014
+ arch: dict,
1015
+ dev: "torch.device",
1016
+ ) -> list["torch.Tensor"]:
1017
+ """Execute DeepSeek-V4.1 causal forward pass (4-stream Sinkhorn HC + MLA + FP4/FP8 MoE)."""
1018
+ num_layers = int(arch.get("num_hidden_layers", 40))
1019
+ dim = int(arch.get("hidden_size", 5120))
1020
+ eps = float(arch.get("rms_norm_eps", 1.0e-20))
1021
+ hc_mult = int(arch.get("hc_mult", 4))
1022
+ hc_iters = int(arch.get("hc_sinkhorn_iters", 20))
1023
+ hc_eps = float(arch.get("hc_eps", 1.0e-6))
1024
+ n_heads = int(arch.get("num_attention_heads", 64))
1025
+ head_dim = int(arch.get("head_dim", 512))
1026
+ rope_dim = int(arch.get("qk_rope_head_dim", 64))
1027
+ o_groups = int(arch.get("o_groups", 8))
1028
+ o_lora_rank = int(arch.get("o_lora_rank", 1024))
1029
+ top_k = int(arch.get("num_experts_per_tok", arch.get("num_experts_per_token", 6)))
1030
+ route_scale = float(arch.get("routed_scaling_factor", 1.5))
1031
+ swiglu_limit = float(arch.get("swiglu_limit", 10.0))
1032
+ rope_theta = float(arch.get("rope_theta", 10000.0))
1033
+ softmax_scale = head_dim ** -0.5
1034
+
1035
+ lut = torch.tensor(_FP4_LUT_CPU, dtype=torch.float32, device=dev)
1036
+ max_t = max(len(s) for s in token_seqs)
1037
+ freqs = 1.0 / (rope_theta ** (torch.arange(0, rope_dim, 2, dtype=torch.float32, device=dev) / rope_dim))
1038
+ freqs_cis_all = torch.polar(torch.ones((max_t, rope_dim // 2), device=dev), torch.outer(torch.arange(max_t, device=dev, dtype=torch.float32), freqs))
1039
+
1040
+ streams = []
1041
+ pre_mixes = []
1042
+ if coords is not None and basis_in is not None:
1043
+ for seq in token_seqs:
1044
+ c_seq = torch.from_numpy(coords[seq]).to(dev, dtype=torch.float32)
1045
+ inp = (c_seq @ basis_in * scale_in).to(torch.bfloat16).unsqueeze(0)
1046
+ h0 = inp.unsqueeze(2).repeat(1, 1, hc_mult, 1)
1047
+ pm = torch.zeros(1, len(seq), hc_mult, dtype=torch.float32, device=dev)
1048
+ pm[:, :, 0] = 1.0
1049
+ streams.append(h0)
1050
+ pre_mixes.append(pm)
1051
+ else:
1052
+ emb_w = read_fn("embed.weight")
1053
+ for seq in token_seqs:
1054
+ ids_t = torch.tensor([seq], dtype=torch.long, device=dev)
1055
+ inp = F.embedding(ids_t, emb_w).to(torch.bfloat16)
1056
+ h0 = inp.unsqueeze(2).repeat(1, 1, hc_mult, 1)
1057
+ pm = torch.zeros(1, len(seq), hc_mult, dtype=torch.float32, device=dev)
1058
+ pm[:, :, 0] = 1.0
1059
+ streams.append(h0)
1060
+ pre_mixes.append(pm)
1061
+ del emb_w
1062
+
1063
+ # Cache layer weights if multiple layers are identical (e.g. single-shard anchor recovery)
1064
+ cached_layer_ signature = None
1065
+ cached_layer_data = None
1066
+
1067
+ for lidx in range(num_layers):
1068
+ lp = f"layers.{lidx}"
1069
+ if not has_key_fn(f"{lp}.attn_norm.weight"):
1070
+ lp = f"model.layers.{lidx}"
1071
+ w_anorm = read_fn(f"{lp}.attn_norm.weight")
1072
+ w_fnorm = read_fn(f"{lp}.ffn_norm.weight")
1073
+ hc_afn = read_fn(f"{lp}.hc_attn_fn")
1074
+ hc_asc = read_fn(f"{lp}.hc_attn_scale")
1075
+ hc_ab = read_fn(f"{lp}.hc_attn_base")
1076
+ hc_ffn = read_fn(f"{lp}.hc_ffn_fn")
1077
+ hc_fsc = read_fn(f"{lp}.hc_ffn_scale")
1078
+ hc_fb = read_fn(f"{lp}.hc_ffn_base")
1079
+
1080
+ sig = float(hc_ab.float().sum().item())
1081
+ if cached_layer_data is not None and cached_layer_signature == sig:
1082
+ wq_a, wq_b, wkv, wo_a, wo_b, q_norm_w, kv_norm_w, attn_sink, sw1, sw2, sw3, gw, gb = cached_layer_data
1083
+ else:
1084
+ wq_a = _ds4_dequant_fp8_32x32(read_fn(f"{lp}.attn.wq_a.weight"), read_fn(f"{lp}.attn.wq_a.scale")).to(torch.bfloat16)
1085
+ wq_b = _ds4_dequant_fp8_32x32(read_fn(f"{lp}.attn.wq_b.weight"), read_fn(f"{lp}.attn.wq_b.scale")).to(torch.bfloat16)
1086
+ wkv = _ds4_dequant_fp8_32x32(read_fn(f"{lp}.attn.wkv.weight"), read_fn(f"{lp}.attn.wkv.scale")).to(torch.bfloat16)
1087
+ wo_a = _ds4_dequant_fp8_32x32(read_fn(f"{lp}.attn.wo_a.weight"), read_fn(f"{lp}.attn.wo_a.scale")).to(torch.bfloat16)
1088
+ wo_b = _ds4_dequant_fp8_32x32(read_fn(f"{lp}.attn.wo_b.weight"), read_fn(f"{lp}.attn.wo_b.scale")).to(torch.bfloat16)
1089
+ q_norm_w = read_fn(f"{lp}.attn.q_norm.weight")
1090
+ kv_norm_w = read_fn(f"{lp}.attn.kv_norm.weight")
1091
+ attn_sink = read_fn(f"{lp}.attn.attn_sink").float()
1092
+ sw1 = _ds4_dequant_fp8_32x32(read_fn(f"{lp}.ffn.shared_experts.w1.weight"), read_fn(f"{lp}.ffn.shared_experts.w1.scale")).to(torch.bfloat16)
1093
+ sw2 = _ds4_dequant_fp8_32x32(read_fn(f"{lp}.ffn.shared_experts.w2.weight"), read_fn(f"{lp}.ffn.shared_experts.w2.scale")).to(torch.bfloat16)
1094
+ sw3 = _ds4_dequant_fp8_32x32(read_fn(f"{lp}.ffn.shared_experts.w3.weight"), read_fn(f"{lp}.ffn.shared_experts.w3.scale")).to(torch.bfloat16)
1095
+ gw = read_fn(f"{lp}.ffn.gate.weight").float()
1096
+ gb = read_fn(f"{lp}.ffn.gate.bias").float()
1097
+ cached_layer_signature = sig
1098
+ cached_layer_data = (wq_a, wq_b, wkv, wo_a, wo_b, q_norm_w, kv_norm_w, attn_sink, sw1, sw2, sw3, gw, gb)
1099
+
1100
+ n_routed_eff = gw.shape[0]
1101
+ top_k_eff = min(top_k, n_routed_eff)
1102
+ wo_a_grouped = wo_a.view(o_groups, o_lora_rank, -1)
1103
+
1104
+ in_ffn_list = []
1105
+ ffn_meta = []
1106
+
1107
+ for s_idx, h in enumerate(streams):
1108
+ B, T, _, _ = h.shape
1109
+ fc = freqs_cis_all[:T]
1110
+ residual = h
1111
+ attn_pre, attn_post, attn_comb = _ds4_hc_mixes(h, hc_afn, hc_asc, hc_ab, hc_mult, hc_iters, eps, hc_eps)
1112
+ x = torch.sum(pre_mixes[s_idx].unsqueeze(-1) * h.float(), dim=2).to(torch.bfloat16)
1113
+ x = _rms_norm_torch(x, w_anorm, eps)
1114
+
1115
+ qr = _rms_norm_torch(F.linear(x, wq_a), q_norm_w, eps)
1116
+ q = F.linear(qr, wq_b).view(B, T, n_heads, head_dim)
1117
+ q = _ds4_apply_rope(q, fc, inverse=False)
1118
+ kv = _rms_norm_torch(F.linear(x, wkv), kv_norm_w, eps)
1119
+ kv = _ds4_apply_rope(kv, fc, inverse=False)
1120
+
1121
+ # Causal attention with attn_sink
1122
+ scores = torch.einsum("bthd,bsd->bhts", q.float(), kv.float()) * softmax_scale
1123
+ if T > 1:
1124
+ causal_mask = torch.triu(torch.ones((T, T), dtype=torch.bool, device=dev), diagonal=1)
1125
+ scores = scores.masked_fill(causal_mask[None, None, :, :], -1.0e30)
1126
+ s_max = torch.maximum(scores.amax(dim=-1, keepdim=True), attn_sink.view(1, n_heads, 1, 1))
1127
+ exp_s = torch.exp(scores - s_max)
1128
+ denom = exp_s.sum(dim=-1, keepdim=True) + torch.exp(attn_sink.view(1, n_heads, 1, 1) - s_max)
1129
+ probs_a = (exp_s / denom).to(torch.bfloat16)
1130
+ o = torch.einsum("bhts,bsd->bthd", probs_a, kv)
1131
+ o = _ds4_apply_rope(o, fc, inverse=True)
1132
+ o_grp = o.reshape(B, T, o_groups, -1)
1133
+ o_proj = torch.einsum("bsgd,grd->bsgr", o_grp, wo_a_grouped).flatten(2)
1134
+ attn_out = F.linear(o_proj, wo_b)
1135
+
1136
+ h = (attn_post.unsqueeze(-1) * attn_out.float().unsqueeze(-2) + torch.sum(attn_comb.unsqueeze(-1) * residual.float().unsqueeze(-2), dim=2)).to(torch.bfloat16)
1137
+ residual2 = h
1138
+ ffn_pre, ffn_post, ffn_comb = _ds4_hc_mixes(h, hc_ffn, hc_fsc, hc_fb, hc_mult, hc_iters, eps, hc_eps)
1139
+ x_ffn = _rms_norm_torch(torch.sum(attn_pre.unsqueeze(-1) * h.float(), dim=2).to(torch.bfloat16), w_fnorm, eps)
1140
+ in_ffn_list.append(x_ffn.reshape(B * T, dim))
1141
+ ffn_meta.append((s_idx, B, T, residual2, ffn_pre, ffn_post, ffn_comb))
1142
+
1143
+ flat_all = torch.cat(in_ffn_list, dim=0)
1144
+ g_scores = F.softplus(F.linear(flat_all.float(), gw)).sqrt()
1145
+ _, top_idx = (g_scores + gb).topk(top_k_eff, dim=-1)
1146
+ top_w = g_scores.gather(1, top_idx)
1147
+ top_w = (top_w / (top_w.sum(dim=-1, keepdim=True) + 1.0e-20)) * route_scale
1148
+
1149
+ y_all = torch.zeros_like(flat_all, dtype=torch.float32)
1150
+ hit = torch.bincount(top_idx.flatten(), minlength=n_routed_eff)
1151
+ for eidx in hit.nonzero().flatten().tolist():
1152
+ erows, eslot = torch.where(top_idx == eidx)
1153
+ xe = flat_all.index_select(0, erows)
1154
+ ep = f"{lp}.ffn.experts.{eidx}"
1155
+ ew1 = _ds4_dequant_fp4_1x32(read_fn(f"{ep}.w1.weight"), read_fn(f"{ep}.w1.scale"), lut).to(torch.bfloat16)
1156
+ ew2 = _ds4_dequant_fp4_1x32(read_fn(f"{ep}.w2.weight"), read_fn(f"{ep}.w2.scale"), lut).to(torch.bfloat16)
1157
+ ew3 = _ds4_dequant_fp4_1x32(read_fn(f"{ep}.w3.weight"), read_fn(f"{ep}.w3.scale"), lut).to(torch.bfloat16)
1158
+ egate = F.linear(xe, ew1).float().clamp(max=swiglu_limit)
1159
+ eup = F.linear(xe, ew3).float().clamp(min=-swiglu_limit, max=swiglu_limit)
1160
+ eact = (F.silu(egate) * eup) * top_w[erows, eslot, None]
1161
+ y_all.index_add_(0, erows, F.linear(eact.to(torch.bfloat16), ew2).float())
1162
+
1163
+ sgate = F.linear(flat_all, sw1).float().clamp(max=swiglu_limit)
1164
+ sup = F.linear(flat_all, sw3).float().clamp(min=-swiglu_limit, max=swiglu_limit)
1165
+ y_all = y_all + F.linear((F.silu(sgate) * sup).to(torch.bfloat16), sw2).float()
1166
+
1167
+ off = 0
1168
+ for s_idx, B, T, residual2, ffn_pre, ffn_post, ffn_comb in ffn_meta:
1169
+ nt = B * T
1170
+ fout = y_all[off : off + nt].reshape(B, T, dim)
1171
+ off += nt
1172
+ h_next = (ffn_post.unsqueeze(-1) * fout.unsqueeze(-2) + torch.sum(ffn_comb.unsqueeze(-1) * residual2.float().unsqueeze(-2), dim=2)).to(torch.bfloat16)
1173
+ streams[s_idx] = h_next
1174
+ pre_mixes[s_idx] = ffn_pre
1175
+
1176
+ norm_key = next((k for k in ("norm.weight", "model.norm.weight") if has_key_fn(k)), None)
1177
+ w_final = read_fn(norm_key) if norm_key else torch.ones(dim, dtype=torch.bfloat16, device=dev)
1178
+ if w_final.numel() != dim:
1179
+ w_final = torch.ones(dim, dtype=torch.bfloat16, device=dev)
1180
+ outputs = []
1181
+ for s_idx, h in enumerate(streams):
1182
+ h_col = torch.sum(pre_mixes[s_idx].unsqueeze(-1) * h.float(), dim=2).to(torch.bfloat16)
1183
+ out_h = _rms_norm_torch(h_col, w_final, eps)
1184
+ outputs.append(out_h[0].float())
1185
+ return outputs
1186
+
1187
+
1188
+ def run_deepseek_v41_generate(
1189
+ safetensors_path: str | Path,
1190
+ config_path: str | Path,
1191
+ tokenizer_dir: str | Path,
1192
+ prompt: str = "hello",
1193
+ max_new_tokens: int = 16,
1194
+ use_chat_template: bool = False,
1195
+ device: str = "auto",
1196
+ ) -> tuple[str, list[int]]:
1197
+ """Run autoregressive greedy generation on a recovered DeepSeek-V4.1 safetensors model."""
1198
+ from transformers import AutoTokenizer
1199
+
1200
+ tok = AutoTokenizer.from_pretrained(str(tokenizer_dir), trust_remote_code=True, local_files_only=True)
1201
+ raw_cfg = json.loads(Path(config_path).read_text())
1202
+ arch = _normalize_arch_config(raw_cfg)
1203
+ dev = torch.device("cuda:0" if (device in ("auto", "cuda") and torch.cuda.is_available()) else "cpu")
1204
+
1205
+ if use_chat_template and getattr(tok, "chat_template", None):
1206
+ ids = tok.apply_chat_template(
1207
+ [{"role": "user", "content": prompt}],
1208
+ add_generation_prompt=True,
1209
+ tokenize=True,
1210
+ )
1211
+ if isinstance(ids, dict):
1212
+ ids = ids["input_ids"]
1213
+ else:
1214
+ ids = tok.encode(prompt, add_special_tokens=False)
1215
+ if not ids:
1216
+ ids = [0]
1217
+
1218
+ prompt_len = len(ids)
1219
+ cur_ids = list(ids)
1220
+ eos_id = tok.eos_token_id if tok.eos_token_id is not None else int(arch.get("eos_token_id", 1))
1221
+ im_end_id = tok.convert_tokens_to_ids("<|im_end|>") if "<|im_end|>" in tok.get_vocab() else -1
1222
+
1223
+ with safe_open(str(safetensors_path), framework="pt", device="cpu") as sf:
1224
+ keys_set = set(sf.keys())
1225
+ head_key = next((k for k in _HEAD_NAMES if k in keys_set), "head.weight")
1226
+ head_w = sf.get_tensor(head_key).to(dev, dtype=torch.bfloat16)
1227
+
1228
+ def read_fn(k: str) -> "torch.Tensor":
1229
+ return sf.get_tensor(k).to(dev, non_blocking=True)
1230
+
1231
+ def has_key_fn(k: str) -> bool:
1232
+ return k in keys_set
1233
+
1234
+ with torch.no_grad():
1235
+ for _ in range(max_new_tokens):
1236
+ h_outs = _run_deepseek_v41_forward(
1237
+ read_fn, has_key_fn, [cur_ids], None, None, 1.0, arch, dev
1238
+ )
1239
+ last_h = h_outs[0][-1].to(torch.bfloat16)
1240
+ logits = F.linear(last_h, head_w).float()
1241
+ next_id = int(torch.argmax(logits).item())
1242
+ cur_ids.append(next_id)
1243
+ if next_id in (eos_id, im_end_id):
1244
+ break
1245
+
1246
+ text = tok.decode(cur_ids[prompt_len:] if use_chat_template else cur_ids, skip_special_tokens=False)
1247
+ return text, cur_ids
1248
+
1249
+
1250
  def _synthesize_embed_tokens_checkfree(
1251
  f_handle,
1252
  present: set[str],