KaedeTai commited on
Commit
3a5a89f
·
verified ·
1 Parent(s): 29ce1aa

Initial: extracted Escha packed AQLM codebook + audit + reproducers

Browse files
Files changed (6) hide show
  1. LAYOUT_NOTES.md +110 -0
  2. OP_SIGNATURE_AUDIT.md +201 -0
  3. README.md +131 -0
  4. compact.pkl +3 -0
  5. modal_op_audit.py +303 -0
  6. 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)")