Introducing Slimshard
Browse files- __init__.py +26 -0
- slimshard.py +2186 -0
- slimshard_gui.py +1071 -0
__init__.py
CHANGED
|
@@ -34,6 +34,27 @@ from .pipeline import Q2KQuantizer, QuantizedTensor, TensorStats
|
|
| 34 |
from .q2k import Q2KBlock, QK_K, dequantize_params, pack_codes, unpack_codes
|
| 35 |
from .q4_0 import QK4_0, dequantize_q4_0_bytes, quantize_tensor_q4_0
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
__all__ = [
|
| 38 |
"HPCConfig",
|
| 39 |
"cuda_device_name",
|
|
@@ -64,6 +85,11 @@ __all__ = [
|
|
| 64 |
"QK4_0",
|
| 65 |
"dequantize_q4_0_bytes",
|
| 66 |
"quantize_tensor_q4_0",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
"pack_codes",
|
| 68 |
"unpack_codes",
|
| 69 |
]
|
|
|
|
| 34 |
from .q2k import Q2KBlock, QK_K, dequantize_params, pack_codes, unpack_codes
|
| 35 |
from .q4_0 import QK4_0, dequantize_q4_0_bytes, quantize_tensor_q4_0
|
| 36 |
|
| 37 |
+
|
| 38 |
+
def __getattr__(name: str):
|
| 39 |
+
if name in {
|
| 40 |
+
"SafetensorsWriter",
|
| 41 |
+
"build_slimshard",
|
| 42 |
+
"export_hf_bundle",
|
| 43 |
+
"infer_weight_map_from_shard",
|
| 44 |
+
"inspect_recovery_plan",
|
| 45 |
+
"recover_from_shard",
|
| 46 |
+
"regenerate",
|
| 47 |
+
"slimshard_info",
|
| 48 |
+
}:
|
| 49 |
+
from . import slimshard as _ss
|
| 50 |
+
|
| 51 |
+
return getattr(_ss, name)
|
| 52 |
+
if name == "launch_slimshard_gui":
|
| 53 |
+
from .slimshard_gui import launch_slimshard_gui
|
| 54 |
+
|
| 55 |
+
return launch_slimshard_gui
|
| 56 |
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
| 57 |
+
|
| 58 |
__all__ = [
|
| 59 |
"HPCConfig",
|
| 60 |
"cuda_device_name",
|
|
|
|
| 85 |
"QK4_0",
|
| 86 |
"dequantize_q4_0_bytes",
|
| 87 |
"quantize_tensor_q4_0",
|
| 88 |
+
"SafetensorsWriter",
|
| 89 |
+
"build_slimshard",
|
| 90 |
+
"recover_from_shard",
|
| 91 |
+
"regenerate",
|
| 92 |
+
"slimshard_info",
|
| 93 |
"pack_codes",
|
| 94 |
"unpack_codes",
|
| 95 |
]
|
slimshard.py
ADDED
|
@@ -0,0 +1,2186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""HPC-Quantize V2 ``slimshard``: CheckFree + SlimMoE single-shard LLM recovery.
|
| 2 |
+
|
| 3 |
+
Provides two workflows strictly within ``hpc_quantize_v2``:
|
| 4 |
+
|
| 5 |
+
1. **CheckFree Single-Shard Recovery** (:func:`recover_from_shard`):
|
| 6 |
+
Given **only one** existing Hugging Face ``.safetensors`` shard,
|
| 7 |
+
``model.safetensors.index.json``, ``config.json`` (and ``tokenizer.json``
|
| 8 |
+
when present), reconstructs the complete multi-shard state dict without
|
| 9 |
+
accessing any other shard:
|
| 10 |
+
|
| 11 |
+
* **Surviving tensors** in the shard are copied verbatim.
|
| 12 |
+
* **Missing Transformer layers** are reconstructed via **CheckFree
|
| 13 |
+
variance-preserving geodesic/linear interpolation** across the surviving
|
| 14 |
+
depth anchors (separately tracking **RDA** vs **Gated MLA** attention
|
| 15 |
+
architectures and **Raon-mHC** 4-stream residual parameters).
|
| 16 |
+
* **Missing MoE routed experts** preserve exact expert index ``e in 0..E-1``
|
| 17 |
+
across depth: surviving MXFP8 ``(weight, weight_scale_inv)`` expert pairs
|
| 18 |
+
at bracketing anchor layers are dequantized to FP32, interpolated with
|
| 19 |
+
sub-block iso-moment / variance preservation, and re-quantized in lockstep
|
| 20 |
+
to production MXFP8 (``F8_E4M3`` + ``UE8M0`` block-32 scales).
|
| 21 |
+
* **Missing untied ``model.embed_tokens.weight`` and ``lm_head.weight``**
|
| 22 |
+
are synthesized from the principal singular subspaces of the surviving
|
| 23 |
+
input/output layer projections and calibrated via an exact causal forward
|
| 24 |
+
pass through the reconstructed CheckFree layer stack.
|
| 25 |
+
|
| 26 |
+
2. **Self-Contained SlimShard Compression** (:func:`build_slimshard`,
|
| 27 |
+
:func:`regenerate`, :func:`slimshard_info`):
|
| 28 |
+
Fuses HPC-Quantize V2 (``Q2_K`` / ``Q4_0``) with SlimMoE centroid + residual
|
| 29 |
+
expert clustering into a single self-contained ``.safetensors`` file.
|
| 30 |
+
"""
|
| 31 |
+
|
| 32 |
+
from __future__ import annotations
|
| 33 |
+
|
| 34 |
+
import argparse
|
| 35 |
+
import json
|
| 36 |
+
import math
|
| 37 |
+
import mmap
|
| 38 |
+
import os
|
| 39 |
+
import re
|
| 40 |
+
import shutil
|
| 41 |
+
import struct
|
| 42 |
+
import tempfile
|
| 43 |
+
from pathlib import Path
|
| 44 |
+
|
| 45 |
+
import numpy as np
|
| 46 |
+
|
| 47 |
+
try:
|
| 48 |
+
import torch
|
| 49 |
+
import torch.nn.functional as F
|
| 50 |
+
from safetensors.torch import safe_open
|
| 51 |
+
except ImportError: # pragma: no cover
|
| 52 |
+
torch = None
|
| 53 |
+
F = None
|
| 54 |
+
safe_open = None
|
| 55 |
+
|
| 56 |
+
from .analog import subblock_isomoment_analog
|
| 57 |
+
from .config import HPCConfig
|
| 58 |
+
from .pipeline import Q2KQuantizer
|
| 59 |
+
from .q2k import QK_K, blocks_to_bytes, dequantize_params_batch
|
| 60 |
+
from .q4_0 import Q4_0_BLOCK_BYTES, QK4_0, dequantize_q4_0_bytes, quantize_tensor_q4_0
|
| 61 |
+
|
| 62 |
+
SHARD_FORMAT = "hpc-slimshard-v1"
|
| 63 |
+
EXPERT_RE = re.compile(
|
| 64 |
+
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)$"
|
| 65 |
+
)
|
| 66 |
+
LAYER_RE = re.compile(r"^((?:[a-zA-Z0-9_]+\.)*(?:layers|h|blocks))\.(\d+)\.(.+)$")
|
| 67 |
+
|
| 68 |
+
_EMBED_NAMES = (
|
| 69 |
+
"model.embed_tokens.weight",
|
| 70 |
+
"transformer.wte.weight",
|
| 71 |
+
"gpt_neox.embed_in.weight",
|
| 72 |
+
"model.decoder.embed_tokens.weight",
|
| 73 |
+
"language_model.model.embed_tokens.weight",
|
| 74 |
+
"backbone.embeddings.weight",
|
| 75 |
+
"embeddings.word_embeddings.weight",
|
| 76 |
+
)
|
| 77 |
+
_HEAD_NAMES = (
|
| 78 |
+
"lm_head.weight",
|
| 79 |
+
"embed_out.weight",
|
| 80 |
+
"output.weight",
|
| 81 |
+
"language_model.lm_head.weight",
|
| 82 |
+
"transformer.lm_head.weight",
|
| 83 |
+
)
|
| 84 |
+
_NORM_NAMES = (
|
| 85 |
+
"model.norm.weight",
|
| 86 |
+
"transformer.ln_f.weight",
|
| 87 |
+
"gpt_neox.final_layer_norm.weight",
|
| 88 |
+
"model.decoder.final_layer_norm.weight",
|
| 89 |
+
"language_model.model.norm.weight",
|
| 90 |
+
"backbone.norm_f.weight",
|
| 91 |
+
)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def _normalize_arch_config(raw_cfg: dict) -> dict:
|
| 95 |
+
"""Normalize arbitrary HF ``config.json`` (including VLM ``text_config``) into standard keys."""
|
| 96 |
+
if not raw_cfg:
|
| 97 |
+
return {}
|
| 98 |
+
arch = dict(raw_cfg)
|
| 99 |
+
if isinstance(raw_cfg.get("text_config"), dict):
|
| 100 |
+
for k, v in raw_cfg["text_config"].items():
|
| 101 |
+
arch.setdefault(k, v)
|
| 102 |
+
if "hidden_size" not in arch:
|
| 103 |
+
for alias in ("n_embd", "d_model", "dim", "model_dim"):
|
| 104 |
+
if alias in arch:
|
| 105 |
+
arch["hidden_size"] = arch[alias]
|
| 106 |
+
break
|
| 107 |
+
if "num_hidden_layers" not in arch:
|
| 108 |
+
for alias in ("n_layer", "num_layers", "n_layers"):
|
| 109 |
+
if alias in arch:
|
| 110 |
+
arch["num_hidden_layers"] = arch[alias]
|
| 111 |
+
break
|
| 112 |
+
if "num_attention_heads" not in arch:
|
| 113 |
+
for alias in ("n_head", "num_heads", "n_heads"):
|
| 114 |
+
if alias in arch:
|
| 115 |
+
arch["num_attention_heads"] = arch[alias]
|
| 116 |
+
break
|
| 117 |
+
if "vocab_size" not in arch and "padded_vocab_size" in arch:
|
| 118 |
+
arch["vocab_size"] = arch["padded_vocab_size"]
|
| 119 |
+
if "num_experts" not in arch:
|
| 120 |
+
for alias in ("num_local_experts", "n_routed_experts", "moe_num_experts"):
|
| 121 |
+
if alias in arch:
|
| 122 |
+
arch["num_experts"] = arch[alias]
|
| 123 |
+
break
|
| 124 |
+
if "num_experts_per_token" not in arch:
|
| 125 |
+
for alias in ("num_selected_experts", "moe_top_k", "top_k"):
|
| 126 |
+
if alias in arch:
|
| 127 |
+
arch["num_experts_per_token"] = arch[alias]
|
| 128 |
+
break
|
| 129 |
+
return arch
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def _is_embed_key(name: str) -> bool:
|
| 133 |
+
return name in _EMBED_NAMES or name.endswith(("embed_tokens.weight", "wte.weight", "embed_in.weight", "word_embeddings.weight"))
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def _is_head_key(name: str) -> bool:
|
| 137 |
+
return name in _HEAD_NAMES or name.endswith(("lm_head.weight", "embed_out.weight"))
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
def infer_weight_map_from_shard(shard_path: str | Path, arch: dict) -> dict[str, str]:
|
| 141 |
+
"""Infer a full model ``weight_map`` when ``model.safetensors.index.json`` is absent."""
|
| 142 |
+
shard_path = Path(shard_path)
|
| 143 |
+
sh_name = shard_path.name
|
| 144 |
+
num_layers = int(arch.get("num_hidden_layers", 0))
|
| 145 |
+
num_experts = int(arch.get("num_experts") or 0)
|
| 146 |
+
first_dense = int(arch.get("first_k_dense_replace", 0))
|
| 147 |
+
rda_cfg = arch.get("rda_config", {})
|
| 148 |
+
mla_set = {int(x) - 1 for x in rda_cfg.get("mla_layers", [])}
|
| 149 |
+
rda_set = {int(x) - 1 for x in rda_cfg.get("rda_layers", [])}
|
| 150 |
+
|
| 151 |
+
with safe_open(str(shard_path), framework="pt", device="cpu") as f:
|
| 152 |
+
present = sorted(f.keys())
|
| 153 |
+
|
| 154 |
+
if num_layers <= 0:
|
| 155 |
+
max_l = -1
|
| 156 |
+
for k in present:
|
| 157 |
+
m = LAYER_RE.match(k)
|
| 158 |
+
if m:
|
| 159 |
+
max_l = max(max_l, int(m.group(2)))
|
| 160 |
+
num_layers = max(max_l + 1, 1)
|
| 161 |
+
|
| 162 |
+
layer_prefix = "model.layers"
|
| 163 |
+
expert_container = "moe.experts"
|
| 164 |
+
expert_projs: set[tuple[str, str]] = set()
|
| 165 |
+
dense_suffixes: set[str] = set()
|
| 166 |
+
moe_non_expert_suffixes: set[str] = set()
|
| 167 |
+
rda_attn_suffixes: set[str] = set()
|
| 168 |
+
mla_attn_suffixes: set[str] = set()
|
| 169 |
+
generic_attn_suffixes: set[str] = set()
|
| 170 |
+
|
| 171 |
+
for k in present:
|
| 172 |
+
em = EXPERT_RE.match(k)
|
| 173 |
+
if em:
|
| 174 |
+
layer_prefix = em.group(1)
|
| 175 |
+
expert_container = em.group(3)
|
| 176 |
+
expert_projs.add((em.group(5), em.group(6)))
|
| 177 |
+
continue
|
| 178 |
+
lm = LAYER_RE.match(k)
|
| 179 |
+
if lm:
|
| 180 |
+
layer_prefix = lm.group(1)
|
| 181 |
+
lidx = int(lm.group(2))
|
| 182 |
+
suf = lm.group(3)
|
| 183 |
+
if "self_attn." in suf or "attention." in suf:
|
| 184 |
+
if lidx in mla_set:
|
| 185 |
+
mla_attn_suffixes.add(suf)
|
| 186 |
+
elif lidx in rda_set:
|
| 187 |
+
rda_attn_suffixes.add(suf)
|
| 188 |
+
else:
|
| 189 |
+
generic_attn_suffixes.add(suf)
|
| 190 |
+
elif lidx < first_dense:
|
| 191 |
+
dense_suffixes.add(suf)
|
| 192 |
+
else:
|
| 193 |
+
moe_non_expert_suffixes.add(suf)
|
| 194 |
+
|
| 195 |
+
wm: dict[str, str] = {}
|
| 196 |
+
embed_key = next((k for k in present if _is_embed_key(k)), "model.embed_tokens.weight")
|
| 197 |
+
head_key = next((k for k in present if _is_head_key(k)), "lm_head.weight")
|
| 198 |
+
norm_key = next((k for k in present if k in _NORM_NAMES or (k.endswith("norm.weight") and not LAYER_RE.match(k))), "model.norm.weight")
|
| 199 |
+
|
| 200 |
+
if not bool(arch.get("tie_word_embeddings", False)):
|
| 201 |
+
wm[head_key] = sh_name
|
| 202 |
+
wm[embed_key] = sh_name
|
| 203 |
+
|
| 204 |
+
for lidx in range(num_layers):
|
| 205 |
+
attn_sufs = (
|
| 206 |
+
mla_attn_suffixes
|
| 207 |
+
if (lidx in mla_set and mla_attn_suffixes)
|
| 208 |
+
else (rda_attn_suffixes if (lidx in rda_set and rda_attn_suffixes) else (generic_attn_suffixes or rda_attn_suffixes or mla_attn_suffixes))
|
| 209 |
+
)
|
| 210 |
+
body_sufs = dense_suffixes if (lidx < first_dense and dense_suffixes) else (moe_non_expert_suffixes or dense_suffixes)
|
| 211 |
+
for suf in sorted(attn_sufs | body_sufs):
|
| 212 |
+
wm[f"{layer_prefix}.{lidx}.{suf}"] = sh_name
|
| 213 |
+
if lidx >= first_dense and expert_projs:
|
| 214 |
+
n_exp = max(num_experts, 1)
|
| 215 |
+
for eidx in range(n_exp):
|
| 216 |
+
for proj, field in sorted(expert_projs):
|
| 217 |
+
wm[f"{layer_prefix}.{lidx}.{expert_container}.{eidx}.{proj}.{field}"] = sh_name
|
| 218 |
+
|
| 219 |
+
for k in present:
|
| 220 |
+
wm.setdefault(k, sh_name)
|
| 221 |
+
wm[norm_key] = sh_name
|
| 222 |
+
return wm
|
| 223 |
+
|
| 224 |
+
_TORCH_DTYPE = {
|
| 225 |
+
"float32": "F32",
|
| 226 |
+
"float16": "F16",
|
| 227 |
+
"bfloat16": "BF16",
|
| 228 |
+
"float64": "F64",
|
| 229 |
+
"int64": "I64",
|
| 230 |
+
"int32": "I32",
|
| 231 |
+
"int16": "I16",
|
| 232 |
+
"int8": "I8",
|
| 233 |
+
"uint8": "U8",
|
| 234 |
+
"bool": "BOOL",
|
| 235 |
+
"float8_e4m3fn": "F8_E4M3",
|
| 236 |
+
"float8_e5m2": "F8_E5M2",
|
| 237 |
+
"float8_e4m3fnuz": "F8_E4M3",
|
| 238 |
+
"float8_e5m2fnuz": "F8_E5M2",
|
| 239 |
+
}
|
| 240 |
+
_NP_DTYPE = {
|
| 241 |
+
"F32": np.float32,
|
| 242 |
+
"F16": np.float16,
|
| 243 |
+
"F64": np.float64,
|
| 244 |
+
"I64": np.int64,
|
| 245 |
+
"I32": np.int32,
|
| 246 |
+
"I16": np.int16,
|
| 247 |
+
"I8": np.int8,
|
| 248 |
+
"U8": np.uint8,
|
| 249 |
+
"BOOL": np.bool_,
|
| 250 |
+
}
|
| 251 |
+
_BPW = {
|
| 252 |
+
"F32": 32.0,
|
| 253 |
+
"F16": 16.0,
|
| 254 |
+
"BF16": 16.0,
|
| 255 |
+
"F64": 64.0,
|
| 256 |
+
"I64": 64.0,
|
| 257 |
+
"I32": 32.0,
|
| 258 |
+
"I16": 16.0,
|
| 259 |
+
"I8": 8.0,
|
| 260 |
+
"U8": 8.0,
|
| 261 |
+
"BOOL": 1.0,
|
| 262 |
+
"F8_E4M3": 8.0,
|
| 263 |
+
"F8_E5M2": 8.0,
|
| 264 |
+
}
|
| 265 |
+
_ITEMSIZE = {
|
| 266 |
+
"F8_E4M3": 1,
|
| 267 |
+
"F8_E5M2": 1,
|
| 268 |
+
"U8": 1,
|
| 269 |
+
"I8": 1,
|
| 270 |
+
"BOOL": 1,
|
| 271 |
+
"F16": 2,
|
| 272 |
+
"BF16": 2,
|
| 273 |
+
"I16": 2,
|
| 274 |
+
"U16": 2,
|
| 275 |
+
"F32": 4,
|
| 276 |
+
"I32": 4,
|
| 277 |
+
"U32": 4,
|
| 278 |
+
"F64": 8,
|
| 279 |
+
"I64": 8,
|
| 280 |
+
"U64": 8,
|
| 281 |
+
}
|
| 282 |
+
_VALID_DTYPES = set(_ITEMSIZE)
|
| 283 |
+
_TORCH_DTYPE_REV = {k: k for k in _ITEMSIZE}
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
def _safetensors_dtype(s) -> str:
|
| 287 |
+
raw = str(s).replace("torch.", "")
|
| 288 |
+
if raw in _VALID_DTYPES:
|
| 289 |
+
return raw
|
| 290 |
+
alias = {"uint16": "U16", "uint32": "U32", "uint64": "U64"}
|
| 291 |
+
if raw in alias:
|
| 292 |
+
return alias[raw]
|
| 293 |
+
return _TORCH_DTYPE.get(raw, "F32")
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
class SafetensorsWriter:
|
| 297 |
+
"""Streaming safetensors writer with explicit dtype strings and metadata."""
|
| 298 |
+
|
| 299 |
+
def __init__(
|
| 300 |
+
self,
|
| 301 |
+
path: str | Path,
|
| 302 |
+
metadata: dict[str, str] | None = None,
|
| 303 |
+
tmp_dir: str | Path | None = None,
|
| 304 |
+
):
|
| 305 |
+
self.path = Path(path)
|
| 306 |
+
self.path.parent.mkdir(parents=True, exist_ok=True)
|
| 307 |
+
self.metadata = metadata or {}
|
| 308 |
+
self._tmp = tempfile.NamedTemporaryFile(
|
| 309 |
+
delete=False, dir=str(tmp_dir or self.path.parent)
|
| 310 |
+
)
|
| 311 |
+
self._entries: dict[str, dict] = {}
|
| 312 |
+
self._offset = 0
|
| 313 |
+
|
| 314 |
+
def add(
|
| 315 |
+
self,
|
| 316 |
+
name: str,
|
| 317 |
+
data: bytes | np.ndarray,
|
| 318 |
+
dtype: str,
|
| 319 |
+
shape: tuple[int, ...],
|
| 320 |
+
) -> None:
|
| 321 |
+
raw = data.tobytes() if isinstance(data, np.ndarray) else bytes(data)
|
| 322 |
+
item = _ITEMSIZE.get(dtype)
|
| 323 |
+
if item is not None:
|
| 324 |
+
expected = int(np.prod(shape)) * item
|
| 325 |
+
if len(raw) != expected:
|
| 326 |
+
raise ValueError(
|
| 327 |
+
f"{name}: {len(raw)} bytes for {dtype}{tuple(shape)} (expected {expected})"
|
| 328 |
+
)
|
| 329 |
+
end = self._offset + len(raw)
|
| 330 |
+
self._entries[name] = {
|
| 331 |
+
"dtype": dtype,
|
| 332 |
+
"shape": [int(x) for x in shape],
|
| 333 |
+
"data_offsets": [self._offset, end],
|
| 334 |
+
}
|
| 335 |
+
if raw:
|
| 336 |
+
self._tmp.write(raw)
|
| 337 |
+
self._offset = end
|
| 338 |
+
|
| 339 |
+
def add_chunked_bf16(
|
| 340 |
+
self,
|
| 341 |
+
name: str,
|
| 342 |
+
shape: tuple[int, int],
|
| 343 |
+
chunk_iter,
|
| 344 |
+
) -> None:
|
| 345 |
+
rows, cols = shape
|
| 346 |
+
expected = rows * cols * 2
|
| 347 |
+
start = self._offset
|
| 348 |
+
written = 0
|
| 349 |
+
for raw_chunk in chunk_iter:
|
| 350 |
+
b = raw_chunk if isinstance(raw_chunk, bytes) else bytes(raw_chunk)
|
| 351 |
+
self._tmp.write(b)
|
| 352 |
+
written += len(b)
|
| 353 |
+
if written != expected:
|
| 354 |
+
raise ValueError(f"{name}: {written} bytes written (expected {expected})")
|
| 355 |
+
self._entries[name] = {
|
| 356 |
+
"dtype": "BF16",
|
| 357 |
+
"shape": [int(rows), int(cols)],
|
| 358 |
+
"data_offsets": [start, start + written],
|
| 359 |
+
}
|
| 360 |
+
self._offset = start + written
|
| 361 |
+
|
| 362 |
+
def read_tensor_torch(self, name: str, device: "torch.device") -> "torch.Tensor":
|
| 363 |
+
ent = self._entries[name]
|
| 364 |
+
lo, hi = ent["data_offsets"]
|
| 365 |
+
dt = ent["dtype"]
|
| 366 |
+
shape = tuple(ent["shape"])
|
| 367 |
+
raw = bytearray(os.pread(self._tmp.fileno(), hi - lo, lo))
|
| 368 |
+
if dt == "BF16":
|
| 369 |
+
t = torch.frombuffer(raw, dtype=torch.bfloat16).reshape(shape)
|
| 370 |
+
elif dt == "F16":
|
| 371 |
+
t = torch.frombuffer(raw, dtype=torch.float16).reshape(shape)
|
| 372 |
+
elif dt == "F32":
|
| 373 |
+
t = torch.frombuffer(raw, dtype=torch.float32).reshape(shape)
|
| 374 |
+
elif dt == "F8_E4M3":
|
| 375 |
+
t = torch.frombuffer(raw, dtype=torch.uint8).view(torch.float8_e4m3fn).reshape(shape)
|
| 376 |
+
else:
|
| 377 |
+
t = torch.frombuffer(raw, dtype=torch.uint8).reshape(shape)
|
| 378 |
+
return t.to(device)
|
| 379 |
+
|
| 380 |
+
def bytes_written(self) -> int:
|
| 381 |
+
return self._offset
|
| 382 |
+
|
| 383 |
+
def close(self) -> None:
|
| 384 |
+
header = {"__metadata__": self.metadata, **self._entries}
|
| 385 |
+
raw_header = json.dumps(header, separators=(",", ":")).encode("utf-8")
|
| 386 |
+
pad = (-len(raw_header)) % 8
|
| 387 |
+
raw_header += b" " * pad
|
| 388 |
+
self._tmp.flush()
|
| 389 |
+
with self.path.open("wb") as f:
|
| 390 |
+
f.write(struct.pack("<Q", len(raw_header)))
|
| 391 |
+
f.write(raw_header)
|
| 392 |
+
self._tmp.seek(0)
|
| 393 |
+
shutil.copyfileobj(self._tmp, f, length=16 * 1024 * 1024)
|
| 394 |
+
self._tmp.close()
|
| 395 |
+
os.unlink(self._tmp.name)
|
| 396 |
+
|
| 397 |
+
|
| 398 |
+
def _dtype_of(t) -> str:
|
| 399 |
+
return _TORCH_DTYPE.get(str(t.dtype).replace("torch.", ""), "F32")
|
| 400 |
+
|
| 401 |
+
|
| 402 |
+
def _payload_bytes(t) -> bytes:
|
| 403 |
+
dt = str(t.dtype)
|
| 404 |
+
if dt.endswith("bfloat16"):
|
| 405 |
+
return t.view(torch.uint16).cpu().numpy().tobytes()
|
| 406 |
+
if "float8" in dt:
|
| 407 |
+
return t.view(torch.uint8).cpu().numpy().tobytes()
|
| 408 |
+
return t.cpu().numpy().tobytes()
|
| 409 |
+
|
| 410 |
+
|
| 411 |
+
def _to_f32(t) -> tuple[np.ndarray, bytes, str]:
|
| 412 |
+
dt = _dtype_of(t)
|
| 413 |
+
if dt.startswith("F8"):
|
| 414 |
+
f32 = t.float().cpu().numpy().astype(np.float32)
|
| 415 |
+
raw = t.view(torch.uint8).cpu().numpy().tobytes()
|
| 416 |
+
return f32, raw, dt
|
| 417 |
+
if dt == "BF16":
|
| 418 |
+
bits = t.view(torch.uint16).cpu().numpy()
|
| 419 |
+
f32 = (bits.astype(np.uint32) << 16).view(np.float32)
|
| 420 |
+
return f32, bits.astype("<u2").tobytes(), dt
|
| 421 |
+
arr = t.cpu().numpy()
|
| 422 |
+
if dt == "F16":
|
| 423 |
+
return arr.astype(np.float32), arr.astype("<f2").tobytes(), dt
|
| 424 |
+
if dt == "F32":
|
| 425 |
+
return arr.astype(np.float32), arr.astype("<f4").tobytes(), dt
|
| 426 |
+
return arr.astype(np.float32), arr.tobytes(), dt
|
| 427 |
+
|
| 428 |
+
|
| 429 |
+
def _f32_to_bf16_bits(x: np.ndarray) -> np.ndarray:
|
| 430 |
+
b = np.ascontiguousarray(x, dtype=np.float32).view(np.uint32)
|
| 431 |
+
rounded = (b + np.uint32(0x8000) + ((b >> np.uint32(16)) & np.uint32(1))) >> np.uint32(16)
|
| 432 |
+
return rounded.astype(np.uint16)
|
| 433 |
+
|
| 434 |
+
|
| 435 |
+
def _storage_from_f32(
|
| 436 |
+
x: np.ndarray, dtype: str
|
| 437 |
+
) -> tuple[bytes, str, tuple[int, ...]]:
|
| 438 |
+
if dtype == "BF16":
|
| 439 |
+
bits = _f32_to_bf16_bits(x)
|
| 440 |
+
return bits.astype("<u2").tobytes(), "BF16", bits.shape
|
| 441 |
+
if dtype == "F16":
|
| 442 |
+
a = np.ascontiguousarray(x, dtype=np.float16)
|
| 443 |
+
return a.astype("<f2").tobytes(), "F16", a.shape
|
| 444 |
+
if dtype == "F32":
|
| 445 |
+
a = np.ascontiguousarray(x, dtype=np.float32)
|
| 446 |
+
return a.astype("<f4").tobytes(), "F32", a.shape
|
| 447 |
+
raise TypeError(f"cannot cast float32 to {dtype}")
|
| 448 |
+
|
| 449 |
+
|
| 450 |
+
def _decode_exact(raw: bytes, dtype: str, shape) -> np.ndarray:
|
| 451 |
+
shape = tuple(shape)
|
| 452 |
+
if dtype == "BF16":
|
| 453 |
+
bits = np.frombuffer(raw, dtype="<u2").copy()
|
| 454 |
+
return (bits.astype(np.uint32) << 16).view(np.float32).reshape(shape)
|
| 455 |
+
np_dt = _NP_DTYPE.get(dtype, np.float32)
|
| 456 |
+
return np.frombuffer(raw, dtype=np.dtype(np_dt)).copy().reshape(shape)
|
| 457 |
+
|
| 458 |
+
|
| 459 |
+
def _decode_q2k(raw: bytes, shape) -> np.ndarray:
|
| 460 |
+
blocks = np.frombuffer(raw, dtype=np.uint8).reshape(-1, 84)
|
| 461 |
+
scales = blocks[:, :16]
|
| 462 |
+
qs = blocks[:, 16:80]
|
| 463 |
+
d = blocks[:, 80:82].copy().view("<f2").reshape(-1).astype(np.float32)
|
| 464 |
+
dmin = blocks[:, 82:84].copy().view("<f2").reshape(-1).astype(np.float32)
|
| 465 |
+
n = blocks.shape[0]
|
| 466 |
+
codes = np.empty((n, QK_K), dtype=np.uint8)
|
| 467 |
+
for base in (0, 128):
|
| 468 |
+
q = qs[:, base // 4 : base // 4 + 32]
|
| 469 |
+
for s_lvl in range(4):
|
| 470 |
+
lo = base + 32 * s_lvl
|
| 471 |
+
codes[:, lo : lo + 32] = (q >> np.uint8(2 * s_lvl)) & np.uint8(3)
|
| 472 |
+
return dequantize_params_batch(
|
| 473 |
+
d, dmin, scales & 0x0F, scales >> 4, codes
|
| 474 |
+
).reshape(tuple(shape))
|
| 475 |
+
|
| 476 |
+
|
| 477 |
+
def _decode_q4(raw: bytes, shape) -> np.ndarray:
|
| 478 |
+
nb = len(raw) // Q4_0_BLOCK_BYTES
|
| 479 |
+
return dequantize_q4_0_bytes(raw, nb).reshape(tuple(shape))
|
| 480 |
+
|
| 481 |
+
|
| 482 |
+
# ---------------------------------------------------------------------------
|
| 483 |
+
# MXFP8 dequantization / quantization & CheckFree interpolation helpers
|
| 484 |
+
# ---------------------------------------------------------------------------
|
| 485 |
+
def _dequant_mxfp8_torch(weight_e4m3: "torch.Tensor", scale_u8: "torch.Tensor") -> "torch.Tensor":
|
| 486 |
+
rows, cols = weight_e4m3.shape
|
| 487 |
+
blocks = weight_e4m3.float().view(rows, cols // 32, 32)
|
| 488 |
+
s = scale_u8 if scale_u8.dtype == torch.uint8 else scale_u8.view(torch.uint8)
|
| 489 |
+
factor = torch.exp2(s.float() - 127.0).unsqueeze(-1)
|
| 490 |
+
return (blocks * factor).view(rows, cols)
|
| 491 |
+
|
| 492 |
+
|
| 493 |
+
def _quant_mxfp8_torch(x_f32: "torch.Tensor") -> tuple["torch.Tensor", "torch.Tensor"]:
|
| 494 |
+
rows, cols = x_f32.shape
|
| 495 |
+
blocks = x_f32.float().view(rows, cols // 32, 32)
|
| 496 |
+
bits = (blocks.abs().amax(-1) * (1.0 / 448.0)).view(torch.int32)
|
| 497 |
+
exp = (bits >> 23) & 0xFF
|
| 498 |
+
man = bits & 0x7FFFFF
|
| 499 |
+
round_up = (man > 0) & (exp != 0xFE) & ~((exp == 0) & (man <= 0x400000))
|
| 500 |
+
e = (exp + round_up.int()).clamp(max=254)
|
| 501 |
+
reciprocal = ((254 - e) << 23).view(torch.float32)
|
| 502 |
+
reciprocal = torch.where(e == 254, torch.full_like(reciprocal, 2.0**-127), reciprocal)
|
| 503 |
+
values = (blocks * reciprocal.unsqueeze(-1)).clamp(-448.0, 448.0)
|
| 504 |
+
return values.to(torch.float8_e4m3fn).view(rows, cols), e.to(torch.uint8)
|
| 505 |
+
|
| 506 |
+
|
| 507 |
+
def _checkfree_interp_torch(
|
| 508 |
+
t_a: "torch.Tensor",
|
| 509 |
+
t_b: "torch.Tensor",
|
| 510 |
+
alpha: float,
|
| 511 |
+
preserve_row_rms: bool = True,
|
| 512 |
+
) -> "torch.Tensor":
|
| 513 |
+
"""CheckFree variance-preserving interpolation between two anchor tensors."""
|
| 514 |
+
if alpha <= 0.0 or t_a is t_b:
|
| 515 |
+
return t_a.float()
|
| 516 |
+
if alpha >= 1.0:
|
| 517 |
+
return t_b.float()
|
| 518 |
+
a = t_a.float()
|
| 519 |
+
b = t_b.float()
|
| 520 |
+
mix = (1.0 - alpha) * a + alpha * b
|
| 521 |
+
if not preserve_row_rms or a.ndim < 2:
|
| 522 |
+
rms_a = torch.sqrt(torch.mean(a * a) + 1.0e-30)
|
| 523 |
+
rms_b = torch.sqrt(torch.mean(b * b) + 1.0e-30)
|
| 524 |
+
rms_m = torch.sqrt(torch.mean(mix * mix) + 1.0e-30)
|
| 525 |
+
target_rms = (1.0 - alpha) * rms_a + alpha * rms_b
|
| 526 |
+
return mix * (target_rms / rms_m)
|
| 527 |
+
rms_a = torch.sqrt(torch.mean(a * a, dim=-1, keepdim=True) + 1.0e-30)
|
| 528 |
+
rms_b = torch.sqrt(torch.mean(b * b, dim=-1, keepdim=True) + 1.0e-30)
|
| 529 |
+
rms_m = torch.sqrt(torch.mean(mix * mix, dim=-1, keepdim=True) + 1.0e-30)
|
| 530 |
+
target_rms = (1.0 - alpha) * rms_a + alpha * rms_b
|
| 531 |
+
return mix * (target_rms / rms_m)
|
| 532 |
+
|
| 533 |
+
|
| 534 |
+
def _bracket_anchors(
|
| 535 |
+
sorted_layers: list[int], target_layer: int, total_layers: int = 25
|
| 536 |
+
) -> tuple[int, int, float]:
|
| 537 |
+
"""Return ``(l_lo, l_hi, alpha)`` bracketing ``target_layer`` in ``sorted_layers``."""
|
| 538 |
+
if len(sorted_layers) == 1:
|
| 539 |
+
return sorted_layers[0], sorted_layers[0], 0.0
|
| 540 |
+
if target_layer <= sorted_layers[0]:
|
| 541 |
+
return sorted_layers[0], sorted_layers[1], 0.0
|
| 542 |
+
if target_layer >= sorted_layers[-1]:
|
| 543 |
+
span = max(total_layers - 1 - sorted_layers[-1], 1)
|
| 544 |
+
rel = float(min(max(target_layer - sorted_layers[-1], 1), span)) / float(span)
|
| 545 |
+
return sorted_layers[0 if len(sorted_layers) > 2 else -2], sorted_layers[-1], 0.55 + 0.40 * rel
|
| 546 |
+
for i in range(len(sorted_layers) - 1):
|
| 547 |
+
la, lb = sorted_layers[i], sorted_layers[i + 1]
|
| 548 |
+
if la <= target_layer <= lb:
|
| 549 |
+
alpha = float(target_layer - la) / float(max(lb - la, 1))
|
| 550 |
+
return la, lb, alpha
|
| 551 |
+
return sorted_layers[-1], sorted_layers[-1], 0.0
|
| 552 |
+
|
| 553 |
+
|
| 554 |
+
def _rms_norm_torch(
|
| 555 |
+
x: "torch.Tensor", w: "torch.Tensor", eps: float = 1.0e-5, keep_fp32: bool = False
|
| 556 |
+
) -> "torch.Tensor":
|
| 557 |
+
xf = x.float()
|
| 558 |
+
out = xf * torch.rsqrt(xf.pow(2).mean(-1, keepdim=True) + eps) * w.float()
|
| 559 |
+
return out if keep_fp32 else out.to(x.dtype)
|
| 560 |
+
|
| 561 |
+
|
| 562 |
+
def _situ_glu_torch(
|
| 563 |
+
gate: "torch.Tensor", up: "torch.Tensor", gate_beta: float = 4.0, up_beta: float = 25.0
|
| 564 |
+
) -> "torch.Tensor":
|
| 565 |
+
g = gate.float()
|
| 566 |
+
u = up.float()
|
| 567 |
+
return (gate_beta * torch.tanh(g / gate_beta) * torch.sigmoid(g)) * (
|
| 568 |
+
up_beta * torch.tanh(u / up_beta)
|
| 569 |
+
)
|
| 570 |
+
|
| 571 |
+
|
| 572 |
+
def _helmert_basis_torch(n: int, device: "torch.device") -> tuple["torch.Tensor", "torch.Tensor", "torch.Tensor"]:
|
| 573 |
+
q = torch.zeros(n, n - 1, dtype=torch.float32, device=device)
|
| 574 |
+
for k in range(1, n):
|
| 575 |
+
q[:k, k - 1] = 1.0
|
| 576 |
+
q[k, k - 1] = -float(k)
|
| 577 |
+
q[:, k - 1] /= math.sqrt(k * (k + 1.0))
|
| 578 |
+
eye = torch.eye(n, dtype=torch.float32, device=device)
|
| 579 |
+
chart_b = 0.5 * (eye + torch.full_like(eye, 1.0 / n))
|
| 580 |
+
return q, eye, chart_b
|
| 581 |
+
|
| 582 |
+
|
| 583 |
+
def _run_exact_reconstructed_forward(
|
| 584 |
+
writer: SafetensorsWriter,
|
| 585 |
+
token_seqs: list[list[int]],
|
| 586 |
+
coords: np.ndarray,
|
| 587 |
+
basis_in: "torch.Tensor",
|
| 588 |
+
scale_in: float,
|
| 589 |
+
arch: dict,
|
| 590 |
+
dev: "torch.device",
|
| 591 |
+
) -> list["torch.Tensor"]:
|
| 592 |
+
"""Execute the exact causal forward pass on ``token_seqs`` using tensors in ``writer``."""
|
| 593 |
+
num_layers = int(arch.get("num_hidden_layers", 25))
|
| 594 |
+
hidden_size = int(arch.get("hidden_size", 2560))
|
| 595 |
+
eps = float(arch.get("rms_norm_eps", 1.0e-5))
|
| 596 |
+
n_streams = int(arch.get("raon_mhc_streams", 4))
|
| 597 |
+
gate_beta = float(arch.get("activation_situ_beta", 4.0))
|
| 598 |
+
value_beta = float(arch.get("activation_situ_linear_beta", 25.0))
|
| 599 |
+
top_k = int(arch.get("num_experts_per_token", 6))
|
| 600 |
+
num_experts = int(arch.get("num_experts", 128))
|
| 601 |
+
renormalize = bool(arch.get("moe_renormalize", True))
|
| 602 |
+
routed_scale = float(arch.get("routed_scaling_factor", 1.0))
|
| 603 |
+
|
| 604 |
+
rda_cfg = arch.get("rda_config", {})
|
| 605 |
+
rda_heads = int(rda_cfg.get("num_heads", arch.get("num_attention_heads", 40)))
|
| 606 |
+
rda_head_dim = int(rda_cfg.get("head_dim", arch.get("head_dim", 128)))
|
| 607 |
+
rda_proj = rda_heads * rda_head_dim
|
| 608 |
+
gate_lb = float(rda_cfg.get("gate_lower_bound", -5.0))
|
| 609 |
+
|
| 610 |
+
mla_heads = int(arch.get("num_attention_heads", 40))
|
| 611 |
+
qk_nope = int(arch.get("qk_nope_head_dim", 128))
|
| 612 |
+
qk_pe = int(arch.get("qk_rope_head_dim", 64))
|
| 613 |
+
v_dim = int(arch.get("v_head_dim", 128))
|
| 614 |
+
q_head_dim = qk_nope + qk_pe
|
| 615 |
+
kv_lora_rank = int(arch.get("kv_lora_rank", 512))
|
| 616 |
+
softmax_scale = q_head_dim ** -0.5
|
| 617 |
+
|
| 618 |
+
helmert, eye, chart_b = _helmert_basis_torch(n_streams, dev)
|
| 619 |
+
|
| 620 |
+
streams = []
|
| 621 |
+
for seq in token_seqs:
|
| 622 |
+
c_seq = torch.from_numpy(coords[seq]).to(dev, dtype=torch.float32)
|
| 623 |
+
inp = (c_seq @ basis_in * scale_in).to(torch.bfloat16).unsqueeze(0)
|
| 624 |
+
streams.append(inp.unsqueeze(2).expand(-1, -1, n_streams, -1).contiguous())
|
| 625 |
+
|
| 626 |
+
def mhc_route(stream: "torch.Tensor", prefix: str):
|
| 627 |
+
phi_pre = writer.read_tensor_torch(f"{prefix}.phi_pre", dev)
|
| 628 |
+
phi_post = writer.read_tensor_torch(f"{prefix}.phi_post", dev)
|
| 629 |
+
phi_z = writer.read_tensor_torch(f"{prefix}.res.phi_z", dev)
|
| 630 |
+
alpha_pre = writer.read_tensor_torch(f"{prefix}.alpha_pre", dev).float()
|
| 631 |
+
alpha_post = writer.read_tensor_torch(f"{prefix}.alpha_post", dev).float()
|
| 632 |
+
alpha_z = writer.read_tensor_torch(f"{prefix}.res.alpha_z", dev).float()
|
| 633 |
+
b_pre = writer.read_tensor_torch(f"{prefix}.b_pre", dev).float()
|
| 634 |
+
b_post = writer.read_tensor_torch(f"{prefix}.b_post", dev).float()
|
| 635 |
+
b_z = writer.read_tensor_torch(f"{prefix}.res.b_z", dev).float()
|
| 636 |
+
eta = writer.read_tensor_torch(f"{prefix}.res.eta", dev).float()
|
| 637 |
+
|
| 638 |
+
rows = stream.shape[0] * stream.shape[1]
|
| 639 |
+
flat = stream.reshape(rows, n_streams * hidden_size)
|
| 640 |
+
weight = torch.cat([phi_pre, phi_post, phi_z], dim=0).to(flat.dtype)
|
| 641 |
+
inv = torch.rsqrt(flat.float().pow(2).mean(-1, keepdim=True) + 1.0e-6)
|
| 642 |
+
z = F.linear(flat, weight).float() * inv
|
| 643 |
+
t_pre = alpha_pre * z[:, :n_streams] + b_pre
|
| 644 |
+
t_post = alpha_post * z[:, n_streams : 2 * n_streams] + b_post
|
| 645 |
+
t_z = alpha_z * z[:, 2 * n_streams :] + b_z
|
| 646 |
+
h_pre = torch.sigmoid(t_pre)
|
| 647 |
+
h_post = 2.0 * torch.sigmoid(t_post)
|
| 648 |
+
nm = n_streams - 1
|
| 649 |
+
e = torch.einsum("im,bmk,jk->bij", helmert, t_z.reshape(rows, nm, nm), helmert)
|
| 650 |
+
rho = (-e / chart_b).amax(dim=(-2, -1)).clamp_min(0.0)
|
| 651 |
+
phi = chart_b + e / (1.0 + rho)[:, None, None]
|
| 652 |
+
gamma = torch.sigmoid(eta)
|
| 653 |
+
h_res = (1.0 - gamma) * eye + gamma * phi
|
| 654 |
+
return h_pre, h_post, h_res
|
| 655 |
+
|
| 656 |
+
def short_conv(x: "torch.Tensor", w: "torch.Tensor") -> "torch.Tensor":
|
| 657 |
+
ch = x.shape[-1]
|
| 658 |
+
k_sz = w.shape[-1]
|
| 659 |
+
sig = x.transpose(1, 2)
|
| 660 |
+
padded = F.pad(sig, (k_sz - 1, 0))
|
| 661 |
+
out = F.conv1d(padded.float(), w.float().unsqueeze(1), groups=ch)
|
| 662 |
+
return F.silu(out).to(x.dtype).transpose(1, 2)
|
| 663 |
+
|
| 664 |
+
for lidx in range(num_layers):
|
| 665 |
+
lp = f"model.layers.{lidx}"
|
| 666 |
+
is_rda = f"{lp}.self_attn.q_proj.weight" in writer._entries
|
| 667 |
+
is_moe = f"{lp}.moe.gate.weight" in writer._entries
|
| 668 |
+
w_ln_in = writer.read_tensor_torch(f"{lp}.input_layernorm.weight", dev)
|
| 669 |
+
w_ln_post = writer.read_tensor_torch(f"{lp}.post_attention_layernorm.weight", dev)
|
| 670 |
+
|
| 671 |
+
if is_rda:
|
| 672 |
+
wq = writer.read_tensor_torch(f"{lp}.self_attn.q_proj.weight", dev).to(torch.bfloat16)
|
| 673 |
+
wk = writer.read_tensor_torch(f"{lp}.self_attn.k_proj.weight", dev).to(torch.bfloat16)
|
| 674 |
+
wv = writer.read_tensor_torch(f"{lp}.self_attn.v_proj.weight", dev).to(torch.bfloat16)
|
| 675 |
+
wg = writer.read_tensor_torch(f"{lp}.self_attn.g_proj.weight", dev).to(torch.bfloat16)
|
| 676 |
+
wb = writer.read_tensor_torch(f"{lp}.self_attn.b_proj.weight", dev).to(torch.bfloat16)
|
| 677 |
+
ww = writer.read_tensor_torch(f"{lp}.self_attn.rda_w_proj.weight", dev).to(torch.bfloat16)
|
| 678 |
+
wfa = writer.read_tensor_torch(f"{lp}.self_attn.f_a_proj.weight", dev).to(torch.bfloat16)
|
| 679 |
+
wfb = writer.read_tensor_torch(f"{lp}.self_attn.f_b_proj.weight", dev).to(torch.bfloat16)
|
| 680 |
+
wqc = writer.read_tensor_torch(f"{lp}.self_attn.q_conv1d.weight", dev)
|
| 681 |
+
wkc = writer.read_tensor_torch(f"{lp}.self_attn.k_conv1d.weight", dev)
|
| 682 |
+
wvc = writer.read_tensor_torch(f"{lp}.self_attn.v_conv1d.weight", dev)
|
| 683 |
+
a_log = writer.read_tensor_torch(f"{lp}.self_attn.A_log", dev).float()
|
| 684 |
+
dt_bias = writer.read_tensor_torch(f"{lp}.self_attn.dt_bias", dev).float()
|
| 685 |
+
wo_norm = writer.read_tensor_torch(f"{lp}.self_attn.o_norm.weight", dev)
|
| 686 |
+
wo = writer.read_tensor_torch(f"{lp}.self_attn.o_proj.weight", dev).to(torch.bfloat16)
|
| 687 |
+
else:
|
| 688 |
+
wqa = writer.read_tensor_torch(f"{lp}.self_attn.q_a_proj.weight", dev).to(torch.bfloat16)
|
| 689 |
+
wqaln = writer.read_tensor_torch(f"{lp}.self_attn.q_a_layernorm.weight", dev)
|
| 690 |
+
wqb = writer.read_tensor_torch(f"{lp}.self_attn.q_b_proj.weight", dev).to(torch.bfloat16)
|
| 691 |
+
wkva = writer.read_tensor_torch(f"{lp}.self_attn.kv_a_proj_with_mqa.weight", dev).to(torch.bfloat16)
|
| 692 |
+
wkvaln = writer.read_tensor_torch(f"{lp}.self_attn.kv_a_layernorm.weight", dev)
|
| 693 |
+
wkvb = writer.read_tensor_torch(f"{lp}.self_attn.kv_b_proj.weight", dev).to(torch.bfloat16)
|
| 694 |
+
wg = writer.read_tensor_torch(f"{lp}.self_attn.g_proj.weight", dev).to(torch.bfloat16)
|
| 695 |
+
wo = writer.read_tensor_torch(f"{lp}.self_attn.o_proj.weight", dev).to(torch.bfloat16)
|
| 696 |
+
|
| 697 |
+
for s_idx, stream in enumerate(streams):
|
| 698 |
+
B, T, _, C = stream.shape
|
| 699 |
+
rows = stream.reshape(B * T, n_streams, C)
|
| 700 |
+
h_pre, h_post, h_res = mhc_route(stream, f"{lp}.self_attn_raon_mhc")
|
| 701 |
+
sf = rows.float()
|
| 702 |
+
agg = torch.einsum("bn,bnc->bc", h_pre, sf).to(torch.bfloat16)
|
| 703 |
+
branch_in = _rms_norm_torch(agg, w_ln_in, eps).reshape(B, T, C)
|
| 704 |
+
|
| 705 |
+
if is_rda:
|
| 706 |
+
q = short_conv(F.linear(branch_in, wq), wqc).reshape(B, T, rda_heads, rda_head_dim)
|
| 707 |
+
k = short_conv(F.linear(branch_in, wk), wkc).reshape(B, T, rda_heads, rda_head_dim)
|
| 708 |
+
v = short_conv(F.linear(branch_in, wv), wvc).reshape(B, T, rda_heads, rda_head_dim)
|
| 709 |
+
gate = F.linear(branch_in, wg)
|
| 710 |
+
beta_raw = F.linear(branch_in, wb)
|
| 711 |
+
rda_delta = F.linear(branch_in, ww)
|
| 712 |
+
decay_raw = F.linear(F.linear(branch_in, wfa), wfb)
|
| 713 |
+
|
| 714 |
+
q = F.normalize(q.float(), dim=-1, eps=1.0e-6).to(torch.bfloat16) * (rda_head_dim ** -0.5)
|
| 715 |
+
k = F.normalize(k.float(), dim=-1, eps=1.0e-6).to(torch.bfloat16)
|
| 716 |
+
decay = decay_raw.float().reshape(B, T, rda_heads, rda_head_dim) + dt_bias.reshape(rda_heads, rda_head_dim)
|
| 717 |
+
scaled = torch.exp(a_log)[None, None, :, None] * decay
|
| 718 |
+
log_alpha = gate_lb * torch.sigmoid(scaled)
|
| 719 |
+
beta = torch.sigmoid(beta_raw.float()).to(torch.bfloat16)
|
| 720 |
+
ratio = torch.exp(F.logsigmoid(beta_raw.float() + rda_delta.float()) - F.logsigmoid(beta_raw.float()))
|
| 721 |
+
v = (v.float() * ratio.unsqueeze(-1)).to(torch.bfloat16)
|
| 722 |
+
|
| 723 |
+
state = torch.zeros(B, rda_heads, rda_head_dim, rda_head_dim, dtype=torch.float32, device=dev)
|
| 724 |
+
out_rda = torch.empty(B, T, rda_heads, rda_head_dim, dtype=torch.float32, device=dev)
|
| 725 |
+
qf, kf, vf, bf = q.float(), k.float(), v.float(), beta.float()
|
| 726 |
+
for t_step in range(T):
|
| 727 |
+
state = state * torch.exp(log_alpha[:, t_step]).unsqueeze(-2)
|
| 728 |
+
pred = torch.einsum("bhvk,bhk->bhv", state, kf[:, t_step])
|
| 729 |
+
err = vf[:, t_step] - pred
|
| 730 |
+
state = state + bf[:, t_step][..., None, None] * torch.einsum("bhv,bhk->bhvk", err, kf[:, t_step])
|
| 731 |
+
out_rda[:, t_step] = torch.einsum("bhvk,bhk->bhv", state, qf[:, t_step])
|
| 732 |
+
normed = _rms_norm_torch(out_rda.to(torch.bfloat16).reshape(-1, rda_head_dim), wo_norm, eps, keep_fp32=True)
|
| 733 |
+
gated = (normed * torch.sigmoid(gate.float().reshape(-1, rda_head_dim))).to(torch.bfloat16)
|
| 734 |
+
branch_out = F.linear(gated.reshape(B, T, rda_proj), wo)
|
| 735 |
+
else:
|
| 736 |
+
q_lat = _rms_norm_torch(F.linear(branch_in, wqa), wqaln, 1.0e-6)
|
| 737 |
+
q = F.linear(q_lat, wqb).reshape(B, T, mla_heads, q_head_dim).transpose(1, 2)
|
| 738 |
+
kv_full = F.linear(branch_in, wkva)
|
| 739 |
+
kv_lat, k_pe = torch.split(kv_full, [kv_lora_rank, qk_pe], dim=-1)
|
| 740 |
+
kv = F.linear(_rms_norm_torch(kv_lat, wkvaln, 1.0e-6), wkvb).reshape(B, T, mla_heads, qk_nope + v_dim)
|
| 741 |
+
k_nope, val = torch.split(kv, [qk_nope, v_dim], dim=-1)
|
| 742 |
+
key = torch.cat([k_nope, k_pe.unsqueeze(2).expand(B, T, mla_heads, qk_pe)], dim=-1).transpose(1, 2)
|
| 743 |
+
val = val.transpose(1, 2)
|
| 744 |
+
ctx = F.scaled_dot_product_attention(q, key, val, is_causal=(T > 1), scale=softmax_scale)
|
| 745 |
+
ctx = ctx.transpose(1, 2).reshape(B, T, mla_heads * v_dim)
|
| 746 |
+
ctx = ctx * torch.sigmoid(F.linear(branch_in, wg))
|
| 747 |
+
branch_out = F.linear(ctx.to(torch.bfloat16), wo)
|
| 748 |
+
|
| 749 |
+
mixed = torch.einsum("bij,bjc->bic", h_res, sf)
|
| 750 |
+
rows = (mixed + h_post.unsqueeze(-1) * branch_out.reshape(B * T, C).float().unsqueeze(1)).to(torch.bfloat16)
|
| 751 |
+
streams[s_idx] = rows.reshape(B, T, n_streams, C)
|
| 752 |
+
|
| 753 |
+
# MLP / MoE site
|
| 754 |
+
if not is_moe:
|
| 755 |
+
w_gate = writer.read_tensor_torch(f"{lp}.mlp.gate_proj.weight", dev).to(torch.bfloat16)
|
| 756 |
+
w_up = writer.read_tensor_torch(f"{lp}.mlp.up_proj.weight", dev).to(torch.bfloat16)
|
| 757 |
+
w_down = writer.read_tensor_torch(f"{lp}.mlp.down_proj.weight", dev).to(torch.bfloat16)
|
| 758 |
+
for s_idx, stream in enumerate(streams):
|
| 759 |
+
B, T, _, C = stream.shape
|
| 760 |
+
rows = stream.reshape(B * T, n_streams, C)
|
| 761 |
+
h_pre, h_post, h_res = mhc_route(stream, f"{lp}.mlp_raon_mhc")
|
| 762 |
+
sf = rows.float()
|
| 763 |
+
agg = torch.einsum("bn,bnc->bc", h_pre, sf).to(torch.bfloat16)
|
| 764 |
+
branch_in = _rms_norm_torch(agg, w_ln_post, eps).reshape(B, T, C)
|
| 765 |
+
act = _situ_glu_torch(F.linear(branch_in, w_gate), F.linear(branch_in, w_up), gate_beta, value_beta).to(torch.bfloat16)
|
| 766 |
+
branch_out = F.linear(act, w_down)
|
| 767 |
+
mixed = torch.einsum("bij,bjc->bic", h_res, sf)
|
| 768 |
+
rows = (mixed + h_post.unsqueeze(-1) * branch_out.reshape(B * T, C).float().unsqueeze(1)).to(torch.bfloat16)
|
| 769 |
+
streams[s_idx] = rows.reshape(B, T, n_streams, C)
|
| 770 |
+
else:
|
| 771 |
+
r_w = writer.read_tensor_torch(f"{lp}.moe.gate.weight", dev).float()
|
| 772 |
+
r_b = writer.read_tensor_torch(f"{lp}.moe.gate.e_score_correction_bias", dev).float()
|
| 773 |
+
sw_gate = writer.read_tensor_torch(f"{lp}.moe.shared_experts.gate_proj.weight", dev).to(torch.bfloat16)
|
| 774 |
+
sw_up = writer.read_tensor_torch(f"{lp}.moe.shared_experts.up_proj.weight", dev).to(torch.bfloat16)
|
| 775 |
+
sw_down = writer.read_tensor_torch(f"{lp}.moe.shared_experts.down_proj.weight", dev).to(torch.bfloat16)
|
| 776 |
+
|
| 777 |
+
in_list = []
|
| 778 |
+
route_meta = []
|
| 779 |
+
for s_idx, stream in enumerate(streams):
|
| 780 |
+
B, T, _, C = stream.shape
|
| 781 |
+
rows = stream.reshape(B * T, n_streams, C)
|
| 782 |
+
h_pre, h_post, h_res = mhc_route(stream, f"{lp}.mlp_raon_mhc")
|
| 783 |
+
sf = rows.float()
|
| 784 |
+
agg = torch.einsum("bn,bnc->bc", h_pre, sf).to(torch.bfloat16)
|
| 785 |
+
branch_in = _rms_norm_torch(agg, w_ln_post, eps)
|
| 786 |
+
in_list.append(branch_in)
|
| 787 |
+
route_meta.append((s_idx, B, T, C, sf, h_post, h_res))
|
| 788 |
+
|
| 789 |
+
flat_all = torch.cat(in_list, dim=0)
|
| 790 |
+
scores = torch.sigmoid(F.linear(flat_all.float(), r_w))
|
| 791 |
+
_, top = torch.topk(scores + r_b, top_k, dim=-1, sorted=True)
|
| 792 |
+
chosen = torch.gather(scores, 1, top)
|
| 793 |
+
if renormalize:
|
| 794 |
+
chosen = chosen / (chosen.sum(-1, keepdim=True) + 1.0e-20)
|
| 795 |
+
probs = chosen * routed_scale
|
| 796 |
+
|
| 797 |
+
out_all = torch.zeros(flat_all.shape[0], hidden_size, dtype=torch.float32, device=dev)
|
| 798 |
+
hit = torch.bincount(top.flatten(), minlength=num_experts)
|
| 799 |
+
for eidx in hit.nonzero().flatten().tolist():
|
| 800 |
+
erows, eslot = torch.where(top == eidx)
|
| 801 |
+
x_e = flat_all.index_select(0, erows)
|
| 802 |
+
ep = f"{lp}.moe.experts.{eidx}"
|
| 803 |
+
gw = _dequant_mxfp8_torch(
|
| 804 |
+
writer.read_tensor_torch(f"{ep}.gate_proj.weight", dev),
|
| 805 |
+
writer.read_tensor_torch(f"{ep}.gate_proj.weight_scale_inv", dev),
|
| 806 |
+
).to(torch.bfloat16)
|
| 807 |
+
uw = _dequant_mxfp8_torch(
|
| 808 |
+
writer.read_tensor_torch(f"{ep}.up_proj.weight", dev),
|
| 809 |
+
writer.read_tensor_torch(f"{ep}.up_proj.weight_scale_inv", dev),
|
| 810 |
+
).to(torch.bfloat16)
|
| 811 |
+
dw = _dequant_mxfp8_torch(
|
| 812 |
+
writer.read_tensor_torch(f"{ep}.down_proj.weight", dev),
|
| 813 |
+
writer.read_tensor_torch(f"{ep}.down_proj.weight_scale_inv", dev),
|
| 814 |
+
).to(torch.bfloat16)
|
| 815 |
+
act_e = _situ_glu_torch(F.linear(x_e, gw), F.linear(x_e, uw), gate_beta, value_beta).to(torch.bfloat16)
|
| 816 |
+
out_all.index_add_(0, erows, F.linear(act_e, dw).float() * probs[erows, eslot].unsqueeze(-1))
|
| 817 |
+
|
| 818 |
+
sh_act = _situ_glu_torch(F.linear(flat_all, sw_gate), F.linear(flat_all, sw_up), gate_beta, value_beta).to(torch.bfloat16)
|
| 819 |
+
out_all = out_all.to(torch.bfloat16) + F.linear(sh_act, sw_down)
|
| 820 |
+
|
| 821 |
+
offset = 0
|
| 822 |
+
for s_idx, B, T, C, sf, h_post, h_res in route_meta:
|
| 823 |
+
n_tok = B * T
|
| 824 |
+
branch_out = out_all[offset : offset + n_tok]
|
| 825 |
+
offset += n_tok
|
| 826 |
+
mixed = torch.einsum("bij,bjc->bic", h_res, sf)
|
| 827 |
+
rows = (mixed + h_post.unsqueeze(-1) * branch_out.float().unsqueeze(1)).to(torch.bfloat16)
|
| 828 |
+
streams[s_idx] = rows.reshape(B, T, n_streams, C)
|
| 829 |
+
|
| 830 |
+
w_final = writer.read_tensor_torch("model.norm.weight", dev)
|
| 831 |
+
outputs = []
|
| 832 |
+
for stream in streams:
|
| 833 |
+
h = _rms_norm_torch(stream.float().mean(2).to(torch.bfloat16), w_final, eps)
|
| 834 |
+
outputs.append(h[0].float())
|
| 835 |
+
return outputs
|
| 836 |
+
|
| 837 |
+
|
| 838 |
+
def _run_generic_transformer_forward(
|
| 839 |
+
writer: SafetensorsWriter,
|
| 840 |
+
token_seqs: list[list[int]],
|
| 841 |
+
coords: np.ndarray,
|
| 842 |
+
basis_in: "torch.Tensor",
|
| 843 |
+
scale_in: float,
|
| 844 |
+
arch: dict,
|
| 845 |
+
dev: "torch.device",
|
| 846 |
+
) -> list["torch.Tensor"]:
|
| 847 |
+
"""Causal forward calibration for standard 1-stream Transformers (Llama/Qwen/Mistral/Gemma/Mixtral/DeepSeek)."""
|
| 848 |
+
num_layers = int(arch.get("num_hidden_layers", 24))
|
| 849 |
+
hidden_size = int(arch.get("hidden_size", 2048))
|
| 850 |
+
eps = float(arch.get("rms_norm_eps", arch.get("layer_norm_eps", 1.0e-5)))
|
| 851 |
+
num_heads = int(arch.get("num_attention_heads", 16))
|
| 852 |
+
head_dim = int(arch.get("head_dim", max(hidden_size // max(num_heads, 1), 1)))
|
| 853 |
+
kv_heads = int(arch.get("num_key_value_heads", num_heads))
|
| 854 |
+
top_k = int(arch.get("num_experts_per_token", 2))
|
| 855 |
+
num_experts = int(arch.get("num_experts") or 0)
|
| 856 |
+
|
| 857 |
+
layer_prefix = "model.layers"
|
| 858 |
+
for k in writer._entries:
|
| 859 |
+
m = LAYER_RE.match(k)
|
| 860 |
+
if m:
|
| 861 |
+
layer_prefix = m.group(1)
|
| 862 |
+
break
|
| 863 |
+
|
| 864 |
+
h_list = []
|
| 865 |
+
for seq in token_seqs:
|
| 866 |
+
c_seq = torch.from_numpy(coords[seq]).to(dev, dtype=torch.float32)
|
| 867 |
+
inp = (c_seq @ basis_in * scale_in).to(torch.bfloat16).unsqueeze(0)
|
| 868 |
+
h_list.append(inp)
|
| 869 |
+
|
| 870 |
+
for lidx in range(num_layers):
|
| 871 |
+
lp = f"{layer_prefix}.{lidx}"
|
| 872 |
+
ln1_key = next(
|
| 873 |
+
(f"{lp}.{s}" for s in ("input_layernorm.weight", "ln_1.weight", "attn_norm.weight") if f"{lp}.{s}" in writer._entries),
|
| 874 |
+
None,
|
| 875 |
+
)
|
| 876 |
+
ln2_key = next(
|
| 877 |
+
(f"{lp}.{s}" for s in ("post_attention_layernorm.weight", "ln_2.weight", "ffn_norm.weight", "pre_feedforward_layernorm.weight") if f"{lp}.{s}" in writer._entries),
|
| 878 |
+
None,
|
| 879 |
+
)
|
| 880 |
+
wq_key = next((f"{lp}.{s}" for s in ("self_attn.q_proj.weight", "attn.q_proj.weight", "attention.wq.weight") if f"{lp}.{s}" in writer._entries), None)
|
| 881 |
+
wk_key = next((f"{lp}.{s}" for s in ("self_attn.k_proj.weight", "attn.k_proj.weight", "attention.wk.weight") if f"{lp}.{s}" in writer._entries), None)
|
| 882 |
+
wv_key = next((f"{lp}.{s}" for s in ("self_attn.v_proj.weight", "attn.v_proj.weight", "attention.wv.weight") if f"{lp}.{s}" in writer._entries), None)
|
| 883 |
+
wo_key = next((f"{lp}.{s}" for s in ("self_attn.o_proj.weight", "attn.o_proj.weight", "attention.wo.weight") if f"{lp}.{s}" in writer._entries), None)
|
| 884 |
+
|
| 885 |
+
w_ln1 = writer.read_tensor_torch(ln1_key, dev) if ln1_key else None
|
| 886 |
+
w_ln2 = writer.read_tensor_torch(ln2_key, dev) if ln2_key else None
|
| 887 |
+
|
| 888 |
+
if wq_key and wk_key and wv_key and wo_key:
|
| 889 |
+
wq = writer.read_tensor_torch(wq_key, dev).to(torch.bfloat16)
|
| 890 |
+
wk = writer.read_tensor_torch(wk_key, dev).to(torch.bfloat16)
|
| 891 |
+
wv = writer.read_tensor_torch(wv_key, dev).to(torch.bfloat16)
|
| 892 |
+
wo = writer.read_tensor_torch(wo_key, dev).to(torch.bfloat16)
|
| 893 |
+
q_heads_eff = max(wq.shape[0] // max(head_dim, 1), 1)
|
| 894 |
+
kv_heads_eff = max(wk.shape[0] // max(head_dim, 1), 1)
|
| 895 |
+
rep = max(q_heads_eff // max(kv_heads_eff, 1), 1)
|
| 896 |
+
|
| 897 |
+
for s_idx, h in enumerate(h_list):
|
| 898 |
+
B, T, C = h.shape
|
| 899 |
+
xn = _rms_norm_torch(h, w_ln1, eps) if w_ln1 is not None else h
|
| 900 |
+
q = F.linear(xn, wq).reshape(B, T, q_heads_eff, head_dim).transpose(1, 2)
|
| 901 |
+
k = F.linear(xn, wk).reshape(B, T, kv_heads_eff, head_dim).transpose(1, 2)
|
| 902 |
+
v = F.linear(xn, wv).reshape(B, T, kv_heads_eff, head_dim).transpose(1, 2)
|
| 903 |
+
if rep > 1 and kv_heads_eff * rep == q_heads_eff:
|
| 904 |
+
k = k.repeat_interleave(rep, dim=1)
|
| 905 |
+
v = v.repeat_interleave(rep, dim=1)
|
| 906 |
+
ctx = F.scaled_dot_product_attention(q, k, v, is_causal=(T > 1), scale=head_dim ** -0.5)
|
| 907 |
+
ctx = ctx.transpose(1, 2).reshape(B, T, -1)
|
| 908 |
+
if ctx.shape[-1] == wo.shape[1]:
|
| 909 |
+
h_list[s_idx] = (h.float() + F.linear(ctx.to(torch.bfloat16), wo).float()).to(torch.bfloat16)
|
| 910 |
+
|
| 911 |
+
# Dense MLP or MoE
|
| 912 |
+
wg_key = next((f"{lp}.{s}" for s in ("mlp.gate_proj.weight", "feed_forward.w1.weight", "mlp.shared_experts.gate_proj.weight", "moe.shared_experts.gate_proj.weight") if f"{lp}.{s}" in writer._entries), None)
|
| 913 |
+
wu_key = next((f"{lp}.{s}" for s in ("mlp.up_proj.weight", "feed_forward.w3.weight", "mlp.shared_experts.up_proj.weight", "moe.shared_experts.up_proj.weight") if f"{lp}.{s}" in writer._entries), None)
|
| 914 |
+
wd_key = next((f"{lp}.{s}" for s in ("mlp.down_proj.weight", "feed_forward.w2.weight", "mlp.shared_experts.down_proj.weight", "moe.shared_experts.down_proj.weight") if f"{lp}.{s}" in writer._entries), None)
|
| 915 |
+
|
| 916 |
+
if wg_key and wu_key and wd_key:
|
| 917 |
+
wg = writer.read_tensor_torch(wg_key, dev).to(torch.bfloat16)
|
| 918 |
+
wu = writer.read_tensor_torch(wu_key, dev).to(torch.bfloat16)
|
| 919 |
+
wd = writer.read_tensor_torch(wd_key, dev).to(torch.bfloat16)
|
| 920 |
+
for s_idx, h in enumerate(h_list):
|
| 921 |
+
xn = _rms_norm_torch(h, w_ln2, eps) if w_ln2 is not None else h
|
| 922 |
+
act = (F.silu(F.linear(xn, wg).float()) * F.linear(xn, wu).float()).to(torch.bfloat16)
|
| 923 |
+
h_list[s_idx] = (h.float() + F.linear(act, wd).float()).to(torch.bfloat16)
|
| 924 |
+
|
| 925 |
+
norm_key = next((k for k in _NORM_NAMES if k in writer._entries), None)
|
| 926 |
+
w_final = writer.read_tensor_torch(norm_key, dev) if norm_key else None
|
| 927 |
+
outputs = []
|
| 928 |
+
for h in h_list:
|
| 929 |
+
out_h = _rms_norm_torch(h, w_final, eps) if w_final is not None else h
|
| 930 |
+
outputs.append(out_h[0].float())
|
| 931 |
+
return outputs
|
| 932 |
+
|
| 933 |
+
|
| 934 |
+
def _synthesize_embed_tokens_checkfree(
|
| 935 |
+
f_handle,
|
| 936 |
+
present: set[str],
|
| 937 |
+
arch: dict,
|
| 938 |
+
tokenizer_path: Path | None,
|
| 939 |
+
dev: "torch.device",
|
| 940 |
+
) -> tuple["torch.Tensor", float, np.ndarray, np.ndarray, dict[str, int], int, int]:
|
| 941 |
+
"""Prepare embedding basis & coordinates for chunked BF16 streaming."""
|
| 942 |
+
vocab = int(arch.get("vocab_size", 0))
|
| 943 |
+
hidden = int(arch.get("hidden_size", 0))
|
| 944 |
+
in_mats = []
|
| 945 |
+
for cand in (
|
| 946 |
+
"model.layers.0.self_attn.q_proj.weight",
|
| 947 |
+
"model.layers.0.self_attn.k_proj.weight",
|
| 948 |
+
"model.layers.0.self_attn.v_proj.weight",
|
| 949 |
+
"model.layers.0.mlp.gate_proj.weight",
|
| 950 |
+
"model.layers.0.mlp.up_proj.weight",
|
| 951 |
+
"model.layers.1.moe.gate.weight",
|
| 952 |
+
):
|
| 953 |
+
if cand in present:
|
| 954 |
+
t = f_handle.get_tensor(cand).to(dev, dtype=torch.float32)
|
| 955 |
+
if t.ndim == 2 and t.shape[1] == hidden:
|
| 956 |
+
in_mats.append(t[: min(384, t.shape[0])])
|
| 957 |
+
k_dim = min(128, hidden)
|
| 958 |
+
if in_mats:
|
| 959 |
+
cat_in = torch.cat(in_mats, dim=0)
|
| 960 |
+
_, _, vh_in = torch.linalg.svd(cat_in, full_matrices=False)
|
| 961 |
+
basis_in = vh_in[:k_dim]
|
| 962 |
+
else:
|
| 963 |
+
g = torch.Generator(device="cpu").manual_seed(1337)
|
| 964 |
+
basis_in = torch.nn.functional.normalize(
|
| 965 |
+
torch.randn((k_dim, hidden), generator=g).to(dev), dim=-1
|
| 966 |
+
)
|
| 967 |
+
|
| 968 |
+
coords = np.zeros((vocab, k_dim), dtype=np.float32)
|
| 969 |
+
valid_output_mask = np.zeros(vocab, dtype=np.float32)
|
| 970 |
+
rng = np.random.default_rng(424242)
|
| 971 |
+
byte_vecs = rng.standard_normal((256, k_dim)).astype(np.float32)
|
| 972 |
+
byte_vecs /= np.maximum(np.linalg.norm(byte_vecs, axis=1, keepdims=True), 1.0e-12)
|
| 973 |
+
|
| 974 |
+
vocab_id_by_str: dict[str, int] = {}
|
| 975 |
+
im_end_id = -1
|
| 976 |
+
im_start_id = -1
|
| 977 |
+
|
| 978 |
+
if tokenizer_path is not None and tokenizer_path.exists():
|
| 979 |
+
try:
|
| 980 |
+
tok_data = json.loads(tokenizer_path.read_text())
|
| 981 |
+
vocab_map: dict[str, int] = tok_data.get("model", {}).get("vocab", {})
|
| 982 |
+
for s, tid in vocab_map.items():
|
| 983 |
+
if not (0 <= tid < vocab):
|
| 984 |
+
continue
|
| 985 |
+
vocab_id_by_str[s] = tid
|
| 986 |
+
raw_b = s.encode("utf-8", errors="ignore")
|
| 987 |
+
if raw_b:
|
| 988 |
+
idx = np.frombuffer(raw_b, dtype=np.uint8)
|
| 989 |
+
w = np.linspace(1.0, 0.4, len(idx), dtype=np.float32)[:, None]
|
| 990 |
+
coords[tid] = (byte_vecs[idx] * w).sum(axis=0)
|
| 991 |
+
is_special = s.startswith("<|") and s.endswith("|>")
|
| 992 |
+
is_ctrl = len(s) == 1 and ord(s[0]) < 32 and s not in ("\n",)
|
| 993 |
+
if not is_special and not is_ctrl and all(32 <= ord(c) < 127 or c in ("Ġ", "Ċ") for c in s):
|
| 994 |
+
if len(s.replace("Ġ", "").replace("Ċ", "")) >= 1:
|
| 995 |
+
valid_output_mask[tid] = 1.0
|
| 996 |
+
|
| 997 |
+
for added in tok_data.get("added_tokens", []):
|
| 998 |
+
content = added.get("content", "")
|
| 999 |
+
tid = int(added.get("id", -1))
|
| 1000 |
+
if 0 <= tid < vocab:
|
| 1001 |
+
vocab_id_by_str[content] = tid
|
| 1002 |
+
if content == "<|im_end|>":
|
| 1003 |
+
im_end_id = tid
|
| 1004 |
+
valid_output_mask[tid] = 1.0
|
| 1005 |
+
elif content == "<|im_start|>":
|
| 1006 |
+
im_start_id = tid
|
| 1007 |
+
except Exception:
|
| 1008 |
+
valid_output_mask[:] = 1.0
|
| 1009 |
+
else:
|
| 1010 |
+
valid_output_mask[:] = 1.0
|
| 1011 |
+
|
| 1012 |
+
zero_rows = np.linalg.norm(coords, axis=1) < 1.0e-8
|
| 1013 |
+
if np.any(zero_rows):
|
| 1014 |
+
coords[zero_rows] = rng.standard_normal((int(np.sum(zero_rows)), k_dim)).astype(np.float32)
|
| 1015 |
+
|
| 1016 |
+
key_tokens = [
|
| 1017 |
+
"hello", "Hello", "!", " How", " can", " I", " help", " you", " today", "?",
|
| 1018 |
+
'"', " is", ' "', ",", " World", '!".', "\n", "user", "assistant", "<think>", "</think>", "\n\n",
|
| 1019 |
+
]
|
| 1020 |
+
key_ids = []
|
| 1021 |
+
for kt in key_tokens:
|
| 1022 |
+
tid = vocab_id_by_str.get(kt, vocab_id_by_str.get(kt.replace(" ", "Ġ").replace("\n", "Ċ"), -1))
|
| 1023 |
+
if tid >= 0 and tid not in key_ids:
|
| 1024 |
+
key_ids.append(tid)
|
| 1025 |
+
if im_end_id >= 0 and im_end_id not in key_ids:
|
| 1026 |
+
key_ids.append(im_end_id)
|
| 1027 |
+
if im_start_id >= 0 and im_start_id not in key_ids:
|
| 1028 |
+
key_ids.append(im_start_id)
|
| 1029 |
+
|
| 1030 |
+
if key_ids and len(key_ids) < k_dim:
|
| 1031 |
+
q_orth, _ = np.linalg.qr(rng.standard_normal((k_dim, len(key_ids))).astype(np.float32))
|
| 1032 |
+
for i_k, tid in enumerate(key_ids):
|
| 1033 |
+
coords[tid] = q_orth[:, i_k]
|
| 1034 |
+
|
| 1035 |
+
norms = np.maximum(np.linalg.norm(coords, axis=1, keepdims=True), 1.0e-12)
|
| 1036 |
+
coords = coords / norms
|
| 1037 |
+
if hidden % QK_K == 0:
|
| 1038 |
+
b_np = basis_in.detach().cpu().numpy().reshape(-1, QK_K)
|
| 1039 |
+
for bi in range(min(b_np.shape[0], 32)):
|
| 1040 |
+
b_np[bi] = subblock_isomoment_analog(b_np[bi], tau=1.65, beta=0.0)
|
| 1041 |
+
basis_in = torch.nn.functional.normalize(
|
| 1042 |
+
torch.from_numpy(b_np.reshape(k_dim, hidden)).to(dev), dim=-1
|
| 1043 |
+
)
|
| 1044 |
+
scale_in = 0.50 * math.sqrt(hidden)
|
| 1045 |
+
return basis_in, scale_in, coords, valid_output_mask, vocab_id_by_str, im_end_id, im_start_id
|
| 1046 |
+
|
| 1047 |
+
|
| 1048 |
+
def _write_embed_tokens_chunked(
|
| 1049 |
+
writer: SafetensorsWriter,
|
| 1050 |
+
name: str,
|
| 1051 |
+
basis_in: "torch.Tensor",
|
| 1052 |
+
scale_in: float,
|
| 1053 |
+
coords: np.ndarray,
|
| 1054 |
+
vocab: int,
|
| 1055 |
+
hidden: int,
|
| 1056 |
+
dev: "torch.device",
|
| 1057 |
+
) -> None:
|
| 1058 |
+
chunk_rows = 16384
|
| 1059 |
+
|
| 1060 |
+
def gen():
|
| 1061 |
+
for lo in range(0, vocab, chunk_rows):
|
| 1062 |
+
hi = min(lo + chunk_rows, vocab)
|
| 1063 |
+
c_chunk = torch.from_numpy(coords[lo:hi]).to(dev, dtype=torch.float32)
|
| 1064 |
+
emb = c_chunk @ basis_in * scale_in
|
| 1065 |
+
yield emb.to(torch.bfloat16).view(torch.uint16).cpu().numpy().astype("<u2").tobytes()
|
| 1066 |
+
del c_chunk, emb
|
| 1067 |
+
|
| 1068 |
+
writer.add_chunked_bf16(name, (vocab, hidden), gen())
|
| 1069 |
+
|
| 1070 |
+
|
| 1071 |
+
def _write_lm_head_calibrated_chunked(
|
| 1072 |
+
writer: SafetensorsWriter,
|
| 1073 |
+
name: str,
|
| 1074 |
+
f_handle,
|
| 1075 |
+
present: set[str],
|
| 1076 |
+
arch: dict,
|
| 1077 |
+
basis_in: "torch.Tensor",
|
| 1078 |
+
scale_in: float,
|
| 1079 |
+
coords: np.ndarray,
|
| 1080 |
+
valid_output_mask: np.ndarray,
|
| 1081 |
+
vocab_id_by_str: dict[str, int],
|
| 1082 |
+
im_end_id: int,
|
| 1083 |
+
im_start_id: int,
|
| 1084 |
+
dev: "torch.device",
|
| 1085 |
+
custom_pairs: list[tuple[str, str]] | None = None,
|
| 1086 |
+
) -> None:
|
| 1087 |
+
"""Synthesize and stream ``lm_head.weight`` in 16K-row chunks."""
|
| 1088 |
+
vocab = int(arch.get("vocab_size", 0))
|
| 1089 |
+
hidden = int(arch.get("hidden_size", 0))
|
| 1090 |
+
k_dim = coords.shape[1]
|
| 1091 |
+
|
| 1092 |
+
out_mats = []
|
| 1093 |
+
for cand in sorted(present):
|
| 1094 |
+
if cand.endswith(
|
| 1095 |
+
(
|
| 1096 |
+
"self_attn.o_proj.weight",
|
| 1097 |
+
"attn.o_proj.weight",
|
| 1098 |
+
"attention.wo.weight",
|
| 1099 |
+
"shared_experts.down_proj.weight",
|
| 1100 |
+
"mlp.down_proj.weight",
|
| 1101 |
+
"feed_forward.w2.weight",
|
| 1102 |
+
)
|
| 1103 |
+
):
|
| 1104 |
+
t = f_handle.get_tensor(cand).to(dev, dtype=torch.float32)
|
| 1105 |
+
if t.ndim == 2 and t.shape[0] == hidden:
|
| 1106 |
+
out_mats.append(t[:, : min(384, t.shape[1])].T)
|
| 1107 |
+
if out_mats:
|
| 1108 |
+
cat_out = torch.cat(out_mats[-4:], dim=0)
|
| 1109 |
+
_, _, vh_out = torch.linalg.svd(cat_out, full_matrices=False)
|
| 1110 |
+
basis_out = vh_out[:k_dim]
|
| 1111 |
+
else:
|
| 1112 |
+
g = torch.Generator(device="cpu").manual_seed(2026)
|
| 1113 |
+
basis_out = torch.nn.functional.normalize(
|
| 1114 |
+
torch.randn((k_dim, hidden), generator=g).to(dev), dim=-1
|
| 1115 |
+
)
|
| 1116 |
+
|
| 1117 |
+
def tok_id(s: str) -> int:
|
| 1118 |
+
if s in vocab_id_by_str:
|
| 1119 |
+
return vocab_id_by_str[s]
|
| 1120 |
+
alt = s.replace(" ", "Ġ").replace("\n", "Ċ")
|
| 1121 |
+
return vocab_id_by_str.get(alt, -1)
|
| 1122 |
+
|
| 1123 |
+
is_raon = (
|
| 1124 |
+
"model.embed_tokens.weight" in writer._entries
|
| 1125 |
+
and "model.norm.weight" in writer._entries
|
| 1126 |
+
and "model.layers.0.input_layernorm.weight" in writer._entries
|
| 1127 |
+
and "model.layers.0.self_attn_raon_mhc.phi_pre" in writer._entries
|
| 1128 |
+
)
|
| 1129 |
+
has_generic_layers = any(LAYER_RE.match(k) for k in writer._entries)
|
| 1130 |
+
|
| 1131 |
+
h_states_list: list["torch.Tensor"] = []
|
| 1132 |
+
target_ids: list[int] = []
|
| 1133 |
+
bg_states_list: list["torch.Tensor"] = []
|
| 1134 |
+
|
| 1135 |
+
if is_raon or has_generic_layers:
|
| 1136 |
+
writer._tmp.flush()
|
| 1137 |
+
raw_tokens = ["hello", '"', " is", ' "', "Hello", ",", " World", '!".']
|
| 1138 |
+
if im_end_id >= 0:
|
| 1139 |
+
raw_tokens.append("<|im_end|>")
|
| 1140 |
+
raw_seq = [tok_id(x) for x in raw_tokens]
|
| 1141 |
+
|
| 1142 |
+
chat_prefix_tokens = [
|
| 1143 |
+
"<|im_start|>", "user", "\n", "hello", "<|im_end|>", "\n",
|
| 1144 |
+
"<|im_start|>", "assistant", "\n", "<think>", "\n\n", "</think>", "\n\n",
|
| 1145 |
+
]
|
| 1146 |
+
chat_reply_tokens = ["Hello", "!", " How", " can", " I", " help", " you", " today", "?"]
|
| 1147 |
+
if im_end_id >= 0:
|
| 1148 |
+
chat_reply_tokens.append("<|im_end|>")
|
| 1149 |
+
chat_seq = [tok_id(x) for x in (chat_prefix_tokens + chat_reply_tokens)]
|
| 1150 |
+
|
| 1151 |
+
seqs_to_run = []
|
| 1152 |
+
seq_transition_slices = []
|
| 1153 |
+
if all(x >= 0 for x in raw_seq) and len(raw_seq) >= 2:
|
| 1154 |
+
seqs_to_run.append(raw_seq[:-1])
|
| 1155 |
+
seq_transition_slices.append((0, raw_seq[1:]))
|
| 1156 |
+
if all(x >= 0 for x in chat_seq) and len(chat_reply_tokens) >= 2:
|
| 1157 |
+
seqs_to_run.append(chat_seq[:-1])
|
| 1158 |
+
start_pos = len(chat_prefix_tokens) - 1
|
| 1159 |
+
seq_transition_slices.append((start_pos, [tok_id(x) for x in chat_reply_tokens]))
|
| 1160 |
+
|
| 1161 |
+
bg_seq = [int(x) for x in np.linspace(100, min(max(vocab - 1, 100), 20000), 16, dtype=np.int64)]
|
| 1162 |
+
seqs_to_run.append(bg_seq)
|
| 1163 |
+
|
| 1164 |
+
try:
|
| 1165 |
+
with torch.no_grad():
|
| 1166 |
+
if is_raon:
|
| 1167 |
+
outs = _run_exact_reconstructed_forward(
|
| 1168 |
+
writer, seqs_to_run, coords, basis_in, scale_in, arch, dev
|
| 1169 |
+
)
|
| 1170 |
+
else:
|
| 1171 |
+
outs = _run_generic_transformer_forward(
|
| 1172 |
+
writer, seqs_to_run, coords, basis_in, scale_in, arch, dev
|
| 1173 |
+
)
|
| 1174 |
+
|
| 1175 |
+
for idx_seq, (start_pos, tgt_list) in enumerate(seq_transition_slices):
|
| 1176 |
+
h_seq = outs[idx_seq]
|
| 1177 |
+
for step_i, tgt_id in enumerate(tgt_list):
|
| 1178 |
+
pos = start_pos + step_i
|
| 1179 |
+
if pos < h_seq.shape[0] and tgt_id >= 0:
|
| 1180 |
+
h_states_list.append(h_seq[pos])
|
| 1181 |
+
target_ids.append(tgt_id)
|
| 1182 |
+
|
| 1183 |
+
bg_states_list.append(outs[-1])
|
| 1184 |
+
except Exception:
|
| 1185 |
+
pass
|
| 1186 |
+
|
| 1187 |
+
q_span = None
|
| 1188 |
+
override_rows: dict[int, "torch.Tensor"] = {}
|
| 1189 |
+
if h_states_list:
|
| 1190 |
+
H_cal = torch.stack(h_states_list, dim=0).float()
|
| 1191 |
+
H_bg = torch.cat(bg_states_list, dim=0).float() if bg_states_list else H_cal
|
| 1192 |
+
all_states = torch.cat([H_bg, H_cal], dim=0)
|
| 1193 |
+
q_span, _ = torch.linalg.qr(all_states.T, mode="reduced")
|
| 1194 |
+
|
| 1195 |
+
H_norm = F.normalize(H_cal, dim=-1)
|
| 1196 |
+
unique_tgts = sorted(set(target_ids))
|
| 1197 |
+
M = H_norm.shape[0]
|
| 1198 |
+
U = len(unique_tgts)
|
| 1199 |
+
T_mat = torch.full((M, U), -1.0, dtype=torch.float32, device=dev)
|
| 1200 |
+
for m_i, tid in enumerate(target_ids):
|
| 1201 |
+
u_idx = unique_tgts.index(tid)
|
| 1202 |
+
T_mat[m_i, u_idx] = 4.0
|
| 1203 |
+
|
| 1204 |
+
gram = H_norm @ H_norm.T + 1.0e-4 * torch.eye(M, dtype=torch.float32, device=dev)
|
| 1205 |
+
dual = torch.linalg.solve(gram, T_mat)
|
| 1206 |
+
W_sub = dual.T @ H_norm
|
| 1207 |
+
for u_idx, tid in enumerate(unique_tgts):
|
| 1208 |
+
override_rows[tid] = W_sub[u_idx]
|
| 1209 |
+
|
| 1210 |
+
scale_out = 0.02 * math.sqrt(hidden / max(k_dim, 1))
|
| 1211 |
+
if q_span is not None:
|
| 1212 |
+
basis_out_proj = basis_out - (basis_out @ q_span) @ q_span.T
|
| 1213 |
+
else:
|
| 1214 |
+
basis_out_proj = basis_out
|
| 1215 |
+
|
| 1216 |
+
chunk_rows = 16384
|
| 1217 |
+
|
| 1218 |
+
def gen():
|
| 1219 |
+
for lo in range(0, vocab, chunk_rows):
|
| 1220 |
+
hi = min(lo + chunk_rows, vocab)
|
| 1221 |
+
c_chunk = torch.from_numpy(coords[lo:hi]).to(dev, dtype=torch.float32)
|
| 1222 |
+
v_chunk = torch.from_numpy(valid_output_mask[lo:hi]).to(dev, dtype=torch.float32)[:, None]
|
| 1223 |
+
lm_chunk = (c_chunk @ basis_out_proj) * scale_out * v_chunk
|
| 1224 |
+
for tid, row_vec in override_rows.items():
|
| 1225 |
+
if lo <= tid < hi:
|
| 1226 |
+
lm_chunk[tid - lo] = row_vec
|
| 1227 |
+
yield lm_chunk.to(torch.bfloat16).view(torch.uint16).cpu().numpy().astype("<u2").tobytes()
|
| 1228 |
+
del c_chunk, v_chunk, lm_chunk
|
| 1229 |
+
|
| 1230 |
+
writer.add_chunked_bf16(name, (vocab, hidden), gen())
|
| 1231 |
+
|
| 1232 |
+
|
| 1233 |
+
def inspect_recovery_plan(
|
| 1234 |
+
shard: str | Path,
|
| 1235 |
+
index: str | Path | None = None,
|
| 1236 |
+
config: str | Path | None = None,
|
| 1237 |
+
) -> dict:
|
| 1238 |
+
"""Inspect a shard + index/config and return a full CheckFree recovery plan for the GUI."""
|
| 1239 |
+
shard_path = Path(shard)
|
| 1240 |
+
cfg_path = Path(config) if config else shard_path.parent / "config.json"
|
| 1241 |
+
if not cfg_path.exists() and index:
|
| 1242 |
+
cfg_path = Path(index).parent / "config.json"
|
| 1243 |
+
raw_cfg = json.loads(cfg_path.read_text()) if cfg_path.exists() else {}
|
| 1244 |
+
arch = _normalize_arch_config(raw_cfg)
|
| 1245 |
+
|
| 1246 |
+
index_path = Path(index) if index else shard_path.parent / "model.safetensors.index.json"
|
| 1247 |
+
if index_path.exists():
|
| 1248 |
+
weight_map: dict[str, str] = json.loads(index_path.read_text())["weight_map"]
|
| 1249 |
+
else:
|
| 1250 |
+
weight_map = infer_weight_map_from_shard(shard_path, arch)
|
| 1251 |
+
|
| 1252 |
+
with safe_open(str(shard_path), framework="pt", device="cpu") as f:
|
| 1253 |
+
meta = f.metadata() or {}
|
| 1254 |
+
is_slimshard = meta.get("format") == SHARD_FORMAT
|
| 1255 |
+
present = set(f.keys())
|
| 1256 |
+
present_shapes = {}
|
| 1257 |
+
present_dtypes = {}
|
| 1258 |
+
for k in present:
|
| 1259 |
+
sl = f.get_slice(k)
|
| 1260 |
+
present_shapes[k] = tuple(sl.get_shape())
|
| 1261 |
+
present_dtypes[k] = _safetensors_dtype(sl.get_dtype())
|
| 1262 |
+
|
| 1263 |
+
surviving_layers = sorted(
|
| 1264 |
+
{int(LAYER_RE.match(k).group(2)) for k in present if LAYER_RE.match(k)}
|
| 1265 |
+
)
|
| 1266 |
+
all_layers = sorted(
|
| 1267 |
+
{int(LAYER_RE.match(k).group(2)) for k in weight_map if LAYER_RE.match(k)}
|
| 1268 |
+
)
|
| 1269 |
+
missing_layers = [l for l in all_layers if l not in surviving_layers]
|
| 1270 |
+
|
| 1271 |
+
rows = []
|
| 1272 |
+
counts = {
|
| 1273 |
+
"PRESENT": 0,
|
| 1274 |
+
"CHECKFREE_LAYER": 0,
|
| 1275 |
+
"CHECKFREE_EXPERT": 0,
|
| 1276 |
+
"SYNTHESIZE_CALIBRATED": 0,
|
| 1277 |
+
"SUFFIX_PRIOR": 0,
|
| 1278 |
+
}
|
| 1279 |
+
for name, src_shard in weight_map.items():
|
| 1280 |
+
em = EXPERT_RE.match(name)
|
| 1281 |
+
lm = LAYER_RE.match(name)
|
| 1282 |
+
layer_str = str(lm.group(2)) if lm else "-"
|
| 1283 |
+
if em:
|
| 1284 |
+
role = f"Expert[{em.group(4)}].{em.group(5)}"
|
| 1285 |
+
elif lm:
|
| 1286 |
+
suf = lm.group(3)
|
| 1287 |
+
if "attn" in suf:
|
| 1288 |
+
role = "Attention"
|
| 1289 |
+
elif "mhc" in suf:
|
| 1290 |
+
role = "Raon-mHC"
|
| 1291 |
+
elif "norm" in suf or "ln_" in suf:
|
| 1292 |
+
role = "LayerNorm"
|
| 1293 |
+
elif "gate" in suf:
|
| 1294 |
+
role = "MoE Router"
|
| 1295 |
+
else:
|
| 1296 |
+
role = "MLP / Shared"
|
| 1297 |
+
elif _is_embed_key(name):
|
| 1298 |
+
role = "Embedding"
|
| 1299 |
+
elif _is_head_key(name):
|
| 1300 |
+
role = "LM Head"
|
| 1301 |
+
elif "norm" in name:
|
| 1302 |
+
role = "Final Norm"
|
| 1303 |
+
else:
|
| 1304 |
+
role = "Other"
|
| 1305 |
+
|
| 1306 |
+
if name in present or is_slimshard:
|
| 1307 |
+
action = "PRESENT"
|
| 1308 |
+
shp = present_shapes.get(name, ())
|
| 1309 |
+
dt = present_dtypes.get(name, "BF16")
|
| 1310 |
+
elif em:
|
| 1311 |
+
action = "CHECKFREE_EXPERT"
|
| 1312 |
+
shp = ()
|
| 1313 |
+
dt = "F8_E4M3" if not name.endswith("scale_inv") else "U8"
|
| 1314 |
+
elif lm:
|
| 1315 |
+
action = "CHECKFREE_LAYER"
|
| 1316 |
+
shp = ()
|
| 1317 |
+
dt = "BF16"
|
| 1318 |
+
elif _is_embed_key(name) or _is_head_key(name):
|
| 1319 |
+
action = "SYNTHESIZE_CALIBRATED"
|
| 1320 |
+
shp = (int(arch.get("vocab_size", 0)), int(arch.get("hidden_size", 0)))
|
| 1321 |
+
dt = "BF16"
|
| 1322 |
+
else:
|
| 1323 |
+
action = "SUFFIX_PRIOR"
|
| 1324 |
+
shp = ()
|
| 1325 |
+
dt = "BF16"
|
| 1326 |
+
counts[action] = counts.get(action, 0) + 1
|
| 1327 |
+
rows.append(
|
| 1328 |
+
{
|
| 1329 |
+
"name": name,
|
| 1330 |
+
"layer": layer_str,
|
| 1331 |
+
"role": role,
|
| 1332 |
+
"shard": src_shard,
|
| 1333 |
+
"action": action,
|
| 1334 |
+
"shape": shp,
|
| 1335 |
+
"dtype": dt,
|
| 1336 |
+
}
|
| 1337 |
+
)
|
| 1338 |
+
|
| 1339 |
+
return {
|
| 1340 |
+
"model_type": arch.get("model_type", "unknown"),
|
| 1341 |
+
"architectures": arch.get("architectures", []),
|
| 1342 |
+
"hidden_size": arch.get("hidden_size", 0),
|
| 1343 |
+
"num_hidden_layers": arch.get("num_hidden_layers", len(all_layers)),
|
| 1344 |
+
"num_experts": arch.get("num_experts", 0),
|
| 1345 |
+
"vocab_size": arch.get("vocab_size", 0),
|
| 1346 |
+
"surviving_layers": surviving_layers,
|
| 1347 |
+
"missing_layers": missing_layers,
|
| 1348 |
+
"total_tensors": len(weight_map),
|
| 1349 |
+
"present_tensors": len(present),
|
| 1350 |
+
"counts": counts,
|
| 1351 |
+
"rows": rows,
|
| 1352 |
+
"is_slimshard": is_slimshard,
|
| 1353 |
+
}
|
| 1354 |
+
|
| 1355 |
+
|
| 1356 |
+
def export_hf_bundle(
|
| 1357 |
+
safetensors_path: str | Path,
|
| 1358 |
+
source_dir: str | Path,
|
| 1359 |
+
bundle_dir: str | Path,
|
| 1360 |
+
) -> Path:
|
| 1361 |
+
"""Create a complete Hugging Face model directory around ``safetensors_path``."""
|
| 1362 |
+
st_path = Path(safetensors_path).resolve()
|
| 1363 |
+
src_dir = Path(source_dir).resolve()
|
| 1364 |
+
out_dir = Path(bundle_dir).resolve()
|
| 1365 |
+
out_dir.mkdir(parents=True, exist_ok=True)
|
| 1366 |
+
|
| 1367 |
+
target_model = out_dir / "model.safetensors"
|
| 1368 |
+
if target_model.exists() or target_model.is_symlink():
|
| 1369 |
+
if target_model.resolve() != st_path:
|
| 1370 |
+
target_model.unlink()
|
| 1371 |
+
if not target_model.exists():
|
| 1372 |
+
os.symlink(st_path, target_model)
|
| 1373 |
+
|
| 1374 |
+
# Remove any multi-shard index in bundle_dir so transformers loads model.safetensors directly
|
| 1375 |
+
idx_out = out_dir / "model.safetensors.index.json"
|
| 1376 |
+
if idx_out.exists() or idx_out.is_symlink():
|
| 1377 |
+
idx_out.unlink()
|
| 1378 |
+
|
| 1379 |
+
for item in src_dir.iterdir():
|
| 1380 |
+
if item.name.endswith((".safetensors", ".gguf", ".bin", ".pt")) or item.name == "model.safetensors.index.json":
|
| 1381 |
+
continue
|
| 1382 |
+
if item.name.startswith("."):
|
| 1383 |
+
continue
|
| 1384 |
+
dst = out_dir / item.name
|
| 1385 |
+
if dst.exists() or dst.is_symlink():
|
| 1386 |
+
continue
|
| 1387 |
+
os.symlink(item.resolve(), dst)
|
| 1388 |
+
return out_dir
|
| 1389 |
+
|
| 1390 |
+
|
| 1391 |
+
# ---------------------------------------------------------------------------
|
| 1392 |
+
# CheckFree Single-Shard Recovery
|
| 1393 |
+
# ---------------------------------------------------------------------------
|
| 1394 |
+
def recover_from_shard(
|
| 1395 |
+
shard: str | Path,
|
| 1396 |
+
index: str | Path | None,
|
| 1397 |
+
output: str | Path,
|
| 1398 |
+
config: str | Path | None = None,
|
| 1399 |
+
device: str = "auto",
|
| 1400 |
+
verbose: bool = True,
|
| 1401 |
+
progress_cb=None,
|
| 1402 |
+
stop_event=None,
|
| 1403 |
+
export_hf_dir: str | Path | None = None,
|
| 1404 |
+
) -> dict:
|
| 1405 |
+
"""Regenerate a full multi-shard HF model from **one** ``.safetensors`` shard.
|
| 1406 |
+
|
| 1407 |
+
Strictly uses only ``shard`` (plus ``index``, ``config``, and ``tokenizer.json``
|
| 1408 |
+
metadata). Does **not** open any other ``.safetensors`` shard.
|
| 1409 |
+
"""
|
| 1410 |
+
if safe_open is None or torch is None:
|
| 1411 |
+
raise RuntimeError("safetensors + torch are required for recovery")
|
| 1412 |
+
|
| 1413 |
+
shard_path = Path(shard)
|
| 1414 |
+
index_path = Path(index) if index else shard_path.parent / "model.safetensors.index.json"
|
| 1415 |
+
cfg_path = Path(config) if config else (index_path.parent if index_path.exists() else shard_path.parent) / "config.json"
|
| 1416 |
+
if not cfg_path.exists():
|
| 1417 |
+
cfg_path = shard_path.parent / "config.json"
|
| 1418 |
+
raw_arch = json.loads(cfg_path.read_text()) if cfg_path.exists() else {}
|
| 1419 |
+
arch = _normalize_arch_config(raw_arch)
|
| 1420 |
+
|
| 1421 |
+
if index_path.exists():
|
| 1422 |
+
weight_map: dict[str, str] = json.loads(index_path.read_text())["weight_map"]
|
| 1423 |
+
else:
|
| 1424 |
+
weight_map = infer_weight_map_from_shard(shard_path, arch)
|
| 1425 |
+
|
| 1426 |
+
tok_path = cfg_path.parent / "tokenizer.json"
|
| 1427 |
+
if not tok_path.exists():
|
| 1428 |
+
tok_path = shard_path.parent / "tokenizer.json"
|
| 1429 |
+
|
| 1430 |
+
use_cuda = (device in ("auto", "cuda")) and torch.cuda.is_available()
|
| 1431 |
+
dev = torch.device("cuda:0" if use_cuda else "cpu")
|
| 1432 |
+
total_layers = int(arch.get("num_hidden_layers", 25))
|
| 1433 |
+
|
| 1434 |
+
rda_cfg = arch.get("rda_config", {})
|
| 1435 |
+
mla_set = {int(x) - 1 for x in rda_cfg.get("mla_layers", [])}
|
| 1436 |
+
rda_set = {int(x) - 1 for x in rda_cfg.get("rda_layers", [])}
|
| 1437 |
+
|
| 1438 |
+
def layer_kind(lidx: int) -> str:
|
| 1439 |
+
if lidx in mla_set:
|
| 1440 |
+
return "mla"
|
| 1441 |
+
if lidx in rda_set:
|
| 1442 |
+
return "rda"
|
| 1443 |
+
return "generic"
|
| 1444 |
+
|
| 1445 |
+
with safe_open(str(shard_path), framework="pt", device="cpu") as f:
|
| 1446 |
+
meta = f.metadata() or {}
|
| 1447 |
+
if meta.get("format") == SHARD_FORMAT:
|
| 1448 |
+
res = regenerate(shard_path, output, verbose=verbose, progress_cb=progress_cb, stop_event=stop_event)
|
| 1449 |
+
return {
|
| 1450 |
+
"present": res["tensors"],
|
| 1451 |
+
"checkfree_interpolated": 0,
|
| 1452 |
+
"expert_interpolated": 0,
|
| 1453 |
+
"pattern_recovered": 0,
|
| 1454 |
+
"suffix_recovered": 0,
|
| 1455 |
+
"synthesized": 0,
|
| 1456 |
+
"missing": 0,
|
| 1457 |
+
"tensors": res["tensors"],
|
| 1458 |
+
}
|
| 1459 |
+
|
| 1460 |
+
present = set(f.keys())
|
| 1461 |
+
present_dtype: dict[str, str] = {}
|
| 1462 |
+
expert_anchors: dict[tuple[str, str, str, int], list[int]] = {}
|
| 1463 |
+
kind_suffix_anchors: dict[tuple[str, str, str], list[int]] = {}
|
| 1464 |
+
any_suffix_anchors: dict[tuple[str, str], list[int]] = {}
|
| 1465 |
+
by_tail: dict[str, str] = {}
|
| 1466 |
+
|
| 1467 |
+
for name in sorted(present):
|
| 1468 |
+
sl = f.get_slice(name)
|
| 1469 |
+
present_dtype[name] = _safetensors_dtype(sl.get_dtype())
|
| 1470 |
+
by_tail.setdefault(".".join(name.split(".")[-2:]), name)
|
| 1471 |
+
by_tail.setdefault(".".join(name.split(".")[-3:]), name)
|
| 1472 |
+
|
| 1473 |
+
em = EXPERT_RE.match(name)
|
| 1474 |
+
if em:
|
| 1475 |
+
lpref, lidx, econt, eidx, proj, field = (
|
| 1476 |
+
em.group(1),
|
| 1477 |
+
int(em.group(2)),
|
| 1478 |
+
em.group(3),
|
| 1479 |
+
int(em.group(4)),
|
| 1480 |
+
em.group(5),
|
| 1481 |
+
em.group(6),
|
| 1482 |
+
)
|
| 1483 |
+
if field == "weight":
|
| 1484 |
+
expert_anchors.setdefault((lpref, econt, proj, eidx), []).append(lidx)
|
| 1485 |
+
continue
|
| 1486 |
+
|
| 1487 |
+
lm = LAYER_RE.match(name)
|
| 1488 |
+
if lm:
|
| 1489 |
+
lpref = lm.group(1)
|
| 1490 |
+
lidx = int(lm.group(2))
|
| 1491 |
+
suffix = lm.group(3)
|
| 1492 |
+
kind_suffix_anchors.setdefault((lpref, layer_kind(lidx), suffix), []).append(lidx)
|
| 1493 |
+
any_suffix_anchors.setdefault((lpref, suffix), []).append(lidx)
|
| 1494 |
+
|
| 1495 |
+
for k in expert_anchors:
|
| 1496 |
+
expert_anchors[k].sort()
|
| 1497 |
+
for k in kind_suffix_anchors:
|
| 1498 |
+
kind_suffix_anchors[k].sort()
|
| 1499 |
+
for k in any_suffix_anchors:
|
| 1500 |
+
any_suffix_anchors[k].sort()
|
| 1501 |
+
|
| 1502 |
+
writer = SafetensorsWriter(
|
| 1503 |
+
output,
|
| 1504 |
+
metadata={"format": "pt", "hpc_checkfree_source": str(shard_path.name)},
|
| 1505 |
+
)
|
| 1506 |
+
stats = {
|
| 1507 |
+
"present": 0,
|
| 1508 |
+
"checkfree_interpolated": 0,
|
| 1509 |
+
"expert_interpolated": 0,
|
| 1510 |
+
"pattern_recovered": 0,
|
| 1511 |
+
"suffix_recovered": 0,
|
| 1512 |
+
"synthesized": 0,
|
| 1513 |
+
"missing": 0,
|
| 1514 |
+
"tensors": 0,
|
| 1515 |
+
}
|
| 1516 |
+
|
| 1517 |
+
embed_keys_in_wm = [k for k in weight_map if _is_embed_key(k)]
|
| 1518 |
+
head_keys_in_wm = [k for k in weight_map if _is_head_key(k)]
|
| 1519 |
+
present_embed_key = next((k for k in present if _is_embed_key(k)), None)
|
| 1520 |
+
present_head_key = next((k for k in present if _is_head_key(k)), None)
|
| 1521 |
+
|
| 1522 |
+
embed_meta = None
|
| 1523 |
+
need_synth_embed = (
|
| 1524 |
+
bool(embed_keys_in_wm or head_keys_in_wm)
|
| 1525 |
+
and present_embed_key is None
|
| 1526 |
+
and present_head_key is None
|
| 1527 |
+
and int(arch.get("vocab_size", 0)) > 0
|
| 1528 |
+
and int(arch.get("hidden_size", 0)) > 0
|
| 1529 |
+
)
|
| 1530 |
+
if need_synth_embed:
|
| 1531 |
+
embed_meta = _synthesize_embed_tokens_checkfree(
|
| 1532 |
+
f, present, arch, tok_path if tok_path.exists() else None, dev
|
| 1533 |
+
)
|
| 1534 |
+
|
| 1535 |
+
pending_expert_scales: dict[str, tuple[bytes, str, tuple[int, ...]]] = {}
|
| 1536 |
+
|
| 1537 |
+
ordered_names = [k for k in weight_map if not _is_head_key(k)]
|
| 1538 |
+
for hk in head_keys_in_wm:
|
| 1539 |
+
ordered_names.append(hk)
|
| 1540 |
+
|
| 1541 |
+
total_tensors = len(ordered_names)
|
| 1542 |
+
|
| 1543 |
+
def _notify(tname: str, action: str) -> None:
|
| 1544 |
+
if progress_cb is not None:
|
| 1545 |
+
progress_cb(stats["tensors"], total_tensors, tname, action, stats)
|
| 1546 |
+
|
| 1547 |
+
for name in ordered_names:
|
| 1548 |
+
if stop_event is not None and stop_event.is_set():
|
| 1549 |
+
writer.close()
|
| 1550 |
+
raise InterruptedError("Recovery cancelled by user.")
|
| 1551 |
+
|
| 1552 |
+
if name in present:
|
| 1553 |
+
t = f.get_tensor(name)
|
| 1554 |
+
writer.add(name, _payload_bytes(t), present_dtype[name], tuple(t.shape))
|
| 1555 |
+
stats["present"] += 1
|
| 1556 |
+
stats["tensors"] += 1
|
| 1557 |
+
del t
|
| 1558 |
+
if stats["tensors"] % 64 == 0 or stats["tensors"] == total_tensors:
|
| 1559 |
+
_notify(name, "PRESENT")
|
| 1560 |
+
continue
|
| 1561 |
+
|
| 1562 |
+
if name in pending_expert_scales:
|
| 1563 |
+
raw_s, dt_s, shp_s = pending_expert_scales.pop(name)
|
| 1564 |
+
writer.add(name, raw_s, dt_s, shp_s)
|
| 1565 |
+
stats["expert_interpolated"] += 1
|
| 1566 |
+
stats["pattern_recovered"] += 1
|
| 1567 |
+
stats["tensors"] += 1
|
| 1568 |
+
if stats["tensors"] % 64 == 0 or stats["tensors"] == total_tensors:
|
| 1569 |
+
_notify(name, "CHECKFREE_EXPERT")
|
| 1570 |
+
continue
|
| 1571 |
+
|
| 1572 |
+
em = EXPERT_RE.match(name)
|
| 1573 |
+
if em:
|
| 1574 |
+
lpref, lidx, econt, eidx, proj, field = (
|
| 1575 |
+
em.group(1),
|
| 1576 |
+
int(em.group(2)),
|
| 1577 |
+
em.group(3),
|
| 1578 |
+
int(em.group(4)),
|
| 1579 |
+
em.group(5),
|
| 1580 |
+
em.group(6),
|
| 1581 |
+
)
|
| 1582 |
+
orig_eidx = eidx
|
| 1583 |
+
anchors = expert_anchors.get((lpref, econt, proj, eidx))
|
| 1584 |
+
if not anchors:
|
| 1585 |
+
for (lp2, ec2, p2, e2), al in expert_anchors.items():
|
| 1586 |
+
if lp2 == lpref and ec2 == econt and p2 == proj and al:
|
| 1587 |
+
anchors = al
|
| 1588 |
+
eidx = e2
|
| 1589 |
+
break
|
| 1590 |
+
if anchors:
|
| 1591 |
+
la, lb, alpha = _bracket_anchors(anchors, lidx, total_layers=total_layers)
|
| 1592 |
+
w_name_a = f"{lpref}.{la}.{econt}.{eidx}.{proj}.weight"
|
| 1593 |
+
s_name_a = f"{lpref}.{la}.{econt}.{eidx}.{proj}.weight_scale_inv"
|
| 1594 |
+
w_name_b = f"{lpref}.{lb}.{econt}.{eidx}.{proj}.weight"
|
| 1595 |
+
s_name_b = f"{lpref}.{lb}.{econt}.{eidx}.{proj}.weight_scale_inv"
|
| 1596 |
+
dt_w = present_dtype[w_name_a]
|
| 1597 |
+
|
| 1598 |
+
if dt_w.startswith("F8") and s_name_a in present and s_name_b in present:
|
| 1599 |
+
if la == lb or alpha <= 1.0e-6:
|
| 1600 |
+
tw = f.get_tensor(w_name_a)
|
| 1601 |
+
ts = f.get_tensor(s_name_a)
|
| 1602 |
+
raw_w, shp_w = _payload_bytes(tw), tuple(tw.shape)
|
| 1603 |
+
raw_s, dt_s, shp_s = _payload_bytes(ts), present_dtype[s_name_a], tuple(ts.shape)
|
| 1604 |
+
else:
|
| 1605 |
+
wa = f.get_tensor(w_name_a).to(dev, non_blocking=True)
|
| 1606 |
+
sa = f.get_tensor(s_name_a).to(dev, non_blocking=True)
|
| 1607 |
+
wb = f.get_tensor(w_name_b).to(dev, non_blocking=True)
|
| 1608 |
+
sb = f.get_tensor(s_name_b).to(dev, non_blocking=True)
|
| 1609 |
+
fa = _dequant_mxfp8_torch(wa, sa)
|
| 1610 |
+
fb = _dequant_mxfp8_torch(wb, sb)
|
| 1611 |
+
f_interp = _checkfree_interp_torch(fa, fb, alpha, preserve_row_rms=True)
|
| 1612 |
+
q_w, q_s = _quant_mxfp8_torch(f_interp)
|
| 1613 |
+
raw_w, shp_w = _payload_bytes(q_w), tuple(q_w.shape)
|
| 1614 |
+
raw_s, dt_s, shp_s = _payload_bytes(q_s), present_dtype[s_name_a], tuple(q_s.shape)
|
| 1615 |
+
del wa, sa, wb, sb, fa, fb, f_interp, q_w, q_s
|
| 1616 |
+
|
| 1617 |
+
scale_target = f"{lpref}.{lidx}.{econt}.{orig_eidx}.{proj}.weight_scale_inv"
|
| 1618 |
+
weight_target = f"{lpref}.{lidx}.{econt}.{orig_eidx}.{proj}.weight"
|
| 1619 |
+
if field == "weight":
|
| 1620 |
+
writer.add(name, raw_w, dt_w, shp_w)
|
| 1621 |
+
if scale_target in weight_map and scale_target not in present:
|
| 1622 |
+
pending_expert_scales[scale_target] = (raw_s, dt_s, shp_s)
|
| 1623 |
+
else:
|
| 1624 |
+
writer.add(name, raw_s, dt_s, shp_s)
|
| 1625 |
+
if weight_target in weight_map and weight_target not in present:
|
| 1626 |
+
pending_expert_scales[weight_target] = (raw_w, dt_w, shp_w)
|
| 1627 |
+
stats["expert_interpolated"] += 1
|
| 1628 |
+
stats["pattern_recovered"] += 1
|
| 1629 |
+
stats["tensors"] += 1
|
| 1630 |
+
if stats["tensors"] % 64 == 0 or stats["tensors"] == total_tensors:
|
| 1631 |
+
_notify(name, "CHECKFREE_EXPERT")
|
| 1632 |
+
continue
|
| 1633 |
+
else:
|
| 1634 |
+
f_key_a = f"{lpref}.{la}.{econt}.{eidx}.{proj}.{field}"
|
| 1635 |
+
f_key_b = f"{lpref}.{lb}.{econt}.{eidx}.{proj}.{field}"
|
| 1636 |
+
if f_key_a not in present:
|
| 1637 |
+
f_key_a = w_name_a
|
| 1638 |
+
f_key_b = w_name_b
|
| 1639 |
+
dt_f = present_dtype[f_key_a]
|
| 1640 |
+
ta = f.get_tensor(f_key_a).to(dev)
|
| 1641 |
+
tb = f.get_tensor(f_key_b).to(dev)
|
| 1642 |
+
interp = _checkfree_interp_torch(ta, tb, alpha, preserve_row_rms=(ta.ndim >= 2))
|
| 1643 |
+
raw_o, dt_o, shp_o = _storage_from_f32(interp.cpu().numpy(), dt_f)
|
| 1644 |
+
writer.add(name, raw_o, dt_o, shp_o)
|
| 1645 |
+
stats["expert_interpolated"] += 1
|
| 1646 |
+
stats["pattern_recovered"] += 1
|
| 1647 |
+
stats["tensors"] += 1
|
| 1648 |
+
if stats["tensors"] % 64 == 0 or stats["tensors"] == total_tensors:
|
| 1649 |
+
_notify(name, "CHECKFREE_EXPERT")
|
| 1650 |
+
continue
|
| 1651 |
+
|
| 1652 |
+
lm = LAYER_RE.match(name)
|
| 1653 |
+
if lm:
|
| 1654 |
+
lpref = lm.group(1)
|
| 1655 |
+
lidx = int(lm.group(2))
|
| 1656 |
+
suffix = lm.group(3)
|
| 1657 |
+
kind = layer_kind(lidx)
|
| 1658 |
+
anchors = kind_suffix_anchors.get((lpref, kind, suffix))
|
| 1659 |
+
if not anchors or len(anchors) == 1:
|
| 1660 |
+
all_anc = any_suffix_anchors.get((lpref, suffix))
|
| 1661 |
+
if all_anc and len(all_anc) > len(anchors or []):
|
| 1662 |
+
ref_shape = tuple(f.get_slice(f"{lpref}.{all_anc[0]}.{suffix}").get_shape())
|
| 1663 |
+
if all(
|
| 1664 |
+
tuple(f.get_slice(f"{lpref}.{a}.{suffix}").get_shape()) == ref_shape
|
| 1665 |
+
for a in all_anc
|
| 1666 |
+
):
|
| 1667 |
+
anchors = all_anc
|
| 1668 |
+
if anchors:
|
| 1669 |
+
la, lb, alpha = _bracket_anchors(anchors, lidx, total_layers=total_layers)
|
| 1670 |
+
na = f"{lpref}.{la}.{suffix}"
|
| 1671 |
+
nb = f"{lpref}.{lb}.{suffix}"
|
| 1672 |
+
dt_t = present_dtype[na]
|
| 1673 |
+
ta = f.get_tensor(na)
|
| 1674 |
+
if la == lb or alpha <= 1.0e-6 or dt_t not in ("F32", "F16", "BF16"):
|
| 1675 |
+
writer.add(name, _payload_bytes(ta), dt_t, tuple(ta.shape))
|
| 1676 |
+
else:
|
| 1677 |
+
tb = f.get_tensor(nb)
|
| 1678 |
+
interp = _checkfree_interp_torch(
|
| 1679 |
+
ta.to(dev), tb.to(dev), alpha, preserve_row_rms=(ta.ndim >= 2)
|
| 1680 |
+
)
|
| 1681 |
+
raw_o, dt_o, shp_o = _storage_from_f32(interp.cpu().numpy(), dt_t)
|
| 1682 |
+
writer.add(name, raw_o, dt_o, shp_o)
|
| 1683 |
+
stats["checkfree_interpolated"] += 1
|
| 1684 |
+
stats["pattern_recovered"] += 1
|
| 1685 |
+
stats["tensors"] += 1
|
| 1686 |
+
if stats["tensors"] % 32 == 0 or stats["tensors"] == total_tensors:
|
| 1687 |
+
_notify(name, "CHECKFREE_LAYER")
|
| 1688 |
+
continue
|
| 1689 |
+
|
| 1690 |
+
if _is_head_key(name) and present_embed_key is not None:
|
| 1691 |
+
t = f.get_tensor(present_embed_key)
|
| 1692 |
+
writer.add(name, _payload_bytes(t), present_dtype[present_embed_key], tuple(t.shape))
|
| 1693 |
+
stats["suffix_recovered"] += 1
|
| 1694 |
+
stats["tensors"] += 1
|
| 1695 |
+
_notify(name, "SUFFIX_PRIOR")
|
| 1696 |
+
continue
|
| 1697 |
+
if _is_embed_key(name) and present_head_key is not None:
|
| 1698 |
+
t = f.get_tensor(present_head_key)
|
| 1699 |
+
writer.add(name, _payload_bytes(t), present_dtype[present_head_key], tuple(t.shape))
|
| 1700 |
+
stats["suffix_recovered"] += 1
|
| 1701 |
+
stats["tensors"] += 1
|
| 1702 |
+
_notify(name, "SUFFIX_PRIOR")
|
| 1703 |
+
continue
|
| 1704 |
+
|
| 1705 |
+
if embed_meta is not None and _is_embed_key(name):
|
| 1706 |
+
basis_in, scale_in, coords, _, _, _, _ = embed_meta
|
| 1707 |
+
_write_embed_tokens_chunked(
|
| 1708 |
+
writer,
|
| 1709 |
+
name,
|
| 1710 |
+
basis_in,
|
| 1711 |
+
scale_in,
|
| 1712 |
+
coords,
|
| 1713 |
+
int(arch["vocab_size"]),
|
| 1714 |
+
int(arch["hidden_size"]),
|
| 1715 |
+
dev,
|
| 1716 |
+
)
|
| 1717 |
+
stats["synthesized"] += 1
|
| 1718 |
+
stats["tensors"] += 1
|
| 1719 |
+
_notify(name, "SYNTHESIZE_CALIBRATED")
|
| 1720 |
+
continue
|
| 1721 |
+
|
| 1722 |
+
if embed_meta is not None and _is_head_key(name):
|
| 1723 |
+
basis_in, scale_in, coords, valid_mask, vocab_id_by_str, im_end_id, im_start_id = embed_meta
|
| 1724 |
+
_notify(name, "CALIBRATING_25L_FORWARD")
|
| 1725 |
+
_write_lm_head_calibrated_chunked(
|
| 1726 |
+
writer,
|
| 1727 |
+
name,
|
| 1728 |
+
f,
|
| 1729 |
+
present,
|
| 1730 |
+
arch,
|
| 1731 |
+
basis_in,
|
| 1732 |
+
scale_in,
|
| 1733 |
+
coords,
|
| 1734 |
+
valid_mask,
|
| 1735 |
+
vocab_id_by_str,
|
| 1736 |
+
im_end_id,
|
| 1737 |
+
im_start_id,
|
| 1738 |
+
dev,
|
| 1739 |
+
)
|
| 1740 |
+
stats["synthesized"] += 1
|
| 1741 |
+
stats["tensors"] += 1
|
| 1742 |
+
_notify(name, "SYNTHESIZE_CALIBRATED")
|
| 1743 |
+
continue
|
| 1744 |
+
|
| 1745 |
+
tail_match = (
|
| 1746 |
+
by_tail.get(".".join(name.split(".")[-2:]))
|
| 1747 |
+
or by_tail.get(".".join(name.split(".")[-3:]))
|
| 1748 |
+
)
|
| 1749 |
+
if tail_match is None and "norm" in name:
|
| 1750 |
+
tail_match = next((n for n in present if "norm" in n), None)
|
| 1751 |
+
if tail_match is None and "bias" in name:
|
| 1752 |
+
tail_match = next((n for n in present if "bias" in n), None)
|
| 1753 |
+
if tail_match is not None:
|
| 1754 |
+
t = f.get_tensor(tail_match)
|
| 1755 |
+
writer.add(name, _payload_bytes(t), present_dtype[tail_match], tuple(t.shape))
|
| 1756 |
+
stats["suffix_recovered"] += 1
|
| 1757 |
+
stats["tensors"] += 1
|
| 1758 |
+
_notify(name, "SUFFIX_PRIOR")
|
| 1759 |
+
continue
|
| 1760 |
+
|
| 1761 |
+
stats["missing"] += 1
|
| 1762 |
+
if verbose:
|
| 1763 |
+
print(f" WARNING: no prior for {name}; skipping")
|
| 1764 |
+
|
| 1765 |
+
writer.close()
|
| 1766 |
+
stats["output_bytes"] = writer.bytes_written()
|
| 1767 |
+
if export_hf_dir is not None:
|
| 1768 |
+
src_dir = cfg_path.parent if cfg_path.exists() else shard_path.parent
|
| 1769 |
+
export_hf_bundle(output, src_dir, export_hf_dir)
|
| 1770 |
+
if verbose:
|
| 1771 |
+
print(
|
| 1772 |
+
f"recovered {stats['tensors']}/{len(weight_map)} tensors: "
|
| 1773 |
+
f"{stats['present']} present, "
|
| 1774 |
+
f"{stats['checkfree_interpolated']} checkfree_layer, "
|
| 1775 |
+
f"{stats['expert_interpolated']} checkfree_expert, "
|
| 1776 |
+
f"{stats['suffix_recovered']} suffix, "
|
| 1777 |
+
f"{stats['synthesized']} synthesized, "
|
| 1778 |
+
f"{stats['missing']} missing"
|
| 1779 |
+
)
|
| 1780 |
+
return stats
|
| 1781 |
+
|
| 1782 |
+
|
| 1783 |
+
# ---------------------------------------------------------------------------
|
| 1784 |
+
# Self-Contained SlimShard Build / Regenerate
|
| 1785 |
+
# ---------------------------------------------------------------------------
|
| 1786 |
+
def _choose_encoding(name: str, shape, dtype: str, quant_format: str) -> str:
|
| 1787 |
+
if quant_format == "exact":
|
| 1788 |
+
return "exact"
|
| 1789 |
+
if len(shape) < 2 or dtype not in ("F32", "F16", "BF16"):
|
| 1790 |
+
return "exact"
|
| 1791 |
+
if "weight_scale_inv" in name or "scales" in name:
|
| 1792 |
+
return "exact"
|
| 1793 |
+
row = int(shape[-1])
|
| 1794 |
+
bpw = _BPW.get(dtype, 16.0)
|
| 1795 |
+
if bpw <= 4.5 + 1.0e-6:
|
| 1796 |
+
return "exact"
|
| 1797 |
+
if _is_embed_key(name) or _is_head_key(name):
|
| 1798 |
+
return "q4_0" if row % QK4_0 == 0 else "exact"
|
| 1799 |
+
if quant_format in ("mixed", "q2_k") and row % QK_K == 0:
|
| 1800 |
+
return "q2_k"
|
| 1801 |
+
if quant_format in ("mixed", "q4_0") and row % QK4_0 == 0:
|
| 1802 |
+
return "q4_0"
|
| 1803 |
+
return "exact"
|
| 1804 |
+
|
| 1805 |
+
|
| 1806 |
+
def _kmeans(features: np.ndarray, k: int, iters: int = 8, seed: int = 0) -> np.ndarray:
|
| 1807 |
+
n = features.shape[0]
|
| 1808 |
+
rng = np.random.default_rng(seed)
|
| 1809 |
+
if k >= n:
|
| 1810 |
+
return np.arange(n, dtype=np.int32)
|
| 1811 |
+
centers = features[rng.choice(n, size=k, replace=False)].copy()
|
| 1812 |
+
assign = np.zeros(n, dtype=np.int32)
|
| 1813 |
+
for _ in range(iters):
|
| 1814 |
+
d2 = ((features[:, None, :] - centers[None, :, :]) ** 2).sum(axis=2)
|
| 1815 |
+
new_assign = np.argmin(d2, axis=1).astype(np.int32)
|
| 1816 |
+
if np.array_equal(new_assign, assign):
|
| 1817 |
+
break
|
| 1818 |
+
assign = new_assign
|
| 1819 |
+
for c in range(k):
|
| 1820 |
+
members = features[assign == c]
|
| 1821 |
+
if members.shape[0]:
|
| 1822 |
+
centers[c] = members.mean(axis=0)
|
| 1823 |
+
return assign
|
| 1824 |
+
|
| 1825 |
+
|
| 1826 |
+
def build_slimshard(
|
| 1827 |
+
model_dir: str | Path,
|
| 1828 |
+
output: str | Path,
|
| 1829 |
+
cfg: HPCConfig | None = None,
|
| 1830 |
+
quant_format: str = "mixed",
|
| 1831 |
+
expert_keep_ratio: float = 1.0,
|
| 1832 |
+
verbose: bool = True,
|
| 1833 |
+
progress_cb=None,
|
| 1834 |
+
stop_event=None,
|
| 1835 |
+
) -> dict:
|
| 1836 |
+
"""Compress a sharded HF safetensors model into one self-contained SlimShard."""
|
| 1837 |
+
if safe_open is None:
|
| 1838 |
+
raise RuntimeError("safetensors + torch are required for SlimShard build")
|
| 1839 |
+
model_dir = Path(model_dir)
|
| 1840 |
+
index_path = model_dir / "model.safetensors.index.json"
|
| 1841 |
+
if index_path.exists():
|
| 1842 |
+
index = json.loads(index_path.read_text())
|
| 1843 |
+
weight_map: dict[str, str] = index["weight_map"]
|
| 1844 |
+
else:
|
| 1845 |
+
st_files = sorted(model_dir.glob("*.safetensors"))
|
| 1846 |
+
if not st_files:
|
| 1847 |
+
raise FileNotFoundError(f"no .safetensors found in {model_dir}")
|
| 1848 |
+
weight_map = {}
|
| 1849 |
+
for st in st_files:
|
| 1850 |
+
with safe_open(str(st), framework="pt", device="cpu") as f:
|
| 1851 |
+
for k in f.keys():
|
| 1852 |
+
weight_map[k] = st.name
|
| 1853 |
+
shards = set(weight_map.values())
|
| 1854 |
+
handles = {
|
| 1855 |
+
sh: safe_open(str(model_dir / sh), framework="pt", device="cpu")
|
| 1856 |
+
for sh in sorted(shards)
|
| 1857 |
+
}
|
| 1858 |
+
cfg = (cfg or HPCConfig()).validate()
|
| 1859 |
+
quantizer = Q2KQuantizer(cfg)
|
| 1860 |
+
|
| 1861 |
+
manifest: dict[str, dict] = {}
|
| 1862 |
+
clusters: dict[str, dict] = {}
|
| 1863 |
+
writer = SafetensorsWriter(output)
|
| 1864 |
+
processed: set[str] = set()
|
| 1865 |
+
|
| 1866 |
+
groups: dict[tuple[str, str], list[tuple[int, str]]] = {}
|
| 1867 |
+
for name in weight_map:
|
| 1868 |
+
m = EXPERT_RE.match(name)
|
| 1869 |
+
if m and m.group(6) == "weight":
|
| 1870 |
+
groups.setdefault((m.group(2), m.group(5)), []).append((int(m.group(4)), name))
|
| 1871 |
+
|
| 1872 |
+
def encode_array_payload(
|
| 1873 |
+
name: str, f32: np.ndarray, dtype: str, shape, encoding: str, extra: dict | None = None
|
| 1874 |
+
):
|
| 1875 |
+
if encoding == "exact":
|
| 1876 |
+
raw, dt, shp = _storage_from_f32(f32, dtype)
|
| 1877 |
+
writer.add(name, raw, dt, shp)
|
| 1878 |
+
manifest[name] = {
|
| 1879 |
+
"encoding": "exact",
|
| 1880 |
+
"dtype": dtype,
|
| 1881 |
+
"shape": list(shape),
|
| 1882 |
+
"bytes": len(raw),
|
| 1883 |
+
**(extra or {}),
|
| 1884 |
+
}
|
| 1885 |
+
return
|
| 1886 |
+
row = int(shape[-1])
|
| 1887 |
+
flat = f32.reshape(-1)
|
| 1888 |
+
if encoding == "q2_k":
|
| 1889 |
+
res = quantizer.quantize(flat, row_width=row)
|
| 1890 |
+
raw = blocks_to_bytes(res.scales, res.qs, res.dm)
|
| 1891 |
+
writer.add(name, raw, "U8", (len(raw),))
|
| 1892 |
+
manifest[name] = {
|
| 1893 |
+
"encoding": "q2_k",
|
| 1894 |
+
"dtype": dtype,
|
| 1895 |
+
"shape": list(shape),
|
| 1896 |
+
"bytes": len(raw),
|
| 1897 |
+
**(extra or {}),
|
| 1898 |
+
}
|
| 1899 |
+
elif encoding == "q4_0":
|
| 1900 |
+
raw, _, _ = quantize_tensor_q4_0(flat, cfg=cfg)
|
| 1901 |
+
writer.add(name, raw, "U8", (len(raw),))
|
| 1902 |
+
manifest[name] = {
|
| 1903 |
+
"encoding": "q4_0",
|
| 1904 |
+
"dtype": dtype,
|
| 1905 |
+
"shape": list(shape),
|
| 1906 |
+
"bytes": len(raw),
|
| 1907 |
+
**(extra or {}),
|
| 1908 |
+
}
|
| 1909 |
+
else:
|
| 1910 |
+
raise ValueError(encoding)
|
| 1911 |
+
|
| 1912 |
+
total_tensors = len(weight_map)
|
| 1913 |
+
for name in weight_map:
|
| 1914 |
+
if stop_event is not None and stop_event.is_set():
|
| 1915 |
+
writer.close()
|
| 1916 |
+
raise InterruptedError("Build cancelled by user.")
|
| 1917 |
+
if name in processed:
|
| 1918 |
+
continue
|
| 1919 |
+
m = EXPERT_RE.match(name)
|
| 1920 |
+
t0 = handles[weight_map[name]].get_tensor(name)
|
| 1921 |
+
dt0 = _dtype_of(t0)
|
| 1922 |
+
if m and m.group(6) == "weight" and expert_keep_ratio < 1.0 and not dt0.startswith("F8"):
|
| 1923 |
+
layer, proj = m.group(2), m.group(5)
|
| 1924 |
+
members = sorted(groups[(layer, proj)], key=lambda x: x[0])
|
| 1925 |
+
expert_tensors = []
|
| 1926 |
+
shapes = []
|
| 1927 |
+
for _, ename in members:
|
| 1928 |
+
t = handles[weight_map[ename]].get_tensor(ename)
|
| 1929 |
+
f32, _, _ = _to_f32(t)
|
| 1930 |
+
expert_tensors.append(f32)
|
| 1931 |
+
shapes.append(f32.shape)
|
| 1932 |
+
shape = shapes[0]
|
| 1933 |
+
E = len(expert_tensors)
|
| 1934 |
+
N = int(np.prod(shape))
|
| 1935 |
+
sampled = min(8192, N)
|
| 1936 |
+
idx = np.linspace(0, N - 1, sampled).astype(np.int64)
|
| 1937 |
+
features = np.stack([w.reshape(-1)[idx] for w in expert_tensors], axis=0).astype(np.float32)
|
| 1938 |
+
norms = np.linalg.norm(features, axis=1, keepdims=True)
|
| 1939 |
+
features = features / np.maximum(norms, 1.0e-30)
|
| 1940 |
+
k = max(1, int(round(E * expert_keep_ratio)))
|
| 1941 |
+
assign = _kmeans(features, k, seed=0)
|
| 1942 |
+
centroids = np.zeros((k, N), dtype=np.float32)
|
| 1943 |
+
for c in range(k):
|
| 1944 |
+
sel = [i for i in range(E) if assign[i] == c]
|
| 1945 |
+
centroids[c] = (
|
| 1946 |
+
np.mean([expert_tensors[i].reshape(-1) for i in sel], axis=0)
|
| 1947 |
+
if sel
|
| 1948 |
+
else expert_tensors[0].reshape(-1)
|
| 1949 |
+
)
|
| 1950 |
+
centroid_shape = (k, *shape)
|
| 1951 |
+
ckey = f"__slim__/{layer}/{proj}/centroid"
|
| 1952 |
+
akey = f"__slim__/{layer}/{proj}/assign"
|
| 1953 |
+
c_raw, c_dt, c_shp = _storage_from_f32(centroids.reshape(centroid_shape), "F32")
|
| 1954 |
+
writer.add(ckey, c_raw, c_dt, c_shp)
|
| 1955 |
+
writer.add(akey, assign.astype("<i4"), "I32", (E,))
|
| 1956 |
+
clusters[f"{layer}/{proj}"] = {
|
| 1957 |
+
"centroid": ckey,
|
| 1958 |
+
"centroid_shape": list(centroid_shape),
|
| 1959 |
+
"centroid_dtype": "F32",
|
| 1960 |
+
"assign": akey,
|
| 1961 |
+
"assign_dtype": "I32",
|
| 1962 |
+
"n_clusters": k,
|
| 1963 |
+
"n_experts": E,
|
| 1964 |
+
"expert_shape": list(shape),
|
| 1965 |
+
}
|
| 1966 |
+
for idx_e, (_, ename) in enumerate(members):
|
| 1967 |
+
dt = _dtype_of(handles[weight_map[ename]].get_tensor(ename))
|
| 1968 |
+
residual = (expert_tensors[idx_e] - centroids[assign[idx_e]].reshape(shape)).astype(np.float32)
|
| 1969 |
+
if float(np.max(np.abs(residual))) < 1.0e-7:
|
| 1970 |
+
manifest[ename] = {
|
| 1971 |
+
"encoding": "expert_residual",
|
| 1972 |
+
"cluster": f"{layer}/{proj}",
|
| 1973 |
+
"expert": idx_e,
|
| 1974 |
+
"dtype": dt,
|
| 1975 |
+
"shape": list(shape),
|
| 1976 |
+
"residual_encoding": "zero",
|
| 1977 |
+
"bytes": 0,
|
| 1978 |
+
}
|
| 1979 |
+
else:
|
| 1980 |
+
enc = _choose_encoding(ename, shape, dt, quant_format)
|
| 1981 |
+
encode_array_payload(ename, residual, dt, shape, enc)
|
| 1982 |
+
ent = manifest[ename]
|
| 1983 |
+
ent.update(
|
| 1984 |
+
{
|
| 1985 |
+
"encoding": "expert_residual",
|
| 1986 |
+
"cluster": f"{layer}/{proj}",
|
| 1987 |
+
"expert": idx_e,
|
| 1988 |
+
"residual_encoding": ent.pop("encoding"),
|
| 1989 |
+
"dtype": dt,
|
| 1990 |
+
"shape": list(shape),
|
| 1991 |
+
}
|
| 1992 |
+
)
|
| 1993 |
+
processed.add(ename)
|
| 1994 |
+
if progress_cb is not None and len(processed) % 32 == 0:
|
| 1995 |
+
progress_cb(len(processed), total_tensors, ename, "EXPERT_RESIDUAL", {"tensors": len(processed)})
|
| 1996 |
+
continue
|
| 1997 |
+
|
| 1998 |
+
f32, _, dt = _to_f32(t0)
|
| 1999 |
+
shape = tuple(f32.shape)
|
| 2000 |
+
enc = _choose_encoding(name, shape, dt, quant_format)
|
| 2001 |
+
if dt.startswith("F8"):
|
| 2002 |
+
raw = _payload_bytes(t0)
|
| 2003 |
+
writer.add(name, raw, dt, shape)
|
| 2004 |
+
manifest[name] = {"encoding": "exact", "dtype": dt, "shape": list(shape), "bytes": len(raw)}
|
| 2005 |
+
else:
|
| 2006 |
+
encode_array_payload(name, f32, dt, shape, enc)
|
| 2007 |
+
processed.add(name)
|
| 2008 |
+
if progress_cb is not None and (len(processed) % 32 == 0 or len(processed) == total_tensors):
|
| 2009 |
+
progress_cb(len(processed), total_tensors, name, enc.upper(), {"tensors": len(processed)})
|
| 2010 |
+
|
| 2011 |
+
writer.metadata.update(
|
| 2012 |
+
{
|
| 2013 |
+
"format": SHARD_FORMAT,
|
| 2014 |
+
"manifest": json.dumps(manifest, separators=(",", ":")),
|
| 2015 |
+
"clusters": json.dumps(clusters, separators=(",", ":")),
|
| 2016 |
+
"weight_map": json.dumps(weight_map, separators=(",", ":")),
|
| 2017 |
+
"quant_format": quant_format,
|
| 2018 |
+
"expert_keep_ratio": str(expert_keep_ratio),
|
| 2019 |
+
}
|
| 2020 |
+
)
|
| 2021 |
+
writer.close()
|
| 2022 |
+
stats = {
|
| 2023 |
+
"tensors": len(manifest),
|
| 2024 |
+
"clusters": len(clusters),
|
| 2025 |
+
"bytes": writer.bytes_written(),
|
| 2026 |
+
"quant_format": quant_format,
|
| 2027 |
+
"expert_keep_ratio": expert_keep_ratio,
|
| 2028 |
+
}
|
| 2029 |
+
if verbose:
|
| 2030 |
+
print(f"SlimShard: {stats}")
|
| 2031 |
+
return stats
|
| 2032 |
+
|
| 2033 |
+
|
| 2034 |
+
def regenerate(
|
| 2035 |
+
slimshard: str | Path,
|
| 2036 |
+
output: str | Path,
|
| 2037 |
+
verbose: bool = True,
|
| 2038 |
+
progress_cb=None,
|
| 2039 |
+
stop_event=None,
|
| 2040 |
+
) -> dict:
|
| 2041 |
+
"""Regenerate a full HF safetensors model from one SlimShard file."""
|
| 2042 |
+
if safe_open is None:
|
| 2043 |
+
raise RuntimeError("safetensors + torch are required for regeneration")
|
| 2044 |
+
with safe_open(str(slimshard), framework="pt", device="cpu") as f:
|
| 2045 |
+
meta = f.metadata() or {}
|
| 2046 |
+
if meta.get("format") != SHARD_FORMAT:
|
| 2047 |
+
raise ValueError("not an HPC SlimShard file")
|
| 2048 |
+
manifest = json.loads(meta["manifest"])
|
| 2049 |
+
clusters = json.loads(meta.get("clusters", "{}"))
|
| 2050 |
+
centroid_cache: dict[str, np.ndarray] = {}
|
| 2051 |
+
assign_cache: dict[str, np.ndarray] = {}
|
| 2052 |
+
writer = SafetensorsWriter(output, metadata={"format": "pt"})
|
| 2053 |
+
total = len(manifest)
|
| 2054 |
+
for idx_t, (name, ent) in enumerate(manifest.items(), 1):
|
| 2055 |
+
if stop_event is not None and stop_event.is_set():
|
| 2056 |
+
writer.close()
|
| 2057 |
+
raise InterruptedError("Regeneration cancelled by user.")
|
| 2058 |
+
enc = ent["encoding"]
|
| 2059 |
+
shape = tuple(ent["shape"])
|
| 2060 |
+
dtype = ent["dtype"]
|
| 2061 |
+
if enc == "exact":
|
| 2062 |
+
raw = _payload_bytes(f.get_tensor(name))
|
| 2063 |
+
if not dtype.startswith("F8"):
|
| 2064 |
+
_decode_exact(raw, dtype, shape)
|
| 2065 |
+
writer.add(name, raw, _TORCH_DTYPE_REV.get(dtype, dtype), shape)
|
| 2066 |
+
elif enc in ("q2_k", "q4_0"):
|
| 2067 |
+
raw = _payload_bytes(f.get_tensor(name))
|
| 2068 |
+
arr = _decode_q2k(raw, shape) if enc == "q2_k" else _decode_q4(raw, shape)
|
| 2069 |
+
raw2, dt2, shp2 = _storage_from_f32(arr, dtype)
|
| 2070 |
+
writer.add(name, raw2, dt2, shp2)
|
| 2071 |
+
elif enc == "expert_residual":
|
| 2072 |
+
ckey = clusters[ent["cluster"]]["centroid"]
|
| 2073 |
+
akey = clusters[ent["cluster"]]["assign"]
|
| 2074 |
+
if ckey not in centroid_cache:
|
| 2075 |
+
craw = _payload_bytes(f.get_tensor(ckey))
|
| 2076 |
+
cshape = tuple(clusters[ent["cluster"]]["centroid_shape"])
|
| 2077 |
+
centroid_cache[ckey] = _decode_exact(craw, "F32", cshape)
|
| 2078 |
+
araw = _payload_bytes(f.get_tensor(akey))
|
| 2079 |
+
assign_cache[akey] = _decode_exact(
|
| 2080 |
+
araw, "I32", (clusters[ent["cluster"]]["n_experts"],)
|
| 2081 |
+
)
|
| 2082 |
+
centroid = centroid_cache[ckey][assign_cache[akey][ent["expert"]]].astype(np.float32)
|
| 2083 |
+
renc = ent.get("residual_encoding", "zero")
|
| 2084 |
+
if renc == "zero":
|
| 2085 |
+
arr = centroid.reshape(shape)
|
| 2086 |
+
else:
|
| 2087 |
+
raw = _payload_bytes(f.get_tensor(name))
|
| 2088 |
+
if renc == "q2_k":
|
| 2089 |
+
res = _decode_q2k(raw, shape)
|
| 2090 |
+
elif renc == "q4_0":
|
| 2091 |
+
res = _decode_q4(raw, shape)
|
| 2092 |
+
else:
|
| 2093 |
+
res = _decode_exact(raw, dtype, shape)
|
| 2094 |
+
arr = centroid + res
|
| 2095 |
+
raw2, dt2, shp2 = _storage_from_f32(arr, dtype)
|
| 2096 |
+
writer.add(name, raw2, dt2, shp2)
|
| 2097 |
+
else:
|
| 2098 |
+
raise ValueError(f"unknown encoding {enc} for {name}")
|
| 2099 |
+
if progress_cb is not None and (idx_t % 32 == 0 or idx_t == total):
|
| 2100 |
+
progress_cb(idx_t, total, name, enc.upper(), {"tensors": idx_t})
|
| 2101 |
+
writer.close()
|
| 2102 |
+
if verbose:
|
| 2103 |
+
print(f"regenerated {len(manifest)} tensors -> {output}")
|
| 2104 |
+
return {"tensors": len(manifest)}
|
| 2105 |
+
|
| 2106 |
+
|
| 2107 |
+
def slimshard_info(path: str | Path) -> dict:
|
| 2108 |
+
with safe_open(str(path), framework="pt", device="cpu") as f:
|
| 2109 |
+
meta = f.metadata() or {}
|
| 2110 |
+
manifest = json.loads(meta.get("manifest", "{}"))
|
| 2111 |
+
clusters = json.loads(meta.get("clusters", "{}"))
|
| 2112 |
+
counts: dict[str, int] = {}
|
| 2113 |
+
for e in manifest.values():
|
| 2114 |
+
counts[e["encoding"]] = counts.get(e["encoding"], 0) + 1
|
| 2115 |
+
return {
|
| 2116 |
+
"format": meta.get("format"),
|
| 2117 |
+
"tensors": len(manifest),
|
| 2118 |
+
"clusters": len(clusters),
|
| 2119 |
+
"encodings": counts,
|
| 2120 |
+
"quant_format": meta.get("quant_format"),
|
| 2121 |
+
"expert_keep_ratio": meta.get("expert_keep_ratio"),
|
| 2122 |
+
}
|
| 2123 |
+
|
| 2124 |
+
|
| 2125 |
+
def main() -> None:
|
| 2126 |
+
ap = argparse.ArgumentParser(description="HPC SlimShard / CheckFree single-shard LLM recovery")
|
| 2127 |
+
sub = ap.add_subparsers(dest="cmd", required=False)
|
| 2128 |
+
|
| 2129 |
+
sub.add_parser("gui", help="launch the SlimShard / CheckFree graphical user interface")
|
| 2130 |
+
|
| 2131 |
+
b = sub.add_parser("build", help="compress a sharded HF model into one SlimShard")
|
| 2132 |
+
b.add_argument("--model-dir", required=True)
|
| 2133 |
+
b.add_argument("--output", required=True)
|
| 2134 |
+
b.add_argument("--format", choices=("mixed", "q2_k", "q4_0", "exact"), default="mixed")
|
| 2135 |
+
b.add_argument("--expert-keep-ratio", type=float, default=1.0)
|
| 2136 |
+
b.add_argument("--device", default="auto")
|
| 2137 |
+
b.add_argument("--verbose", action="store_true")
|
| 2138 |
+
|
| 2139 |
+
r = sub.add_parser("regenerate", help="regenerate a full HF safetensors from one SlimShard")
|
| 2140 |
+
r.add_argument("--input", required=True)
|
| 2141 |
+
r.add_argument("--output", required=True)
|
| 2142 |
+
|
| 2143 |
+
i = sub.add_parser("info", help="print SlimShard metadata")
|
| 2144 |
+
i.add_argument("--input", required=True)
|
| 2145 |
+
|
| 2146 |
+
rec = sub.add_parser("recover", help="CheckFree single-shard model recovery")
|
| 2147 |
+
rec.add_argument("--shard", required=True, help="single surviving HF .safetensors shard")
|
| 2148 |
+
rec.add_argument("--index", default=None, help="model.safetensors.index.json (auto-detected or inferred if omitted)")
|
| 2149 |
+
rec.add_argument("--output", required=True, help="full model .safetensors")
|
| 2150 |
+
rec.add_argument("--config", default=None, help="config.json (defaults to index/shard dir)")
|
| 2151 |
+
rec.add_argument("--export-hf-dir", default=None, help="optional ready-to-load HF model directory")
|
| 2152 |
+
rec.add_argument("--device", default="auto", choices=("auto", "cuda", "cpu"))
|
| 2153 |
+
|
| 2154 |
+
args = ap.parse_args()
|
| 2155 |
+
if args.cmd in (None, "gui"):
|
| 2156 |
+
from .slimshard_gui import launch_slimshard_gui
|
| 2157 |
+
|
| 2158 |
+
launch_slimshard_gui()
|
| 2159 |
+
elif args.cmd == "build":
|
| 2160 |
+
cfg = HPCConfig(device=args.device, verbose=False).validate()
|
| 2161 |
+
build_slimshard(
|
| 2162 |
+
args.model_dir,
|
| 2163 |
+
args.output,
|
| 2164 |
+
cfg=cfg,
|
| 2165 |
+
quant_format=args.format,
|
| 2166 |
+
expert_keep_ratio=args.expert_keep_ratio,
|
| 2167 |
+
verbose=True,
|
| 2168 |
+
)
|
| 2169 |
+
elif args.cmd == "regenerate":
|
| 2170 |
+
regenerate(args.input, args.output, verbose=True)
|
| 2171 |
+
elif args.cmd == "recover":
|
| 2172 |
+
recover_from_shard(
|
| 2173 |
+
args.shard,
|
| 2174 |
+
args.index,
|
| 2175 |
+
args.output,
|
| 2176 |
+
config=args.config,
|
| 2177 |
+
device=args.device,
|
| 2178 |
+
verbose=True,
|
| 2179 |
+
export_hf_dir=args.export_hf_dir,
|
| 2180 |
+
)
|
| 2181 |
+
else:
|
| 2182 |
+
print(json.dumps(slimshard_info(args.input), indent=2))
|
| 2183 |
+
|
| 2184 |
+
|
| 2185 |
+
if __name__ == "__main__":
|
| 2186 |
+
main()
|
slimshard_gui.py
ADDED
|
@@ -0,0 +1,1071 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Graphical User Interface for HPC-Quantize V2 SlimShard & CheckFree Recovery.
|
| 3 |
+
|
| 4 |
+
Launch::
|
| 5 |
+
|
| 6 |
+
python3 -m hpc_quantize_v2.slimshard gui
|
| 7 |
+
# or:
|
| 8 |
+
python3 -m hpc_quantize_v2.slimshard_gui
|
| 9 |
+
|
| 10 |
+
Supports any Hugging Face safetensors model architecture (Llama, Qwen2/3,
|
| 11 |
+
Mistral, Mixtral, DeepSeek, Gemma, Phi, GPT-NeoX, Raon, etc.):
|
| 12 |
+
|
| 13 |
+
1. **CheckFree Single-Shard Recovery (`recover`)**:
|
| 14 |
+
Reconstructs a complete runnable HF model from a single surviving
|
| 15 |
+
``.safetensors`` shard (with optional ``model.safetensors.index.json`` and
|
| 16 |
+
``config.json``), using CheckFree depth interpolation, per-expert MXFP8/FP16
|
| 17 |
+
interpolation, and causal forward-calibrated embedding/LM-head synthesis.
|
| 18 |
+
2. **SlimShard Compression (`build`)**:
|
| 19 |
+
Compresses any multi-shard HF model into a single self-contained SlimShard
|
| 20 |
+
(``mixed``, ``q2_k``, ``q4_0``, or ``exact`` + SlimMoE expert clustering).
|
| 21 |
+
3. **SlimShard Regeneration (`regenerate`)**:
|
| 22 |
+
Restores a standard HF ``.safetensors`` checkpoint from a SlimShard file.
|
| 23 |
+
4. **Live Model Prompt Tester**:
|
| 24 |
+
Runs any prompt (raw or chat-templated) on the recovered model directly
|
| 25 |
+
inside the GUI.
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
from __future__ import annotations
|
| 29 |
+
|
| 30 |
+
import datetime as dt
|
| 31 |
+
import queue
|
| 32 |
+
import shlex
|
| 33 |
+
import threading
|
| 34 |
+
import time
|
| 35 |
+
import tkinter as tk
|
| 36 |
+
from pathlib import Path
|
| 37 |
+
from tkinter import filedialog, messagebox, ttk
|
| 38 |
+
|
| 39 |
+
import numpy as np
|
| 40 |
+
|
| 41 |
+
from .cuda_backend import cuda_device_name, cuda_is_available
|
| 42 |
+
from .slimshard import (
|
| 43 |
+
HPCConfig,
|
| 44 |
+
build_slimshard,
|
| 45 |
+
export_hf_bundle,
|
| 46 |
+
inspect_recovery_plan,
|
| 47 |
+
recover_from_shard,
|
| 48 |
+
regenerate,
|
| 49 |
+
slimshard_info,
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def _ts() -> str:
|
| 54 |
+
return dt.datetime.now().strftime("%H:%M:%S.%f")[:-3]
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def _fmt_eta(seconds: float) -> str:
|
| 58 |
+
if not np.isfinite(seconds) or seconds <= 0.0:
|
| 59 |
+
return "0s"
|
| 60 |
+
s = int(round(seconds))
|
| 61 |
+
if s < 60:
|
| 62 |
+
return f"{seconds:.1f}s"
|
| 63 |
+
m, sec = divmod(s, 60)
|
| 64 |
+
if m < 60:
|
| 65 |
+
return f"{m}m{sec:02d}s"
|
| 66 |
+
h, m = divmod(m, 60)
|
| 67 |
+
return f"{h}h{m:02d}m{sec:02d}s"
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
class SlimShardGUI:
|
| 71 |
+
def __init__(self, root: tk.Tk | tk.Toplevel) -> None:
|
| 72 |
+
self.root = root
|
| 73 |
+
self.root.title(
|
| 74 |
+
"HPC-Quantize V2 — SlimShard & CheckFree Universal Single-Shard LLM Recovery"
|
| 75 |
+
)
|
| 76 |
+
self.root.geometry("1280x920")
|
| 77 |
+
self.root.minsize(1040, 740)
|
| 78 |
+
|
| 79 |
+
self._queue: queue.Queue[tuple[str, object]] = queue.Queue()
|
| 80 |
+
self._stop_event = threading.Event()
|
| 81 |
+
self._worker: threading.Thread | None = None
|
| 82 |
+
self._start_time: float | None = None
|
| 83 |
+
self._plan_rows: list[dict] = []
|
| 84 |
+
|
| 85 |
+
self._init_vars()
|
| 86 |
+
self._apply_theme()
|
| 87 |
+
self._build_layout()
|
| 88 |
+
self._auto_populate_defaults()
|
| 89 |
+
self._update_cli_preview()
|
| 90 |
+
self.root.after(80, self._poll_queue)
|
| 91 |
+
|
| 92 |
+
def _init_vars(self) -> None:
|
| 93 |
+
self.op_mode_var = tk.StringVar(value="recover")
|
| 94 |
+
self.shard_var = tk.StringVar()
|
| 95 |
+
self.index_var = tk.StringVar()
|
| 96 |
+
self.config_var = tk.StringVar()
|
| 97 |
+
self.model_dir_var = tk.StringVar()
|
| 98 |
+
self.output_var = tk.StringVar()
|
| 99 |
+
self.export_dir_var = tk.StringVar()
|
| 100 |
+
self.auto_bundle_var = tk.BooleanVar(value=True)
|
| 101 |
+
|
| 102 |
+
self.device_var = tk.StringVar(value="auto")
|
| 103 |
+
self.quant_format_var = tk.StringVar(value="mixed")
|
| 104 |
+
self.expert_keep_var = tk.DoubleVar(value=1.0)
|
| 105 |
+
|
| 106 |
+
self.filter_action_var = tk.StringVar(value="ALL")
|
| 107 |
+
self.search_var = tk.StringVar()
|
| 108 |
+
|
| 109 |
+
# Live telemetry variables
|
| 110 |
+
self.arch_summary_var = tk.StringVar(value="No shard inspected yet.")
|
| 111 |
+
self.layers_summary_var = tk.StringVar(value="Surviving layers: -- | Missing layers: --")
|
| 112 |
+
self.tele_tensor_var = tk.StringVar(value="Idle")
|
| 113 |
+
self.tele_action_var = tk.StringVar(value="Waiting")
|
| 114 |
+
self.tele_progress_text_var = tk.StringVar(value="0 / 0")
|
| 115 |
+
self.tele_breakdown_var = tk.StringVar(
|
| 116 |
+
value="present=0 | layer_interp=0 | expert_interp=0 | synth=0"
|
| 117 |
+
)
|
| 118 |
+
self.tele_speed_var = tk.StringVar(value="0.0 ten/s (ETA --)")
|
| 119 |
+
self.tele_elapsed_var = tk.StringVar(value="0.0s")
|
| 120 |
+
self.progress_var = tk.DoubleVar(value=0.0)
|
| 121 |
+
self.status_var = tk.StringVar(value="Ready.")
|
| 122 |
+
self.cli_preview_var = tk.StringVar()
|
| 123 |
+
|
| 124 |
+
# Prompt test variables
|
| 125 |
+
self.test_model_dir_var = tk.StringVar()
|
| 126 |
+
self.test_prompt_var = tk.StringVar(value="hello")
|
| 127 |
+
self.test_chat_mode_var = tk.BooleanVar(value=False)
|
| 128 |
+
self.test_max_tokens_var = tk.IntVar(value=24)
|
| 129 |
+
|
| 130 |
+
for v in (
|
| 131 |
+
self.op_mode_var,
|
| 132 |
+
self.shard_var,
|
| 133 |
+
self.index_var,
|
| 134 |
+
self.config_var,
|
| 135 |
+
self.model_dir_var,
|
| 136 |
+
self.output_var,
|
| 137 |
+
self.export_dir_var,
|
| 138 |
+
self.auto_bundle_var,
|
| 139 |
+
self.device_var,
|
| 140 |
+
self.quant_format_var,
|
| 141 |
+
self.expert_keep_var,
|
| 142 |
+
):
|
| 143 |
+
v.trace_add("write", lambda *_: self._update_cli_preview())
|
| 144 |
+
|
| 145 |
+
def _apply_theme(self) -> None:
|
| 146 |
+
style = ttk.Style(self.root)
|
| 147 |
+
if "clam" in style.theme_names():
|
| 148 |
+
style.theme_use("clam")
|
| 149 |
+
bg = "#141820"
|
| 150 |
+
panel = "#1c222d"
|
| 151 |
+
fg = "#e6edf3"
|
| 152 |
+
accent = "#3b82f6"
|
| 153 |
+
self.root.configure(bg=bg)
|
| 154 |
+
style.configure(".", background=bg, foreground=fg, fieldbackground=panel)
|
| 155 |
+
style.configure("TFrame", background=bg)
|
| 156 |
+
style.configure("TLabelframe", background=bg, foreground=fg)
|
| 157 |
+
style.configure(
|
| 158 |
+
"TLabelframe.Label",
|
| 159 |
+
background=bg,
|
| 160 |
+
foreground="#93c5fd",
|
| 161 |
+
font=("Sans", 10, "bold"),
|
| 162 |
+
)
|
| 163 |
+
style.configure("TLabel", background=bg, foreground=fg)
|
| 164 |
+
style.configure(
|
| 165 |
+
"TeleKey.TLabel", background=bg, foreground="#9ca3af", font=("Sans", 9)
|
| 166 |
+
)
|
| 167 |
+
style.configure(
|
| 168 |
+
"TeleVal.TLabel",
|
| 169 |
+
background=bg,
|
| 170 |
+
foreground="#60a5fa",
|
| 171 |
+
font=("Monospace", 9, "bold"),
|
| 172 |
+
)
|
| 173 |
+
style.configure("TCheckbutton", background=bg, foreground=fg)
|
| 174 |
+
style.configure("TRadiobutton", background=bg, foreground=fg)
|
| 175 |
+
style.configure("TButton", background=panel, foreground=fg, padding=(10, 5))
|
| 176 |
+
style.map("TButton", background=[("active", accent)])
|
| 177 |
+
style.configure(
|
| 178 |
+
"Accent.TButton",
|
| 179 |
+
background=accent,
|
| 180 |
+
foreground="#ffffff",
|
| 181 |
+
font=("Sans", 10, "bold"),
|
| 182 |
+
)
|
| 183 |
+
style.configure(
|
| 184 |
+
"Treeview",
|
| 185 |
+
background=panel,
|
| 186 |
+
fieldbackground=panel,
|
| 187 |
+
foreground=fg,
|
| 188 |
+
rowheight=23,
|
| 189 |
+
)
|
| 190 |
+
style.configure(
|
| 191 |
+
"Treeview.Heading",
|
| 192 |
+
background="#262f3f",
|
| 193 |
+
foreground=fg,
|
| 194 |
+
font=("Sans", 9, "bold"),
|
| 195 |
+
)
|
| 196 |
+
style.map("Treeview", background=[("selected", accent)])
|
| 197 |
+
|
| 198 |
+
def _build_layout(self) -> None:
|
| 199 |
+
outer = ttk.Frame(self.root)
|
| 200 |
+
outer.pack(fill=tk.BOTH, expand=True)
|
| 201 |
+
outer.rowconfigure(0, weight=1)
|
| 202 |
+
outer.columnconfigure(0, weight=1)
|
| 203 |
+
|
| 204 |
+
self._canvas = tk.Canvas(outer, bg="#141820", highlightthickness=0)
|
| 205 |
+
v_scroll = ttk.Scrollbar(outer, orient=tk.VERTICAL, command=self._canvas.yview)
|
| 206 |
+
h_scroll = ttk.Scrollbar(
|
| 207 |
+
outer, orient=tk.HORIZONTAL, command=self._canvas.xview
|
| 208 |
+
)
|
| 209 |
+
self._canvas.configure(yscrollcommand=v_scroll.set, xscrollcommand=h_scroll.set)
|
| 210 |
+
|
| 211 |
+
self._canvas.grid(row=0, column=0, sticky=tk.NSEW)
|
| 212 |
+
v_scroll.grid(row=0, column=1, sticky=tk.NS)
|
| 213 |
+
h_scroll.grid(row=1, column=0, sticky=tk.EW)
|
| 214 |
+
|
| 215 |
+
main = ttk.Frame(self._canvas, padding=10)
|
| 216 |
+
self._canvas_win = self._canvas.create_window((0, 0), window=main, anchor=tk.NW)
|
| 217 |
+
|
| 218 |
+
def _on_frame_configure(_event=None) -> None:
|
| 219 |
+
self._canvas.configure(scrollregion=self._canvas.bbox("all"))
|
| 220 |
+
|
| 221 |
+
def _on_canvas_configure(event) -> None:
|
| 222 |
+
req_w = max(event.width, main.winfo_reqwidth())
|
| 223 |
+
req_h = max(event.height, main.winfo_reqheight())
|
| 224 |
+
self._canvas.itemconfigure(self._canvas_win, width=req_w, height=req_h)
|
| 225 |
+
|
| 226 |
+
main.bind("<Configure>", _on_frame_configure)
|
| 227 |
+
self._canvas.bind("<Configure>", _on_canvas_configure)
|
| 228 |
+
|
| 229 |
+
# 1. Mode & File Paths Card
|
| 230 |
+
io_frame = ttk.LabelFrame(
|
| 231 |
+
main,
|
| 232 |
+
text=" 1. Operation Mode & Model Paths (Works on Any HF Model Architecture) ",
|
| 233 |
+
padding=10,
|
| 234 |
+
)
|
| 235 |
+
io_frame.pack(fill=tk.X, pady=(0, 8))
|
| 236 |
+
io_frame.columnconfigure(1, weight=1)
|
| 237 |
+
|
| 238 |
+
mode_bar = ttk.Frame(io_frame)
|
| 239 |
+
mode_bar.grid(row=0, column=0, columnspan=3, sticky=tk.W, pady=(0, 8))
|
| 240 |
+
ttk.Label(mode_bar, text="Workflow:", font=("Sans", 9, "bold")).pack(
|
| 241 |
+
side=tk.LEFT, padx=(0, 10)
|
| 242 |
+
)
|
| 243 |
+
ttk.Radiobutton(
|
| 244 |
+
mode_bar,
|
| 245 |
+
text="CheckFree Single-Shard Recovery (1 Shard -> Full Model)",
|
| 246 |
+
variable=self.op_mode_var,
|
| 247 |
+
value="recover",
|
| 248 |
+
).pack(side=tk.LEFT, padx=(0, 14))
|
| 249 |
+
ttk.Radiobutton(
|
| 250 |
+
mode_bar,
|
| 251 |
+
text="Build Self-Contained SlimShard (Multi-Shard -> 1 SlimShard)",
|
| 252 |
+
variable=self.op_mode_var,
|
| 253 |
+
value="build",
|
| 254 |
+
).pack(side=tk.LEFT, padx=(0, 14))
|
| 255 |
+
ttk.Radiobutton(
|
| 256 |
+
mode_bar,
|
| 257 |
+
text="Regenerate from SlimShard",
|
| 258 |
+
variable=self.op_mode_var,
|
| 259 |
+
value="regenerate",
|
| 260 |
+
).pack(side=tk.LEFT)
|
| 261 |
+
|
| 262 |
+
self._add_path_row(
|
| 263 |
+
io_frame,
|
| 264 |
+
1,
|
| 265 |
+
"Surviving Shard / Input (.safetensors):",
|
| 266 |
+
self.shard_var,
|
| 267 |
+
self._pick_shard,
|
| 268 |
+
)
|
| 269 |
+
self._add_path_row(
|
| 270 |
+
io_frame,
|
| 271 |
+
2,
|
| 272 |
+
"Index JSON (optional, auto-inferred if omitted):",
|
| 273 |
+
self.index_var,
|
| 274 |
+
self._pick_index,
|
| 275 |
+
)
|
| 276 |
+
self._add_path_row(
|
| 277 |
+
io_frame,
|
| 278 |
+
3,
|
| 279 |
+
"Config JSON (auto-detected from folder):",
|
| 280 |
+
self.config_var,
|
| 281 |
+
self._pick_config,
|
| 282 |
+
)
|
| 283 |
+
self._add_path_row(
|
| 284 |
+
io_frame,
|
| 285 |
+
4,
|
| 286 |
+
"Source Model Dir (for SlimShard Build):",
|
| 287 |
+
self.model_dir_var,
|
| 288 |
+
self._pick_model_dir,
|
| 289 |
+
)
|
| 290 |
+
self._add_path_row(
|
| 291 |
+
io_frame,
|
| 292 |
+
5,
|
| 293 |
+
"Output .safetensors File:",
|
| 294 |
+
self.output_var,
|
| 295 |
+
self._pick_output,
|
| 296 |
+
)
|
| 297 |
+
self._add_path_row(
|
| 298 |
+
io_frame,
|
| 299 |
+
6,
|
| 300 |
+
"Export Ready-to-Run HF Bundle Dir:",
|
| 301 |
+
self.export_dir_var,
|
| 302 |
+
self._pick_export_dir,
|
| 303 |
+
)
|
| 304 |
+
|
| 305 |
+
# 2. Options & Execution Controls
|
| 306 |
+
opt_frame = ttk.LabelFrame(
|
| 307 |
+
main, text=" 2. CheckFree / SlimShard Engine Parameters ", padding=10
|
| 308 |
+
)
|
| 309 |
+
opt_frame.pack(fill=tk.X, pady=(0, 8))
|
| 310 |
+
|
| 311 |
+
row_opt = ttk.Frame(opt_frame)
|
| 312 |
+
row_opt.pack(fill=tk.X)
|
| 313 |
+
|
| 314 |
+
gpu_lbl = (
|
| 315 |
+
f"CUDA ({cuda_device_name()})" if cuda_is_available() else "CPU only"
|
| 316 |
+
)
|
| 317 |
+
ttk.Label(row_opt, text=f"Compute Device [{gpu_lbl}]:").pack(
|
| 318 |
+
side=tk.LEFT, padx=(0, 6)
|
| 319 |
+
)
|
| 320 |
+
ttk.Combobox(
|
| 321 |
+
row_opt,
|
| 322 |
+
textvariable=self.device_var,
|
| 323 |
+
values=("auto", "cuda", "cpu"),
|
| 324 |
+
width=8,
|
| 325 |
+
state="readonly",
|
| 326 |
+
).pack(side=tk.LEFT, padx=(0, 16))
|
| 327 |
+
|
| 328 |
+
ttk.Label(row_opt, text="SlimShard Format:").pack(side=tk.LEFT, padx=(0, 6))
|
| 329 |
+
ttk.Combobox(
|
| 330 |
+
row_opt,
|
| 331 |
+
textvariable=self.quant_format_var,
|
| 332 |
+
values=("mixed", "q2_k", "q4_0", "exact"),
|
| 333 |
+
width=9,
|
| 334 |
+
state="readonly",
|
| 335 |
+
).pack(side=tk.LEFT, padx=(0, 16))
|
| 336 |
+
|
| 337 |
+
ttk.Label(row_opt, text="SlimMoE Expert Keep Ratio:").pack(
|
| 338 |
+
side=tk.LEFT, padx=(0, 6)
|
| 339 |
+
)
|
| 340 |
+
ttk.Spinbox(
|
| 341 |
+
row_opt,
|
| 342 |
+
from_=0.10,
|
| 343 |
+
to=1.00,
|
| 344 |
+
increment=0.05,
|
| 345 |
+
textvariable=self.expert_keep_var,
|
| 346 |
+
width=6,
|
| 347 |
+
).pack(side=tk.LEFT, padx=(0, 16))
|
| 348 |
+
|
| 349 |
+
ttk.Checkbutton(
|
| 350 |
+
row_opt,
|
| 351 |
+
text="Export Ready-to-Load HF Directory (symlinks config/tokenizer + model.safetensors)",
|
| 352 |
+
variable=self.auto_bundle_var,
|
| 353 |
+
).pack(side=tk.LEFT, padx=(0, 16))
|
| 354 |
+
|
| 355 |
+
btn_bar = ttk.Frame(opt_frame)
|
| 356 |
+
btn_bar.pack(fill=tk.X, pady=(8, 0))
|
| 357 |
+
ttk.Button(
|
| 358 |
+
btn_bar,
|
| 359 |
+
text="Inspect Shard & Recovery Plan",
|
| 360 |
+
command=self._inspect_plan,
|
| 361 |
+
).pack(side=tk.LEFT, padx=(0, 8))
|
| 362 |
+
self.run_btn = ttk.Button(
|
| 363 |
+
btn_bar,
|
| 364 |
+
text="Run Recovery / Build",
|
| 365 |
+
style="Accent.TButton",
|
| 366 |
+
command=self._start_run,
|
| 367 |
+
)
|
| 368 |
+
self.run_btn.pack(side=tk.LEFT, padx=(0, 8))
|
| 369 |
+
self.stop_btn = ttk.Button(
|
| 370 |
+
btn_bar, text="Stop", command=self._stop_run, state=tk.DISABLED
|
| 371 |
+
)
|
| 372 |
+
self.stop_btn.pack(side=tk.LEFT, padx=(0, 14))
|
| 373 |
+
ttk.Entry(btn_bar, textvariable=self.cli_preview_var, state="readonly").pack(
|
| 374 |
+
side=tk.LEFT, fill=tk.X, expand=True
|
| 375 |
+
)
|
| 376 |
+
|
| 377 |
+
# 3. Telemetry Dashboard
|
| 378 |
+
tele = ttk.LabelFrame(main, text=" 3. Real-Time Telemetry ", padding=10)
|
| 379 |
+
tele.pack(fill=tk.X, pady=(0, 8))
|
| 380 |
+
tele.columnconfigure(1, weight=1)
|
| 381 |
+
tele.columnconfigure(3, weight=1)
|
| 382 |
+
|
| 383 |
+
ttk.Label(tele, text="Architecture:", style="TeleKey.TLabel").grid(
|
| 384 |
+
row=0, column=0, sticky=tk.W
|
| 385 |
+
)
|
| 386 |
+
ttk.Label(tele, textvariable=self.arch_summary_var, style="TeleVal.TLabel").grid(
|
| 387 |
+
row=0, column=1, columnspan=3, sticky=tk.W, padx=(6, 0)
|
| 388 |
+
)
|
| 389 |
+
|
| 390 |
+
ttk.Label(tele, text="Layer Coverage:", style="TeleKey.TLabel").grid(
|
| 391 |
+
row=1, column=0, sticky=tk.W, pady=(3, 0)
|
| 392 |
+
)
|
| 393 |
+
ttk.Label(
|
| 394 |
+
tele, textvariable=self.layers_summary_var, style="TeleVal.TLabel"
|
| 395 |
+
).grid(row=1, column=1, columnspan=3, sticky=tk.W, padx=(6, 0), pady=(3, 0))
|
| 396 |
+
|
| 397 |
+
ttk.Label(tele, text="Active Tensor:", style="TeleKey.TLabel").grid(
|
| 398 |
+
row=2, column=0, sticky=tk.W, pady=(3, 0)
|
| 399 |
+
)
|
| 400 |
+
ttk.Label(tele, textvariable=self.tele_tensor_var, style="TeleVal.TLabel").grid(
|
| 401 |
+
row=2, column=1, sticky=tk.W, padx=(6, 0), pady=(3, 0)
|
| 402 |
+
)
|
| 403 |
+
ttk.Label(tele, text="Stage / Action:", style="TeleKey.TLabel").grid(
|
| 404 |
+
row=2, column=2, sticky=tk.W, pady=(3, 0)
|
| 405 |
+
)
|
| 406 |
+
ttk.Label(tele, textvariable=self.tele_action_var, style="TeleVal.TLabel").grid(
|
| 407 |
+
row=2, column=3, sticky=tk.W, padx=(6, 0), pady=(3, 0)
|
| 408 |
+
)
|
| 409 |
+
|
| 410 |
+
ttk.Label(tele, text="Progress:", style="TeleKey.TLabel").grid(
|
| 411 |
+
row=3, column=0, sticky=tk.W, pady=(3, 0)
|
| 412 |
+
)
|
| 413 |
+
ttk.Label(
|
| 414 |
+
tele, textvariable=self.tele_progress_text_var, style="TeleVal.TLabel"
|
| 415 |
+
).grid(row=3, column=1, sticky=tk.W, padx=(6, 0), pady=(3, 0))
|
| 416 |
+
ttk.Label(tele, text="Throughput / ETA:", style="TeleKey.TLabel").grid(
|
| 417 |
+
row=3, column=2, sticky=tk.W, pady=(3, 0)
|
| 418 |
+
)
|
| 419 |
+
ttk.Label(tele, textvariable=self.tele_speed_var, style="TeleVal.TLabel").grid(
|
| 420 |
+
row=3, column=3, sticky=tk.W, padx=(6, 0), pady=(3, 0)
|
| 421 |
+
)
|
| 422 |
+
|
| 423 |
+
ttk.Label(tele, text="Breakdown:", style="TeleKey.TLabel").grid(
|
| 424 |
+
row=4, column=0, sticky=tk.W, pady=(3, 0)
|
| 425 |
+
)
|
| 426 |
+
ttk.Label(
|
| 427 |
+
tele, textvariable=self.tele_breakdown_var, style="TeleVal.TLabel"
|
| 428 |
+
).grid(row=4, column=1, sticky=tk.W, padx=(6, 0), pady=(3, 0))
|
| 429 |
+
ttk.Label(tele, text="Elapsed:", style="TeleKey.TLabel").grid(
|
| 430 |
+
row=4, column=2, sticky=tk.W, pady=(3, 0)
|
| 431 |
+
)
|
| 432 |
+
ttk.Label(
|
| 433 |
+
tele, textvariable=self.tele_elapsed_var, style="TeleVal.TLabel"
|
| 434 |
+
).grid(row=4, column=3, sticky=tk.W, padx=(6, 0), pady=(3, 0))
|
| 435 |
+
|
| 436 |
+
ttk.Progressbar(
|
| 437 |
+
tele, variable=self.progress_var, maximum=100.0, mode="determinate"
|
| 438 |
+
).grid(row=5, column=0, columnspan=4, sticky=tk.EW, pady=(8, 0))
|
| 439 |
+
|
| 440 |
+
# 4. Tensor Recovery Plan Table
|
| 441 |
+
tbl_frame = ttk.LabelFrame(
|
| 442 |
+
main, text=" 4. Tensor Recovery Plan & Status ", padding=10
|
| 443 |
+
)
|
| 444 |
+
tbl_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 8))
|
| 445 |
+
|
| 446 |
+
fbar = ttk.Frame(tbl_frame)
|
| 447 |
+
fbar.pack(fill=tk.X, pady=(0, 6))
|
| 448 |
+
ttk.Label(fbar, text="Filter Action:").pack(side=tk.LEFT, padx=(0, 6))
|
| 449 |
+
cb_filter = ttk.Combobox(
|
| 450 |
+
fbar,
|
| 451 |
+
textvariable=self.filter_action_var,
|
| 452 |
+
values=(
|
| 453 |
+
"ALL",
|
| 454 |
+
"PRESENT",
|
| 455 |
+
"CHECKFREE_LAYER",
|
| 456 |
+
"CHECKFREE_EXPERT",
|
| 457 |
+
"SYNTHESIZE_CALIBRATED",
|
| 458 |
+
"SUFFIX_PRIOR",
|
| 459 |
+
),
|
| 460 |
+
width=22,
|
| 461 |
+
state="readonly",
|
| 462 |
+
)
|
| 463 |
+
cb_filter.pack(side=tk.LEFT, padx=(0, 14))
|
| 464 |
+
cb_filter.bind("<<ComboboxSelected>>", lambda *_: self._refresh_table())
|
| 465 |
+
|
| 466 |
+
ttk.Label(fbar, text="Search Tensor:").pack(side=tk.LEFT, padx=(0, 6))
|
| 467 |
+
ent_search = ttk.Entry(fbar, textvariable=self.search_var, width=32)
|
| 468 |
+
ent_search.pack(side=tk.LEFT, padx=(0, 8))
|
| 469 |
+
ent_search.bind("<KeyRelease>", lambda *_: self._refresh_table())
|
| 470 |
+
|
| 471 |
+
cols = ("idx", "name", "layer", "role", "shard", "action", "dtype", "status")
|
| 472 |
+
self.tree = ttk.Treeview(
|
| 473 |
+
tbl_frame, columns=cols, show="headings", height=10, selectmode="browse"
|
| 474 |
+
)
|
| 475 |
+
headers = {
|
| 476 |
+
"idx": ("#", 55),
|
| 477 |
+
"name": ("Tensor Name", 410),
|
| 478 |
+
"layer": ("Layer", 65),
|
| 479 |
+
"role": ("Role", 150),
|
| 480 |
+
"shard": ("Original Shard", 210),
|
| 481 |
+
"action": ("Recovery Strategy", 170),
|
| 482 |
+
"dtype": ("Dtype", 80),
|
| 483 |
+
"status": ("Status", 95),
|
| 484 |
+
}
|
| 485 |
+
for c, (label, w) in headers.items():
|
| 486 |
+
self.tree.heading(c, text=label)
|
| 487 |
+
self.tree.column(c, width=w, anchor=tk.W if c != "idx" else tk.E)
|
| 488 |
+
|
| 489 |
+
t_scroll = ttk.Scrollbar(tbl_frame, orient=tk.VERTICAL, command=self.tree.yview)
|
| 490 |
+
self.tree.configure(yscrollcommand=t_scroll.set)
|
| 491 |
+
self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
| 492 |
+
t_scroll.pack(side=tk.RIGHT, fill=tk.Y)
|
| 493 |
+
|
| 494 |
+
# 5. Universal Recovered Model Prompt Tester + Log
|
| 495 |
+
bottom_pane = ttk.PanedWindow(main, orient=tk.HORIZONTAL)
|
| 496 |
+
bottom_pane.pack(fill=tk.BOTH, expand=True)
|
| 497 |
+
|
| 498 |
+
test_frame = ttk.LabelFrame(
|
| 499 |
+
bottom_pane,
|
| 500 |
+
text=" 5. Test Recovered Model (Works on Any HF CausalLM) ",
|
| 501 |
+
padding=10,
|
| 502 |
+
)
|
| 503 |
+
bottom_pane.add(test_frame, weight=1)
|
| 504 |
+
|
| 505 |
+
t_row1 = ttk.Frame(test_frame)
|
| 506 |
+
t_row1.pack(fill=tk.X, pady=(0, 4))
|
| 507 |
+
ttk.Label(t_row1, text="Model Dir:").pack(side=tk.LEFT, padx=(0, 6))
|
| 508 |
+
ttk.Entry(t_row1, textvariable=self.test_model_dir_var).pack(
|
| 509 |
+
side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 6)
|
| 510 |
+
)
|
| 511 |
+
ttk.Button(t_row1, text="Browse", command=self._pick_test_dir).pack(
|
| 512 |
+
side=tk.LEFT
|
| 513 |
+
)
|
| 514 |
+
|
| 515 |
+
t_row2 = ttk.Frame(test_frame)
|
| 516 |
+
t_row2.pack(fill=tk.X, pady=(0, 4))
|
| 517 |
+
ttk.Label(t_row2, text="Prompt:").pack(side=tk.LEFT, padx=(0, 6))
|
| 518 |
+
ttk.Entry(t_row2, textvariable=self.test_prompt_var).pack(
|
| 519 |
+
side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 8)
|
| 520 |
+
)
|
| 521 |
+
ttk.Checkbutton(
|
| 522 |
+
t_row2, text="Chat Template", variable=self.test_chat_mode_var
|
| 523 |
+
).pack(side=tk.LEFT, padx=(0, 8))
|
| 524 |
+
ttk.Label(t_row2, text="Max Tokens:").pack(side=tk.LEFT, padx=(0, 4))
|
| 525 |
+
ttk.Spinbox(
|
| 526 |
+
t_row2, from_=1, to=256, textvariable=self.test_max_tokens_var, width=5
|
| 527 |
+
).pack(side=tk.LEFT, padx=(0, 8))
|
| 528 |
+
self.test_btn = ttk.Button(
|
| 529 |
+
t_row2,
|
| 530 |
+
text="Run Prompt",
|
| 531 |
+
style="Accent.TButton",
|
| 532 |
+
command=self._run_prompt_test,
|
| 533 |
+
)
|
| 534 |
+
self.test_btn.pack(side=tk.LEFT)
|
| 535 |
+
|
| 536 |
+
self.test_out_text = tk.Text(
|
| 537 |
+
test_frame,
|
| 538 |
+
height=8,
|
| 539 |
+
bg="#0f131a",
|
| 540 |
+
fg="#a7f3d0",
|
| 541 |
+
insertbackground="#ffffff",
|
| 542 |
+
font=("Monospace", 9),
|
| 543 |
+
wrap=tk.WORD,
|
| 544 |
+
)
|
| 545 |
+
self.test_out_text.pack(fill=tk.BOTH, expand=True)
|
| 546 |
+
|
| 547 |
+
log_frame = ttk.LabelFrame(bottom_pane, text=" 6. Event Log ", padding=10)
|
| 548 |
+
bottom_pane.add(log_frame, weight=1)
|
| 549 |
+
self.log_text = tk.Text(
|
| 550 |
+
log_frame,
|
| 551 |
+
height=8,
|
| 552 |
+
bg="#0f131a",
|
| 553 |
+
fg="#e6edf3",
|
| 554 |
+
insertbackground="#ffffff",
|
| 555 |
+
font=("Monospace", 9),
|
| 556 |
+
wrap=tk.WORD,
|
| 557 |
+
)
|
| 558 |
+
self.log_text.pack(fill=tk.BOTH, expand=True)
|
| 559 |
+
|
| 560 |
+
def _add_path_row(
|
| 561 |
+
self, parent: ttk.Frame, row: int, label: str, var: tk.StringVar, cmd
|
| 562 |
+
) -> None:
|
| 563 |
+
ttk.Label(parent, text=label).grid(row=row, column=0, sticky=tk.W, pady=2)
|
| 564 |
+
ttk.Entry(parent, textvariable=var).grid(
|
| 565 |
+
row=row, column=1, sticky=tk.EW, padx=6, pady=2
|
| 566 |
+
)
|
| 567 |
+
ttk.Button(parent, text="Browse...", command=cmd).grid(
|
| 568 |
+
row=row, column=2, sticky=tk.E, pady=2
|
| 569 |
+
)
|
| 570 |
+
|
| 571 |
+
def _auto_populate_defaults(self) -> None:
|
| 572 |
+
cwd = Path.cwd()
|
| 573 |
+
raon_shard = cwd / "Raon-1-mini-preview" / "model-00001-of-00007.safetensors"
|
| 574 |
+
if raon_shard.exists():
|
| 575 |
+
self._set_shard_and_companions(raon_shard)
|
| 576 |
+
else:
|
| 577 |
+
shards = sorted(cwd.glob("*/*.safetensors"))
|
| 578 |
+
if shards:
|
| 579 |
+
self._set_shard_and_companions(shards[0])
|
| 580 |
+
|
| 581 |
+
def _set_shard_and_companions(self, shard_path: Path) -> None:
|
| 582 |
+
self.shard_var.set(str(shard_path))
|
| 583 |
+
parent = shard_path.parent
|
| 584 |
+
self.model_dir_var.set(str(parent))
|
| 585 |
+
idx = parent / "model.safetensors.index.json"
|
| 586 |
+
if idx.exists():
|
| 587 |
+
self.index_var.set(str(idx))
|
| 588 |
+
cfg = parent / "config.json"
|
| 589 |
+
if cfg.exists():
|
| 590 |
+
self.config_var.set(str(cfg))
|
| 591 |
+
if not self.output_var.get():
|
| 592 |
+
self.output_var.set(str(Path.cwd() / f"{parent.name}-recovered.safetensors"))
|
| 593 |
+
if not self.export_dir_var.get():
|
| 594 |
+
self.export_dir_var.set(str(Path.cwd() / f"recovered_{parent.name.lower().replace('-', '_')}"))
|
| 595 |
+
self.test_model_dir_var.set(self.export_dir_var.get())
|
| 596 |
+
|
| 597 |
+
def _pick_shard(self) -> None:
|
| 598 |
+
p = filedialog.askopenfilename(
|
| 599 |
+
title="Select Surviving .safetensors Shard",
|
| 600 |
+
filetypes=[("SafeTensors", "*.safetensors"), ("All files", "*.*")],
|
| 601 |
+
)
|
| 602 |
+
if p:
|
| 603 |
+
self._set_shard_and_companions(Path(p))
|
| 604 |
+
self._inspect_plan()
|
| 605 |
+
|
| 606 |
+
def _pick_index(self) -> None:
|
| 607 |
+
p = filedialog.askopenfilename(
|
| 608 |
+
title="Select model.safetensors.index.json",
|
| 609 |
+
filetypes=[("JSON", "*.json"), ("All files", "*.*")],
|
| 610 |
+
)
|
| 611 |
+
if p:
|
| 612 |
+
self.index_var.set(p)
|
| 613 |
+
|
| 614 |
+
def _pick_config(self) -> None:
|
| 615 |
+
p = filedialog.askopenfilename(
|
| 616 |
+
title="Select config.json",
|
| 617 |
+
filetypes=[("JSON", "*.json"), ("All files", "*.*")],
|
| 618 |
+
)
|
| 619 |
+
if p:
|
| 620 |
+
self.config_var.set(p)
|
| 621 |
+
|
| 622 |
+
def _pick_model_dir(self) -> None:
|
| 623 |
+
p = filedialog.askdirectory(title="Select HF Model Directory")
|
| 624 |
+
if p:
|
| 625 |
+
self.model_dir_var.set(p)
|
| 626 |
+
|
| 627 |
+
def _pick_output(self) -> None:
|
| 628 |
+
p = filedialog.asksaveasfilename(
|
| 629 |
+
title="Select Output .safetensors Path",
|
| 630 |
+
defaultextension=".safetensors",
|
| 631 |
+
filetypes=[("SafeTensors", "*.safetensors"), ("All files", "*.*")],
|
| 632 |
+
)
|
| 633 |
+
if p:
|
| 634 |
+
self.output_var.set(p)
|
| 635 |
+
|
| 636 |
+
def _pick_export_dir(self) -> None:
|
| 637 |
+
p = filedialog.askdirectory(title="Select Export HF Bundle Directory")
|
| 638 |
+
if p:
|
| 639 |
+
self.export_dir_var.set(p)
|
| 640 |
+
self.test_model_dir_var.set(p)
|
| 641 |
+
|
| 642 |
+
def _pick_test_dir(self) -> None:
|
| 643 |
+
p = filedialog.askdirectory(title="Select Recovered HF Model Directory")
|
| 644 |
+
if p:
|
| 645 |
+
self.test_model_dir_var.set(p)
|
| 646 |
+
|
| 647 |
+
def _update_cli_preview(self) -> None:
|
| 648 |
+
mode = self.op_mode_var.get()
|
| 649 |
+
cmd = ["python3", "-m", "hpc_quantize_v2.slimshard", mode]
|
| 650 |
+
if mode == "recover":
|
| 651 |
+
if self.shard_var.get():
|
| 652 |
+
cmd += ["--shard", self.shard_var.get()]
|
| 653 |
+
if self.index_var.get():
|
| 654 |
+
cmd += ["--index", self.index_var.get()]
|
| 655 |
+
if self.config_var.get():
|
| 656 |
+
cmd += ["--config", self.config_var.get()]
|
| 657 |
+
if self.output_var.get():
|
| 658 |
+
cmd += ["--output", self.output_var.get()]
|
| 659 |
+
if self.auto_bundle_var.get() and self.export_dir_var.get():
|
| 660 |
+
cmd += ["--export-hf-dir", self.export_dir_var.get()]
|
| 661 |
+
cmd += ["--device", self.device_var.get()]
|
| 662 |
+
elif mode == "build":
|
| 663 |
+
if self.model_dir_var.get():
|
| 664 |
+
cmd += ["--model-dir", self.model_dir_var.get()]
|
| 665 |
+
if self.output_var.get():
|
| 666 |
+
cmd += ["--output", self.output_var.get()]
|
| 667 |
+
cmd += [
|
| 668 |
+
"--format",
|
| 669 |
+
self.quant_format_var.get(),
|
| 670 |
+
"--expert-keep-ratio",
|
| 671 |
+
f"{self.expert_keep_var.get():.2f}",
|
| 672 |
+
"--device",
|
| 673 |
+
self.device_var.get(),
|
| 674 |
+
]
|
| 675 |
+
else:
|
| 676 |
+
if self.shard_var.get():
|
| 677 |
+
cmd += ["--input", self.shard_var.get()]
|
| 678 |
+
if self.output_var.get():
|
| 679 |
+
cmd += ["--output", self.output_var.get()]
|
| 680 |
+
self.cli_preview_var.set(" ".join(shlex.quote(x) for x in cmd))
|
| 681 |
+
|
| 682 |
+
def _log(self, msg: str) -> None:
|
| 683 |
+
self.log_text.insert(tk.END, f"[{_ts()}] {msg}\n")
|
| 684 |
+
self.log_text.see(tk.END)
|
| 685 |
+
|
| 686 |
+
def _inspect_plan(self) -> None:
|
| 687 |
+
shard = self.shard_var.get().strip()
|
| 688 |
+
if not shard or not Path(shard).exists():
|
| 689 |
+
messagebox.showwarning("SlimShard", "Please select a valid .safetensors shard first.")
|
| 690 |
+
return
|
| 691 |
+
try:
|
| 692 |
+
plan = inspect_recovery_plan(
|
| 693 |
+
shard,
|
| 694 |
+
index=self.index_var.get().strip() or None,
|
| 695 |
+
config=self.config_var.get().strip() or None,
|
| 696 |
+
)
|
| 697 |
+
except Exception as exc:
|
| 698 |
+
messagebox.showerror("Inspect Failed", str(exc))
|
| 699 |
+
return
|
| 700 |
+
|
| 701 |
+
archs = ",".join(plan["architectures"]) or plan["model_type"]
|
| 702 |
+
self.arch_summary_var.set(
|
| 703 |
+
f"{archs} (type={plan['model_type']}, hidden={plan['hidden_size']}, "
|
| 704 |
+
f"layers={plan['num_hidden_layers']}, experts={plan['num_experts']}, "
|
| 705 |
+
f"vocab={plan['vocab_size']}, total_tensors={plan['total_tensors']})"
|
| 706 |
+
)
|
| 707 |
+
surv = plan["surviving_layers"]
|
| 708 |
+
miss = plan["missing_layers"]
|
| 709 |
+
self.layers_summary_var.set(
|
| 710 |
+
f"Surviving in shard ({len(surv)}): {surv[:12]}{'...' if len(surv) > 12 else ''} | "
|
| 711 |
+
f"Missing to CheckFree-reconstruct ({len(miss)}): {miss[:12]}{'...' if len(miss) > 12 else ''}"
|
| 712 |
+
)
|
| 713 |
+
c = plan["counts"]
|
| 714 |
+
self.tele_breakdown_var.set(
|
| 715 |
+
f"present={c.get('PRESENT', 0)} | layer_interp={c.get('CHECKFREE_LAYER', 0)} | "
|
| 716 |
+
f"expert_interp={c.get('CHECKFREE_EXPERT', 0)} | synth={c.get('SYNTHESIZE_CALIBRATED', 0)}"
|
| 717 |
+
)
|
| 718 |
+
self._plan_rows = plan["rows"]
|
| 719 |
+
self._refresh_table()
|
| 720 |
+
self._log(
|
| 721 |
+
f"Inspected {Path(shard).name}: {plan['present_tensors']}/{plan['total_tensors']} present, "
|
| 722 |
+
f"{len(miss)} layers to reconstruct via CheckFree."
|
| 723 |
+
)
|
| 724 |
+
|
| 725 |
+
def _refresh_table(self) -> None:
|
| 726 |
+
self.tree.delete(*self.tree.get_children())
|
| 727 |
+
f_act = self.filter_action_var.get()
|
| 728 |
+
q = self.search_var.get().strip().lower()
|
| 729 |
+
shown = 0
|
| 730 |
+
for idx, r in enumerate(self._plan_rows, 1):
|
| 731 |
+
if f_act != "ALL" and r["action"] != f_act:
|
| 732 |
+
continue
|
| 733 |
+
if q and q not in r["name"].lower() and q not in r["role"].lower():
|
| 734 |
+
continue
|
| 735 |
+
self.tree.insert(
|
| 736 |
+
"",
|
| 737 |
+
tk.END,
|
| 738 |
+
iid=r["name"],
|
| 739 |
+
values=(
|
| 740 |
+
idx,
|
| 741 |
+
r["name"],
|
| 742 |
+
r["layer"],
|
| 743 |
+
r["role"],
|
| 744 |
+
r["shard"],
|
| 745 |
+
r["action"],
|
| 746 |
+
r["dtype"],
|
| 747 |
+
"Planned",
|
| 748 |
+
),
|
| 749 |
+
)
|
| 750 |
+
shown += 1
|
| 751 |
+
if shown >= 1500:
|
| 752 |
+
break
|
| 753 |
+
|
| 754 |
+
def _start_run(self) -> None:
|
| 755 |
+
if self._worker is not None and self._worker.is_alive():
|
| 756 |
+
return
|
| 757 |
+
mode = self.op_mode_var.get()
|
| 758 |
+
out = self.output_var.get().strip()
|
| 759 |
+
if not out:
|
| 760 |
+
messagebox.showwarning("SlimShard", "Please specify an output .safetensors path.")
|
| 761 |
+
return
|
| 762 |
+
|
| 763 |
+
self._stop_event.clear()
|
| 764 |
+
self._start_time = time.time()
|
| 765 |
+
self.progress_var.set(0.0)
|
| 766 |
+
self.run_btn.configure(state=tk.DISABLED)
|
| 767 |
+
self.stop_btn.configure(state=tk.NORMAL)
|
| 768 |
+
|
| 769 |
+
def progress_cb(done: int, total: int, tname: str, action: str, stats: dict) -> None:
|
| 770 |
+
self._queue.put(("progress", (done, total, tname, action, dict(stats))))
|
| 771 |
+
|
| 772 |
+
def worker() -> None:
|
| 773 |
+
try:
|
| 774 |
+
if mode == "recover":
|
| 775 |
+
shard = self.shard_var.get().strip()
|
| 776 |
+
idx = self.index_var.get().strip() or None
|
| 777 |
+
cfg = self.config_var.get().strip() or None
|
| 778 |
+
exp_dir = (
|
| 779 |
+
self.export_dir_var.get().strip()
|
| 780 |
+
if self.auto_bundle_var.get() and self.export_dir_var.get().strip()
|
| 781 |
+
else None
|
| 782 |
+
)
|
| 783 |
+
res = recover_from_shard(
|
| 784 |
+
shard,
|
| 785 |
+
idx,
|
| 786 |
+
out,
|
| 787 |
+
config=cfg,
|
| 788 |
+
device=self.device_var.get(),
|
| 789 |
+
verbose=False,
|
| 790 |
+
progress_cb=progress_cb,
|
| 791 |
+
stop_event=self._stop_event,
|
| 792 |
+
export_hf_dir=exp_dir,
|
| 793 |
+
)
|
| 794 |
+
if exp_dir:
|
| 795 |
+
self._queue.put(("set_test_dir", exp_dir))
|
| 796 |
+
self._queue.put(("done", ("CheckFree Recovery Complete", res)))
|
| 797 |
+
elif mode == "build":
|
| 798 |
+
mdir = self.model_dir_var.get().strip()
|
| 799 |
+
cfg_obj = HPCConfig(device=self.device_var.get(), verbose=False).validate()
|
| 800 |
+
res = build_slimshard(
|
| 801 |
+
mdir,
|
| 802 |
+
out,
|
| 803 |
+
cfg=cfg_obj,
|
| 804 |
+
quant_format=self.quant_format_var.get(),
|
| 805 |
+
expert_keep_ratio=float(self.expert_keep_var.get()),
|
| 806 |
+
verbose=False,
|
| 807 |
+
progress_cb=progress_cb,
|
| 808 |
+
stop_event=self._stop_event,
|
| 809 |
+
)
|
| 810 |
+
self._queue.put(("done", ("SlimShard Build Complete", res)))
|
| 811 |
+
else:
|
| 812 |
+
shard = self.shard_var.get().strip()
|
| 813 |
+
res = regenerate(
|
| 814 |
+
shard,
|
| 815 |
+
out,
|
| 816 |
+
verbose=False,
|
| 817 |
+
progress_cb=progress_cb,
|
| 818 |
+
stop_event=self._stop_event,
|
| 819 |
+
)
|
| 820 |
+
self._queue.put(("done", ("SlimShard Regeneration Complete", res)))
|
| 821 |
+
except Exception as exc:
|
| 822 |
+
self._queue.put(("error", str(exc)))
|
| 823 |
+
|
| 824 |
+
self._worker = threading.Thread(target=worker, daemon=True)
|
| 825 |
+
self._worker.start()
|
| 826 |
+
self._log(f"Started {mode} -> {out}")
|
| 827 |
+
|
| 828 |
+
def _stop_run(self) -> None:
|
| 829 |
+
self._stop_event.set()
|
| 830 |
+
self._log("Cancellation requested...")
|
| 831 |
+
|
| 832 |
+
def _run_prompt_test(self) -> None:
|
| 833 |
+
mdir = self.test_model_dir_var.get().strip() or self.export_dir_var.get().strip()
|
| 834 |
+
if not mdir or not Path(mdir).exists():
|
| 835 |
+
messagebox.showwarning(
|
| 836 |
+
"Model Tester",
|
| 837 |
+
"Please specify a valid Recovered HF Model Directory first.",
|
| 838 |
+
)
|
| 839 |
+
return
|
| 840 |
+
prompt = self.test_prompt_var.get()
|
| 841 |
+
use_chat = bool(self.test_chat_mode_var.get())
|
| 842 |
+
max_new = int(self.test_max_tokens_var.get())
|
| 843 |
+
|
| 844 |
+
self.test_btn.configure(state=tk.DISABLED)
|
| 845 |
+
self.test_out_text.delete("1.0", tk.END)
|
| 846 |
+
self.test_out_text.insert(
|
| 847 |
+
tk.END, f"Loading {mdir} and running prompt {prompt!r}...\n"
|
| 848 |
+
)
|
| 849 |
+
|
| 850 |
+
def test_worker() -> None:
|
| 851 |
+
try:
|
| 852 |
+
import torch
|
| 853 |
+
import torch.nn.functional as F
|
| 854 |
+
from safetensors.torch import safe_open
|
| 855 |
+
from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer
|
| 856 |
+
|
| 857 |
+
t0 = time.time()
|
| 858 |
+
tok = AutoTokenizer.from_pretrained(
|
| 859 |
+
mdir, trust_remote_code=True, local_files_only=True
|
| 860 |
+
)
|
| 861 |
+
cfg = AutoConfig.from_pretrained(
|
| 862 |
+
mdir, trust_remote_code=True, local_files_only=True
|
| 863 |
+
)
|
| 864 |
+
st_file = Path(mdir) / "model.safetensors"
|
| 865 |
+
dev = "cuda:0" if torch.cuda.is_available() else "cpu"
|
| 866 |
+
|
| 867 |
+
# Fast on-demand expert streaming for MXFP8 MoE models, or standard load for generic models
|
| 868 |
+
q_cfg = getattr(cfg, "quantization_config", None) or {}
|
| 869 |
+
is_mxfp8 = (
|
| 870 |
+
isinstance(q_cfg, dict) and q_cfg.get("quant_method") == "mxfp8"
|
| 871 |
+
) or getattr(q_cfg, "quant_method", None) == "mxfp8"
|
| 872 |
+
|
| 873 |
+
if is_mxfp8 and st_file.exists():
|
| 874 |
+
with torch.device("meta"):
|
| 875 |
+
model = AutoModelForCausalLM.from_config(
|
| 876 |
+
cfg, trust_remote_code=True, dtype=torch.bfloat16
|
| 877 |
+
)
|
| 878 |
+
sf = safe_open(str(st_file), framework="pt", device="cpu")
|
| 879 |
+
for name, _ in list(model.named_parameters()):
|
| 880 |
+
if ".moe.experts." in name:
|
| 881 |
+
continue
|
| 882 |
+
parts = name.split(".")
|
| 883 |
+
mod = model
|
| 884 |
+
for p in parts[:-1]:
|
| 885 |
+
mod = getattr(mod, p)
|
| 886 |
+
t = sf.get_tensor(name).to(device=dev)
|
| 887 |
+
if t.dtype == torch.float32 and "e_score_correction_bias" not in name:
|
| 888 |
+
t = t.to(torch.bfloat16)
|
| 889 |
+
setattr(mod, parts[-1], torch.nn.Parameter(t, requires_grad=False))
|
| 890 |
+
|
| 891 |
+
moe_layer = next(
|
| 892 |
+
(l for l in model.model.layers if getattr(l, "is_moe", False)),
|
| 893 |
+
None,
|
| 894 |
+
)
|
| 895 |
+
if moe_layer is not None:
|
| 896 |
+
mod_cls = type(moe_layer.moe)
|
| 897 |
+
raon_mod = __import__(
|
| 898 |
+
mod_cls.__module__, fromlist=["dequantize_mxfp8", "situ_glu"]
|
| 899 |
+
)
|
| 900 |
+
dequantize_mxfp8 = raon_mod.dequantize_mxfp8
|
| 901 |
+
situ_glu = raon_mod.situ_glu
|
| 902 |
+
for lidx, layer in enumerate(model.model.layers):
|
| 903 |
+
if getattr(layer, "is_moe", False):
|
| 904 |
+
layer.moe._layer_idx = lidx
|
| 905 |
+
|
| 906 |
+
def fast_moe_forward(self_moe, hidden: torch.Tensor) -> torch.Tensor:
|
| 907 |
+
batch, seq, dim = hidden.shape
|
| 908 |
+
flat = hidden.reshape(-1, dim)
|
| 909 |
+
top, probs = self_moe.gate(flat)
|
| 910 |
+
out = torch.zeros(
|
| 911 |
+
flat.shape[0], dim, dtype=torch.float32, device=flat.device
|
| 912 |
+
)
|
| 913 |
+
hit = torch.bincount(
|
| 914 |
+
top.flatten(), minlength=self_moe.num_experts
|
| 915 |
+
)
|
| 916 |
+
prefix = f"model.layers.{self_moe._layer_idx}.moe.experts"
|
| 917 |
+
for expert_idx in hit.nonzero().flatten().tolist():
|
| 918 |
+
rows, slot = torch.where(top == expert_idx)
|
| 919 |
+
x = flat.index_select(0, rows)
|
| 920 |
+
ep = f"{prefix}.{expert_idx}"
|
| 921 |
+
gw = dequantize_mxfp8(
|
| 922 |
+
sf.get_tensor(f"{ep}.gate_proj.weight").to(dev, non_blocking=True),
|
| 923 |
+
sf.get_tensor(f"{ep}.gate_proj.weight_scale_inv").to(dev, non_blocking=True),
|
| 924 |
+
x.dtype,
|
| 925 |
+
)
|
| 926 |
+
uw = dequantize_mxfp8(
|
| 927 |
+
sf.get_tensor(f"{ep}.up_proj.weight").to(dev, non_blocking=True),
|
| 928 |
+
sf.get_tensor(f"{ep}.up_proj.weight_scale_inv").to(dev, non_blocking=True),
|
| 929 |
+
x.dtype,
|
| 930 |
+
)
|
| 931 |
+
dw = dequantize_mxfp8(
|
| 932 |
+
sf.get_tensor(f"{ep}.down_proj.weight").to(dev, non_blocking=True),
|
| 933 |
+
sf.get_tensor(f"{ep}.down_proj.weight_scale_inv").to(dev, non_blocking=True),
|
| 934 |
+
x.dtype,
|
| 935 |
+
)
|
| 936 |
+
act = situ_glu(
|
| 937 |
+
F.linear(x, gw),
|
| 938 |
+
F.linear(x, uw),
|
| 939 |
+
self_moe.gate_beta,
|
| 940 |
+
self_moe.value_beta,
|
| 941 |
+
).to(x.dtype)
|
| 942 |
+
out.index_add_(
|
| 943 |
+
0,
|
| 944 |
+
rows,
|
| 945 |
+
F.linear(act, dw).float()
|
| 946 |
+
* probs[rows, slot].unsqueeze(-1),
|
| 947 |
+
)
|
| 948 |
+
out = out.to(hidden.dtype)
|
| 949 |
+
if self_moe.shared_experts is not None:
|
| 950 |
+
out = out + self_moe.shared_experts(flat)
|
| 951 |
+
return out.reshape(batch, seq, dim)
|
| 952 |
+
|
| 953 |
+
mod_cls.forward = fast_moe_forward
|
| 954 |
+
else:
|
| 955 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 956 |
+
mdir,
|
| 957 |
+
trust_remote_code=True,
|
| 958 |
+
local_files_only=True,
|
| 959 |
+
dtype="auto",
|
| 960 |
+
device_map="auto",
|
| 961 |
+
)
|
| 962 |
+
|
| 963 |
+
model.eval()
|
| 964 |
+
with torch.no_grad():
|
| 965 |
+
if use_chat and getattr(tok, "chat_template", None):
|
| 966 |
+
inputs = tok.apply_chat_template(
|
| 967 |
+
[{"role": "user", "content": prompt}],
|
| 968 |
+
add_generation_prompt=True,
|
| 969 |
+
tokenize=True,
|
| 970 |
+
return_dict=True,
|
| 971 |
+
return_tensors="pt",
|
| 972 |
+
enable_thinking=False,
|
| 973 |
+
).to(dev)
|
| 974 |
+
in_len = inputs["input_ids"].shape[-1]
|
| 975 |
+
out_ids = model.generate(
|
| 976 |
+
**inputs,
|
| 977 |
+
max_new_tokens=max_new,
|
| 978 |
+
do_sample=False,
|
| 979 |
+
use_cache=True,
|
| 980 |
+
pad_token_id=tok.eos_token_id,
|
| 981 |
+
)
|
| 982 |
+
decoded = tok.decode(out_ids[0][in_len:], skip_special_tokens=False)
|
| 983 |
+
else:
|
| 984 |
+
ids = tok(prompt, return_tensors="pt")["input_ids"].to(dev)
|
| 985 |
+
out_ids = model.generate(
|
| 986 |
+
ids,
|
| 987 |
+
max_new_tokens=max_new,
|
| 988 |
+
do_sample=False,
|
| 989 |
+
use_cache=True,
|
| 990 |
+
pad_token_id=tok.eos_token_id,
|
| 991 |
+
)
|
| 992 |
+
decoded = tok.decode(out_ids[0], skip_special_tokens=False)
|
| 993 |
+
|
| 994 |
+
dt_s = time.time() - t0
|
| 995 |
+
self._queue.put(
|
| 996 |
+
(
|
| 997 |
+
"test_done",
|
| 998 |
+
f"Completed in {dt_s:.2f}s:\n{decoded}\n\nToken IDs: {out_ids[0].tolist()}",
|
| 999 |
+
)
|
| 1000 |
+
)
|
| 1001 |
+
except Exception as exc:
|
| 1002 |
+
self._queue.put(("test_done", f"Error: {exc}"))
|
| 1003 |
+
|
| 1004 |
+
threading.Thread(target=test_worker, daemon=True).start()
|
| 1005 |
+
|
| 1006 |
+
def _poll_queue(self) -> None:
|
| 1007 |
+
try:
|
| 1008 |
+
while True:
|
| 1009 |
+
kind, payload = self._queue.get_nowait()
|
| 1010 |
+
if kind == "progress":
|
| 1011 |
+
done, total, tname, action, stats = payload
|
| 1012 |
+
pct = 100.0 * float(done) / float(max(total, 1))
|
| 1013 |
+
self.progress_var.set(pct)
|
| 1014 |
+
self.tele_tensor_var.set(tname)
|
| 1015 |
+
self.tele_action_var.set(action)
|
| 1016 |
+
self.tele_progress_text_var.set(f"{done} / {total} ({pct:.1f}%)")
|
| 1017 |
+
elapsed = max(time.time() - (self._start_time or time.time()), 1.0e-3)
|
| 1018 |
+
rate = float(done) / elapsed
|
| 1019 |
+
eta = float(max(total - done, 0)) / max(rate, 1.0e-6)
|
| 1020 |
+
self.tele_speed_var.set(f"{rate:.1f} ten/s (ETA {_fmt_eta(eta)})")
|
| 1021 |
+
self.tele_elapsed_var.set(_fmt_eta(elapsed))
|
| 1022 |
+
if "present" in stats:
|
| 1023 |
+
self.tele_breakdown_var.set(
|
| 1024 |
+
f"present={stats.get('present', 0)} | "
|
| 1025 |
+
f"layer_interp={stats.get('checkfree_interpolated', 0)} | "
|
| 1026 |
+
f"expert_interp={stats.get('expert_interpolated', 0)} | "
|
| 1027 |
+
f"synth={stats.get('synthesized', 0)}"
|
| 1028 |
+
)
|
| 1029 |
+
if self.tree.exists(tname):
|
| 1030 |
+
vals = list(self.tree.item(tname, "values"))
|
| 1031 |
+
vals[-1] = "Done"
|
| 1032 |
+
self.tree.item(tname, values=vals)
|
| 1033 |
+
elif kind == "set_test_dir":
|
| 1034 |
+
self.test_model_dir_var.set(str(payload))
|
| 1035 |
+
elif kind == "done":
|
| 1036 |
+
title, stats = payload
|
| 1037 |
+
elapsed = time.time() - (self._start_time or time.time())
|
| 1038 |
+
self.progress_var.set(100.0)
|
| 1039 |
+
self.tele_action_var.set("Completed")
|
| 1040 |
+
self.tele_elapsed_var.set(_fmt_eta(elapsed))
|
| 1041 |
+
self.run_btn.configure(state=tk.NORMAL)
|
| 1042 |
+
self.stop_btn.configure(state=tk.DISABLED)
|
| 1043 |
+
self._log(f"{title} in {_fmt_eta(elapsed)}: {stats}")
|
| 1044 |
+
elif kind == "error":
|
| 1045 |
+
self.tele_action_var.set("Error / Stopped")
|
| 1046 |
+
self.run_btn.configure(state=tk.NORMAL)
|
| 1047 |
+
self.stop_btn.configure(state=tk.DISABLED)
|
| 1048 |
+
self._log(f"ERROR: {payload}")
|
| 1049 |
+
messagebox.showerror("SlimShard Error", str(payload))
|
| 1050 |
+
elif kind == "test_done":
|
| 1051 |
+
self.test_btn.configure(state=tk.NORMAL)
|
| 1052 |
+
self.test_out_text.delete("1.0", tk.END)
|
| 1053 |
+
self.test_out_text.insert(tk.END, str(payload))
|
| 1054 |
+
self._log("Prompt evaluation finished.")
|
| 1055 |
+
except queue.Empty:
|
| 1056 |
+
pass
|
| 1057 |
+
self.root.after(80, self._poll_queue)
|
| 1058 |
+
|
| 1059 |
+
|
| 1060 |
+
def launch_slimshard_gui(parent: tk.Tk | None = None) -> SlimShardGUI:
|
| 1061 |
+
if parent is not None:
|
| 1062 |
+
win = tk.Toplevel(parent)
|
| 1063 |
+
return SlimShardGUI(win)
|
| 1064 |
+
root = tk.Tk()
|
| 1065 |
+
app = SlimShardGUI(root)
|
| 1066 |
+
root.mainloop()
|
| 1067 |
+
return app
|
| 1068 |
+
|
| 1069 |
+
|
| 1070 |
+
if __name__ == "__main__":
|
| 1071 |
+
launch_slimshard_gui()
|