Upload 2 files
Browse files- slimshard.py +38 -20
- slimshard_gui.py +39 -1
slimshard.py
CHANGED
|
@@ -1895,12 +1895,14 @@ def plan_minimum_shards_from_hf(
|
|
| 1895 |
total_layers = int(arch.get("num_hidden_layers") or 0)
|
| 1896 |
layer_to_shards: dict[int, set[str]] = {}
|
| 1897 |
shard_to_layers: dict[str, set[int]] = {}
|
|
|
|
| 1898 |
for k, sh in filtered_wm.items():
|
| 1899 |
lm = LAYER_RE.match(k)
|
| 1900 |
if lm:
|
| 1901 |
lidx = int(lm.group(2))
|
| 1902 |
layer_to_shards.setdefault(lidx, set()).add(sh)
|
| 1903 |
shard_to_layers.setdefault(sh, set()).add(lidx)
|
|
|
|
| 1904 |
if total_layers <= 0 and layer_to_shards:
|
| 1905 |
total_layers = max(layer_to_shards) + 1
|
| 1906 |
|
|
@@ -1930,38 +1932,29 @@ def plan_minimum_shards_from_hf(
|
|
| 1930 |
target_anchors = sorted(l for l in explicit_anchors if l in layer_to_shards)
|
| 1931 |
else:
|
| 1932 |
n_anc = max(1, int(num_anchor_layers))
|
| 1933 |
-
already_layers = sorted(
|
| 1934 |
-
{
|
| 1935 |
-
l
|
| 1936 |
-
for sh in selected_shards
|
| 1937 |
-
for l in shard_to_layers.get(sh, set())
|
| 1938 |
-
if l >= first_dense
|
| 1939 |
-
}
|
| 1940 |
-
)
|
| 1941 |
target_anchors = []
|
| 1942 |
if first_dense > 0 and 0 in layer_to_shards:
|
| 1943 |
target_anchors.append(0)
|
| 1944 |
moe_start = min(first_dense, max(total_layers - 1, 0))
|
| 1945 |
if total_layers > 0:
|
| 1946 |
-
grid = np.linspace(moe_start, max(total_layers - 1, moe_start),
|
| 1947 |
for g_l in grid:
|
| 1948 |
-
# Prefer a nearby layer that lives in
|
| 1949 |
best_l = int(g_l)
|
| 1950 |
-
best_cost = (999, 999)
|
| 1951 |
-
for cand_l in range(max(moe_start, int(g_l) -
|
| 1952 |
if cand_l not in layer_to_shards:
|
| 1953 |
continue
|
| 1954 |
shs = layer_to_shards[cand_l]
|
| 1955 |
new_shs = len([s for s in shs if s not in selected_shards])
|
| 1956 |
-
cost = (new_shs, abs(cand_l - int(g_l)))
|
| 1957 |
if cost < best_cost:
|
| 1958 |
best_cost = cost
|
| 1959 |
best_l = cand_l
|
| 1960 |
if best_l not in target_anchors:
|
| 1961 |
target_anchors.append(best_l)
|
| 1962 |
-
|
| 1963 |
-
|
| 1964 |
-
target_anchors.append(al)
|
| 1965 |
target_anchors.sort()
|
| 1966 |
|
| 1967 |
for lidx in target_anchors:
|
|
@@ -1969,6 +1962,7 @@ def plan_minimum_shards_from_hf(
|
|
| 1969 |
_add_shard(sh, f"Anchor Layer {lidx}")
|
| 1970 |
|
| 1971 |
# 3. Ensure every non-layer and layer template suffix in filtered_wm has at least one anchor in selected_shards
|
|
|
|
| 1972 |
covered_keys = {k for k, sh in filtered_wm.items() if sh in selected_shards}
|
| 1973 |
covered_suffixes = {LAYER_RE.match(k).group(3) for k in covered_keys if LAYER_RE.match(k)}
|
| 1974 |
covered_exp_projs = {
|
|
@@ -1983,6 +1977,7 @@ def plan_minimum_shards_from_hf(
|
|
| 1983 |
if sig not in covered_exp_projs:
|
| 1984 |
_add_shard(sh, f"Expert template e={em.group(4)}")
|
| 1985 |
covered_exp_projs.add(sig)
|
|
|
|
| 1986 |
continue
|
| 1987 |
lm = LAYER_RE.match(k)
|
| 1988 |
if lm:
|
|
@@ -1990,6 +1985,7 @@ def plan_minimum_shards_from_hf(
|
|
| 1990 |
if suf not in covered_suffixes:
|
| 1991 |
_add_shard(sh, f"Layer template ({suf})")
|
| 1992 |
covered_suffixes.add(suf)
|
|
|
|
| 1993 |
|
| 1994 |
# Compute exact surgical tensors needed from selected_shards
|
| 1995 |
anchor_set = set(target_anchors)
|
|
@@ -1999,7 +1995,7 @@ def plan_minimum_shards_from_hf(
|
|
| 1999 |
continue
|
| 2000 |
lm = LAYER_RE.match(k)
|
| 2001 |
if lm:
|
| 2002 |
-
if int(lm.group(2)) in anchor_set:
|
| 2003 |
surgical_tensors[k] = sh
|
| 2004 |
else:
|
| 2005 |
surgical_tensors[k] = sh
|
|
@@ -2566,7 +2562,7 @@ def recover_from_shard(
|
|
| 2566 |
|
| 2567 |
writer = SafetensorsWriter(
|
| 2568 |
output,
|
| 2569 |
-
metadata={"format": "pt", "hpc_checkfree_source":
|
| 2570 |
)
|
| 2571 |
stats = {
|
| 2572 |
"present": 0,
|
|
@@ -3868,16 +3864,26 @@ def main() -> None:
|
|
| 3868 |
i = sub.add_parser("info", help="print SlimShard metadata")
|
| 3869 |
i.add_argument("--input", required=True)
|
| 3870 |
|
| 3871 |
-
rec = sub.add_parser("recover", help="CheckFree single-shard model recovery")
|
| 3872 |
-
rec.add_argument("--shard", required=True, help="
|
| 3873 |
rec.add_argument("--index", default=None, help="model.safetensors.index.json (auto-detected or inferred if omitted)")
|
| 3874 |
rec.add_argument("--output", required=True, help="full model .safetensors")
|
| 3875 |
rec.add_argument("--config", default=None, help="config.json (defaults to index/shard dir)")
|
| 3876 |
rec.add_argument("--export-hf-dir", default=None, help="optional ready-to-load HF model directory")
|
| 3877 |
rec.add_argument("--target-params-b", type=float, default=None, help="optional target parameter budget in billions (e.g. 30.0)")
|
| 3878 |
rec.add_argument("--max-experts", type=int, default=None, help="optional max routed experts per layer to keep")
|
|
|
|
| 3879 |
rec.add_argument("--device", default="auto", choices=("auto", "cuda", "cpu"))
|
| 3880 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3881 |
eg = sub.add_parser("export-gguf", help="convert a SafeTensors model (FP4/FP8/BF16) to GGUF")
|
| 3882 |
eg.add_argument("--input", required=True, help="input .safetensors file")
|
| 3883 |
eg.add_argument("--output", required=True, help="output .gguf file")
|
|
@@ -3913,6 +3919,18 @@ def main() -> None:
|
|
| 3913 |
export_hf_dir=args.export_hf_dir,
|
| 3914 |
target_params_b=args.target_params_b,
|
| 3915 |
max_experts=args.max_experts,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3916 |
)
|
| 3917 |
elif args.cmd == "export-gguf":
|
| 3918 |
export_safetensors_to_gguf(
|
|
|
|
| 1895 |
total_layers = int(arch.get("num_hidden_layers") or 0)
|
| 1896 |
layer_to_shards: dict[int, set[str]] = {}
|
| 1897 |
shard_to_layers: dict[str, set[int]] = {}
|
| 1898 |
+
layer_suffix_count: dict[int, int] = {}
|
| 1899 |
for k, sh in filtered_wm.items():
|
| 1900 |
lm = LAYER_RE.match(k)
|
| 1901 |
if lm:
|
| 1902 |
lidx = int(lm.group(2))
|
| 1903 |
layer_to_shards.setdefault(lidx, set()).add(sh)
|
| 1904 |
shard_to_layers.setdefault(sh, set()).add(lidx)
|
| 1905 |
+
layer_suffix_count[lidx] = layer_suffix_count.get(lidx, 0) + 1
|
| 1906 |
if total_layers <= 0 and layer_to_shards:
|
| 1907 |
total_layers = max(layer_to_shards) + 1
|
| 1908 |
|
|
|
|
| 1932 |
target_anchors = sorted(l for l in explicit_anchors if l in layer_to_shards)
|
| 1933 |
else:
|
| 1934 |
n_anc = max(1, int(num_anchor_layers))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1935 |
target_anchors = []
|
| 1936 |
if first_dense > 0 and 0 in layer_to_shards:
|
| 1937 |
target_anchors.append(0)
|
| 1938 |
moe_start = min(first_dense, max(total_layers - 1, 0))
|
| 1939 |
if total_layers > 0:
|
| 1940 |
+
grid = np.linspace(moe_start, max(total_layers - 1, moe_start), n_anc, dtype=int).tolist()
|
| 1941 |
for g_l in grid:
|
| 1942 |
+
# Prefer a nearby layer that lives in fewest new shards and has maximal suffixes (e.g. compressor+indexer)
|
| 1943 |
best_l = int(g_l)
|
| 1944 |
+
best_cost = (999, 999, 999)
|
| 1945 |
+
for cand_l in range(max(moe_start, int(g_l) - 5), min(total_layers, int(g_l) + 6)):
|
| 1946 |
if cand_l not in layer_to_shards:
|
| 1947 |
continue
|
| 1948 |
shs = layer_to_shards[cand_l]
|
| 1949 |
new_shs = len([s for s in shs if s not in selected_shards])
|
| 1950 |
+
cost = (new_shs, -layer_suffix_count.get(cand_l, 0), abs(cand_l - int(g_l)))
|
| 1951 |
if cost < best_cost:
|
| 1952 |
best_cost = cost
|
| 1953 |
best_l = cand_l
|
| 1954 |
if best_l not in target_anchors:
|
| 1955 |
target_anchors.append(best_l)
|
| 1956 |
+
for sh in sorted(layer_to_shards.get(best_l, set())):
|
| 1957 |
+
_add_shard(sh, f"Anchor Layer {best_l}")
|
|
|
|
| 1958 |
target_anchors.sort()
|
| 1959 |
|
| 1960 |
for lidx in target_anchors:
|
|
|
|
| 1962 |
_add_shard(sh, f"Anchor Layer {lidx}")
|
| 1963 |
|
| 1964 |
# 3. Ensure every non-layer and layer template suffix in filtered_wm has at least one anchor in selected_shards
|
| 1965 |
+
extra_template_keys: set[str] = set()
|
| 1966 |
covered_keys = {k for k, sh in filtered_wm.items() if sh in selected_shards}
|
| 1967 |
covered_suffixes = {LAYER_RE.match(k).group(3) for k in covered_keys if LAYER_RE.match(k)}
|
| 1968 |
covered_exp_projs = {
|
|
|
|
| 1977 |
if sig not in covered_exp_projs:
|
| 1978 |
_add_shard(sh, f"Expert template e={em.group(4)}")
|
| 1979 |
covered_exp_projs.add(sig)
|
| 1980 |
+
extra_template_keys.add(k)
|
| 1981 |
continue
|
| 1982 |
lm = LAYER_RE.match(k)
|
| 1983 |
if lm:
|
|
|
|
| 1985 |
if suf not in covered_suffixes:
|
| 1986 |
_add_shard(sh, f"Layer template ({suf})")
|
| 1987 |
covered_suffixes.add(suf)
|
| 1988 |
+
extra_template_keys.add(k)
|
| 1989 |
|
| 1990 |
# Compute exact surgical tensors needed from selected_shards
|
| 1991 |
anchor_set = set(target_anchors)
|
|
|
|
| 1995 |
continue
|
| 1996 |
lm = LAYER_RE.match(k)
|
| 1997 |
if lm:
|
| 1998 |
+
if int(lm.group(2)) in anchor_set or k in extra_template_keys:
|
| 1999 |
surgical_tensors[k] = sh
|
| 2000 |
else:
|
| 2001 |
surgical_tensors[k] = sh
|
|
|
|
| 2562 |
|
| 2563 |
writer = SafetensorsWriter(
|
| 2564 |
output,
|
| 2565 |
+
metadata={"format": "pt", "hpc_checkfree_source": ",".join(p.name for p in shard_paths)},
|
| 2566 |
)
|
| 2567 |
stats = {
|
| 2568 |
"present": 0,
|
|
|
|
| 3864 |
i = sub.add_parser("info", help="print SlimShard metadata")
|
| 3865 |
i.add_argument("--input", required=True)
|
| 3866 |
|
| 3867 |
+
rec = sub.add_parser("recover", help="CheckFree single/multi-shard model recovery")
|
| 3868 |
+
rec.add_argument("--shard", required=True, help="surviving HF .safetensors shard(s) (comma-separated or directory)")
|
| 3869 |
rec.add_argument("--index", default=None, help="model.safetensors.index.json (auto-detected or inferred if omitted)")
|
| 3870 |
rec.add_argument("--output", required=True, help="full model .safetensors")
|
| 3871 |
rec.add_argument("--config", default=None, help="config.json (defaults to index/shard dir)")
|
| 3872 |
rec.add_argument("--export-hf-dir", default=None, help="optional ready-to-load HF model directory")
|
| 3873 |
rec.add_argument("--target-params-b", type=float, default=None, help="optional target parameter budget in billions (e.g. 30.0)")
|
| 3874 |
rec.add_argument("--max-experts", type=int, default=None, help="optional max routed experts per layer to keep")
|
| 3875 |
+
rec.add_argument("--anchor-layers", default=None, help="optional comma-separated anchor layer indices (e.g. 0,4,20,39)")
|
| 3876 |
rec.add_argument("--device", default="auto", choices=("auto", "cuda", "cpu"))
|
| 3877 |
|
| 3878 |
+
fhf = sub.add_parser("fetch-hf", help="retrieve minimum shards needed for full reconstruction from a Hugging Face link")
|
| 3879 |
+
fhf.add_argument("--repo", required=True, help="Hugging Face repo URL or org/repo (e.g. https://huggingface.co/deepseek-ai/DeepSeek-V4-Pro/tree/main)")
|
| 3880 |
+
fhf.add_argument("--output-dir", required=True, help="directory to store retrieved minimum shards and config/tokenizer")
|
| 3881 |
+
fhf.add_argument("--target-params-b", type=float, default=None, help="optional target parameter budget in billions")
|
| 3882 |
+
fhf.add_argument("--max-experts", type=int, default=None, help="optional max routed experts per layer")
|
| 3883 |
+
fhf.add_argument("--num-anchor-layers", type=int, default=3, help="number of depth anchor layers to retrieve")
|
| 3884 |
+
fhf.add_argument("--anchor-layers", default=None, help="explicit comma-separated anchor layers (e.g. 0,14,39)")
|
| 3885 |
+
fhf.add_argument("--mode", choices=("surgical", "full_shards"), default="surgical")
|
| 3886 |
+
|
| 3887 |
eg = sub.add_parser("export-gguf", help="convert a SafeTensors model (FP4/FP8/BF16) to GGUF")
|
| 3888 |
eg.add_argument("--input", required=True, help="input .safetensors file")
|
| 3889 |
eg.add_argument("--output", required=True, help="output .gguf file")
|
|
|
|
| 3919 |
export_hf_dir=args.export_hf_dir,
|
| 3920 |
target_params_b=args.target_params_b,
|
| 3921 |
max_experts=args.max_experts,
|
| 3922 |
+
anchor_layers=args.anchor_layers,
|
| 3923 |
+
)
|
| 3924 |
+
elif args.cmd == "fetch-hf":
|
| 3925 |
+
fetch_minimum_shards_from_hf(
|
| 3926 |
+
args.repo,
|
| 3927 |
+
args.output_dir,
|
| 3928 |
+
target_params_b=args.target_params_b,
|
| 3929 |
+
max_experts=args.max_experts,
|
| 3930 |
+
num_anchor_layers=args.num_anchor_layers,
|
| 3931 |
+
anchor_layers=args.anchor_layers,
|
| 3932 |
+
mode=args.mode,
|
| 3933 |
+
verbose=True,
|
| 3934 |
)
|
| 3935 |
elif args.cmd == "export-gguf":
|
| 3936 |
export_safetensors_to_gguf(
|
slimshard_gui.py
CHANGED
|
@@ -1010,7 +1010,7 @@ class SlimShardGUI:
|
|
| 1010 |
return
|
| 1011 |
mode = self.op_mode_var.get()
|
| 1012 |
out = self.output_var.get().strip()
|
| 1013 |
-
if not out:
|
| 1014 |
messagebox.showwarning("SlimShard", "Please specify an output .safetensors path.")
|
| 1015 |
return
|
| 1016 |
|
|
@@ -1054,10 +1054,40 @@ class SlimShardGUI:
|
|
| 1054 |
export_hf_dir=exp_dir,
|
| 1055 |
target_params_b=tp if tp > 0.0 else None,
|
| 1056 |
max_experts=me if me > 0 else None,
|
|
|
|
| 1057 |
)
|
| 1058 |
if exp_dir:
|
| 1059 |
self._queue.put(("set_test_dir", exp_dir))
|
| 1060 |
self._queue.put(("done", ("CheckFree Recovery Complete", res)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1061 |
elif mode == "build":
|
| 1062 |
mdir = self.model_dir_var.get().strip()
|
| 1063 |
cfg_obj = HPCConfig(device=self.device_var.get(), verbose=False).validate()
|
|
@@ -1346,6 +1376,14 @@ class SlimShardGUI:
|
|
| 1346 |
self.tree.item(tname, values=vals)
|
| 1347 |
elif kind == "set_test_dir":
|
| 1348 |
self.test_model_dir_var.set(str(payload))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1349 |
elif kind == "done":
|
| 1350 |
title, stats = payload
|
| 1351 |
elapsed = time.time() - (self._start_time or time.time())
|
|
|
|
| 1010 |
return
|
| 1011 |
mode = self.op_mode_var.get()
|
| 1012 |
out = self.output_var.get().strip()
|
| 1013 |
+
if mode != "fetch-hf" and not out:
|
| 1014 |
messagebox.showwarning("SlimShard", "Please specify an output .safetensors path.")
|
| 1015 |
return
|
| 1016 |
|
|
|
|
| 1054 |
export_hf_dir=exp_dir,
|
| 1055 |
target_params_b=tp if tp > 0.0 else None,
|
| 1056 |
max_experts=me if me > 0 else None,
|
| 1057 |
+
anchor_layers=self.anchor_layers_var.get().strip() or None,
|
| 1058 |
)
|
| 1059 |
if exp_dir:
|
| 1060 |
self._queue.put(("set_test_dir", exp_dir))
|
| 1061 |
self._queue.put(("done", ("CheckFree Recovery Complete", res)))
|
| 1062 |
+
elif mode == "fetch-hf":
|
| 1063 |
+
url = self.hf_url_var.get().strip()
|
| 1064 |
+
mdir = self.model_dir_var.get().strip() or str(Path.cwd() / "hf_min_shards")
|
| 1065 |
+
try:
|
| 1066 |
+
tp = float(self.target_params_b_var.get())
|
| 1067 |
+
except Exception:
|
| 1068 |
+
tp = 0.0
|
| 1069 |
+
try:
|
| 1070 |
+
me = int(self.max_experts_var.get())
|
| 1071 |
+
except Exception:
|
| 1072 |
+
me = 0
|
| 1073 |
+
try:
|
| 1074 |
+
na = int(self.num_anchor_layers_var.get())
|
| 1075 |
+
except Exception:
|
| 1076 |
+
na = 3
|
| 1077 |
+
res = fetch_minimum_shards_from_hf(
|
| 1078 |
+
url,
|
| 1079 |
+
mdir,
|
| 1080 |
+
target_params_b=tp if tp > 0.0 else None,
|
| 1081 |
+
max_experts=me if me > 0 else None,
|
| 1082 |
+
num_anchor_layers=na,
|
| 1083 |
+
anchor_layers=self.anchor_layers_var.get().strip() or None,
|
| 1084 |
+
mode=self.hf_fetch_mode_var.get(),
|
| 1085 |
+
verbose=False,
|
| 1086 |
+
progress_cb=progress_cb,
|
| 1087 |
+
stop_event=self._stop_event,
|
| 1088 |
+
)
|
| 1089 |
+
self._queue.put(("hf_fetched", (mdir, res)))
|
| 1090 |
+
self._queue.put(("done", ("HF Minimum Shards Retrieved", res)))
|
| 1091 |
elif mode == "build":
|
| 1092 |
mdir = self.model_dir_var.get().strip()
|
| 1093 |
cfg_obj = HPCConfig(device=self.device_var.get(), verbose=False).validate()
|
|
|
|
| 1376 |
self.tree.item(tname, values=vals)
|
| 1377 |
elif kind == "set_test_dir":
|
| 1378 |
self.test_model_dir_var.set(str(payload))
|
| 1379 |
+
elif kind == "hf_fetched":
|
| 1380 |
+
mdir, res = payload
|
| 1381 |
+
sh_paths = res.get("shard_paths", [])
|
| 1382 |
+
if sh_paths:
|
| 1383 |
+
self._set_shard_and_companions(Path(sh_paths[0]))
|
| 1384 |
+
self.shard_var.set(", ".join(str(p) for p in sh_paths))
|
| 1385 |
+
self.op_mode_var.set("recover")
|
| 1386 |
+
self._inspect_plan()
|
| 1387 |
elif kind == "done":
|
| 1388 |
title, stats = payload
|
| 1389 |
elapsed = time.time() - (self._start_time or time.time())
|