:D :D
Browse files- slimshard.py +88 -3
slimshard.py
CHANGED
|
@@ -66,12 +66,13 @@ from .q4_0 import Q4_0_BLOCK_BYTES, QK4_0, dequantize_q4_0_bytes, quantize_tenso
|
|
| 66 |
|
| 67 |
SHARD_FORMAT = "hpc-slimshard-v1"
|
| 68 |
EXPERT_RE = re.compile(
|
| 69 |
-
r"^((?:[a-zA-Z0-9_]+\.)*(?:layers|h|blocks))\.(\d+)\.((?:moe\.|mlp\.|block_sparse_moe\.|feed_forward\.)?experts)\.(\d+)\.([a-zA-Z0-9_]+)\.(weight|bias|weight_scale_inv|weight_scale|scales)$"
|
| 70 |
)
|
| 71 |
LAYER_RE = re.compile(r"^((?:[a-zA-Z0-9_]+\.)*(?:layers|h|blocks))\.(\d+)\.(.+)$")
|
| 72 |
|
| 73 |
_EMBED_NAMES = (
|
| 74 |
"model.embed_tokens.weight",
|
|
|
|
| 75 |
"transformer.wte.weight",
|
| 76 |
"gpt_neox.embed_in.weight",
|
| 77 |
"model.decoder.embed_tokens.weight",
|
|
@@ -81,6 +82,7 @@ _EMBED_NAMES = (
|
|
| 81 |
)
|
| 82 |
_HEAD_NAMES = (
|
| 83 |
"lm_head.weight",
|
|
|
|
| 84 |
"embed_out.weight",
|
| 85 |
"output.weight",
|
| 86 |
"language_model.lm_head.weight",
|
|
@@ -88,6 +90,7 @@ _HEAD_NAMES = (
|
|
| 88 |
)
|
| 89 |
_NORM_NAMES = (
|
| 90 |
"model.norm.weight",
|
|
|
|
| 91 |
"transformer.ln_f.weight",
|
| 92 |
"gpt_neox.final_layer_norm.weight",
|
| 93 |
"model.decoder.final_layer_norm.weight",
|
|
@@ -241,6 +244,8 @@ _TORCH_DTYPE = {
|
|
| 241 |
"float8_e5m2": "F8_E5M2",
|
| 242 |
"float8_e4m3fnuz": "F8_E4M3",
|
| 243 |
"float8_e5m2fnuz": "F8_E5M2",
|
|
|
|
|
|
|
| 244 |
}
|
| 245 |
_NP_DTYPE = {
|
| 246 |
"F32": np.float32,
|
|
@@ -1235,10 +1240,86 @@ def _write_lm_head_calibrated_chunked(
|
|
| 1235 |
writer.add_chunked_bf16(name, (vocab, hidden), gen())
|
| 1236 |
|
| 1237 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1238 |
def inspect_recovery_plan(
|
| 1239 |
shard: str | Path,
|
| 1240 |
index: str | Path | None = None,
|
| 1241 |
config: str | Path | None = None,
|
|
|
|
|
|
|
| 1242 |
) -> dict:
|
| 1243 |
"""Inspect a shard + index/config and return a full CheckFree recovery plan for the GUI."""
|
| 1244 |
shard_path = Path(shard)
|
|
@@ -1250,9 +1331,9 @@ def inspect_recovery_plan(
|
|
| 1250 |
|
| 1251 |
index_path = Path(index) if index else shard_path.parent / "model.safetensors.index.json"
|
| 1252 |
if index_path.exists():
|
| 1253 |
-
|
| 1254 |
else:
|
| 1255 |
-
|
| 1256 |
|
| 1257 |
with safe_open(str(shard_path), framework="pt", device="cpu") as f:
|
| 1258 |
meta = f.metadata() or {}
|
|
@@ -1265,6 +1346,10 @@ def inspect_recovery_plan(
|
|
| 1265 |
present_shapes[k] = tuple(sl.get_shape())
|
| 1266 |
present_dtypes[k] = _safetensors_dtype(sl.get_dtype())
|
| 1267 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1268 |
surviving_layers = sorted(
|
| 1269 |
{int(LAYER_RE.match(k).group(2)) for k in present if LAYER_RE.match(k)}
|
| 1270 |
)
|
|
|
|
| 66 |
|
| 67 |
SHARD_FORMAT = "hpc-slimshard-v1"
|
| 68 |
EXPERT_RE = re.compile(
|
| 69 |
+
r"^((?:[a-zA-Z0-9_]+\.)*(?:layers|h|blocks))\.(\d+)\.((?:moe\.|mlp\.|ffn\.|block_sparse_moe\.|feed_forward\.)?experts)\.(\d+)\.([a-zA-Z0-9_]+)\.(weight|bias|weight_scale_inv|weight_scale|scales|scale)$"
|
| 70 |
)
|
| 71 |
LAYER_RE = re.compile(r"^((?:[a-zA-Z0-9_]+\.)*(?:layers|h|blocks))\.(\d+)\.(.+)$")
|
| 72 |
|
| 73 |
_EMBED_NAMES = (
|
| 74 |
"model.embed_tokens.weight",
|
| 75 |
+
"embed.weight",
|
| 76 |
"transformer.wte.weight",
|
| 77 |
"gpt_neox.embed_in.weight",
|
| 78 |
"model.decoder.embed_tokens.weight",
|
|
|
|
| 82 |
)
|
| 83 |
_HEAD_NAMES = (
|
| 84 |
"lm_head.weight",
|
| 85 |
+
"head.weight",
|
| 86 |
"embed_out.weight",
|
| 87 |
"output.weight",
|
| 88 |
"language_model.lm_head.weight",
|
|
|
|
| 90 |
)
|
| 91 |
_NORM_NAMES = (
|
| 92 |
"model.norm.weight",
|
| 93 |
+
"norm.weight",
|
| 94 |
"transformer.ln_f.weight",
|
| 95 |
"gpt_neox.final_layer_norm.weight",
|
| 96 |
"model.decoder.final_layer_norm.weight",
|
|
|
|
| 244 |
"float8_e5m2": "F8_E5M2",
|
| 245 |
"float8_e4m3fnuz": "F8_E4M3",
|
| 246 |
"float8_e5m2fnuz": "F8_E5M2",
|
| 247 |
+
"float8_e8m0fnu": "U8",
|
| 248 |
+
"F8_E8M0": "U8",
|
| 249 |
}
|
| 250 |
_NP_DTYPE = {
|
| 251 |
"F32": np.float32,
|
|
|
|
| 1240 |
writer.add_chunked_bf16(name, (vocab, hidden), gen())
|
| 1241 |
|
| 1242 |
|
| 1243 |
+
def _filter_weight_map_for_target(
|
| 1244 |
+
weight_map: dict[str, str],
|
| 1245 |
+
present: set[str],
|
| 1246 |
+
arch: dict,
|
| 1247 |
+
target_params_b: float | None = None,
|
| 1248 |
+
max_experts: int | None = None,
|
| 1249 |
+
) -> tuple[dict[str, str], int | None, float]:
|
| 1250 |
+
"""Filter ``weight_map`` for single-shard recovery and optional parameter-budget compression.
|
| 1251 |
+
|
| 1252 |
+
* Strips external multi-hundred-GB ``.engram.`` tables, ``mtp.`` draft layers,
|
| 1253 |
+
and ``vision.`` / ``aligner.`` / ``image_`` branches if absent from ``present``.
|
| 1254 |
+
* Computes ``kept_experts`` when ``target_params_b`` (e.g. ``30.0``) or
|
| 1255 |
+
``max_experts`` is specified, pruning routed experts ``>= kept_experts``.
|
| 1256 |
+
* Returns ``(filtered_weight_map, kept_experts, estimated_params_b)``.
|
| 1257 |
+
"""
|
| 1258 |
+
has_vision = any(k.startswith(("vision.", "aligner.", "image_")) for k in present)
|
| 1259 |
+
has_mtp = any(k.startswith("mtp.") for k in present)
|
| 1260 |
+
has_engram = any(".engram." in k for k in present)
|
| 1261 |
+
|
| 1262 |
+
orig_experts = int(arch.get("num_experts") or 0)
|
| 1263 |
+
num_layers = int(arch.get("num_hidden_layers") or 25)
|
| 1264 |
+
hidden = int(arch.get("hidden_size") or 2560)
|
| 1265 |
+
moe_inter = int(arch.get("moe_intermediate_size") or arch.get("intermediate_size") or 1088)
|
| 1266 |
+
vocab = int(arch.get("vocab_size") or 128000)
|
| 1267 |
+
top_k = int(arch.get("num_experts_per_token") or arch.get("num_experts_per_tok") or 6)
|
| 1268 |
+
|
| 1269 |
+
# Estimate dense/non-routed parameters (embed + head + attention + shared experts)
|
| 1270 |
+
tie_emb = bool(arch.get("tie_word_embeddings", False))
|
| 1271 |
+
embed_params = vocab * hidden * (1 if tie_emb else 2)
|
| 1272 |
+
attn_shared_per_layer = (4 * hidden * hidden) + (3 * moe_inter * hidden)
|
| 1273 |
+
dense_params = float(embed_params + num_layers * attn_shared_per_layer)
|
| 1274 |
+
params_per_expert = float(3 * moe_inter * hidden)
|
| 1275 |
+
|
| 1276 |
+
kept_experts: int | None = None
|
| 1277 |
+
if max_experts is not None and max_experts > 0 and orig_experts > 0:
|
| 1278 |
+
kept_experts = min(orig_experts, max(top_k, int(max_experts)))
|
| 1279 |
+
elif target_params_b is not None and target_params_b > 0.0 and orig_experts > 0 and params_per_expert > 0:
|
| 1280 |
+
target_p = float(target_params_b) * 1.0e9
|
| 1281 |
+
avail_for_routed = max(0.0, target_p - dense_params)
|
| 1282 |
+
moe_layers = max(1, num_layers - int(arch.get("first_k_dense_replace", 0)))
|
| 1283 |
+
est_e = int(round(avail_for_routed / (moe_layers * params_per_expert)))
|
| 1284 |
+
kept_experts = min(orig_experts, max(top_k, est_e))
|
| 1285 |
+
|
| 1286 |
+
filtered: dict[str, str] = {}
|
| 1287 |
+
for k, sh in weight_map.items():
|
| 1288 |
+
if not has_engram and ".engram." in k:
|
| 1289 |
+
continue
|
| 1290 |
+
if not has_mtp and k.startswith("mtp."):
|
| 1291 |
+
continue
|
| 1292 |
+
if not has_vision and (k.startswith(("vision.", "aligner.", "image_")) or k.endswith(".bias_vl")):
|
| 1293 |
+
continue
|
| 1294 |
+
em = EXPERT_RE.match(k)
|
| 1295 |
+
if em and kept_experts is not None:
|
| 1296 |
+
eidx = int(em.group(4))
|
| 1297 |
+
if eidx >= kept_experts:
|
| 1298 |
+
continue
|
| 1299 |
+
filtered[k] = sh
|
| 1300 |
+
|
| 1301 |
+
moe_layers = max(1, num_layers - int(arch.get("first_k_dense_replace", 0)))
|
| 1302 |
+
eff_experts = kept_experts if kept_experts is not None else orig_experts
|
| 1303 |
+
est_total_b = (dense_params + (moe_layers * eff_experts * params_per_expert if eff_experts > 0 else 0.0)) / 1.0e9
|
| 1304 |
+
return filtered, kept_experts, est_total_b
|
| 1305 |
+
|
| 1306 |
+
|
| 1307 |
+
def _is_router_gate_tensor(name: str, orig_experts: int, shape: tuple[int, ...]) -> bool:
|
| 1308 |
+
if orig_experts <= 0 or not shape or shape[0] != orig_experts:
|
| 1309 |
+
return False
|
| 1310 |
+
return (
|
| 1311 |
+
".gate.weight" in name
|
| 1312 |
+
or ".gate.bias" in name
|
| 1313 |
+
or name.endswith("e_score_correction_bias")
|
| 1314 |
+
) and ".experts." not in name
|
| 1315 |
+
|
| 1316 |
+
|
| 1317 |
def inspect_recovery_plan(
|
| 1318 |
shard: str | Path,
|
| 1319 |
index: str | Path | None = None,
|
| 1320 |
config: str | Path | None = None,
|
| 1321 |
+
target_params_b: float | None = None,
|
| 1322 |
+
max_experts: int | None = None,
|
| 1323 |
) -> dict:
|
| 1324 |
"""Inspect a shard + index/config and return a full CheckFree recovery plan for the GUI."""
|
| 1325 |
shard_path = Path(shard)
|
|
|
|
| 1331 |
|
| 1332 |
index_path = Path(index) if index else shard_path.parent / "model.safetensors.index.json"
|
| 1333 |
if index_path.exists():
|
| 1334 |
+
raw_weight_map: dict[str, str] = json.loads(index_path.read_text())["weight_map"]
|
| 1335 |
else:
|
| 1336 |
+
raw_weight_map = infer_weight_map_from_shard(shard_path, arch)
|
| 1337 |
|
| 1338 |
with safe_open(str(shard_path), framework="pt", device="cpu") as f:
|
| 1339 |
meta = f.metadata() or {}
|
|
|
|
| 1346 |
present_shapes[k] = tuple(sl.get_shape())
|
| 1347 |
present_dtypes[k] = _safetensors_dtype(sl.get_dtype())
|
| 1348 |
|
| 1349 |
+
weight_map, kept_experts, est_params_b = _filter_weight_map_for_target(
|
| 1350 |
+
raw_weight_map, present, arch, target_params_b=target_params_b, max_experts=max_experts
|
| 1351 |
+
)
|
| 1352 |
+
|
| 1353 |
surviving_layers = sorted(
|
| 1354 |
{int(LAYER_RE.match(k).group(2)) for k in present if LAYER_RE.match(k)}
|
| 1355 |
)
|