CompressedGemma commited on
Commit
bbc46bd
·
verified ·
1 Parent(s): 1605fee

Upload slimshard_gui.py

Browse files
Files changed (1) hide show
  1. slimshard_gui.py +165 -14
slimshard_gui.py CHANGED
@@ -46,10 +46,14 @@ if __package__ in (None, ""):
46
  from .cuda_backend import cuda_device_name, cuda_is_available
47
  from .slimshard import (
48
  HPCConfig,
 
49
  build_slimshard,
50
  export_hf_bundle,
51
  export_safetensors_to_gguf,
 
52
  inspect_recovery_plan,
 
 
53
  recover_from_shard,
54
  regenerate,
55
  run_deepseek_v41_generate,
@@ -98,6 +102,12 @@ class SlimShardGUI:
98
 
99
  def _init_vars(self) -> None:
100
  self.op_mode_var = tk.StringVar(value="recover")
 
 
 
 
 
 
101
  self.shard_var = tk.StringVar()
102
  self.index_var = tk.StringVar()
103
  self.config_var = tk.StringVar()
@@ -138,6 +148,10 @@ class SlimShardGUI:
138
 
139
  for v in (
140
  self.op_mode_var,
 
 
 
 
141
  self.shard_var,
142
  self.index_var,
143
  self.config_var,
@@ -253,10 +267,16 @@ class SlimShardGUI:
253
  )
254
  ttk.Radiobutton(
255
  mode_bar,
256
- text="CheckFree Single-Shard Recovery (1 Shard -> Full Model)",
257
  variable=self.op_mode_var,
258
  value="recover",
259
  ).pack(side=tk.LEFT, padx=(0, 14))
 
 
 
 
 
 
260
  ttk.Radiobutton(
261
  mode_bar,
262
  text="Build Self-Contained SlimShard (Multi-Shard -> 1 SlimShard)",
@@ -276,44 +296,71 @@ class SlimShardGUI:
276
  value="export-gguf",
277
  ).pack(side=tk.LEFT)
278
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  self._add_path_row(
280
  io_frame,
281
- 1,
282
- "Surviving Shard / Input (.safetensors):",
283
  self.shard_var,
284
  self._pick_shard,
285
  )
286
  self._add_path_row(
287
  io_frame,
288
- 2,
289
  "Index JSON (optional, auto-inferred if omitted):",
290
  self.index_var,
291
  self._pick_index,
292
  )
293
  self._add_path_row(
294
  io_frame,
295
- 3,
296
  "Config JSON (auto-detected from folder):",
297
  self.config_var,
298
  self._pick_config,
299
  )
300
  self._add_path_row(
301
  io_frame,
302
- 4,
303
- "Source Model Dir (for SlimShard Build):",
304
  self.model_dir_var,
305
  self._pick_model_dir,
306
  )
307
  self._add_path_row(
308
  io_frame,
309
- 5,
310
- "Output .safetensors File:",
311
  self.output_var,
312
  self._pick_output,
313
  )
314
  self._add_path_row(
315
  io_frame,
316
- 6,
317
  "Export Ready-to-Run HF Bundle Dir:",
318
  self.export_dir_var,
319
  self._pick_export_dir,
@@ -375,6 +422,27 @@ class SlimShardGUI:
375
  width=5,
376
  ).pack(side=tk.LEFT, padx=(0, 14))
377
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378
  ttk.Label(row_opt, text="SlimMoE Keep Ratio:").pack(
379
  side=tk.LEFT, padx=(0, 6)
380
  )
@@ -638,14 +706,97 @@ class SlimShardGUI:
638
  self.test_model_dir_var.set(self.export_dir_var.get())
639
 
640
  def _pick_shard(self) -> None:
641
- p = filedialog.askopenfilename(
642
- title="Select Surviving .safetensors Shard",
643
  filetypes=[("SafeTensors", "*.safetensors"), ("All files", "*.*")],
644
  )
645
- if p:
646
- self._set_shard_and_companions(Path(p))
 
 
647
  self._inspect_plan()
648
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
649
  def _pick_index(self) -> None:
650
  p = filedialog.askopenfilename(
651
  title="Select model.safetensors.index.json",
 
46
  from .cuda_backend import cuda_device_name, cuda_is_available
47
  from .slimshard import (
48
  HPCConfig,
49
+ _resolve_shard_paths,
50
  build_slimshard,
51
  export_hf_bundle,
52
  export_safetensors_to_gguf,
53
+ fetch_minimum_shards_from_hf,
54
  inspect_recovery_plan,
55
+ parse_hf_repo_url,
56
+ plan_minimum_shards_from_hf,
57
  recover_from_shard,
58
  regenerate,
59
  run_deepseek_v41_generate,
 
102
 
103
  def _init_vars(self) -> None:
104
  self.op_mode_var = tk.StringVar(value="recover")
105
+ self.hf_url_var = tk.StringVar(
106
+ value="https://huggingface.co/deepseek-ai/DeepSeek-V4.1-Flash-1017/tree/main"
107
+ )
108
+ self.hf_fetch_mode_var = tk.StringVar(value="surgical")
109
+ self.num_anchor_layers_var = tk.IntVar(value=3)
110
+ self.anchor_layers_var = tk.StringVar(value="")
111
  self.shard_var = tk.StringVar()
112
  self.index_var = tk.StringVar()
113
  self.config_var = tk.StringVar()
 
148
 
149
  for v in (
150
  self.op_mode_var,
151
+ self.hf_url_var,
152
+ self.hf_fetch_mode_var,
153
+ self.num_anchor_layers_var,
154
+ self.anchor_layers_var,
155
  self.shard_var,
156
  self.index_var,
157
  self.config_var,
 
267
  )
268
  ttk.Radiobutton(
269
  mode_bar,
270
+ text="CheckFree Multi/Single-Shard Recovery (Shards -> Full Model)",
271
  variable=self.op_mode_var,
272
  value="recover",
273
  ).pack(side=tk.LEFT, padx=(0, 14))
274
+ ttk.Radiobutton(
275
+ mode_bar,
276
+ text="Retrieve Minimum Shards from HF Link",
277
+ variable=self.op_mode_var,
278
+ value="fetch-hf",
279
+ ).pack(side=tk.LEFT, padx=(0, 14))
280
  ttk.Radiobutton(
281
  mode_bar,
282
  text="Build Self-Contained SlimShard (Multi-Shard -> 1 SlimShard)",
 
296
  value="export-gguf",
297
  ).pack(side=tk.LEFT)
298
 
299
+ # Hugging Face Link Minimum-Shard Retriever Bar
300
+ hf_bar = ttk.Frame(io_frame)
301
+ hf_bar.grid(row=1, column=0, columnspan=3, sticky=tk.EW, pady=(0, 6))
302
+ hf_bar.columnconfigure(1, weight=1)
303
+ ttk.Label(
304
+ hf_bar, text="Hugging Face Link / Repo:", font=("Sans", 9, "bold")
305
+ ).grid(row=0, column=0, sticky=tk.W, padx=(0, 6))
306
+ ttk.Entry(hf_bar, textvariable=self.hf_url_var).grid(
307
+ row=0, column=1, sticky=tk.EW, padx=(0, 8)
308
+ )
309
+ ttk.Combobox(
310
+ hf_bar,
311
+ textvariable=self.hf_fetch_mode_var,
312
+ values=("surgical", "full_shards"),
313
+ width=12,
314
+ state="readonly",
315
+ ).grid(row=0, column=2, padx=(0, 6))
316
+ ttk.Button(
317
+ hf_bar, text="Analyze Min Shards", command=self._analyze_hf_min_shards
318
+ ).grid(row=0, column=3, padx=(0, 6))
319
+ ttk.Button(
320
+ hf_bar,
321
+ text="Retrieve Min Shards",
322
+ style="Accent.TButton",
323
+ command=self._retrieve_hf_min_shards,
324
+ ).grid(row=0, column=4)
325
+
326
  self._add_path_row(
327
  io_frame,
328
+ 2,
329
+ "Surviving Shard(s) / Input (.safetensors, comma-sep):",
330
  self.shard_var,
331
  self._pick_shard,
332
  )
333
  self._add_path_row(
334
  io_frame,
335
+ 3,
336
  "Index JSON (optional, auto-inferred if omitted):",
337
  self.index_var,
338
  self._pick_index,
339
  )
340
  self._add_path_row(
341
  io_frame,
342
+ 4,
343
  "Config JSON (auto-detected from folder):",
344
  self.config_var,
345
  self._pick_config,
346
  )
347
  self._add_path_row(
348
  io_frame,
349
+ 5,
350
+ "Source / Download Model Dir:",
351
  self.model_dir_var,
352
  self._pick_model_dir,
353
  )
354
  self._add_path_row(
355
  io_frame,
356
+ 6,
357
+ "Output .safetensors / .gguf File:",
358
  self.output_var,
359
  self._pick_output,
360
  )
361
  self._add_path_row(
362
  io_frame,
363
+ 7,
364
  "Export Ready-to-Run HF Bundle Dir:",
365
  self.export_dir_var,
366
  self._pick_export_dir,
 
422
  width=5,
423
  ).pack(side=tk.LEFT, padx=(0, 14))
424
 
425
+ ttk.Label(row_opt, text="# Anchor Layers:").pack(
426
+ side=tk.LEFT, padx=(0, 4)
427
+ )
428
+ ttk.Spinbox(
429
+ row_opt,
430
+ from_=1,
431
+ to=128,
432
+ increment=1,
433
+ textvariable=self.num_anchor_layers_var,
434
+ width=4,
435
+ ).pack(side=tk.LEFT, padx=(0, 10))
436
+
437
+ ttk.Label(row_opt, text="Anchor Layers (e.g. 0,14,39):").pack(
438
+ side=tk.LEFT, padx=(0, 4)
439
+ )
440
+ ttk.Entry(
441
+ row_opt,
442
+ textvariable=self.anchor_layers_var,
443
+ width=12,
444
+ ).pack(side=tk.LEFT, padx=(0, 12))
445
+
446
  ttk.Label(row_opt, text="SlimMoE Keep Ratio:").pack(
447
  side=tk.LEFT, padx=(0, 6)
448
  )
 
706
  self.test_model_dir_var.set(self.export_dir_var.get())
707
 
708
  def _pick_shard(self) -> None:
709
+ ps = filedialog.askopenfilenames(
710
+ title="Select Surviving .safetensors Shard(s) (Multi-Select Supported)",
711
  filetypes=[("SafeTensors", "*.safetensors"), ("All files", "*.*")],
712
  )
713
+ if ps:
714
+ paths = [Path(p) for p in ps]
715
+ self._set_shard_and_companions(paths[0])
716
+ self.shard_var.set(", ".join(str(p) for p in paths))
717
  self._inspect_plan()
718
 
719
+ def _analyze_hf_min_shards(self) -> None:
720
+ url = self.hf_url_var.get().strip()
721
+ if not url:
722
+ messagebox.showwarning("SlimShard", "Please enter a Hugging Face link or repo ID first.")
723
+ return
724
+ try:
725
+ tp = float(self.target_params_b_var.get())
726
+ except Exception:
727
+ tp = 0.0
728
+ try:
729
+ me = int(self.max_experts_var.get())
730
+ except Exception:
731
+ me = 0
732
+ try:
733
+ n_anc = int(self.num_anchor_layers_var.get())
734
+ except Exception:
735
+ n_anc = 3
736
+ anc_str = self.anchor_layers_var.get().strip() or None
737
+
738
+ self._log(f"Analyzing minimum shards on Hugging Face for {url}...")
739
+ try:
740
+ plan = plan_minimum_shards_from_hf(
741
+ url,
742
+ target_params_b=tp if tp > 0.0 else None,
743
+ max_experts=me if me > 0 else None,
744
+ num_anchor_layers=n_anc,
745
+ anchor_layers=anc_str,
746
+ )
747
+ except Exception as exc:
748
+ self._log(f"HF Analyze Failed: {exc}")
749
+ messagebox.showerror("HF Minimum Shards Analysis Failed", str(exc))
750
+ return
751
+
752
+ repo_name = plan["repo_id"].split("/")[-1]
753
+ if not self.model_dir_var.get().strip():
754
+ self.model_dir_var.set(str(Path.cwd() / repo_name))
755
+ if not self.output_var.get().strip():
756
+ self.output_var.set(str(Path.cwd() / repo_name / "model.safetensors"))
757
+ if not self.export_dir_var.get().strip():
758
+ self.export_dir_var.set(str(Path.cwd() / f"recovered_{repo_name.lower().replace('-', '_')}"))
759
+
760
+ min_sh = plan["minimum_shards"]
761
+ tot_sh = plan["total_repo_shards"]
762
+ anchors = plan["anchor_layers"]
763
+ archs = ",".join(plan["architectures"]) or plan["model_type"]
764
+ self.arch_summary_var.set(
765
+ f"{plan['repo_id']} ({archs} | ~{plan['estimated_params_b']}B target | "
766
+ f"layers={plan['num_hidden_layers']}, experts={plan['kept_experts']}/{plan['orig_num_experts']})"
767
+ )
768
+ self.layers_summary_var.set(
769
+ f"Minimum Shards Needed: {len(min_sh)} / {tot_sh} ({', '.join(min_sh)}) | "
770
+ f"Anchor Layers ({len(anchors)}): {anchors}"
771
+ )
772
+ self.tele_breakdown_var.set(
773
+ f"min_shards={len(min_sh)}/{tot_sh} | surgical_tensors={plan['surgical_tensor_count']} | "
774
+ f"full_repo={plan['total_repo_size_gb']} GB"
775
+ )
776
+ roles_lines = [
777
+ f" - {sh}: {', '.join(plan['shard_roles'].get(sh, []))}" for sh in min_sh
778
+ ]
779
+ msg = (
780
+ f"HF Repo: {plan['repo_id']}@{plan['revision']}\n"
781
+ f"Minimum Shards Required: {len(min_sh)} of {tot_sh} shards\n"
782
+ f"Selected Anchor Layers: {anchors}\n"
783
+ f"Surgical Tensor Count: {plan['surgical_tensor_count']} tensors\n"
784
+ + "\n".join(roles_lines)
785
+ )
786
+ self._log(msg)
787
+
788
+ def _retrieve_hf_min_shards(self) -> None:
789
+ self.op_mode_var.set("fetch-hf")
790
+ if not self.model_dir_var.get().strip():
791
+ try:
792
+ repo_id, _ = parse_hf_repo_url(self.hf_url_var.get().strip())
793
+ self.model_dir_var.set(str(Path.cwd() / repo_id.split("/")[-1]))
794
+ except Exception:
795
+ self.model_dir_var.set(str(Path.cwd() / "hf_min_shards"))
796
+ if not self.output_var.get().strip():
797
+ self.output_var.set(str(Path(self.model_dir_var.get().strip()) / "model.safetensors"))
798
+ self._start_run()
799
+
800
  def _pick_index(self) -> None:
801
  p = filedialog.askopenfilename(
802
  title="Select model.safetensors.index.json",