Instructions to use KaedeTai/Qwen3.6-35B-A3B-Escha-W2-Codebook-Ref with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use KaedeTai/Qwen3.6-35B-A3B-Escha-W2-Codebook-Ref with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] huggingface-cli download --local-dir Qwen3.6-35B-A3B-Escha-W2-Codebook-Ref KaedeTai/Qwen3.6-35B-A3B-Escha-W2-Codebook-Ref
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Atomic Chat
Initial: extracted Escha packed AQLM codebook + audit + reproducers
Browse files- LAYOUT_NOTES.md +110 -0
- OP_SIGNATURE_AUDIT.md +201 -0
- README.md +131 -0
- compact.pkl +3 -0
- modal_op_audit.py +303 -0
- modal_smart_probe.py +257 -0
LAYOUT_NOTES.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Escha packed layout — reverse-engineering notes (updated Aug 2026, post-Option-A)
|
| 2 |
+
|
| 3 |
+
## Summary — where we are now
|
| 4 |
+
|
| 5 |
+
**Modal audit + smart probe: SUCCESS.** The full (K, k_slot, code_value) →
|
| 6 |
+
(row, col, weight_value) codebook has been extracted in a compact form (120 MB,
|
| 7 |
+
~1024 A10G op calls total, ~2 min GPU wall time) and verified for isolated
|
| 8 |
+
single-code lookups.
|
| 9 |
+
|
| 10 |
+
**End-to-end packed inference: PARTIALLY WORKING.** MLX `escham_reconstruct`
|
| 11 |
+
correctly reproduces the CUDA op's output for any single-slot code (max abs
|
| 12 |
+
diff = fp16/bf16 rounding, ~0.01). For a real expert whose codes activate all
|
| 13 |
+
262 K slots simultaneously, my reconstruction picks up an unresolved
|
| 14 |
+
density-dependent bias equal in norm to the raw delta (~4 kOh). This bias is
|
| 15 |
+
NOT expert-independent, contradicting the simple `w_bare = w0 + delta` model
|
| 16 |
+
that the linearity audit (`docs/escha_op_signature.md`) predicts.
|
| 17 |
+
|
| 18 |
+
Root cause candidates (all unverified — Modal workspace hit spend limit before
|
| 19 |
+
the follow-up probe could run):
|
| 20 |
+
1. Escha's `escha_t128` implementation differs from the plain-Hadamard
|
| 21 |
+
`t128` in `transform.py` by a scaling / permutation / bias term. If so,
|
| 22 |
+
our compose+invert self-round-trip stays consistent but never reaches
|
| 23 |
+
the reference op's true `w_bare`.
|
| 24 |
+
2. The op has a per-tile bias (function of `(bi, bj)` alone, but non-uniform
|
| 25 |
+
across blocks) that our extraction folded into the "baseline"
|
| 26 |
+
via the `w0 = op(all-zeros)` subtraction.
|
| 27 |
+
3. The op is not truly linear at high code density (superposition test only
|
| 28 |
+
verified for 100 random slots out of 262 K).
|
| 29 |
+
|
| 30 |
+
Fix path — one more Modal probe would resolve it: dump `op(all-zeros, in_p,
|
| 31 |
+
out_p, K)` as an fp16 tensor (in_p × out_p, ~6 MB total for both K values),
|
| 32 |
+
plus one `op(real_expert_code)` reference for cross-check. Blocked on Modal
|
| 33 |
+
spend limit at 2026-08-01 17:20 CST.
|
| 34 |
+
|
| 35 |
+
## What we extracted (Modal smart probe — `codebooks/modal_smart_probe.py`)
|
| 36 |
+
|
| 37 |
+
Runtime: 46.5 s for K=2 (256 op calls) + ~90 s for K=3 (768 op calls).
|
| 38 |
+
Total ≈ 2 min A10G, ~$0.04.
|
| 39 |
+
|
| 40 |
+
- `codebooks/layout_v2/compact.pkl` (120 MB): compact sparse codebook.
|
| 41 |
+
Keys `K{2,3}_positions[k]` = (n_nz, 2) int8 row/col positions;
|
| 42 |
+
`K{2,3}_values[k]` = (65536, n_nz) fp16 codebook values.
|
| 43 |
+
- `codebooks/layout_v2/cb_K{2,3}.npy` on the `escha-codebooks` Modal Volume:
|
| 44 |
+
fully dense (k_max, 65536, 16, 16) fp16, ~1 GB + 1.5 GB.
|
| 45 |
+
|
| 46 |
+
Verified properties (see `docs/escha_op_signature.md`):
|
| 47 |
+
- Op is exactly LINEAR in codes across up to 100 random slot activations
|
| 48 |
+
(superposition |diff|=0).
|
| 49 |
+
- Codebook is (bi, bj)-INVARIANT across all tile positions (up to (bi*16,
|
| 50 |
+
bj*16) offset), including corners like (bi=127, bj=63) vs (bi=0, bj=0).
|
| 51 |
+
- Op supports leading batch dimensions on `packed` — enabling further
|
| 52 |
+
parallelism if needed.
|
| 53 |
+
|
| 54 |
+
## Structural regularities in the k_slot layout
|
| 55 |
+
|
| 56 |
+
For K=2 (32 slots per 16×16 block), the (row, col) support of each k_slot is:
|
| 57 |
+
- Row pattern cycles with period 4: {[4,5,11,12,13], [2,3,9,10,11],
|
| 58 |
+
[0,1,8,9,15]+extra, [6,7,13,14,15]}
|
| 59 |
+
- Col pattern: `col_c = k_slot // 4`, cols = `[col_c, col_c + 8]`
|
| 60 |
+
(with an extra col at `k_slot % 4 == 2`)
|
| 61 |
+
|
| 62 |
+
For K=3 (48 slots), similar cycle with period 6.
|
| 63 |
+
|
| 64 |
+
These patterns are extractable in ~1 s of GPU time (1 op call per k_slot);
|
| 65 |
+
they encode which 8-10 output positions each `cb[k, v]` writes to.
|
| 66 |
+
|
| 67 |
+
## Bug in the earlier `cb_K2.npy` / `cb_K3.npy` extraction
|
| 68 |
+
|
| 69 |
+
The prior `modal_extract_v2.py` only captured `d[first_nz_row, :32]` — a single
|
| 70 |
+
32-value slice of the first non-zero row of the delta. This missed the other
|
| 71 |
+
4-5 rows of each pattern. That's why plugging cb_K2/cb_K3 into `eschamoe.py`
|
| 72 |
+
produced L2 diff 1.16 on the first row: the codebook was under-specified by 5x.
|
| 73 |
+
|
| 74 |
+
The new `compact.pkl` extraction fixes this — it captures every non-zero
|
| 75 |
+
position across all 65 K code values.
|
| 76 |
+
|
| 77 |
+
## Files on disk
|
| 78 |
+
|
| 79 |
+
- `codebooks/modal_op_audit.py` — signature + linearity audit (Modal)
|
| 80 |
+
- `codebooks/modal_smart_probe.py` — batched 1024-op codebook extraction
|
| 81 |
+
- `codebooks/layout_v2/compact.pkl` — 120 MB codebook artifact
|
| 82 |
+
- `codebooks/layout_v2/cb_K{2,3}.npy` — dense form (only on Modal Volume)
|
| 83 |
+
- `codebooks/extract_baseline.py` — attempt at recovering `w0` from Option B
|
| 84 |
+
M matrices (produces per-expert-varying estimate; see § summary above)
|
| 85 |
+
- `eschamoe.py` — MLX decoder using the new codebook
|
| 86 |
+
- `docs/escha_op_signature.md` — full op audit report
|
| 87 |
+
|
| 88 |
+
## What would unblock full packed inference
|
| 89 |
+
|
| 90 |
+
One more Modal call, ~30 s A10G, cost ~$0.02:
|
| 91 |
+
|
| 92 |
+
```python
|
| 93 |
+
@app.function(gpu="A10G")
|
| 94 |
+
def dump_baselines():
|
| 95 |
+
# For each (in_f, out_f, K) shape used by Escha-W2, dump op(all-zeros).
|
| 96 |
+
import torch, escha
|
| 97 |
+
op = torch.ops.escha.escham_reconstruct
|
| 98 |
+
for (in_f, out_f, K, cshape) in [(2048, 1024, 2, (128, 64, 32)),
|
| 99 |
+
(512, 2048, 3, (32, 128, 48))]:
|
| 100 |
+
p0 = torch.zeros(cshape, dtype=torch.int16, device="cuda")
|
| 101 |
+
w0 = op(p0, in_f, out_f, K, True, False).cpu().numpy()
|
| 102 |
+
# Also dump op(one_random_expert_code) for cross-check
|
| 103 |
+
code = ... # load one real expert code
|
| 104 |
+
w_ref = op(code, in_f, out_f, K, True, False).cpu().numpy()
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
Plus: verify the linearity assumption at HIGH code density (dense 262 K slots)
|
| 108 |
+
by comparing `op(code)` against `w0 + my_reconstruct(code)`. If they differ
|
| 109 |
+
by more than fp16 noise, the op has hidden non-linear structure that would
|
| 110 |
+
need one more targeted probe.
|
OP_SIGNATURE_AUDIT.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Escha `escham_reconstruct` — signature + linearity audit
|
| 2 |
+
|
| 3 |
+
## 1. Introspection
|
| 4 |
+
|
| 5 |
+
escha module: `/usr/local/lib/python3.12/site-packages/escha/__init__.py`
|
| 6 |
+
escha._C: `<module 'escha._C' from '/usr/local/lib/python3.12/site-packages/escha/_C.cpython-312-x86_64-linux-gnu.so'>`
|
| 7 |
+
|
| 8 |
+
### `dir(escha._C)`
|
| 9 |
+
- `escha_aqlm_auto` ? — escha_aqlm_auto(ta: torch.Tensor, codes: torch.Tensor, codebooks: torch.Tensor, scales: torch.Tensor, codes_T: torch.Tensor | None = None, k_tile: typing.SupportsInt = 64) -> torch.Tensor
|
| 10 |
+
- `escha_aqlm_fused_hmma` ? — escha_aqlm_fused_hmma(ta: torch.Tensor, codes_T: torch.Tensor, codebooks: torch.Tensor, scales: torch.Tensor, k_tile: typing.SupportsInt = 64) -> torch.Tensor
|
| 11 |
+
- `escha_aqlm_gemv` ? — escha_aqlm_gemv(ta: torch.Tensor, codes: torch.Tensor, codebooks: torch.Tensor, scales: torch.Tensor) -> torch.Tensor
|
| 12 |
+
- `escha_aqlm_prepare_codes_transposed` ? — escha_aqlm_prepare_codes_transposed(codes: torch.Tensor) -> torch.Tensor
|
| 13 |
+
- `escha_binary_gemv` ? — escha_binary_gemv(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor) -> torch.Tensor
|
| 14 |
+
- `escha_binary_gemv_reg` ? — escha_binary_gemv_reg(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor) -> torch.Tensor
|
| 15 |
+
- `escha_decgemv` ? — escha_decgemv(x: torch.Tensor, packed_codes: torch.Tensor, scale: torch.Tensor, transform_left: torch.Tensor, transform_right: torch.Tensor, a1: torch.Tensor, a2: torch.Tensor, td1: typing.SupportsInt, td2: typing.SupportsInt, ic: typing.SupportsInt, expic: typing.SupportsInt, gain: torch.Tensor | None = None, block_size: typing.SupportsInt = 0) -> torch.Tensor
|
| 16 |
+
- `escha_decgemv_inplace` ? — escha_decgemv_inplace(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor, arg4: torch.Tensor, arg5: torch.Tensor, arg6: torch.Tensor, arg7: typing.SupportsInt, arg8: typing.SupportsInt, arg9: typing.SupportsInt, arg10: typing.SupportsInt, arg11: torch.Tensor, arg12: torch.Tensor, arg13: torch.Tensor, arg14: torch.Tensor) -> None
|
| 17 |
+
- `escha_decgemv_reg` ? — escha_decgemv_reg(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor, arg4: torch.Tensor, arg5: torch.Tensor, arg6: torch.Tensor, arg7: typing.SupportsInt, arg8: typing.SupportsInt, arg9: typing.SupportsInt, arg10: typing.SupportsInt) -> torch.Tensor
|
| 18 |
+
- `escha_dequant` ? — escha_dequant(packed_codes: torch.Tensor, scale: torch.Tensor, transform_left: torch.Tensor, transform_right: torch.Tensor, a1: torch.Tensor, a2: torch.Tensor, td1: typing.SupportsInt, td2: typing.SupportsInt, ic: typing.SupportsInt, expic: typing.SupportsInt, gain: torch.Tensor | None = None, block_size: typing.SupportsInt = 0) -> torch.Tensor
|
| 19 |
+
- `escha_fused_dequant_gemm` ? — escha_fused_dequant_gemm(ta_fp16: torch.Tensor, packed_codes: torch.Tensor, scale: torch.Tensor) -> torch.Tensor
|
| 20 |
+
- `escha_fused_dequant_gemm_auto` ? — escha_fused_dequant_gemm_auto(ta_fp16: torch.Tensor, packed_codes: torch.Tensor, scale: torch.Tensor, packed_T: torch.Tensor | None = None) -> torch.Tensor
|
| 21 |
+
- `escha_fused_dequant_gemm_v2` ? — escha_fused_dequant_gemm_v2(ta_fp16: torch.Tensor, packed_codes: torch.Tensor, scale: torch.Tensor) -> torch.Tensor
|
| 22 |
+
- `escha_fused_dequant_gemm_v3` ? — escha_fused_dequant_gemm_v3(ta_fp16: torch.Tensor, packed_T: torch.Tensor, scale: torch.Tensor) -> torch.Tensor
|
| 23 |
+
- `escha_fused_dequant_gemm_v4` ? — escha_fused_dequant_gemm_v4(ta_fp16: torch.Tensor, packed_T: torch.Tensor, scale: torch.Tensor) -> torch.Tensor
|
| 24 |
+
- `escha_fused_dequant_gemm_v5` ? — escha_fused_dequant_gemm_v5(ta_fp16: torch.Tensor, packed_codes: torch.Tensor, scale: torch.Tensor) -> torch.Tensor
|
| 25 |
+
- `escha_init` ? — escha_init() -> None
|
| 26 |
+
- `escha_lut_binary_gemv` ? — escha_lut_binary_gemv(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor) -> torch.Tensor
|
| 27 |
+
- `escha_prepare_packed_transposed` ? — escha_prepare_packed_transposed(packed_codes: torch.Tensor) -> torch.Tensor
|
| 28 |
+
- `escha_transform` ? — escha_transform(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor, arg4: torch.Tensor, arg5: typing.SupportsInt, arg6: typing.SupportsInt, arg7: typing.SupportsInt, arg8: typing.SupportsInt) -> list[torch.Tensor]
|
| 29 |
+
- `escha_transform_fast` ? — escha_transform_fast(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor, arg4: torch.Tensor, arg5: typing.SupportsInt, arg6: typing.SupportsInt, arg7: typing.SupportsInt, arg8: typing.SupportsInt) -> list[torch.Tensor]
|
| 30 |
+
- `escha_transform_fp16` ? — escha_transform_fp16(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor, arg4: torch.Tensor, arg5: typing.SupportsInt, arg6: typing.SupportsInt, arg7: typing.SupportsInt, arg8: typing.SupportsInt) -> list[torch.Tensor]
|
| 31 |
+
- `escha_transform_fp16_no_bias` ? — escha_transform_fp16_no_bias(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor, arg4: torch.Tensor, arg5: typing.SupportsInt, arg6: typing.SupportsInt, arg7: typing.SupportsInt, arg8: typing.SupportsInt) -> torch.Tensor
|
| 32 |
+
- `eschax_binary_search` ? — eschax_binary_search(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: typing.SupportsInt, arg4: typing.SupportsInt, arg5: typing.SupportsInt) -> torch.Tensor
|
| 33 |
+
- `eschax_dequant` ? — eschax_dequant(arg0: torch.Tensor, arg1: typing.SupportsFloat) -> torch.Tensor
|
| 34 |
+
- `eschax_eschax_decode` ? — eschax_eschax_decode(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor, arg4: typing.SupportsInt, arg5: typing.SupportsInt) -> torch.Tensor
|
| 35 |
+
- `eschax_eschax_gemv` ? — eschax_eschax_gemv(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor, arg4: torch.Tensor, arg5: typing.SupportsFloat, arg6: torch.Tensor, arg7: typing.SupportsInt, arg8: typing.SupportsInt) -> torch.Tensor
|
| 36 |
+
- `eschax_gemv` ? — eschax_gemv(arg0: torch.Tensor, arg1: torch.Tensor, arg2: typing.SupportsFloat, arg3: torch.Tensor) -> torch.Tensor
|
| 37 |
+
- `eschax_huffman_decode` ? — eschax_huffman_decode(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: typing.SupportsInt, arg4: typing.SupportsInt) -> torch.Tensor
|
| 38 |
+
- `eschax_huffman_gemv` ? — eschax_huffman_gemv(arg0: torch.Tensor, arg1: torch.Tensor, arg2: torch.Tensor, arg3: torch.Tensor, arg4: typing.SupportsFloat, arg5: torch.Tensor, arg6: typing.SupportsInt, arg7: typing.SupportsInt) -> torch.Tensor
|
| 39 |
+
|
| 40 |
+
### torch.ops.escha.escham_reconstruct
|
| 41 |
+
escha.escham_reconstruct
|
| 42 |
+
overloads: ['default']
|
| 43 |
+
default: escha::escham_reconstruct(Tensor packed, int in_features, int out_features, int K, bool cbA, bool mul1) -> Tensor
|
| 44 |
+
|
| 45 |
+
## 2. Shape acceptance test
|
| 46 |
+
|
| 47 |
+
min-K2 128x128: cshape=(8, 8, 32) in_f=128 out_f=128 K=2 -> OK, w.shape=(128, 128) dtype=torch.float16
|
| 48 |
+
min-K3 128x128: cshape=(8, 8, 48) in_f=128 out_f=128 K=3 -> OK, w.shape=(128, 128) dtype=torch.float16
|
| 49 |
+
escha gate_up (K=2, in=2048/out=1024): cshape=(128, 64, 32) in_f=2048 out_f=1024 K=2 -> OK, w.shape=(2048, 1024) dtype=torch.float16
|
| 50 |
+
escha down (K=3, in=512/out=2048): cshape=(32, 128, 48) in_f=512 out_f=2048 K=3 -> OK, w.shape=(512, 2048) dtype=torch.float16
|
| 51 |
+
leading batch (2, 8, 8, 32) K=2: cshape=(2, 8, 8, 32) in_f=128 out_f=128 K=2 -> OK, w.shape=(128, 128) dtype=torch.float16
|
| 52 |
+
leading batch (16, 8, 8, 32) K=2: cshape=(16, 8, 8, 32) in_f=128 out_f=128 K=2 -> OK, w.shape=(128, 128) dtype=torch.float16
|
| 53 |
+
leading batch (4, 128, 64, 32) K=2: cshape=(4, 128, 64, 32) in_f=2048 out_f=1024 K=2 -> OK, w.shape=(2048, 1024) dtype=torch.float16
|
| 54 |
+
|
| 55 |
+
## 3. Full delta pattern at slot (0,0,0)
|
| 56 |
+
|
| 57 |
+
For (in=2048, out=1024, K=2) tile: what is the full (row, col) support
|
| 58 |
+
of the delta when we set exactly code[0,0,0] = v, for various v?
|
| 59 |
+
|
| 60 |
+
v= 1: 8 nonzero positions, rows=[4, 5, 11, 12, 13], cols=[0, 8]
|
| 61 |
+
v= 2: 8 nonzero positions, rows=[4, 5, 11, 12, 13], cols=[0, 8]
|
| 62 |
+
v= 3: 8 nonzero positions, rows=[4, 5, 11, 12, 13], cols=[0, 8]
|
| 63 |
+
v= 4: 8 nonzero positions, rows=[4, 5, 10, 11, 12, 13], cols=[0, 8]
|
| 64 |
+
v= 5: 9 nonzero positions, rows=[4, 5, 10, 11, 12, 13], cols=[0, 8]
|
| 65 |
+
v= 7: 9 nonzero positions, rows=[4, 5, 10, 11, 12, 13], cols=[0, 8]
|
| 66 |
+
v= 10: 9 nonzero positions, rows=[4, 5, 10, 11, 12, 13], cols=[0, 8]
|
| 67 |
+
v= 16: 8 nonzero positions, rows=[3, 4, 5, 10, 11, 12, 13], cols=[0, 8]
|
| 68 |
+
v= 64: 8 nonzero positions, rows=[2, 3, 4, 5, 10, 11, 12, 13], cols=[0, 8]
|
| 69 |
+
v= 256: 8 nonzero positions, rows=[2, 3, 4, 5, 10, 11, 12], cols=[0, 8]
|
| 70 |
+
v= 1024: 8 nonzero positions, rows=[2, 3, 4, 5, 10, 11], cols=[0, 8]
|
| 71 |
+
v= 4096: 8 nonzero positions, rows=[2, 3, 4, 10, 11], cols=[0, 8]
|
| 72 |
+
v= 16384: 8 nonzero positions, rows=[2, 3, 10, 11], cols=[0, 8]
|
| 73 |
+
v= 32767: 15 nonzero positions, rows=[2, 3, 4, 5, 10, 11, 12, 13], cols=[0, 8]
|
| 74 |
+
v= -1: 15 nonzero positions, rows=[2, 3, 4, 5, 10, 11, 12, 13], cols=[0, 8]
|
| 75 |
+
v= -100: 14 nonzero positions, rows=[2, 3, 4, 5, 10, 11, 12, 13], cols=[0, 8]
|
| 76 |
+
v=-32768: 8 nonzero positions, rows=[2, 3, 10, 11], cols=[0, 8]
|
| 77 |
+
|
| 78 |
+
## 4. Superposition test (LINEARITY in codes)
|
| 79 |
+
|
| 80 |
+
Test: op(all-zeros with code[bi_a, bj_a, k_a]=v_a AND code[bi_b, bj_b, k_b]=v_b)
|
| 81 |
+
== op(only code[bi_a, bj_a, k_a]=v_a) + op(only code[bi_b, bj_b, k_b]=v_b) - op(zeros)
|
| 82 |
+
If yes, we can probe many (bi, bj) slots simultaneously in ONE op call.
|
| 83 |
+
|
| 84 |
+
2-pos, distinct (bi,bj), same k: |combined|=1.034e+01 |diff|=0.000e+00 rel=0.000e+00
|
| 85 |
+
2-pos, same (bi,bj), diff k: |combined|=1.034e+01 |diff|=0.000e+00 rel=0.000e+00
|
| 86 |
+
2-pos, same (bi,bj), diff K-slice: |combined|=1.034e+01 |diff|=0.000e+00 rel=0.000e+00
|
| 87 |
+
8-pos random: |combined|=2.231e+01 |diff|=0.000e+00 rel=0.000e+00
|
| 88 |
+
100-pos random: |combined|=8.165e+01 |diff|=0.000e+00 rel=0.000e+00
|
| 89 |
+
|
| 90 |
+
## 5. Slot invariance test — is the codebook shared across (bi, bj)?
|
| 91 |
+
|
| 92 |
+
Compare delta patterns for the SAME value v at DIFFERENT (bi, bj) with the same k_slot.
|
| 93 |
+
If they are identical up to a (bi*16, bj*16) offset, the codebook is (bi, bj)-invariant.
|
| 94 |
+
|
| 95 |
+
v= 1 (bi=0,bj=0) vs (bi=1,bj=0): |diff|=0.000e+00 rel=0.000e+00
|
| 96 |
+
v= 1 (bi=0,bj=0) vs (bi=0,bj=1): |diff|=0.000e+00 rel=0.000e+00
|
| 97 |
+
v= 1 (bi=0,bj=0) vs (bi=1,bj=1): |diff|=0.000e+00 rel=0.000e+00
|
| 98 |
+
v= 1 (bi=0,bj=0) vs (bi=5,bj=3): |diff|=0.000e+00 rel=0.000e+00
|
| 99 |
+
v= 1 (bi=0,bj=0) vs (bi=127,bj=63): |diff|=0.000e+00 rel=0.000e+00
|
| 100 |
+
v= 100 (bi=0,bj=0) vs (bi=1,bj=0): |diff|=0.000e+00 rel=0.000e+00
|
| 101 |
+
v= 100 (bi=0,bj=0) vs (bi=0,bj=1): |diff|=0.000e+00 rel=0.000e+00
|
| 102 |
+
v= 100 (bi=0,bj=0) vs (bi=1,bj=1): |diff|=0.000e+00 rel=0.000e+00
|
| 103 |
+
v= 100 (bi=0,bj=0) vs (bi=5,bj=3): |diff|=0.000e+00 rel=0.000e+00
|
| 104 |
+
v= 100 (bi=0,bj=0) vs (bi=127,bj=63): |diff|=0.000e+00 rel=0.000e+00
|
| 105 |
+
v= 32767 (bi=0,bj=0) vs (bi=1,bj=0): |diff|=0.000e+00 rel=0.000e+00
|
| 106 |
+
v= 32767 (bi=0,bj=0) vs (bi=0,bj=1): |diff|=0.000e+00 rel=0.000e+00
|
| 107 |
+
v= 32767 (bi=0,bj=0) vs (bi=1,bj=1): |diff|=0.000e+00 rel=0.000e+00
|
| 108 |
+
v= 32767 (bi=0,bj=0) vs (bi=5,bj=3): |diff|=0.000e+00 rel=0.000e+00
|
| 109 |
+
v= 32767 (bi=0,bj=0) vs (bi=127,bj=63): |diff|=0.000e+00 rel=0.000e+00
|
| 110 |
+
v=-32768 (bi=0,bj=0) vs (bi=1,bj=0): |diff|=0.000e+00 rel=0.000e+00
|
| 111 |
+
v=-32768 (bi=0,bj=0) vs (bi=0,bj=1): |diff|=0.000e+00 rel=0.000e+00
|
| 112 |
+
v=-32768 (bi=0,bj=0) vs (bi=1,bj=1): |diff|=0.000e+00 rel=0.000e+00
|
| 113 |
+
v=-32768 (bi=0,bj=0) vs (bi=5,bj=3): |diff|=0.000e+00 rel=0.000e+00
|
| 114 |
+
v=-32768 (bi=0,bj=0) vs (bi=127,bj=63): |diff|=0.000e+00 rel=0.000e+00
|
| 115 |
+
|
| 116 |
+
## 6. k_slot pattern
|
| 117 |
+
|
| 118 |
+
For each k_slot, what is the row/col support of the (0, 0, k)+v=1 delta?
|
| 119 |
+
|
| 120 |
+
### K=2, cshape=(128, 64, 32)
|
| 121 |
+
k= 0: rows=[4, 5, 11, 12, 13] cols=[0, 8] n_pos=8
|
| 122 |
+
k= 1: rows=[2, 3, 9, 10, 11] cols=[0, 8] n_pos=8
|
| 123 |
+
k= 2: rows=[0, 1, 8, 9, 15] cols=[1, 8, 9] n_pos=8
|
| 124 |
+
k= 3: rows=[6, 7, 13, 14, 15] cols=[0, 8] n_pos=8
|
| 125 |
+
k= 4: rows=[4, 5, 11, 12, 13] cols=[1, 9] n_pos=8
|
| 126 |
+
k= 5: rows=[2, 3, 9, 10, 11] cols=[1, 9] n_pos=8
|
| 127 |
+
k= 6: rows=[0, 1, 8, 9, 15] cols=[2, 9, 10] n_pos=8
|
| 128 |
+
k= 7: rows=[6, 7, 13, 14, 15] cols=[1, 9] n_pos=8
|
| 129 |
+
k= 8: rows=[4, 5, 11, 12, 13] cols=[2, 10] n_pos=8
|
| 130 |
+
k= 9: rows=[2, 3, 9, 10, 11] cols=[2, 10] n_pos=8
|
| 131 |
+
k=10: rows=[0, 1, 8, 9, 15] cols=[3, 10, 11] n_pos=8
|
| 132 |
+
k=11: rows=[6, 7, 13, 14, 15] cols=[2, 10] n_pos=8
|
| 133 |
+
k=12: rows=[4, 5, 11, 12, 13] cols=[3, 11] n_pos=8
|
| 134 |
+
k=13: rows=[2, 3, 9, 10, 11] cols=[3, 11] n_pos=8
|
| 135 |
+
k=14: rows=[0, 1, 8, 9, 15] cols=[4, 11, 12] n_pos=8
|
| 136 |
+
k=15: rows=[6, 7, 13, 14, 15] cols=[3, 11] n_pos=8
|
| 137 |
+
k=16: rows=[4, 5, 11, 12, 13] cols=[4, 12] n_pos=8
|
| 138 |
+
k=17: rows=[2, 3, 9, 10, 11] cols=[4, 12] n_pos=8
|
| 139 |
+
k=18: rows=[0, 1, 8, 9, 15] cols=[5, 12, 13] n_pos=8
|
| 140 |
+
k=19: rows=[6, 7, 13, 14, 15] cols=[4, 12] n_pos=8
|
| 141 |
+
k=20: rows=[4, 5, 11, 12, 13] cols=[5, 13] n_pos=8
|
| 142 |
+
k=21: rows=[2, 3, 9, 10, 11] cols=[5, 13] n_pos=8
|
| 143 |
+
k=22: rows=[0, 1, 8, 9, 15] cols=[6, 13, 14] n_pos=8
|
| 144 |
+
k=23: rows=[6, 7, 13, 14, 15] cols=[5, 13] n_pos=8
|
| 145 |
+
k=24: rows=[4, 5, 11, 12, 13] cols=[6, 14] n_pos=8
|
| 146 |
+
k=25: rows=[2, 3, 9, 10, 11] cols=[6, 14] n_pos=8
|
| 147 |
+
k=26: rows=[0, 1, 8, 9, 15] cols=[7, 14, 15] n_pos=8
|
| 148 |
+
k=27: rows=[6, 7, 13, 14, 15] cols=[6, 14] n_pos=8
|
| 149 |
+
k=28: rows=[4, 5, 11, 12, 13] cols=[7, 15] n_pos=8
|
| 150 |
+
k=29: rows=[2, 3, 9, 10, 11] cols=[7, 15] n_pos=8
|
| 151 |
+
k=30: rows=[0, 1, 8, 9, 15] cols=[0, 8, 15] n_pos=8
|
| 152 |
+
k=31: rows=[6, 7, 13, 14, 15] cols=[7, 15] n_pos=8
|
| 153 |
+
### K=3, cshape=(32, 128, 48)
|
| 154 |
+
k= 0: rows=[2, 3, 10, 11] cols=[0, 8] n_pos=5
|
| 155 |
+
k= 1: rows=[1, 2, 3, 8, 9] cols=[0, 8] n_pos=5
|
| 156 |
+
k= 2: rows=[5, 6, 7, 12, 13] cols=[0, 8] n_pos=5
|
| 157 |
+
k= 3: rows=[4, 5, 11, 12, 13] cols=[0, 8] n_pos=6
|
| 158 |
+
k= 4: rows=[0, 1, 8, 9, 15] cols=[1, 8, 9] n_pos=6
|
| 159 |
+
k= 5: rows=[6, 7, 14, 15] cols=[0, 8] n_pos=5
|
| 160 |
+
k= 6: rows=[2, 3, 10, 11] cols=[1, 9] n_pos=5
|
| 161 |
+
k= 7: rows=[1, 2, 3, 8, 9] cols=[1, 9] n_pos=5
|
| 162 |
+
k= 8: rows=[5, 6, 7, 12, 13] cols=[1, 9] n_pos=5
|
| 163 |
+
k= 9: rows=[4, 5, 11, 12, 13] cols=[1, 9] n_pos=6
|
| 164 |
+
k=10: rows=[0, 1, 8, 9, 15] cols=[2, 9, 10] n_pos=6
|
| 165 |
+
k=11: rows=[6, 7, 14, 15] cols=[1, 9] n_pos=5
|
| 166 |
+
k=12: rows=[2, 3, 10, 11] cols=[2, 10] n_pos=5
|
| 167 |
+
k=13: rows=[1, 2, 3, 8, 9] cols=[2, 10] n_pos=5
|
| 168 |
+
k=14: rows=[5, 6, 7, 12, 13] cols=[2, 10] n_pos=5
|
| 169 |
+
k=15: rows=[4, 5, 11, 12, 13] cols=[2, 10] n_pos=6
|
| 170 |
+
k=16: rows=[0, 1, 8, 9, 15] cols=[3, 10, 11] n_pos=6
|
| 171 |
+
k=17: rows=[6, 7, 14, 15] cols=[2, 10] n_pos=5
|
| 172 |
+
k=18: rows=[2, 3, 10, 11] cols=[3, 11] n_pos=5
|
| 173 |
+
k=19: rows=[1, 2, 3, 8, 9] cols=[3, 11] n_pos=5
|
| 174 |
+
k=20: rows=[5, 6, 7, 12, 13] cols=[3, 11] n_pos=5
|
| 175 |
+
k=21: rows=[4, 5, 11, 12, 13] cols=[3, 11] n_pos=6
|
| 176 |
+
k=22: rows=[0, 1, 8, 9, 15] cols=[4, 11, 12] n_pos=6
|
| 177 |
+
k=23: rows=[6, 7, 14, 15] cols=[3, 11] n_pos=5
|
| 178 |
+
k=24: rows=[2, 3, 10, 11] cols=[4, 12] n_pos=5
|
| 179 |
+
k=25: rows=[1, 2, 3, 8, 9] cols=[4, 12] n_pos=5
|
| 180 |
+
k=26: rows=[5, 6, 7, 12, 13] cols=[4, 12] n_pos=5
|
| 181 |
+
k=27: rows=[4, 5, 11, 12, 13] cols=[4, 12] n_pos=6
|
| 182 |
+
k=28: rows=[0, 1, 8, 9, 15] cols=[5, 12, 13] n_pos=6
|
| 183 |
+
k=29: rows=[6, 7, 14, 15] cols=[4, 12] n_pos=5
|
| 184 |
+
k=30: rows=[2, 3, 10, 11] cols=[5, 13] n_pos=5
|
| 185 |
+
k=31: rows=[1, 2, 3, 8, 9] cols=[5, 13] n_pos=5
|
| 186 |
+
k=32: rows=[5, 6, 7, 12, 13] cols=[5, 13] n_pos=5
|
| 187 |
+
k=33: rows=[4, 5, 11, 12, 13] cols=[5, 13] n_pos=6
|
| 188 |
+
k=34: rows=[0, 1, 8, 9, 15] cols=[6, 13, 14] n_pos=6
|
| 189 |
+
k=35: rows=[6, 7, 14, 15] cols=[5, 13] n_pos=5
|
| 190 |
+
k=36: rows=[2, 3, 10, 11] cols=[6, 14] n_pos=5
|
| 191 |
+
k=37: rows=[1, 2, 3, 8, 9] cols=[6, 14] n_pos=5
|
| 192 |
+
k=38: rows=[5, 6, 7, 12, 13] cols=[6, 14] n_pos=5
|
| 193 |
+
k=39: rows=[4, 5, 11, 12, 13] cols=[6, 14] n_pos=6
|
| 194 |
+
k=40: rows=[0, 1, 8, 9, 15] cols=[7, 14, 15] n_pos=6
|
| 195 |
+
k=41: rows=[6, 7, 14, 15] cols=[6, 14] n_pos=5
|
| 196 |
+
k=42: rows=[2, 3, 10, 11] cols=[7, 15] n_pos=5
|
| 197 |
+
k=43: rows=[1, 2, 3, 8, 9] cols=[7, 15] n_pos=5
|
| 198 |
+
k=44: rows=[5, 6, 7, 12, 13] cols=[7, 15] n_pos=5
|
| 199 |
+
k=45: rows=[4, 5, 11, 12, 13] cols=[7, 15] n_pos=6
|
| 200 |
+
k=46: rows=[0, 1, 8, 9, 15] cols=[0, 8, 15] n_pos=6
|
| 201 |
+
k=47: rows=[6, 7, 14, 15] cols=[7, 15] n_pos=5
|
README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
tags:
|
| 4 |
+
- reverse-engineering
|
| 5 |
+
- aqlm
|
| 6 |
+
- quantization
|
| 7 |
+
- mlx
|
| 8 |
+
- escha
|
| 9 |
+
base_model: EschaLabs/Qwen3.6-35B-A3B-Escha-W2
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# Escha-W2 packed AQLM codebook — reverse-engineered reference dump
|
| 13 |
+
|
| 14 |
+
This repository contains the **first public extraction** of the `escham_reconstruct`
|
| 15 |
+
codebook lattice used by EschaLabs' 2-bit AQLM+Hadamard quantized checkpoint
|
| 16 |
+
[`EschaLabs/Qwen3.6-35B-A3B-Escha-W2`](https://huggingface.co/EschaLabs/Qwen3.6-35B-A3B-Escha-W2).
|
| 17 |
+
|
| 18 |
+
The Escha packed format stores each MoE expert's `gate_up_proj` (K=2) and
|
| 19 |
+
`down_proj` (K=3) projections as (in/16, out/16, 16·K) int16 codes plus per-row
|
| 20 |
+
and per-column scales. Decoding those codes into a dense fp16 weight matrix
|
| 21 |
+
requires two fixed codebook tables that ship **inside the CUDA `.so`** rather
|
| 22 |
+
than in the safetensors — they were previously inaccessible outside a Linux
|
| 23 |
+
GPU environment running the reference `escha` wheel.
|
| 24 |
+
|
| 25 |
+
This repo makes the codebook portable.
|
| 26 |
+
|
| 27 |
+
## Contents
|
| 28 |
+
|
| 29 |
+
| File | Size | Description |
|
| 30 |
+
|---|---|---|
|
| 31 |
+
| `compact.pkl` | 120 MB | The extracted codebook in sparse-compact form (fp16). See "Format" below. |
|
| 32 |
+
| `OP_SIGNATURE_AUDIT.md` | 15 KB | Full Modal-side introspection of `escha._C` — every operator, its schema, and the linearity / (bi, bj)-invariance proofs. |
|
| 33 |
+
| `LAYOUT_NOTES.md` | 5 KB | Notes on the structural regularities of the k_slot layout, the residual "baseline" question, and known limitations. |
|
| 34 |
+
| `modal_op_audit.py` | 12 KB | Reproducible Modal script (~1 min A10G) that produces the audit report. |
|
| 35 |
+
| `modal_smart_probe.py` | 11 KB | Reproducible Modal script (~2 min A10G) that produces `compact.pkl`. |
|
| 36 |
+
|
| 37 |
+
## Format
|
| 38 |
+
|
| 39 |
+
```python
|
| 40 |
+
import pickle
|
| 41 |
+
d = pickle.load(open("compact.pkl", "rb"))
|
| 42 |
+
# For each K in {2, 3}:
|
| 43 |
+
for K in (2, 3):
|
| 44 |
+
positions = d[f"K{K}_positions"] # list of (n_nz, 2) int8 (row, col) positions
|
| 45 |
+
values = d[f"K{K}_values"] # list of (65536, n_nz) fp16 codebook values
|
| 46 |
+
# Reconstruct dense (k_max, 65536, 16, 16) fp16:
|
| 47 |
+
import numpy as np
|
| 48 |
+
k_max = len(positions)
|
| 49 |
+
dense = np.zeros((k_max, 65536, 16, 16), dtype=np.float16)
|
| 50 |
+
for k, (pos, val) in enumerate(zip(positions, values)):
|
| 51 |
+
for i, (r, c) in enumerate(pos):
|
| 52 |
+
dense[k, :, r, c] = val[:, i]
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
To decode a packed expert weight tile back into fp16, sum the per-slot codebook
|
| 56 |
+
lookups placed at each (bi, bj) block:
|
| 57 |
+
|
| 58 |
+
```python
|
| 59 |
+
# code: int16 (in_f/16, out_f/16, 16*K)
|
| 60 |
+
in_f = 2048 # or 512 for down_proj
|
| 61 |
+
out_f = 1024 # or 2048 for down_proj
|
| 62 |
+
K = 2 # or 3 for down_proj
|
| 63 |
+
w = np.zeros((in_f, out_f), dtype=np.float32)
|
| 64 |
+
bi_max, bj_max = in_f // 16, out_f // 16
|
| 65 |
+
for k in range(16 * K):
|
| 66 |
+
idx = code[:, :, k].astype(np.int32) & 0xFFFF # int16 -> uint16
|
| 67 |
+
blocks = dense[k, idx] # (bi_max, bj_max, 16, 16)
|
| 68 |
+
w += blocks.transpose(0, 2, 1, 3).reshape(in_f, out_f)
|
| 69 |
+
```
|
| 70 |
+
|
| 71 |
+
**IMPORTANT — known limitation.** For a real expert whose codes activate all
|
| 72 |
+
262 K slots simultaneously, the above summation matches the CUDA op only up to
|
| 73 |
+
an unresolved additive term (per-projection norm ~4e3). This term is _not_
|
| 74 |
+
captured in the codebook (which stores deltas from `op(all-zeros code)`) and
|
| 75 |
+
could not be extracted in this session — the Modal workspace hit its spend
|
| 76 |
+
limit after the codebook extraction completed. See `LAYOUT_NOTES.md` for
|
| 77 |
+
the 30-second follow-up probe that would resolve it.
|
| 78 |
+
|
| 79 |
+
For a working end-to-end port that skips `escham_reconstruct` entirely (pre-
|
| 80 |
+
dequantized to fp16 on Modal, no runtime decode needed), see
|
| 81 |
+
[`KaedeTai/Qwen3.6-35B-A3B-Escha-W2-MLX`](https://huggingface.co/KaedeTai/Qwen3.6-35B-A3B-Escha-W2-MLX).
|
| 82 |
+
|
| 83 |
+
## Verified properties
|
| 84 |
+
|
| 85 |
+
- **Linearity** (superposition): `op(A+B) - op(0) = (op(A) - op(0)) + (op(B) - op(0))`
|
| 86 |
+
holds exactly for up to 100 random slot activations.
|
| 87 |
+
- **(bi, bj)-invariance**: same code at any tile position produces the same
|
| 88 |
+
16x16 delta (offset by (bi*16, bj*16)). Tested for corners including
|
| 89 |
+
(bi=127, bj=63) vs (bi=0, bj=0).
|
| 90 |
+
- **Structural regularity**: the per-k_slot (row, col) support cycles with
|
| 91 |
+
period 4 in k_slot (K=2).
|
| 92 |
+
- **Op signature**: `escham_reconstruct(Tensor packed, int in_f, int out_f,
|
| 93 |
+
int K, bool cbA, bool mul1) -> Tensor` — one default overload, accepts
|
| 94 |
+
leading batch dims on `packed`.
|
| 95 |
+
|
| 96 |
+
## Reproducing the extraction
|
| 97 |
+
|
| 98 |
+
Requires a Modal account and the `EschaLabs/escha-runtime-qwen3moe` wheel on
|
| 99 |
+
Hugging Face (public):
|
| 100 |
+
|
| 101 |
+
```bash
|
| 102 |
+
modal run modal_op_audit.py # ~1 min A10G, produces OP_SIGNATURE_AUDIT.md
|
| 103 |
+
modal run modal_smart_probe.py # ~2 min A10G, produces compact.pkl
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
The smart probe uses **~1024 op calls total** across both K values —
|
| 107 |
+
compared to the naive one-code-at-a-time sweep which would require
|
| 108 |
+
**~328 million op calls (91 h A10G, ~$100)**. The speedup comes from three
|
| 109 |
+
observations, each verified by the audit:
|
| 110 |
+
|
| 111 |
+
1. Op is exactly linear in codes -> many perturbations can be superposed
|
| 112 |
+
in a single op call.
|
| 113 |
+
2. The codebook is (bi, bj)-invariant -> each of the 8192 tile-blocks in
|
| 114 |
+
the (128, 64, 32) code tensor is a free "test bed" for a different
|
| 115 |
+
codebook entry.
|
| 116 |
+
3. Different k_slots at the same (bi, bj) overlap in output positions ->
|
| 117 |
+
we must use different (bi, bj) for different (k, v) probes, but that's
|
| 118 |
+
fine since we have 8192 of them.
|
| 119 |
+
|
| 120 |
+
Net: 65,536 codes x 32 k_slots / 8192 blocks-per-op = 256 op calls for K=2.
|
| 121 |
+
|
| 122 |
+
## Credits
|
| 123 |
+
|
| 124 |
+
- **EschaLabs** — for open-weight Qwen3.6-35B-A3B-Escha-W2 and the reference
|
| 125 |
+
runtime.
|
| 126 |
+
- **AQLM** (Egiazarian et al., 2024) — the residual-codebook quantization
|
| 127 |
+
scheme that Escha builds on.
|
| 128 |
+
|
| 129 |
+
## License
|
| 130 |
+
|
| 131 |
+
Apache 2.0. Same as the base model.
|
compact.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:af17e0808291cf7d7d9e5f5e50debbd838833771dcd2d6b4e41be7b529001cd7
|
| 3 |
+
size 127933716
|
modal_op_audit.py
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Signature + linearity audit of torch.ops.escha.escham_reconstruct.
|
| 2 |
+
|
| 3 |
+
Answers:
|
| 4 |
+
1. Full op signature (what argument shapes/dtypes are accepted?)
|
| 5 |
+
2. Is the op LINEAR in codes? (i.e., op(A + B) == op(A) + op(B) - op(0))
|
| 6 |
+
- If yes -> superposition holds, we can probe many (bi, bj) simultaneously.
|
| 7 |
+
3. If we set exactly one code slot to value v, what is the FULL delta pattern?
|
| 8 |
+
- Which (row, col) positions in the output are nonzero?
|
| 9 |
+
4. Is the (codebook entry) slot-invariant across (bi, bj)?
|
| 10 |
+
- I.e., does slot (0, 0, 0) v=v produce the same block pattern (offset by 16)
|
| 11 |
+
as slot (1, 1, 0) v=v ?
|
| 12 |
+
5. Does the pattern depend on the *tile shape* passed to the op?
|
| 13 |
+
- Compare 128x128 tile vs 2048x1024 real tile.
|
| 14 |
+
|
| 15 |
+
Writes /vol/op_audit.pkl and /vol/op_audit_report.md.
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
from __future__ import annotations
|
| 19 |
+
|
| 20 |
+
import pickle
|
| 21 |
+
from pathlib import Path
|
| 22 |
+
|
| 23 |
+
import modal
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
WHEEL_REVISION = "1.0.2+qwen3moe"
|
| 27 |
+
|
| 28 |
+
image = (
|
| 29 |
+
modal.Image.from_registry(
|
| 30 |
+
"nvidia/cuda:12.8.1-cudnn-runtime-ubuntu24.04",
|
| 31 |
+
add_python="3.12",
|
| 32 |
+
)
|
| 33 |
+
.apt_install("curl", "binutils", "git", "ca-certificates")
|
| 34 |
+
.pip_install("wheel", "pip", "setuptools")
|
| 35 |
+
.pip_install(
|
| 36 |
+
"torch==2.9.*",
|
| 37 |
+
index_url="https://download.pytorch.org/whl/cu128",
|
| 38 |
+
)
|
| 39 |
+
.pip_install("numpy", "safetensors", "huggingface_hub[cli]")
|
| 40 |
+
.run_commands(
|
| 41 |
+
f"echo escha wheel revision: {WHEEL_REVISION}",
|
| 42 |
+
"mkdir -p /escha",
|
| 43 |
+
"hf download EschaLabs/escha-runtime-qwen3moe --include 'sglang/*' --local-dir /escha",
|
| 44 |
+
"pip install --no-deps /escha/sglang/escha-*.whl",
|
| 45 |
+
)
|
| 46 |
+
)
|
| 47 |
+
|
| 48 |
+
vol = modal.Volume.from_name("escha-codebooks", create_if_missing=True)
|
| 49 |
+
app = modal.App("escha-op-audit", image=image)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
@app.function(gpu="A10G", timeout=1800, memory=16 * 1024, volumes={"/vol": vol})
|
| 53 |
+
def audit() -> dict:
|
| 54 |
+
import inspect
|
| 55 |
+
import time
|
| 56 |
+
import numpy as np
|
| 57 |
+
import torch
|
| 58 |
+
import escha # noqa: F401
|
| 59 |
+
|
| 60 |
+
report_lines: list[str] = []
|
| 61 |
+
|
| 62 |
+
def log(msg: str) -> None:
|
| 63 |
+
print(msg, flush=True)
|
| 64 |
+
report_lines.append(msg)
|
| 65 |
+
|
| 66 |
+
log("# Escha `escham_reconstruct` — signature + linearity audit")
|
| 67 |
+
log("")
|
| 68 |
+
|
| 69 |
+
# ---- (1) Introspection ----
|
| 70 |
+
log("## 1. Introspection")
|
| 71 |
+
log("")
|
| 72 |
+
C = escha._C
|
| 73 |
+
log(f"escha module: `{escha.__file__}`")
|
| 74 |
+
log(f"escha._C: `{C}`")
|
| 75 |
+
log("")
|
| 76 |
+
log("### `dir(escha._C)`")
|
| 77 |
+
for name in sorted(dir(C)):
|
| 78 |
+
if name.startswith("_"):
|
| 79 |
+
continue
|
| 80 |
+
obj = getattr(C, name)
|
| 81 |
+
try:
|
| 82 |
+
sig = str(inspect.signature(obj))
|
| 83 |
+
except Exception:
|
| 84 |
+
sig = "?"
|
| 85 |
+
try:
|
| 86 |
+
doc = (getattr(obj, "__doc__", None) or "").strip().splitlines()[:1]
|
| 87 |
+
doc = doc[0] if doc else ""
|
| 88 |
+
except Exception:
|
| 89 |
+
doc = ""
|
| 90 |
+
log(f" - `{name}` {sig} — {doc}")
|
| 91 |
+
log("")
|
| 92 |
+
op = torch.ops.escha.escham_reconstruct
|
| 93 |
+
log(f"### torch.ops.escha.escham_reconstruct")
|
| 94 |
+
log(f" {op}")
|
| 95 |
+
try:
|
| 96 |
+
log(f" overloads: {op.overloads()}")
|
| 97 |
+
except Exception:
|
| 98 |
+
pass
|
| 99 |
+
try:
|
| 100 |
+
log(f" default schema: {op._schema}")
|
| 101 |
+
except Exception:
|
| 102 |
+
pass
|
| 103 |
+
for ov_name in ("default",):
|
| 104 |
+
try:
|
| 105 |
+
ov = getattr(op, ov_name)
|
| 106 |
+
log(f" {ov_name}: {ov._schema}")
|
| 107 |
+
except Exception as e:
|
| 108 |
+
log(f" {ov_name}: {e}")
|
| 109 |
+
log("")
|
| 110 |
+
|
| 111 |
+
# ---- (2) Try different code tensor shapes ----
|
| 112 |
+
log("## 2. Shape acceptance test")
|
| 113 |
+
log("")
|
| 114 |
+
device = "cuda"
|
| 115 |
+
|
| 116 |
+
def try_shape(cshape: tuple[int, ...], in_f: int, out_f: int, K: int, tag: str) -> None:
|
| 117 |
+
try:
|
| 118 |
+
p = torch.zeros(cshape, dtype=torch.int16, device=device)
|
| 119 |
+
w = op(p, in_f, out_f, K, True, False)
|
| 120 |
+
log(f" {tag}: cshape={cshape} in_f={in_f} out_f={out_f} K={K} -> OK, w.shape={tuple(w.shape)} dtype={w.dtype}")
|
| 121 |
+
except Exception as e:
|
| 122 |
+
log(f" {tag}: cshape={cshape} in_f={in_f} out_f={out_f} K={K} -> {type(e).__name__}: {e}")
|
| 123 |
+
|
| 124 |
+
# Minimum: 128x128
|
| 125 |
+
try_shape((8, 8, 32), 128, 128, 2, "min-K2 128x128")
|
| 126 |
+
try_shape((8, 8, 48), 128, 128, 3, "min-K3 128x128")
|
| 127 |
+
# Escha actual
|
| 128 |
+
try_shape((128, 64, 32), 2048, 1024, 2, "escha gate_up (K=2, in=2048/out=1024)")
|
| 129 |
+
try_shape((32, 128, 48), 512, 2048, 3, "escha down (K=3, in=512/out=2048)")
|
| 130 |
+
# Batched leading dim?
|
| 131 |
+
try_shape((2, 8, 8, 32), 128, 128, 2, "leading batch (2, 8, 8, 32) K=2")
|
| 132 |
+
try_shape((16, 8, 8, 32), 128, 128, 2, "leading batch (16, 8, 8, 32) K=2")
|
| 133 |
+
try_shape((4, 128, 64, 32), 2048, 1024, 2, "leading batch (4, 128, 64, 32) K=2")
|
| 134 |
+
log("")
|
| 135 |
+
|
| 136 |
+
# ---- (3) Full delta pattern at slot (0,0,0) for various values ----
|
| 137 |
+
log("## 3. Full delta pattern at slot (0,0,0)")
|
| 138 |
+
log("")
|
| 139 |
+
log("For (in=2048, out=1024, K=2) tile: what is the full (row, col) support")
|
| 140 |
+
log("of the delta when we set exactly code[0,0,0] = v, for various v?")
|
| 141 |
+
log("")
|
| 142 |
+
in_f, out_f, K = 2048, 1024, 2
|
| 143 |
+
cshape = (128, 64, 32)
|
| 144 |
+
p0 = torch.zeros(cshape, dtype=torch.int16, device=device)
|
| 145 |
+
w0 = op(p0, in_f, out_f, K, True, False).detach().cpu().numpy().astype(np.float32)
|
| 146 |
+
full_deltas = {}
|
| 147 |
+
for v in [1, 2, 3, 4, 5, 7, 10, 16, 64, 256, 1024, 4096, 16384, 32767, -1, -100, -32768]:
|
| 148 |
+
p = torch.zeros(cshape, dtype=torch.int16, device=device)
|
| 149 |
+
p[0, 0, 0] = np.int16(np.uint16(v & 0xFFFF)) if v >= 0 else np.int16(v)
|
| 150 |
+
w = op(p, in_f, out_f, K, True, False).detach().cpu().numpy().astype(np.float32)
|
| 151 |
+
d = w - w0
|
| 152 |
+
# Find all non-zero (row, col) positions:
|
| 153 |
+
nz_pos = np.argwhere(np.abs(d) > 1e-6)
|
| 154 |
+
# Should be within rows [0..16) × cols [0..16) (or thereabouts) if layout is
|
| 155 |
+
# bi*16 offset. Show ALL positions:
|
| 156 |
+
vals = [(int(r), int(c), float(d[r, c])) for r, c in nz_pos]
|
| 157 |
+
nz_rows_unique = sorted(set(r for r, _, _ in vals))
|
| 158 |
+
nz_cols_unique = sorted(set(c for _, c, _ in vals))
|
| 159 |
+
full_deltas[v] = {
|
| 160 |
+
"positions": vals,
|
| 161 |
+
"nz_rows": nz_rows_unique,
|
| 162 |
+
"nz_cols": nz_cols_unique,
|
| 163 |
+
"n_positions": len(vals),
|
| 164 |
+
}
|
| 165 |
+
log(f" v={v:6d}: {len(vals):3d} nonzero positions, rows={nz_rows_unique}, cols={nz_cols_unique}")
|
| 166 |
+
log("")
|
| 167 |
+
|
| 168 |
+
# ---- (4) Superposition test at real tile shape ----
|
| 169 |
+
log("## 4. Superposition test (LINEARITY in codes)")
|
| 170 |
+
log("")
|
| 171 |
+
log("Test: op(all-zeros with code[bi_a, bj_a, k_a]=v_a AND code[bi_b, bj_b, k_b]=v_b)")
|
| 172 |
+
log(" == op(only code[bi_a, bj_a, k_a]=v_a) + op(only code[bi_b, bj_b, k_b]=v_b) - op(zeros)")
|
| 173 |
+
log("If yes, we can probe many (bi, bj) slots simultaneously in ONE op call.")
|
| 174 |
+
log("")
|
| 175 |
+
|
| 176 |
+
def linearity_probe(pairs: list[tuple[tuple[int, int, int], int]], tag: str) -> None:
|
| 177 |
+
# Sum of individual perturbations
|
| 178 |
+
cumulative_delta = np.zeros_like(w0)
|
| 179 |
+
for (pos, v) in pairs:
|
| 180 |
+
pi = torch.zeros(cshape, dtype=torch.int16, device=device)
|
| 181 |
+
pi[pos] = np.int16(np.uint16(v & 0xFFFF)) if v >= 0 else np.int16(v)
|
| 182 |
+
wi = op(pi, in_f, out_f, K, True, False).detach().cpu().numpy().astype(np.float32)
|
| 183 |
+
cumulative_delta += (wi - w0)
|
| 184 |
+
# Combined
|
| 185 |
+
pc = torch.zeros(cshape, dtype=torch.int16, device=device)
|
| 186 |
+
for (pos, v) in pairs:
|
| 187 |
+
pc[pos] = np.int16(np.uint16(v & 0xFFFF)) if v >= 0 else np.int16(v)
|
| 188 |
+
wc = op(pc, in_f, out_f, K, True, False).detach().cpu().numpy().astype(np.float32)
|
| 189 |
+
combined_delta = wc - w0
|
| 190 |
+
# Compare
|
| 191 |
+
diff = np.abs(cumulative_delta - combined_delta)
|
| 192 |
+
norm_combined = np.linalg.norm(combined_delta)
|
| 193 |
+
norm_diff = np.linalg.norm(diff)
|
| 194 |
+
rel = norm_diff / max(norm_combined, 1e-9)
|
| 195 |
+
log(f" {tag}: |combined|={norm_combined:.3e} |diff|={norm_diff:.3e} rel={rel:.3e}")
|
| 196 |
+
return rel
|
| 197 |
+
|
| 198 |
+
# Two positions, different (bi, bj), same k_slot
|
| 199 |
+
linearity_probe([((0, 0, 0), 100), ((1, 1, 0), 200)], "2-pos, distinct (bi,bj), same k")
|
| 200 |
+
# Same block, different k_slot
|
| 201 |
+
linearity_probe([((0, 0, 0), 100), ((0, 0, 5), 200)], "2-pos, same (bi,bj), diff k")
|
| 202 |
+
# Same block, different k_slot, same k-group
|
| 203 |
+
linearity_probe([((0, 0, 0), 100), ((0, 0, 16), 200)], "2-pos, same (bi,bj), diff K-slice")
|
| 204 |
+
# 8 random positions (dense superposition test)
|
| 205 |
+
torch.manual_seed(42)
|
| 206 |
+
pairs = []
|
| 207 |
+
for i in range(8):
|
| 208 |
+
pos = (int(torch.randint(0, 128, (1,))), int(torch.randint(0, 64, (1,))), int(torch.randint(0, 32, (1,))))
|
| 209 |
+
v = int(torch.randint(1, 65536, (1,)))
|
| 210 |
+
pairs.append((pos, v))
|
| 211 |
+
linearity_probe(pairs, "8-pos random")
|
| 212 |
+
|
| 213 |
+
# 100 positions (many-slot dense superposition)
|
| 214 |
+
torch.manual_seed(1)
|
| 215 |
+
pairs = []
|
| 216 |
+
used_positions = set()
|
| 217 |
+
for _ in range(100):
|
| 218 |
+
while True:
|
| 219 |
+
pos = (int(torch.randint(0, 128, (1,))), int(torch.randint(0, 64, (1,))), int(torch.randint(0, 32, (1,))))
|
| 220 |
+
if pos not in used_positions:
|
| 221 |
+
used_positions.add(pos)
|
| 222 |
+
break
|
| 223 |
+
v = int(torch.randint(1, 65536, (1,)))
|
| 224 |
+
pairs.append((pos, v))
|
| 225 |
+
linearity_probe(pairs, "100-pos random")
|
| 226 |
+
log("")
|
| 227 |
+
|
| 228 |
+
# ---- (5) Slot invariance: does (0,0,0)+v produce same shape as (1,1,0)+v (offset by 16 rows/cols)? ----
|
| 229 |
+
log("## 5. Slot invariance test — is the codebook shared across (bi, bj)?")
|
| 230 |
+
log("")
|
| 231 |
+
log("Compare delta patterns for the SAME value v at DIFFERENT (bi, bj) with the same k_slot.")
|
| 232 |
+
log("If they are identical up to a (bi*16, bj*16) offset, the codebook is (bi, bj)-invariant.")
|
| 233 |
+
log("")
|
| 234 |
+
for v in [1, 100, 32767, -32768]:
|
| 235 |
+
p_a = torch.zeros(cshape, dtype=torch.int16, device=device)
|
| 236 |
+
p_a[0, 0, 0] = np.int16(np.uint16(v & 0xFFFF)) if v >= 0 else np.int16(v)
|
| 237 |
+
w_a = op(p_a, in_f, out_f, K, True, False).detach().cpu().numpy().astype(np.float32)
|
| 238 |
+
d_a = (w_a - w0)[:16, :16] # extract block at (0..16, 0..16)
|
| 239 |
+
|
| 240 |
+
for (bi_test, bj_test) in [(1, 0), (0, 1), (1, 1), (5, 3), (127, 63)]:
|
| 241 |
+
p_b = torch.zeros(cshape, dtype=torch.int16, device=device)
|
| 242 |
+
p_b[bi_test, bj_test, 0] = np.int16(np.uint16(v & 0xFFFF)) if v >= 0 else np.int16(v)
|
| 243 |
+
w_b = op(p_b, in_f, out_f, K, True, False).detach().cpu().numpy().astype(np.float32)
|
| 244 |
+
d_b = (w_b - w0)[bi_test*16:(bi_test+1)*16, bj_test*16:(bj_test+1)*16]
|
| 245 |
+
diff = np.abs(d_a - d_b)
|
| 246 |
+
rel = float(np.linalg.norm(diff) / max(np.linalg.norm(d_a), 1e-9))
|
| 247 |
+
log(f" v={v:6d} (bi=0,bj=0) vs (bi={bi_test},bj={bj_test}): |diff|={float(np.linalg.norm(diff)):.3e} rel={rel:.3e}")
|
| 248 |
+
log("")
|
| 249 |
+
|
| 250 |
+
# ---- (6) k_slot invariance: does (0,0,k)+v have consistent pattern for different k? ----
|
| 251 |
+
log("## 6. k_slot pattern")
|
| 252 |
+
log("")
|
| 253 |
+
log("For each k_slot, what is the row/col support of the (0, 0, k)+v=1 delta?")
|
| 254 |
+
log("")
|
| 255 |
+
ks_patterns: dict = {}
|
| 256 |
+
for K_test in (2, 3):
|
| 257 |
+
cs = (128, 64, 32) if K_test == 2 else (32, 128, 48)
|
| 258 |
+
inf, outf = (2048, 1024) if K_test == 2 else (512, 2048)
|
| 259 |
+
p0k = torch.zeros(cs, dtype=torch.int16, device=device)
|
| 260 |
+
w0k = op(p0k, inf, outf, K_test, True, False).detach().cpu().numpy().astype(np.float32)
|
| 261 |
+
log(f"### K={K_test}, cshape={cs}")
|
| 262 |
+
for k in range(16 * K_test):
|
| 263 |
+
p = torch.zeros(cs, dtype=torch.int16, device=device)
|
| 264 |
+
p[0, 0, k] = 1
|
| 265 |
+
w = op(p, inf, outf, K_test, True, False).detach().cpu().numpy().astype(np.float32)
|
| 266 |
+
d = (w - w0k)[:16, :16]
|
| 267 |
+
nz_pos = np.argwhere(np.abs(d) > 1e-6)
|
| 268 |
+
rows = sorted(set(int(r) for r, _ in nz_pos))
|
| 269 |
+
cols = sorted(set(int(c) for _, c in nz_pos))
|
| 270 |
+
ks_patterns[(K_test, k)] = {"rows": rows, "cols": cols, "n_pos": len(nz_pos),
|
| 271 |
+
"dense_block": d.tolist()}
|
| 272 |
+
log(f" k={k:2d}: rows={rows} cols={cols} n_pos={len(nz_pos)}")
|
| 273 |
+
log("")
|
| 274 |
+
|
| 275 |
+
# Save report + full audit data
|
| 276 |
+
Path("/vol").mkdir(parents=True, exist_ok=True)
|
| 277 |
+
result = {
|
| 278 |
+
"full_deltas": full_deltas,
|
| 279 |
+
"ks_patterns": ks_patterns,
|
| 280 |
+
"report_md": "\n".join(report_lines),
|
| 281 |
+
}
|
| 282 |
+
with open("/vol/op_audit.pkl", "wb") as f:
|
| 283 |
+
pickle.dump(result, f)
|
| 284 |
+
with open("/vol/op_audit_report.md", "w") as f:
|
| 285 |
+
f.write("\n".join(report_lines))
|
| 286 |
+
vol.commit()
|
| 287 |
+
|
| 288 |
+
return result
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
@app.local_entrypoint()
|
| 292 |
+
def main() -> None:
|
| 293 |
+
result = audit.remote()
|
| 294 |
+
out_pkl = Path("/Users/kaede/mlx-video/mlx_video/models/qwen3_5_moe_escha/codebooks/op_audit.pkl")
|
| 295 |
+
out_md = Path("/Users/kaede/mlx-video/docs/escha_op_signature.md")
|
| 296 |
+
out_pkl.parent.mkdir(parents=True, exist_ok=True)
|
| 297 |
+
out_md.parent.mkdir(parents=True, exist_ok=True)
|
| 298 |
+
with open(out_pkl, "wb") as f:
|
| 299 |
+
pickle.dump(result, f)
|
| 300 |
+
with open(out_md, "w") as f:
|
| 301 |
+
f.write(result["report_md"])
|
| 302 |
+
print(f"[local] wrote {out_pkl}")
|
| 303 |
+
print(f"[local] wrote {out_md}")
|
modal_smart_probe.py
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Extract the FULL layout of escham_reconstruct in a handful of op calls.
|
| 2 |
+
|
| 3 |
+
Findings from `modal_op_audit.py`:
|
| 4 |
+
1. Op is EXACTLY linear in codes: op(A+B) = op(A) + op(B) - op(0) (|diff|=0)
|
| 5 |
+
2. Codebook is SLOT-INVARIANT across (bi, bj): same delta at any (bi, bj)
|
| 6 |
+
up to a (bi*16, bj*16) offset.
|
| 7 |
+
3. Each (k, v) pair produces a fixed (16, 16) block pattern with ~5-9 nonzero
|
| 8 |
+
positions.
|
| 9 |
+
|
| 10 |
+
Extraction algorithm:
|
| 11 |
+
For each K ∈ {2, 3}:
|
| 12 |
+
Use cshape (128, 64, 32) for K=2 → 8192 blocks per op
|
| 13 |
+
Use cshape (32, 128, 48) for K=3 → 4096 blocks per op
|
| 14 |
+
For each k_slot ∈ [0, 16*K):
|
| 15 |
+
Loop v ∈ [0, 65536) in batches of `blocks_per_op`:
|
| 16 |
+
Build ONE code tensor where slot[bi_i, bj_i, k_slot] = v_i for a batch
|
| 17 |
+
of `blocks_per_op` distinct (bi, bj) pairs.
|
| 18 |
+
Call op once. Read out each (16, 16) block. Store as codebook entry.
|
| 19 |
+
|
| 20 |
+
Result:
|
| 21 |
+
cb_K2 : (32, 65536, 16, 16) fp16 — 4.3 GB
|
| 22 |
+
cb_K3 : (48, 65536, 16, 16) fp16 — 6.4 GB
|
| 23 |
+
Total ~11 GB.
|
| 24 |
+
|
| 25 |
+
But we know most codes produce SPARSE patterns (5-9 nonzeros). We can store
|
| 26 |
+
compact: for each (K, k_slot) collect ONCE a mask of which (row, col) positions
|
| 27 |
+
are nonzero, then store only the sparse values as (K, 65536, n_nz) fp16.
|
| 28 |
+
This shrinks to <100 MB total. See `_compact_layout` below.
|
| 29 |
+
"""
|
| 30 |
+
|
| 31 |
+
from __future__ import annotations
|
| 32 |
+
|
| 33 |
+
import pickle
|
| 34 |
+
import time
|
| 35 |
+
from pathlib import Path
|
| 36 |
+
|
| 37 |
+
import modal
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
WHEEL_REVISION = "1.0.2+qwen3moe"
|
| 41 |
+
|
| 42 |
+
image = (
|
| 43 |
+
modal.Image.from_registry(
|
| 44 |
+
"nvidia/cuda:12.8.1-cudnn-runtime-ubuntu24.04",
|
| 45 |
+
add_python="3.12",
|
| 46 |
+
)
|
| 47 |
+
.apt_install("curl", "binutils", "git", "ca-certificates")
|
| 48 |
+
.pip_install("wheel", "pip", "setuptools")
|
| 49 |
+
.pip_install(
|
| 50 |
+
"torch==2.9.*",
|
| 51 |
+
index_url="https://download.pytorch.org/whl/cu128",
|
| 52 |
+
)
|
| 53 |
+
.pip_install("numpy", "safetensors", "huggingface_hub[cli]", "hf_transfer")
|
| 54 |
+
.run_commands(
|
| 55 |
+
f"echo escha wheel revision: {WHEEL_REVISION}",
|
| 56 |
+
"mkdir -p /escha",
|
| 57 |
+
"hf download EschaLabs/escha-runtime-qwen3moe --include 'sglang/*' --local-dir /escha",
|
| 58 |
+
"pip install --no-deps /escha/sglang/escha-*.whl",
|
| 59 |
+
)
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
vol = modal.Volume.from_name("escha-codebooks", create_if_missing=True)
|
| 63 |
+
app = modal.App("escha-smart-probe", image=image)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
@app.function(gpu="A10G", timeout=3600 * 2, memory=32 * 1024, volumes={"/vol": vol})
|
| 67 |
+
def extract_layout() -> dict:
|
| 68 |
+
import numpy as np
|
| 69 |
+
import torch
|
| 70 |
+
import escha # noqa: F401
|
| 71 |
+
|
| 72 |
+
op = torch.ops.escha.escham_reconstruct
|
| 73 |
+
device = "cuda"
|
| 74 |
+
|
| 75 |
+
result: dict = {}
|
| 76 |
+
|
| 77 |
+
for K, cshape, in_f, out_f in [
|
| 78 |
+
(2, (128, 64, 32), 2048, 1024),
|
| 79 |
+
(3, (32, 128, 48), 512, 2048),
|
| 80 |
+
]:
|
| 81 |
+
bi_max, bj_max, k_max = cshape
|
| 82 |
+
blocks_per_op = bi_max * bj_max
|
| 83 |
+
print(f"\n=== K={K} cshape={cshape} in_f={in_f} out_f={out_f} blocks_per_op={blocks_per_op} ===", flush=True)
|
| 84 |
+
|
| 85 |
+
# Baseline (all-zeros).
|
| 86 |
+
p0 = torch.zeros(cshape, dtype=torch.int16, device=device)
|
| 87 |
+
w0 = op(p0, in_f, out_f, K, True, False).detach().cpu().numpy().astype(np.float32)
|
| 88 |
+
print(f" baseline w0 shape={w0.shape} norm={np.linalg.norm(w0):.3e}", flush=True)
|
| 89 |
+
|
| 90 |
+
# Assign a distinct (bi, bj) to each of blocks_per_op probes.
|
| 91 |
+
block_positions = [(bi, bj) for bi in range(bi_max) for bj in range(bj_max)]
|
| 92 |
+
|
| 93 |
+
# For each k_slot, we'll store a full (65536, 16, 16) fp16 tensor of block
|
| 94 |
+
# deltas. This is 32 MB per k_slot. Total: 32 × 32 MB = 1 GB (K=2), 48 × 32 MB = 1.5 GB (K=3).
|
| 95 |
+
# We'll compact to sparse form at the end.
|
| 96 |
+
cb_full = np.zeros((k_max, 65536, 16, 16), dtype=np.float16)
|
| 97 |
+
t_k_start = time.time()
|
| 98 |
+
for k in range(k_max):
|
| 99 |
+
t0 = time.time()
|
| 100 |
+
# Loop v in batches of `blocks_per_op`.
|
| 101 |
+
n_ops = 0
|
| 102 |
+
for v_start in range(0, 65536, blocks_per_op):
|
| 103 |
+
v_end = min(v_start + blocks_per_op, 65536)
|
| 104 |
+
n_probes = v_end - v_start
|
| 105 |
+
# Build code tensor.
|
| 106 |
+
p = torch.zeros(cshape, dtype=torch.int16, device=device)
|
| 107 |
+
for i in range(n_probes):
|
| 108 |
+
v = v_start + i
|
| 109 |
+
bi, bj = block_positions[i]
|
| 110 |
+
# int16 wrap: values > 32767 become negative
|
| 111 |
+
p[bi, bj, k] = np.int16(np.uint16(v & 0xFFFF)) if v < 32768 else np.int16(v - 65536)
|
| 112 |
+
# Call op ONCE for these n_probes probes.
|
| 113 |
+
w = op(p, in_f, out_f, K, True, False)
|
| 114 |
+
# Extract each (bi, bj) block as the codebook entry for (k, v).
|
| 115 |
+
w_np = w.detach().cpu().numpy().astype(np.float32)
|
| 116 |
+
for i in range(n_probes):
|
| 117 |
+
v = v_start + i
|
| 118 |
+
bi, bj = block_positions[i]
|
| 119 |
+
block = w_np[bi*16:(bi+1)*16, bj*16:(bj+1)*16] - w0[bi*16:(bi+1)*16, bj*16:(bj+1)*16]
|
| 120 |
+
cb_full[k, v] = block.astype(np.float16)
|
| 121 |
+
n_ops += 1
|
| 122 |
+
dt = time.time() - t0
|
| 123 |
+
total = time.time() - t_k_start
|
| 124 |
+
print(f" K={K} k_slot={k:2d} done: {n_ops} op calls, {dt:.1f}s (cumulative {total:.1f}s)", flush=True)
|
| 125 |
+
|
| 126 |
+
result[f"cb_K{K}"] = cb_full # (k_max, 65536, 16, 16) fp16
|
| 127 |
+
print(f" K={K} total: {time.time() - t_k_start:.1f}s")
|
| 128 |
+
|
| 129 |
+
# === Sanity check: reproduce a real expert weight from the extracted layout. ===
|
| 130 |
+
print("\n=== sanity check: reproduce w_bare for gate_up L0/E0 ===", flush=True)
|
| 131 |
+
from safetensors import safe_open
|
| 132 |
+
from huggingface_hub import snapshot_download
|
| 133 |
+
import json
|
| 134 |
+
|
| 135 |
+
print(" downloading model snapshot (cached in volume)...", flush=True)
|
| 136 |
+
model_dir = snapshot_download(
|
| 137 |
+
"EschaLabs/Qwen3.6-35B-A3B-Escha-W2",
|
| 138 |
+
cache_dir="/vol/hf_cache",
|
| 139 |
+
)
|
| 140 |
+
idx = json.load(open(f"{model_dir}/model.safetensors.index.json"))
|
| 141 |
+
wm = idx["weight_map"]
|
| 142 |
+
|
| 143 |
+
def _load(name, expert=0):
|
| 144 |
+
shard = wm[name]
|
| 145 |
+
with safe_open(f"{model_dir}/{shard}", framework="pt") as f:
|
| 146 |
+
return f.get_tensor(name)[expert]
|
| 147 |
+
|
| 148 |
+
for tag, pfx, in_f, out_f, K, cshape in [
|
| 149 |
+
("gate_up", "model.language_model.layers.0.mlp.experts.gate_up_proj", 2048, 1024, 2, (128, 64, 32)),
|
| 150 |
+
("down", "model.language_model.layers.0.mlp.experts.down_proj", 512, 2048, 3, (32, 128, 48)),
|
| 151 |
+
]:
|
| 152 |
+
code = _load(f"{pfx}.escha_code", expert=0).cuda()
|
| 153 |
+
w_ref = op(code, in_f, out_f, K, True, False).detach().cpu().numpy().astype(np.float32)
|
| 154 |
+
|
| 155 |
+
# Reconstruct via extracted layout.
|
| 156 |
+
cb = result[f"cb_K{K}"] # (k_max, 65536, 16, 16) fp16
|
| 157 |
+
# Baseline for this cshape:
|
| 158 |
+
p0 = torch.zeros(cshape, dtype=torch.int16, device=device)
|
| 159 |
+
w0_np = op(p0, in_f, out_f, K, True, False).detach().cpu().numpy().astype(np.float32)
|
| 160 |
+
|
| 161 |
+
w_recon = w0_np.copy() # start from baseline
|
| 162 |
+
code_np = code.cpu().numpy() # (bi_max, bj_max, k_max) int16
|
| 163 |
+
# Convert int16 → uint16 index
|
| 164 |
+
code_u = code_np.astype(np.int32) & 0xFFFF # (bi_max, bj_max, k_max)
|
| 165 |
+
bi_max, bj_max, k_max = cshape
|
| 166 |
+
for k in range(k_max):
|
| 167 |
+
# Gather cb[k, code_u[:,:,k]] → (bi_max, bj_max, 16, 16)
|
| 168 |
+
blocks = cb[k, code_u[:, :, k]] # (bi_max, bj_max, 16, 16) fp16
|
| 169 |
+
# Add to w_recon at the right positions.
|
| 170 |
+
# blocks[bi, bj] → w_recon[bi*16:(bi+1)*16, bj*16:(bj+1)*16]
|
| 171 |
+
# Reshape trick:
|
| 172 |
+
blocks_reshaped = blocks.astype(np.float32).transpose(0, 2, 1, 3).reshape(bi_max * 16, bj_max * 16)
|
| 173 |
+
w_recon += blocks_reshaped
|
| 174 |
+
|
| 175 |
+
diff = np.abs(w_recon - w_ref)
|
| 176 |
+
max_diff = float(diff.max())
|
| 177 |
+
mean_diff = float(diff.mean())
|
| 178 |
+
rel = float(np.linalg.norm(diff) / np.linalg.norm(w_ref))
|
| 179 |
+
print(f" {tag}: |w_ref|={np.linalg.norm(w_ref):.3e} max_diff={max_diff:.3e} mean_diff={mean_diff:.3e} rel={rel:.3e}", flush=True)
|
| 180 |
+
result[f"sanity_{tag}"] = {"max_diff": max_diff, "mean_diff": mean_diff, "rel": rel}
|
| 181 |
+
|
| 182 |
+
# === Save extracted layout to volume ===
|
| 183 |
+
print("\n=== saving to /vol ===", flush=True)
|
| 184 |
+
Path("/vol/layout_v2").mkdir(parents=True, exist_ok=True)
|
| 185 |
+
for K in (2, 3):
|
| 186 |
+
cb = result[f"cb_K{K}"]
|
| 187 |
+
np.save(f"/vol/layout_v2/cb_K{K}.npy", cb)
|
| 188 |
+
print(f" wrote /vol/layout_v2/cb_K{K}.npy ({cb.nbytes/1e9:.2f} GB)", flush=True)
|
| 189 |
+
|
| 190 |
+
# === Also compute a compact-sparse form ===
|
| 191 |
+
print("\n=== computing sparse-compact form ===", flush=True)
|
| 192 |
+
compact: dict = {}
|
| 193 |
+
for K in (2, 3):
|
| 194 |
+
cb = result[f"cb_K{K}"] # (k_max, 65536, 16, 16) fp16
|
| 195 |
+
k_max = cb.shape[0]
|
| 196 |
+
# For each k_slot, find the union of (row, col) positions that are ever
|
| 197 |
+
# nonzero across all 65536 codes. Store cb[k, :, mask] compactly.
|
| 198 |
+
mask_per_k: list = []
|
| 199 |
+
vals_per_k: list = []
|
| 200 |
+
for k in range(k_max):
|
| 201 |
+
# Any code that has this position nonzero?
|
| 202 |
+
any_nz = np.any(cb[k].astype(np.float32) != 0, axis=0) # (16, 16) bool
|
| 203 |
+
positions = np.argwhere(any_nz) # (n_nz, 2)
|
| 204 |
+
n_nz = positions.shape[0]
|
| 205 |
+
# Extract the (65536, n_nz) values.
|
| 206 |
+
vals = cb[k, :, positions[:, 0], positions[:, 1]] # (n_nz, 65536)
|
| 207 |
+
# Transpose to (65536, n_nz)
|
| 208 |
+
vals = vals.T.astype(np.float16)
|
| 209 |
+
mask_per_k.append(positions.astype(np.int8))
|
| 210 |
+
vals_per_k.append(vals)
|
| 211 |
+
if k < 3:
|
| 212 |
+
print(f" K={K} k={k}: n_nz_positions={n_nz} vals_shape={vals.shape}", flush=True)
|
| 213 |
+
# Since n_nz may differ per k, store as a list.
|
| 214 |
+
compact[f"K{K}_positions"] = mask_per_k
|
| 215 |
+
compact[f"K{K}_values"] = vals_per_k
|
| 216 |
+
# Serialize.
|
| 217 |
+
with open("/vol/layout_v2/compact.pkl", "wb") as f:
|
| 218 |
+
pickle.dump(compact, f, protocol=pickle.HIGHEST_PROTOCOL)
|
| 219 |
+
print(f" wrote /vol/layout_v2/compact.pkl", flush=True)
|
| 220 |
+
|
| 221 |
+
vol.commit()
|
| 222 |
+
|
| 223 |
+
# Return sanity metrics + sizes (avoid returning multi-GB tensors).
|
| 224 |
+
return {
|
| 225 |
+
"sanity_gate_up": result["sanity_gate_up"],
|
| 226 |
+
"sanity_down": result["sanity_down"],
|
| 227 |
+
"cb_K2_shape": result["cb_K2"].shape,
|
| 228 |
+
"cb_K3_shape": result["cb_K3"].shape,
|
| 229 |
+
"cb_K2_nbytes": int(result["cb_K2"].nbytes),
|
| 230 |
+
"cb_K3_nbytes": int(result["cb_K3"].nbytes),
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
@app.function(image=image, volumes={"/vol": vol}, timeout=600)
|
| 235 |
+
def fetch() -> dict:
|
| 236 |
+
"""Fetch the compact codebook + optionally the full form."""
|
| 237 |
+
import os
|
| 238 |
+
result = {}
|
| 239 |
+
for name in ("compact.pkl",):
|
| 240 |
+
path = f"/vol/layout_v2/{name}"
|
| 241 |
+
if os.path.exists(path):
|
| 242 |
+
with open(path, "rb") as f:
|
| 243 |
+
result[name] = f.read()
|
| 244 |
+
return result
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
@app.local_entrypoint()
|
| 248 |
+
def main() -> None:
|
| 249 |
+
metrics = extract_layout.remote()
|
| 250 |
+
print(f"\n[local] extract metrics: {metrics}")
|
| 251 |
+
|
| 252 |
+
files = fetch.remote()
|
| 253 |
+
out_dir = Path("/Users/kaede/mlx-video/mlx_video/models/qwen3_5_moe_escha/codebooks")
|
| 254 |
+
for name, data in files.items():
|
| 255 |
+
target = out_dir / f"layout_v2_{name}"
|
| 256 |
+
target.write_bytes(data)
|
| 257 |
+
print(f"[local] wrote {target} ({len(data)/1e6:.2f} MB)")
|