Upload 6 files
Browse files
gui.py
CHANGED
|
@@ -327,10 +327,12 @@ class HPCQuantizeGUI:
|
|
| 327 |
mode_row.pack(fill=tk.X, pady=(0, 4))
|
| 328 |
ttk.Label(mode_row, text="Target Scope:").pack(side=tk.LEFT, padx=(0, 8))
|
| 329 |
ttk.Radiobutton(
|
| 330 |
-
mode_row, text="All Eligible Tensors", variable=self.mode_var, value="all"
|
|
|
|
| 331 |
).pack(side=tk.LEFT, padx=4)
|
| 332 |
ttk.Radiobutton(
|
| 333 |
-
mode_row, text="Selected Tensor(s)", variable=self.mode_var, value="selected"
|
|
|
|
| 334 |
).pack(side=tk.LEFT, padx=4)
|
| 335 |
|
| 336 |
fmt_row = ttk.Frame(opt_frame)
|
|
@@ -511,7 +513,7 @@ class HPCQuantizeGUI:
|
|
| 511 |
self.tree.column("q2k", width=48, anchor=tk.CENTER)
|
| 512 |
self.tree.column("imat", width=56, anchor=tk.CENTER)
|
| 513 |
self.tree.column("state", width=165, anchor=tk.W)
|
| 514 |
-
self.tree.bind("<<TreeviewSelect>>",
|
| 515 |
|
| 516 |
tree_scroll = ttk.Scrollbar(browser_frame, orient=tk.VERTICAL, command=self.tree.yview)
|
| 517 |
self.tree.configure(yscrollcommand=tree_scroll.set)
|
|
@@ -878,7 +880,93 @@ class HPCQuantizeGUI:
|
|
| 878 |
self._reader = None
|
| 879 |
self._log(f"GGUF inspect error: {exc}")
|
| 880 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 881 |
def _populate_tensor_tree(self) -> None:
|
|
|
|
|
|
|
| 882 |
self.tree.delete(*self.tree.get_children())
|
| 883 |
if self._reader is None:
|
| 884 |
return
|
|
@@ -888,16 +976,7 @@ class HPCQuantizeGUI:
|
|
| 888 |
n_q1 = 0
|
| 889 |
planned_bytes = 0
|
| 890 |
for ti in self._reader.tensors:
|
| 891 |
-
tgt =
|
| 892 |
-
ti.name,
|
| 893 |
-
ti.dims,
|
| 894 |
-
enable_q4_fallback=bool(self.q4_fallback_var.get()) and self.quant_format_var.get() not in ("q2_k", "q3_k"),
|
| 895 |
-
quantize_embd_q4=bool(self.embd_q4_var.get()),
|
| 896 |
-
promote_attn_q4=bool(self.promote_attn_q4_var.get()),
|
| 897 |
-
quant_format=self.quant_format_var.get(),
|
| 898 |
-
source_type=ti.type,
|
| 899 |
-
custom_quant_map=self._custom_map_for_plan(),
|
| 900 |
-
)
|
| 901 |
if tgt == "Q2_K":
|
| 902 |
n_q2 += 1
|
| 903 |
elif tgt == "Q3_K":
|
|
@@ -934,11 +1013,14 @@ class HPCQuantizeGUI:
|
|
| 934 |
self._imatrix is not None
|
| 935 |
and lookup_imatrix(self._imatrix, ti.name) is not None
|
| 936 |
)
|
| 937 |
-
|
| 938 |
-
|
| 939 |
-
|
| 940 |
-
|
| 941 |
-
|
|
|
|
|
|
|
|
|
|
| 942 |
self.tree.insert(
|
| 943 |
"",
|
| 944 |
tk.END,
|
|
@@ -954,14 +1036,18 @@ class HPCQuantizeGUI:
|
|
| 954 |
state_str,
|
| 955 |
),
|
| 956 |
)
|
|
|
|
|
|
|
|
|
|
| 957 |
if planned_bytes >= 1024 ** 3:
|
| 958 |
planned_text = f"{planned_bytes / (1024 ** 3):.2f} GiB"
|
| 959 |
elif planned_bytes >= 1024 ** 2:
|
| 960 |
planned_text = f"{planned_bytes / (1024 ** 2):.1f} MiB"
|
| 961 |
else:
|
| 962 |
planned_text = f"{planned_bytes / 1024:.1f} KiB"
|
|
|
|
| 963 |
self.status_var.set(
|
| 964 |
-
f"Plan ({self.quant_format_var.get().upper()}): {n_q1} Q1_0 | {n_q2} Q2_K | {n_q3} Q3_K | {n_q4} Q4_0 | {n_copy} Copy "
|
| 965 |
f"(Total: {len(self._reader.tensors)} tensors, est. {planned_text})"
|
| 966 |
)
|
| 967 |
|
|
@@ -1030,9 +1116,10 @@ class HPCQuantizeGUI:
|
|
| 1030 |
self.bench_btn.configure(state=tk.DISABLED)
|
| 1031 |
self.stop_btn.configure(state=tk.NORMAL)
|
| 1032 |
self.status_var.set("Starting quantization...")
|
|
|
|
| 1033 |
self._log(
|
| 1034 |
f"Starting quantization: source={Path(gguf_path).name} -> output={Path(out_path).name} "
|
| 1035 |
-
f"(cand={cfg.n_cand_d}x{cfg.n_cand_m}, analogs={cfg.use_weight_analogs}, "
|
| 1036 |
f"coupled={cfg.factor_coupled_q2k}, optimizer={cfg.optimizer.upper()})"
|
| 1037 |
)
|
| 1038 |
|
|
|
|
| 327 |
mode_row.pack(fill=tk.X, pady=(0, 4))
|
| 328 |
ttk.Label(mode_row, text="Target Scope:").pack(side=tk.LEFT, padx=(0, 8))
|
| 329 |
ttk.Radiobutton(
|
| 330 |
+
mode_row, text="All Eligible Tensors", variable=self.mode_var, value="all",
|
| 331 |
+
command=self._on_scope_changed,
|
| 332 |
).pack(side=tk.LEFT, padx=4)
|
| 333 |
ttk.Radiobutton(
|
| 334 |
+
mode_row, text="Selected Tensor(s)", variable=self.mode_var, value="selected",
|
| 335 |
+
command=self._on_scope_changed,
|
| 336 |
).pack(side=tk.LEFT, padx=4)
|
| 337 |
|
| 338 |
fmt_row = ttk.Frame(opt_frame)
|
|
|
|
| 513 |
self.tree.column("q2k", width=48, anchor=tk.CENTER)
|
| 514 |
self.tree.column("imat", width=56, anchor=tk.CENTER)
|
| 515 |
self.tree.column("state", width=165, anchor=tk.W)
|
| 516 |
+
self.tree.bind("<<TreeviewSelect>>", self._on_tree_selection)
|
| 517 |
|
| 518 |
tree_scroll = ttk.Scrollbar(browser_frame, orient=tk.VERTICAL, command=self.tree.yview)
|
| 519 |
self.tree.configure(yscrollcommand=tree_scroll.set)
|
|
|
|
| 880 |
self._reader = None
|
| 881 |
self._log(f"GGUF inspect error: {exc}")
|
| 882 |
|
| 883 |
+
def _plan_target(self, ti, chosen: set[str], scope_selected: bool):
|
| 884 |
+
tgt = target_quant_type(
|
| 885 |
+
ti.name,
|
| 886 |
+
ti.dims,
|
| 887 |
+
enable_q4_fallback=bool(self.q4_fallback_var.get()) and self.quant_format_var.get() not in ("q2_k", "q3_k"),
|
| 888 |
+
quantize_embd_q4=bool(self.embd_q4_var.get()),
|
| 889 |
+
promote_attn_q4=bool(self.promote_attn_q4_var.get()),
|
| 890 |
+
quant_format=self.quant_format_var.get(),
|
| 891 |
+
source_type=ti.type,
|
| 892 |
+
custom_quant_map=self._custom_map_for_plan(),
|
| 893 |
+
)
|
| 894 |
+
if scope_selected and ti.name not in chosen:
|
| 895 |
+
return None
|
| 896 |
+
return tgt
|
| 897 |
+
|
| 898 |
+
def _on_scope_changed(self) -> None:
|
| 899 |
+
self._refresh_plan_view()
|
| 900 |
+
self._update_cli_preview()
|
| 901 |
+
|
| 902 |
+
def _on_tree_selection(self, _event=None) -> None:
|
| 903 |
+
if self.mode_var.get() == "selected":
|
| 904 |
+
self._refresh_plan_view()
|
| 905 |
+
self._update_cli_preview()
|
| 906 |
+
|
| 907 |
+
def _refresh_plan_view(self) -> None:
|
| 908 |
+
if self._reader is None:
|
| 909 |
+
return
|
| 910 |
+
chosen = self._selected_tensor_names()
|
| 911 |
+
scope_selected = self.mode_var.get() == "selected"
|
| 912 |
+
n_q2, n_q3, n_q4, n_copy = 0, 0, 0, 0
|
| 913 |
+
n_q1 = 0
|
| 914 |
+
planned_bytes = 0
|
| 915 |
+
for ti in self._reader.tensors:
|
| 916 |
+
tgt = self._plan_target(ti, chosen, scope_selected)
|
| 917 |
+
if tgt == "Q2_K":
|
| 918 |
+
n_q2 += 1
|
| 919 |
+
elif tgt == "Q3_K":
|
| 920 |
+
n_q3 += 1
|
| 921 |
+
elif tgt == "Q4_0":
|
| 922 |
+
n_q4 += 1
|
| 923 |
+
elif tgt == "Q1_0":
|
| 924 |
+
n_q1 += 1
|
| 925 |
+
else:
|
| 926 |
+
n_copy += 1
|
| 927 |
+
|
| 928 |
+
if tgt == "Q2_K":
|
| 929 |
+
planned_bytes += (ti.n_elements // QK_K) * 84
|
| 930 |
+
elif tgt == "Q3_K":
|
| 931 |
+
planned_bytes += (ti.n_elements // QK3_K) * Q3_K_BLOCK_BYTES
|
| 932 |
+
elif tgt == "Q4_0":
|
| 933 |
+
planned_bytes += (ti.n_elements // QK4_0) * 18
|
| 934 |
+
elif tgt == "Q1_0":
|
| 935 |
+
planned_bytes += (ti.n_elements // QK1_0) * Q1_0_BLOCK_BYTES
|
| 936 |
+
else:
|
| 937 |
+
planned_bytes += ti.n_bytes
|
| 938 |
+
|
| 939 |
+
if not self.tree.exists(ti.name):
|
| 940 |
+
continue
|
| 941 |
+
tgt_label = tgt if tgt else "Copy"
|
| 942 |
+
if scope_selected and ti.name not in chosen:
|
| 943 |
+
state_str = "Not selected (copy)"
|
| 944 |
+
else:
|
| 945 |
+
state_str = (
|
| 946 |
+
f"Pending ({tgt_label})"
|
| 947 |
+
if tgt
|
| 948 |
+
else (f"Keep {ti.type_name} (<= target)" if ti.type_name in ("Q1_0", "Q2_K", "Q3_K", "Q4_0") else "Passthrough")
|
| 949 |
+
)
|
| 950 |
+
vals = list(self.tree.item(ti.name, "values"))
|
| 951 |
+
vals[4] = tgt_label
|
| 952 |
+
vals[6] = state_str
|
| 953 |
+
self.tree.item(ti.name, tags=(tgt_label,), values=vals)
|
| 954 |
+
|
| 955 |
+
if planned_bytes >= 1024 ** 3:
|
| 956 |
+
planned_text = f"{planned_bytes / (1024 ** 3):.2f} GiB"
|
| 957 |
+
elif planned_bytes >= 1024 ** 2:
|
| 958 |
+
planned_text = f"{planned_bytes / (1024 ** 2):.1f} MiB"
|
| 959 |
+
else:
|
| 960 |
+
planned_text = f"{planned_bytes / 1024:.1f} KiB"
|
| 961 |
+
scope_text = "selected" if scope_selected else "all"
|
| 962 |
+
self.status_var.set(
|
| 963 |
+
f"Plan ({self.quant_format_var.get().upper()}, {scope_text}): {n_q1} Q1_0 | {n_q2} Q2_K | {n_q3} Q3_K | {n_q4} Q4_0 | {n_copy} Copy "
|
| 964 |
+
f"(Total: {len(self._reader.tensors)} tensors, est. {planned_text})"
|
| 965 |
+
)
|
| 966 |
+
|
| 967 |
def _populate_tensor_tree(self) -> None:
|
| 968 |
+
chosen = self._selected_tensor_names()
|
| 969 |
+
scope_selected = self.mode_var.get() == "selected"
|
| 970 |
self.tree.delete(*self.tree.get_children())
|
| 971 |
if self._reader is None:
|
| 972 |
return
|
|
|
|
| 976 |
n_q1 = 0
|
| 977 |
planned_bytes = 0
|
| 978 |
for ti in self._reader.tensors:
|
| 979 |
+
tgt = self._plan_target(ti, chosen, scope_selected)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 980 |
if tgt == "Q2_K":
|
| 981 |
n_q2 += 1
|
| 982 |
elif tgt == "Q3_K":
|
|
|
|
| 1013 |
self._imatrix is not None
|
| 1014 |
and lookup_imatrix(self._imatrix, ti.name) is not None
|
| 1015 |
)
|
| 1016 |
+
if scope_selected and ti.name not in chosen:
|
| 1017 |
+
state_str = "Not selected (copy)"
|
| 1018 |
+
else:
|
| 1019 |
+
state_str = (
|
| 1020 |
+
f"Pending ({tgt_label})"
|
| 1021 |
+
if tgt
|
| 1022 |
+
else (f"Keep {ti.type_name} (<= target)" if ti.type_name in ("Q1_0", "Q2_K", "Q3_K", "Q4_0") else "Passthrough")
|
| 1023 |
+
)
|
| 1024 |
self.tree.insert(
|
| 1025 |
"",
|
| 1026 |
tk.END,
|
|
|
|
| 1036 |
state_str,
|
| 1037 |
),
|
| 1038 |
)
|
| 1039 |
+
keep_selected = [n for n in chosen if self.tree.exists(n)]
|
| 1040 |
+
if keep_selected:
|
| 1041 |
+
self.tree.selection_set(keep_selected)
|
| 1042 |
if planned_bytes >= 1024 ** 3:
|
| 1043 |
planned_text = f"{planned_bytes / (1024 ** 3):.2f} GiB"
|
| 1044 |
elif planned_bytes >= 1024 ** 2:
|
| 1045 |
planned_text = f"{planned_bytes / (1024 ** 2):.1f} MiB"
|
| 1046 |
else:
|
| 1047 |
planned_text = f"{planned_bytes / 1024:.1f} KiB"
|
| 1048 |
+
scope_text = "selected" if scope_selected else "all"
|
| 1049 |
self.status_var.set(
|
| 1050 |
+
f"Plan ({self.quant_format_var.get().upper()}, {scope_text}): {n_q1} Q1_0 | {n_q2} Q2_K | {n_q3} Q3_K | {n_q4} Q4_0 | {n_copy} Copy "
|
| 1051 |
f"(Total: {len(self._reader.tensors)} tensors, est. {planned_text})"
|
| 1052 |
)
|
| 1053 |
|
|
|
|
| 1116 |
self.bench_btn.configure(state=tk.DISABLED)
|
| 1117 |
self.stop_btn.configure(state=tk.NORMAL)
|
| 1118 |
self.status_var.set("Starting quantization...")
|
| 1119 |
+
scope_text = "all eligible tensors" if selected is None else f"{len(selected)} selected tensor(s)"
|
| 1120 |
self._log(
|
| 1121 |
f"Starting quantization: source={Path(gguf_path).name} -> output={Path(out_path).name} "
|
| 1122 |
+
f"(scope={scope_text}, cand={cfg.n_cand_d}x{cfg.n_cand_m}, analogs={cfg.use_weight_analogs}, "
|
| 1123 |
f"coupled={cfg.factor_coupled_q2k}, optimizer={cfg.optimizer.upper()})"
|
| 1124 |
)
|
| 1125 |
|