Upload slimshard.py
Browse files- slimshard.py +41 -4
slimshard.py
CHANGED
|
@@ -1431,7 +1431,9 @@ def inspect_recovery_plan(
|
|
| 1431 |
"architectures": arch.get("architectures", []),
|
| 1432 |
"hidden_size": arch.get("hidden_size", 0),
|
| 1433 |
"num_hidden_layers": arch.get("num_hidden_layers", len(all_layers)),
|
| 1434 |
-
"num_experts": arch.get("num_experts", 0),
|
|
|
|
|
|
|
| 1435 |
"vocab_size": arch.get("vocab_size", 0),
|
| 1436 |
"surviving_layers": surviving_layers,
|
| 1437 |
"missing_layers": missing_layers,
|
|
@@ -1447,6 +1449,10 @@ def export_hf_bundle(
|
|
| 1447 |
safetensors_path: str | Path,
|
| 1448 |
source_dir: str | Path,
|
| 1449 |
bundle_dir: str | Path,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1450 |
) -> Path:
|
| 1451 |
"""Create a complete Hugging Face model directory around ``safetensors_path``."""
|
| 1452 |
st_path = Path(safetensors_path).resolve()
|
|
@@ -1461,7 +1467,6 @@ def export_hf_bundle(
|
|
| 1461 |
if not target_model.exists():
|
| 1462 |
os.symlink(st_path, target_model)
|
| 1463 |
|
| 1464 |
-
# Remove any multi-shard index in bundle_dir so transformers loads model.safetensors directly
|
| 1465 |
idx_out = out_dir / "model.safetensors.index.json"
|
| 1466 |
if idx_out.exists() or idx_out.is_symlink():
|
| 1467 |
idx_out.unlink()
|
|
@@ -1472,6 +1477,29 @@ def export_hf_bundle(
|
|
| 1472 |
if item.name.startswith("."):
|
| 1473 |
continue
|
| 1474 |
dst = out_dir / item.name
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1475 |
if dst.exists() or dst.is_symlink():
|
| 1476 |
continue
|
| 1477 |
os.symlink(item.resolve(), dst)
|
|
@@ -1491,6 +1519,8 @@ def recover_from_shard(
|
|
| 1491 |
progress_cb=None,
|
| 1492 |
stop_event=None,
|
| 1493 |
export_hf_dir: str | Path | None = None,
|
|
|
|
|
|
|
| 1494 |
) -> dict:
|
| 1495 |
"""Regenerate a full multi-shard HF model from **one** ``.safetensors`` shard.
|
| 1496 |
|
|
@@ -1509,9 +1539,9 @@ def recover_from_shard(
|
|
| 1509 |
arch = _normalize_arch_config(raw_arch)
|
| 1510 |
|
| 1511 |
if index_path.exists():
|
| 1512 |
-
|
| 1513 |
else:
|
| 1514 |
-
|
| 1515 |
|
| 1516 |
tok_path = cfg_path.parent / "tokenizer.json"
|
| 1517 |
if not tok_path.exists():
|
|
@@ -1520,6 +1550,7 @@ def recover_from_shard(
|
|
| 1520 |
use_cuda = (device in ("auto", "cuda")) and torch.cuda.is_available()
|
| 1521 |
dev = torch.device("cuda:0" if use_cuda else "cpu")
|
| 1522 |
total_layers = int(arch.get("num_hidden_layers", 25))
|
|
|
|
| 1523 |
|
| 1524 |
rda_cfg = arch.get("rda_config", {})
|
| 1525 |
mla_set = {int(x) - 1 for x in rda_cfg.get("mla_layers", [])}
|
|
@@ -1548,6 +1579,12 @@ def recover_from_shard(
|
|
| 1548 |
}
|
| 1549 |
|
| 1550 |
present = set(f.keys())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1551 |
present_dtype: dict[str, str] = {}
|
| 1552 |
expert_anchors: dict[tuple[str, str, str, int], list[int]] = {}
|
| 1553 |
kind_suffix_anchors: dict[tuple[str, str, str], list[int]] = {}
|
|
|
|
| 1431 |
"architectures": arch.get("architectures", []),
|
| 1432 |
"hidden_size": arch.get("hidden_size", 0),
|
| 1433 |
"num_hidden_layers": arch.get("num_hidden_layers", len(all_layers)),
|
| 1434 |
+
"num_experts": kept_experts if kept_experts is not None else arch.get("num_experts", 0),
|
| 1435 |
+
"orig_num_experts": arch.get("num_experts", 0),
|
| 1436 |
+
"estimated_params_b": round(est_params_b, 2),
|
| 1437 |
"vocab_size": arch.get("vocab_size", 0),
|
| 1438 |
"surviving_layers": surviving_layers,
|
| 1439 |
"missing_layers": missing_layers,
|
|
|
|
| 1449 |
safetensors_path: str | Path,
|
| 1450 |
source_dir: str | Path,
|
| 1451 |
bundle_dir: str | Path,
|
| 1452 |
+
kept_experts: int | None = None,
|
| 1453 |
+
has_engram: bool = False,
|
| 1454 |
+
has_mtp: bool = False,
|
| 1455 |
+
has_vision: bool = False,
|
| 1456 |
) -> Path:
|
| 1457 |
"""Create a complete Hugging Face model directory around ``safetensors_path``."""
|
| 1458 |
st_path = Path(safetensors_path).resolve()
|
|
|
|
| 1467 |
if not target_model.exists():
|
| 1468 |
os.symlink(st_path, target_model)
|
| 1469 |
|
|
|
|
| 1470 |
idx_out = out_dir / "model.safetensors.index.json"
|
| 1471 |
if idx_out.exists() or idx_out.is_symlink():
|
| 1472 |
idx_out.unlink()
|
|
|
|
| 1477 |
if item.name.startswith("."):
|
| 1478 |
continue
|
| 1479 |
dst = out_dir / item.name
|
| 1480 |
+
if item.name == "config.json" and (kept_experts is not None or not has_engram or not has_mtp):
|
| 1481 |
+
try:
|
| 1482 |
+
cfg_obj = json.loads(item.read_text())
|
| 1483 |
+
for sub in (cfg_obj, cfg_obj.get("text_config") if isinstance(cfg_obj.get("text_config"), dict) else None):
|
| 1484 |
+
if not isinstance(sub, dict):
|
| 1485 |
+
continue
|
| 1486 |
+
if kept_experts is not None:
|
| 1487 |
+
for ek in ("num_experts", "n_routed_experts", "num_local_experts", "dspark_n_routed_experts"):
|
| 1488 |
+
if ek in sub:
|
| 1489 |
+
sub[ek] = int(kept_experts)
|
| 1490 |
+
if not has_engram:
|
| 1491 |
+
if "engram_layer_ids" in sub:
|
| 1492 |
+
sub["engram_layer_ids"] = []
|
| 1493 |
+
if "engram_num_embeddings" in sub:
|
| 1494 |
+
sub["engram_num_embeddings"] = []
|
| 1495 |
+
if not has_mtp and "num_nextn_predict_layers" in sub:
|
| 1496 |
+
sub["num_nextn_predict_layers"] = 0
|
| 1497 |
+
if dst.is_symlink() or dst.exists():
|
| 1498 |
+
dst.unlink()
|
| 1499 |
+
dst.write_text(json.dumps(cfg_obj, indent=2))
|
| 1500 |
+
continue
|
| 1501 |
+
except Exception:
|
| 1502 |
+
pass
|
| 1503 |
if dst.exists() or dst.is_symlink():
|
| 1504 |
continue
|
| 1505 |
os.symlink(item.resolve(), dst)
|
|
|
|
| 1519 |
progress_cb=None,
|
| 1520 |
stop_event=None,
|
| 1521 |
export_hf_dir: str | Path | None = None,
|
| 1522 |
+
target_params_b: float | None = None,
|
| 1523 |
+
max_experts: int | None = None,
|
| 1524 |
) -> dict:
|
| 1525 |
"""Regenerate a full multi-shard HF model from **one** ``.safetensors`` shard.
|
| 1526 |
|
|
|
|
| 1539 |
arch = _normalize_arch_config(raw_arch)
|
| 1540 |
|
| 1541 |
if index_path.exists():
|
| 1542 |
+
raw_weight_map: dict[str, str] = json.loads(index_path.read_text())["weight_map"]
|
| 1543 |
else:
|
| 1544 |
+
raw_weight_map = infer_weight_map_from_shard(shard_path, arch)
|
| 1545 |
|
| 1546 |
tok_path = cfg_path.parent / "tokenizer.json"
|
| 1547 |
if not tok_path.exists():
|
|
|
|
| 1550 |
use_cuda = (device in ("auto", "cuda")) and torch.cuda.is_available()
|
| 1551 |
dev = torch.device("cuda:0" if use_cuda else "cpu")
|
| 1552 |
total_layers = int(arch.get("num_hidden_layers", 25))
|
| 1553 |
+
orig_experts = int(arch.get("num_experts") or 0)
|
| 1554 |
|
| 1555 |
rda_cfg = arch.get("rda_config", {})
|
| 1556 |
mla_set = {int(x) - 1 for x in rda_cfg.get("mla_layers", [])}
|
|
|
|
| 1579 |
}
|
| 1580 |
|
| 1581 |
present = set(f.keys())
|
| 1582 |
+
weight_map, kept_experts, est_params_b = _filter_weight_map_for_target(
|
| 1583 |
+
raw_weight_map, present, arch, target_params_b=target_params_b, max_experts=max_experts
|
| 1584 |
+
)
|
| 1585 |
+
has_engram = any(".engram." in k for k in present)
|
| 1586 |
+
has_mtp = any(k.startswith("mtp.") for k in present)
|
| 1587 |
+
has_vision = any(k.startswith(("vision.", "aligner.", "image_")) for k in present)
|
| 1588 |
present_dtype: dict[str, str] = {}
|
| 1589 |
expert_anchors: dict[tuple[str, str, str, int], list[int]] = {}
|
| 1590 |
kind_suffix_anchors: dict[tuple[str, str, str], list[int]] = {}
|