flashrt-structures 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. flashrt_structures/__init__.py +174 -0
  2. flashrt_structures/adapters/__init__.py +55 -0
  3. flashrt_structures/adapters/diffusers_attention.py +237 -0
  4. flashrt_structures/adapters/diffusers_rotary_attention.py +239 -0
  5. flashrt_structures/adapters/factored_qk_norm_rope.py +252 -0
  6. flashrt_structures/adapters/factored_two_way_attention.py +99 -0
  7. flashrt_structures/adapters/gemma_attention.py +226 -0
  8. flashrt_structures/adapters/packed_qkv_rope.py +342 -0
  9. flashrt_structures/adapters/packed_stream_qk_norm_rope.py +376 -0
  10. flashrt_structures/adapters/qwen_per_head_qk_norm_rope.py +231 -0
  11. flashrt_structures/adapters/sglang_engine.py +207 -0
  12. flashrt_structures/adapters/transformers_attention_interface.py +73 -0
  13. flashrt_structures/adapters/transformers_gated_delta.py +152 -0
  14. flashrt_structures/adapters/transformers_gated_delta_fused.py +96 -0
  15. flashrt_structures/adapters/vllm_engine.py +424 -0
  16. flashrt_structures/adjudicate.py +85 -0
  17. flashrt_structures/aot.py +191 -0
  18. flashrt_structures/autobuild.py +2052 -0
  19. flashrt_structures/beta/__init__.py +43 -0
  20. flashrt_structures/beta/conform.py +94 -0
  21. flashrt_structures/beta/joins.py +113 -0
  22. flashrt_structures/beta/negotiate.py +84 -0
  23. flashrt_structures/beta/ports.py +140 -0
  24. flashrt_structures/decisions.py +80 -0
  25. flashrt_structures/discover.py +623 -0
  26. flashrt_structures/explain.py +70 -0
  27. flashrt_structures/frontdoor.py +572 -0
  28. flashrt_structures/gates.py +465 -0
  29. flashrt_structures/guard.py +421 -0
  30. flashrt_structures/handle.py +189 -0
  31. flashrt_structures/impls/__init__.py +219 -0
  32. flashrt_structures/impls/adaln_producer/__init__.py +8 -0
  33. flashrt_structures/impls/adaln_producer/broker.py +116 -0
  34. flashrt_structures/impls/adaln_producer/fused.py +388 -0
  35. flashrt_structures/impls/adarms_stack/__init__.py +8 -0
  36. flashrt_structures/impls/adarms_stack/fp8_chain.py +832 -0
  37. flashrt_structures/impls/adarms_stack/region.py +102 -0
  38. flashrt_structures/impls/attention_core/__init__.py +132 -0
  39. flashrt_structures/impls/attention_core/fa2_seqused.py +458 -0
  40. flashrt_structures/impls/attention_core/fa4_cute.py +154 -0
  41. flashrt_structures/impls/attention_core/fa4_fp8.py +178 -0
  42. flashrt_structures/impls/attention_core/masked_mha.py +158 -0
  43. flashrt_structures/impls/attention_core/two_way_fa2.py +220 -0
  44. flashrt_structures/impls/cadence_static/__init__.py +18 -0
  45. flashrt_structures/impls/cadence_static/buffers.py +122 -0
  46. flashrt_structures/impls/cadence_static/cross_attention.py +187 -0
  47. flashrt_structures/impls/chain_elements.py +89 -0
  48. flashrt_structures/impls/decode_loop/__init__.py +0 -0
  49. flashrt_structures/impls/decode_loop/fp8_kv.py +206 -0
  50. flashrt_structures/impls/decode_loop/mtp_speculative.py +245 -0
  51. flashrt_structures/impls/decode_loop/whole_step.py +852 -0
  52. flashrt_structures/impls/decoder_block/__init__.py +6 -0
  53. flashrt_structures/impls/decoder_block/attn_sublayer.py +110 -0
  54. flashrt_structures/impls/decoder_block/fused.py +167 -0
  55. flashrt_structures/impls/decoder_ffn/__init__.py +0 -0
  56. flashrt_structures/impls/decoder_ffn/fp8_static.py +310 -0
  57. flashrt_structures/impls/decoder_ffn/fp8_static.yaml +22 -0
  58. flashrt_structures/impls/decoder_ffn/w4a16_static.py +221 -0
  59. flashrt_structures/impls/decoder_ffn/w8a16_static.py +183 -0
  60. flashrt_structures/impls/dit_stack/__init__.py +11 -0
  61. flashrt_structures/impls/dit_stack/fp4_chain.py +417 -0
  62. flashrt_structures/impls/dit_stack/region.py +86 -0
  63. flashrt_structures/impls/fixed_iter/__init__.py +29 -0
  64. flashrt_structures/impls/fixed_iter/openpi.py +264 -0
  65. flashrt_structures/impls/fixed_iter/protocol.py +94 -0
  66. flashrt_structures/impls/gated_delta_core/__init__.py +3 -0
  67. flashrt_structures/impls/gated_delta_core/fused_layer.py +545 -0
  68. flashrt_structures/impls/gated_delta_core/hub_v3.py +152 -0
  69. flashrt_structures/impls/graph_lowering/__init__.py +27 -0
  70. flashrt_structures/impls/graph_lowering/pi052_denoise.py +179 -0
  71. flashrt_structures/impls/graph_lowering/protocol.py +76 -0
  72. flashrt_structures/impls/graph_lowering/qwen3_vl.py +364 -0
  73. flashrt_structures/impls/linear_proj/__init__.py +0 -0
  74. flashrt_structures/impls/linear_proj/fp8_static.py +270 -0
  75. flashrt_structures/impls/linear_proj/nvfp4_balance.py +131 -0
  76. flashrt_structures/impls/linear_proj/nvfp4_dynamic.py +182 -0
  77. flashrt_structures/impls/linear_proj/w8a16_static.py +230 -0
  78. flashrt_structures/impls/modnorm_qkv_chain/__init__.py +0 -0
  79. flashrt_structures/impls/modnorm_qkv_chain/fp8_ptok_table.py +291 -0
  80. flashrt_structures/impls/moe_experts/__init__.py +9 -0
  81. flashrt_structures/impls/moe_experts/nvfp4_dynamic.py +208 -0
  82. flashrt_structures/impls/moe_experts/nvfp4_w4a16.py +129 -0
  83. flashrt_structures/impls/norm_fused/__init__.py +3 -0
  84. flashrt_structures/impls/norm_fused/bf16.py +94 -0
  85. flashrt_structures/impls/norm_fused/fp8_producer.py +84 -0
  86. flashrt_structures/impls/patch_projection/__init__.py +3 -0
  87. flashrt_structures/impls/patch_projection/bf16_flat.py +139 -0
  88. flashrt_structures/impls/prefill_tower/__init__.py +10 -0
  89. flashrt_structures/impls/prefill_tower/fp8_chain.py +955 -0
  90. flashrt_structures/impls/prefill_tower/region.py +99 -0
  91. flashrt_structures/impls/qk_norm_rope/__init__.py +12 -0
  92. flashrt_structures/impls/qk_norm_rope/per_head_gqa.py +199 -0
  93. flashrt_structures/impls/qk_norm_rope/projection_bf16.py +165 -0
  94. flashrt_structures/impls/qkv_pack/__init__.py +5 -0
  95. flashrt_structures/impls/qkv_pack/bf16.py +110 -0
  96. flashrt_structures/impls/qkv_pack/fp8_static.py +435 -0
  97. flashrt_structures/impls/qkv_pack/nvfp4_balance.py +218 -0
  98. flashrt_structures/impls/qkv_rope/__init__.py +3 -0
  99. flashrt_structures/impls/qkv_rope/packed_bias_bf16.py +143 -0
  100. flashrt_structures/impls/step_table.py +113 -0
  101. flashrt_structures/impls/vision_ffn/__init__.py +0 -0
  102. flashrt_structures/impls/vision_ffn/fp8_static.py +261 -0
  103. flashrt_structures/impls/vision_ffn/nvfp4_balance.py +211 -0
  104. flashrt_structures/impls/vision_tower/__init__.py +7 -0
  105. flashrt_structures/impls/vision_tower/fp8_chain.py +533 -0
  106. flashrt_structures/impls/vision_tower/region.py +91 -0
  107. flashrt_structures/matrix.py +126 -0
  108. flashrt_structures/points.py +368 -0
  109. flashrt_structures/prequantized.py +131 -0
  110. flashrt_structures/quantize_on_adopt.py +94 -0
  111. flashrt_structures/recipe.py +438 -0
  112. flashrt_structures/regions.py +208 -0
  113. flashrt_structures/schemes.py +490 -0
  114. flashrt_structures/stages.py +298 -0
  115. flashrt_structures/storage.py +255 -0
  116. flashrt_structures/swap.py +398 -0
  117. flashrt_structures/workspace.py +110 -0
  118. flashrt_structures-0.2.0.dist-info/METADATA +140 -0
  119. flashrt_structures-0.2.0.dist-info/RECORD +122 -0
  120. flashrt_structures-0.2.0.dist-info/WHEEL +5 -0
  121. flashrt_structures-0.2.0.dist-info/licenses/LICENSE +202 -0
  122. flashrt_structures-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,832 @@
1
+ """The fused static-FP8 launch chain over an AdaRMS decoder stack.
2
+
3
+ Per layer: one fused gated-residual/AdaRMS/quantize producer feeds a
4
+ merged-QKV FP8 GEMM, a split+RoPE kernel writes the suffix K/V into a
5
+ chain-owned cache behind the copied prefix, FA2 attends over exactly
6
+ the used keys, and the same producer carries the post-attention
7
+ residual into the FFN's merged gate/up GEMM. The activation quantizer
8
+ sites are calibrated on the probe run against the pristine host.
9
+
10
+ Two equivalences are established at bind, not assumed:
11
+
12
+ - The host rotates pairs ``(i, i + half)`` (rotate-half); the split
13
+ kernel rotates adjacent pairs. The q/k projection rows are permuted
14
+ at quantize time so the kernel's layout carries the host's rotation
15
+ — attention dot products are invariant under a shared permutation
16
+ of the head dimension, and V stays in host order so the output
17
+ projection sees host layout.
18
+ - The host masks with a dense additive mask over
19
+ ``[prefix | pad | suffix]``. The chain checks on the probe call
20
+ that every query row shares that exact pattern, then expresses it
21
+ as a used-key count: prefix rows copied, suffix rows appended, FA2
22
+ told the total. A mask outside this shape refuses the bind.
23
+
24
+ This is a region candidate: adapter contract in, receipts decide
25
+ activation, out-of-contract calls fall back to the retained host
26
+ forward. Contract checks run eager-only and step aside during
27
+ capture — the captured window is certified by its own gate.
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ import types
33
+ from typing import Any, Callable
34
+
35
+ import torch
36
+
37
+ from .. import KernelUnavailable, hub_kernel
38
+ from ..chain_elements import (
39
+ ATTN_RUNGS, FP8_MAX, attention_rungs as _attention_rungs,
40
+ cache_kv as _cache_kv, fp8_weight as _fp8_weight,
41
+ gelu_tanh_like as _gelu_tanh_like,
42
+ interleave_rows as _interleave_rows)
43
+ from ...guard import GuardedSeam
44
+
45
+ GEMM_PACKAGE = "flashrt/fp8-gemm"
46
+ NORM_PACKAGE = "flashrt/flashrt-adaptive-norms"
47
+ ROPE_PACKAGE = "flashrt/flashrt-qkv-cache-rope"
48
+ GEMM_SYMBOLS = ("fp8_linear_bf16",)
49
+ NORM_SYMBOLS = ("gate_residual_ada_norm_fp8_static_bf16",)
50
+ ROPE_SYMBOLS = ("qkv_split_rope_kvcache_bf16",)
51
+ FUSE_PACKAGE = "flashrt/transformer-fused-ops"
52
+ FUSE_SYMBOLS = ("gate_geglu_merged_quant_fp8_static_bf16",
53
+ "quantize_fp8_static_bf16")
54
+ #: the mixed-precision band, the native decoder's own form: the three
55
+ #: norm-fed GEMMs ride W4A4 NVFP4 with dynamic block scales, the down
56
+ #: projection stays static FP8 (its input is the fused GEGLU's FP8)
57
+ FP4_GEMM_PACKAGE = "flashrt/fp4-gemm"
58
+ FP4_NORM_PACKAGE = "flashrt/fp4-fused-ops"
59
+ FP4_GEMM_SYMBOLS = ("nvfp4_gemm_bias_bf16", "quantize_fp4_sfa_bf16")
60
+ FP4_NORM_SYMBOLS = ("gate_res_ada_rms_norm_quant_nvfp4_swizzled_bf16",)
61
+
62
+ #: the band table IS the recipe: one row per precision band, naming
63
+ #: the extra packages the band assembles, its candidate rank, and the
64
+ #: down-projection flavor. The chain body stays one form; adding a
65
+ #: band means adding a row (and its element closures in
66
+ #: :func:`_band_elements`), never another branch in the loop.
67
+ #: ``fp4_full`` is the native decoder's complete form — all four
68
+ #: projections ride NVFP4, the GEGLU emits packed FP4 directly — and
69
+ #: it qualifies the moment its producer ships a bf16 entry.
70
+ BANDS: dict[str, dict] = {
71
+ "fp8": {"packages": (), "precision_rank": 0, "dn": "fp8"},
72
+ "fp4": {"packages": ((FP4_GEMM_PACKAGE, FP4_GEMM_SYMBOLS),
73
+ (FP4_NORM_PACKAGE, FP4_NORM_SYMBOLS)),
74
+ "precision_rank": 1, "dn": "fp8"},
75
+ "fp4_full": {"packages": (
76
+ (FP4_GEMM_PACKAGE, FP4_GEMM_SYMBOLS),
77
+ (FP4_NORM_PACKAGE, FP4_NORM_SYMBOLS
78
+ + ("gelu_mul_nvfp4_bf16",))),
79
+ "precision_rank": 2, "dn": "fp4"},
80
+ }
81
+
82
+ #: the attention element resolves per host: the house CuTe FA4
83
+ #: runtime first — it carries the D256 2CTA forward this stack's
84
+ #: 8-query/1-KV heads need, which the community FA4 package does not
85
+ #: expose — then the FA2 used-keys entry. The chain cache holds
86
+ #: exactly the used keys, so both rungs run the same dense
87
+ #: non-causal call into a caller-owned output; a rung that loads but
88
+ #: cannot execute is eliminated by the bind-time functional probe,
89
+ #: not by device lists.
90
+ #: whole-stack smoke on every probe call; the arm's end-to-end parity
91
+ #: gate (0.99 vs the host's own eager run) stays the judge
92
+ SMOKE_FLOOR = 0.985
93
+
94
+
95
+ def missing_symbols_fp4() -> list[str]:
96
+ return missing_symbols(band="fp4")
97
+
98
+
99
+ def missing_symbols(band: str = "fp8") -> list[str]:
100
+ """The factual prerequisites this box does not meet (may be empty)."""
101
+ gaps: list[str] = []
102
+ packages = ((GEMM_PACKAGE, GEMM_SYMBOLS),
103
+ (NORM_PACKAGE, NORM_SYMBOLS),
104
+ (ROPE_PACKAGE, ROPE_SYMBOLS),
105
+ (FUSE_PACKAGE, FUSE_SYMBOLS)) + BANDS[band]["packages"]
106
+ for repo, symbols in packages:
107
+ try:
108
+ kern = hub_kernel(repo, ">=1")
109
+ except KernelUnavailable:
110
+ gaps.append(repo)
111
+ continue
112
+ gaps.extend(f"{repo}:{s}" for s in symbols
113
+ if not hasattr(kern, s))
114
+ if not _attention_rungs():
115
+ gaps.append("attention: " + " or ".join(
116
+ r[1] for r in ATTN_RUNGS))
117
+ return gaps
118
+
119
+
120
+ class BoundAdaRmsFp8Chain(GuardedSeam, torch.nn.Module):
121
+ """Bind-time state: FP8 weights, style stack, chain-owned caches.
122
+
123
+ Plain tensor attributes, not buffers — a ledger citizen, not a
124
+ state_dict citizen; the truth of every weight stays with the host
125
+ modules the chain absorbs, which keeps revert bit-exact for free.
126
+ """
127
+
128
+ _frt_can_fallback = False # fallback is the routed closure's job
129
+
130
+ def __init__(self) -> None:
131
+ super().__init__()
132
+ self.table: list[dict] = []
133
+ self.dims: dict = {}
134
+ self.buf: dict = {}
135
+ self.style_w_t = None
136
+ self.style_b = None
137
+ self.rope = None
138
+ self.scaling = 1.0
139
+ self.eps = 1e-6
140
+ self.p_used = 0
141
+ self.total_keys = 0
142
+ self.out_ctor = None
143
+ self.kperm = None
144
+ self.kernels: dict = {}
145
+ #: the step-table form (the stack's own house pattern): style
146
+ #: modulations are baked per probed step at bind, and the run
147
+ #: resolves the live conditioning to a table by on-device
148
+ #: nearest-neighbour match — no Python state, so the same
149
+ #: data-driven selection is what a compile traces and a
150
+ #: capture bakes
151
+ self.step_conds = None
152
+ self.style_table = None
153
+ self.fin_table = None
154
+ self.band = "fp8"
155
+ self.zero_bias: dict = {}
156
+ #: armed by the region wire (autobuild) once a bound producer
157
+ #: guarantees the chain caches' prefix rows are written
158
+ #: in-graph before the first decoder step: the per-step prefix
159
+ #: gather leaves the graph. Bind-time state — constant by
160
+ #: capture time, so both a capture and a compile bake one arm.
161
+ self.prefix_wired = False
162
+
163
+
164
+ def _stack_parts(stack):
165
+ layers = list(stack.layers)
166
+ attn = layers[0].self_attn
167
+ head_dim = getattr(attn, "head_dim", None)
168
+ if not isinstance(head_dim, int):
169
+ raise ValueError("attention exposes no integer head_dim")
170
+ nh = attn.q_proj.out_features // head_dim
171
+ kv = attn.k_proj.out_features // head_dim
172
+ dim = attn.q_proj.in_features
173
+ hidden = layers[0].mlp.gate_proj.out_features
174
+ return layers, nh, kv, head_dim, dim, hidden
175
+
176
+
177
+ @torch.no_grad()
178
+ def _quantize(bound: BoundAdaRmsFp8Chain, layers, amax: dict) -> None:
179
+ """Pack every stack GEMM from the pristine host: static FP8 with
180
+ the calibrated activation scale folded into alpha, or — on the
181
+ mixed band — NVFP4 with dynamic block scales for the norm-fed
182
+ GEMMs (the down projection stays FP8; its input already is)."""
183
+ nh, kv, hd = (bound.dims[k] for k in ("nh", "kv", "hd"))
184
+ fp4 = BANDS[bound.band]["packages"] != ()
185
+ dn_fp4 = BANDS[bound.band]["dn"] == "fp4"
186
+ quant4 = (bound.kernels["kg4"].quantize_fp4_sfa_bf16
187
+ if fp4 else None)
188
+ for i, ly in enumerate(layers):
189
+ attn, mlp = ly.self_attn, ly.mlp
190
+ a_qkv, a_o, a_gu, a_dn = (amax[(i, s)] / FP8_MAX for s in
191
+ ("qkv", "o", "gu", "dn"))
192
+ qkv_w = torch.cat([
193
+ _interleave_rows(attn.q_proj.weight, nh, hd),
194
+ _interleave_rows(attn.k_proj.weight, kv, hd),
195
+ attn.v_proj.weight], dim=0)
196
+ gu_w = torch.cat([mlp.gate_proj.weight, mlp.up_proj.weight], dim=0)
197
+ entry: dict[str, Any] = {}
198
+ for name, w, act in (("qkv", qkv_w, a_qkv),
199
+ ("o", attn.o_proj.weight, a_o),
200
+ ("gu", gu_w, a_gu),
201
+ ("dn", mlp.down_proj.weight, a_dn)):
202
+ if fp4 and (name != "dn" or dn_fp4):
203
+ wp, wsf = quant4(
204
+ w.detach().to("cuda", torch.bfloat16)
205
+ .contiguous(), is_sfb=True)
206
+ entry[name] = (wp, wsf)
207
+ if w.shape[0] not in bound.zero_bias:
208
+ bound.zero_bias[w.shape[0]] = torch.zeros(
209
+ w.shape[0], device="cuda",
210
+ dtype=torch.bfloat16)
211
+ continue
212
+ packed, w_scale = _fp8_weight(w)
213
+ entry[name] = packed
214
+ entry[f"a_{name}"] = act * w_scale
215
+ entry["sc_qkv"] = torch.tensor([a_qkv], device="cuda",
216
+ dtype=torch.float32)
217
+ entry["sc_gu"] = torch.tensor([a_gu], device="cuda",
218
+ dtype=torch.float32)
219
+ entry["inv_o"] = 1.0 / a_o if a_o > 0 else 1.0
220
+ entry["inv_dn"] = 1.0 / a_dn if a_dn > 0 else 1.0
221
+ entry["t_sc_o"] = torch.tensor([a_o], device="cuda",
222
+ dtype=torch.float32)
223
+ entry["t_sc_dn"] = torch.tensor([a_dn], device="cuda",
224
+ dtype=torch.float32)
225
+ bound.table.append(entry)
226
+
227
+
228
+ def _style_stack(bound: BoundAdaRmsFp8Chain, stack, layers) -> None:
229
+ """One stacked projection serves every norm's (scale, shift, gate)."""
230
+ norms = []
231
+ for ly in layers:
232
+ norms.extend((ly.input_layernorm, ly.post_attention_layernorm))
233
+ norms.append(stack.norm)
234
+ w = torch.cat([n.dense.weight.detach().float() for n in norms], dim=0)
235
+ b = torch.cat([n.dense.bias.detach().float() for n in norms], dim=0)
236
+ bound.style_w_t = w.t().contiguous().to("cuda")
237
+ bound.style_b = b.to("cuda").unsqueeze(0)
238
+ bound.eps = float(getattr(norms[0], "eps", 1e-6))
239
+
240
+
241
+ def _mask_facts(mask: torch.Tensor, seq: int) -> tuple[int, int] | None:
242
+ """Read ``[prefix | pad | suffix]`` out of the additive mask, or
243
+ refuse: every row identical, valid keys one prefix run plus the
244
+ whole suffix."""
245
+ if mask.dim() != 4 or mask.shape[0] != 1 or mask.shape[-2] != seq:
246
+ return None
247
+ rows = mask[0, 0] if mask.shape[1] == 1 else mask[0, :1, :, :][0]
248
+ valid = rows == 0
249
+ if not bool((valid == valid[:1]).all()):
250
+ return None
251
+ row = valid[0]
252
+ total = row.shape[0]
253
+ p_raw = total - seq
254
+ if p_raw < 1 or not bool(row[p_raw:].all()):
255
+ return None
256
+ prefix = row[:p_raw]
257
+ p_used = int(prefix.sum())
258
+ if p_used < 1 or not bool(prefix[:p_used].all()):
259
+ return None
260
+ return p_used, p_raw
261
+
262
+
263
+ def _build_rope(bound: BoundAdaRmsFp8Chain, stack,
264
+ position_ids: torch.Tensor) -> bool:
265
+ hd = bound.dims["hd"]
266
+ half = hd // 2
267
+ dummy = torch.zeros(1, position_ids.shape[1], hd, device="cuda",
268
+ dtype=torch.float32)
269
+ cos, sin = stack.rotary_emb(dummy, position_ids.to("cuda"))
270
+ cos, sin = cos[0].float(), sin[0].float()
271
+ if not torch.allclose(cos[:, :half], cos[:, half:], atol=1e-5):
272
+ return False
273
+ rope = torch.empty(position_ids.shape[1], hd, device="cuda",
274
+ dtype=torch.bfloat16)
275
+ rope[:, 0::2] = cos[:, :half].to(torch.bfloat16)
276
+ rope[:, 1::2] = sin[:, :half].to(torch.bfloat16)
277
+ bound.rope = rope
278
+ return True
279
+
280
+
281
+ def _alloc(bound: BoundAdaRmsFp8Chain) -> None:
282
+ S, D, nh, kv, hd, H, L = (bound.dims[k] for k in
283
+ ("seq", "dim", "nh", "kv", "hd",
284
+ "hidden", "layers"))
285
+ T = bound.total_keys
286
+ dev, bf = "cuda", torch.bfloat16
287
+ b = bound.buf
288
+ b["zero"] = torch.zeros(S, D, device=dev, dtype=bf)
289
+ b["ones_w"] = torch.ones(D, device=dev, dtype=bf)
290
+ b["res"] = torch.empty(S, D, device=dev, dtype=bf)
291
+ b["xn8"] = torch.empty(S, D, device=dev, dtype=torch.float8_e4m3fn)
292
+ b["g1"] = torch.empty(S, D, device=dev, dtype=bf)
293
+ b["g2"] = torch.empty(S, D, device=dev, dtype=bf)
294
+ b["dn"] = torch.empty(S, D, device=dev, dtype=bf)
295
+ b["qkv"] = torch.empty(S, (nh + 2 * kv) * hd, device=dev, dtype=bf)
296
+ b["q"] = torch.empty(1, S, nh, hd, device=dev, dtype=bf)
297
+ b["gu"] = torch.empty(S, 2 * H, device=dev, dtype=bf)
298
+ b["hid8"] = torch.empty(S, H, device=dev,
299
+ dtype=torch.float8_e4m3fn)
300
+ b["o8"] = torch.empty(S, nh * hd, device=dev,
301
+ dtype=torch.float8_e4m3fn)
302
+ b["kc"] = [torch.zeros(1, T, kv, hd, device=dev, dtype=bf)
303
+ for _ in range(L)]
304
+ b["vc"] = [torch.zeros(1, T, kv, hd, device=dev, dtype=bf)
305
+ for _ in range(L)]
306
+ b["seqused"] = torch.full((1,), T, device=dev, dtype=torch.int32)
307
+ b["att"] = torch.empty(1, S, nh, hd, device=dev, dtype=bf)
308
+ if BANDS[bound.band]["packages"] != ():
309
+ # static FP4 out-buffers, sized by the quantizer's own
310
+ # allocator: the SF tensor's tile-padding entries are zeroed
311
+ # once here and never written by the producers, so one
312
+ # zero-padded pair per site stays valid across every replay —
313
+ # no per-call allocation, no per-call SF memset in the graph
314
+ quant4 = bound.kernels["kg4"].quantize_fp4_sfa_bf16
315
+ b["xp4"], b["xsf4"] = quant4(b["zero"])
316
+ b["op4"], b["osf4"] = quant4(
317
+ torch.zeros(S, nh * hd, device=dev, dtype=bf))
318
+ # the norm kernel's style contract is contiguous (rows, 3*dim):
319
+ # one static stage, filled by a single broadcast copy per step
320
+ b["st4"] = torch.empty(2 * L, S, 3 * D, device=dev, dtype=bf)
321
+ if BANDS[bound.band]["dn"] == "fp4":
322
+ b["hp4"], b["hsf4"] = quant4(
323
+ torch.zeros(S, bound.dims["hidden"], device=dev,
324
+ dtype=bf))
325
+
326
+
327
+ def _make_attend(bound: BoundAdaRmsFp8Chain, mode: str, kern):
328
+ """One rung of the attention ladder, closed over the buffers."""
329
+ b = bound.buf
330
+ S, nh, hd = (bound.dims[k] for k in ("seq", "nh", "hd"))
331
+ scaling = bound.scaling
332
+ att2 = b["att"].view(S, nh * hd)
333
+ if mode == "fa4_cute":
334
+ def attend(layer_index):
335
+ kern.forward_static(
336
+ b["q"], b["kc"][layer_index], b["vc"][layer_index],
337
+ b["att"], softmax_scale=scaling, causal=False,
338
+ pack_gqa=True, seqused_k=b["seqused"])
339
+ return att2
340
+ return attend
341
+ lse = kern.allocate_outputs(b["q"])[1]
342
+
343
+ def attend(layer_index):
344
+ kern.forward_seqused_static(
345
+ b["q"], b["kc"][layer_index], b["vc"][layer_index],
346
+ b["seqused"], out=b["att"], softmax_lse=lse,
347
+ softmax_scale=scaling)
348
+ return att2
349
+ return attend
350
+
351
+
352
+ def _band_elements(bound: BoundAdaRmsFp8Chain):
353
+ """The band row's two element closures, plus the style stager.
354
+
355
+ Every band expresses the same three moves — stage the step's
356
+ styles, feed a style-conditioned producer into a projection site,
357
+ project the attention output — so the chain loop stays one form
358
+ and a band is a table row plus this closure pair.
359
+
360
+ - ``stage_styles(styles)``: per-step staging; returns the handle
361
+ the producer consumes.
362
+ - ``norm_project(styles, slot, x, prev_gate, e, site, out,
363
+ gate_out)``: gated-residual AdaRMS producer into the ``site``
364
+ GEMM, result in ``out``, the norm's gate in ``gate_out``.
365
+ - ``out_project(att2, e, out)``: quantize the attention output and
366
+ run the output projection into ``out``.
367
+ """
368
+ b = bound.buf
369
+ kg = bound.kernels["kg"]
370
+ kn = bound.kernels["kn"]
371
+ kf = bound.kernels["kf"]
372
+ eps = bound.eps
373
+ S, D, L = (bound.dims[k] for k in ("seq", "dim", "layers"))
374
+ row = BANDS[bound.band]
375
+ if row["packages"] != ():
376
+ norm4 = bound.kernels["kn4"] .gate_res_ada_rms_norm_quant_nvfp4_swizzled_bf16
377
+ gemm4 = bound.kernels["kg4"].nvfp4_gemm_bias_bf16
378
+ quant4 = bound.kernels["kg4"].quantize_fp4_sfa_bf16
379
+ zb = bound.zero_bias
380
+ xp4, xsf4 = b["xp4"], b["xsf4"]
381
+ op4, osf4 = b["op4"], b["osf4"]
382
+ st4 = b["st4"]
383
+ # bind-time layout probe: a producer that accepts a single
384
+ # style row drops both the staging copy and the kernel's
385
+ # full-rows style read; an older producer falls back to the
386
+ # staged form. The smoke and the captured parity gate judge.
387
+ try:
388
+ _t = torch.zeros(2, D, device="cuda", dtype=torch.bfloat16)
389
+ norm4(_t, _t, _t.clone(),
390
+ torch.zeros(1, 3 * D, device="cuda",
391
+ dtype=torch.bfloat16))
392
+ torch.cuda.synchronize()
393
+ rows1 = True
394
+ except Exception: # noqa: BLE001 — a layout fact, not an error
395
+ rows1 = False
396
+
397
+ if rows1:
398
+ def stage_styles(styles):
399
+ return styles
400
+ else:
401
+ def stage_styles(styles):
402
+ # one broadcast copy stages every layer's rows for
403
+ # the step — the per-norm expand+contiguous kernels
404
+ # never enter the graph
405
+ st4.copy_(styles[:2 * L].expand(-1, S, -1))
406
+ return st4
407
+
408
+ def norm_project(styles, slot, x, prev_gate, e, site, out,
409
+ gate_out):
410
+ norm4(x, prev_gate, b["res"], styles[slot], packed=xp4,
411
+ sf_swizzled=xsf4, gate=gate_out)
412
+ wp, wsf = e[site]
413
+ gemm4(xp4, wp, xsf4, wsf, zb[out.shape[1]], out=out)
414
+
415
+ def out_project(att2, e, out):
416
+ quant4(att2, op4, osf4)
417
+ gemm4(op4, e["o"][0], osf4, e["o"][1], zb[D], out=out)
418
+
419
+ if row["dn"] == "fp4":
420
+ geglu4 = bound.kernels["kn4"].gelu_mul_nvfp4_bf16
421
+ hp4, hsf4 = b["hp4"], b["hsf4"]
422
+
423
+ def down_project(e):
424
+ geglu4(b["gu"], packed=hp4, sfa=hsf4)
425
+ gemm4(hp4, e["dn"][0], hsf4, e["dn"][1], zb[D],
426
+ out=b["dn"])
427
+ else:
428
+ kf_ = bound.kernels["kf"]
429
+ kg_ = bound.kernels["kg"]
430
+
431
+ def down_project(e):
432
+ kf_.gate_geglu_merged_quant_fp8_static_bf16(
433
+ b["gu"], e["t_sc_dn"], out=b["hid8"])
434
+ kg_.fp8_linear_bf16(b["hid8"], e["dn"],
435
+ alpha=e["a_dn"], out=b["dn"])
436
+
437
+ return stage_styles, norm_project, out_project, down_project
438
+
439
+ def stage_styles(styles):
440
+ return styles
441
+
442
+ def norm_project(styles, slot, x, prev_gate, e, site, out,
443
+ gate_out):
444
+ kn.gate_residual_ada_norm_fp8_static_bf16(
445
+ b["res"], x, prev_gate, b["ones_w"], styles[slot],
446
+ e["sc_" + site], eps, out=b["xn8"], gate_out=gate_out)
447
+ kg.fp8_linear_bf16(b["xn8"], e[site], alpha=e["a_" + site],
448
+ out=out)
449
+
450
+ def out_project(att2, e, out):
451
+ kf.quantize_fp8_static_bf16(att2, e["t_sc_o"], out=b["o8"])
452
+ kg.fp8_linear_bf16(b["o8"], e["o"], alpha=e["a_o"], out=out)
453
+
454
+ def down_project(e):
455
+ kf.gate_geglu_merged_quant_fp8_static_bf16(
456
+ b["gu"], e["t_sc_dn"], out=b["hid8"])
457
+ kg.fp8_linear_bf16(b["hid8"], e["dn"], alpha=e["a_dn"],
458
+ out=b["dn"])
459
+
460
+ return stage_styles, norm_project, out_project, down_project
461
+
462
+
463
+ def _make_run(bound: BoundAdaRmsFp8Chain):
464
+ kg = bound.kernels["kg"]
465
+ kn = bound.kernels["kn"]
466
+ kr = bound.kernels["kr"]
467
+ kf = bound.kernels["kf"]
468
+ attend = bound.kernels["attend"]
469
+ S, D, nh, kv, hd, H, L = (bound.dims[k] for k in
470
+ ("seq", "dim", "nh", "kv", "hd",
471
+ "hidden", "layers"))
472
+ P, T = bound.p_used, bound.total_keys
473
+ b = bound.buf
474
+ table = bound.table
475
+ eps = bound.eps
476
+ qkv3 = b["qkv"].view(1, S, (nh + 2 * kv) * hd)
477
+ fp8 = torch.float8_e4m3fn
478
+ (stage_styles, norm_project, out_project,
479
+ down_project) = _band_elements(bound)
480
+
481
+ kperm = bound.kperm
482
+
483
+ rf = torch.profiler.record_function
484
+
485
+ def run(x2d, cond, prefix_kv):
486
+ if not bound.prefix_wired:
487
+ with rf("ad:prefix"):
488
+ for l, (pk, pv) in enumerate(prefix_kv):
489
+ # rotated pairs are adjacent; the host cached
490
+ # prefix keys in rotate-half layout — gather them
491
+ # into the shared permutation so q·k stays
492
+ # layout-consistent. A wired prefix skips this:
493
+ # the producer already wrote these rows in chain
494
+ # layout, and kperm∘kperm_inv is the identity.
495
+ torch.index_select(pk, -1, kperm,
496
+ out=b["kc"][l][0, :P, 0])
497
+ b["vc"][l][0, :P, 0].copy_(pv)
498
+ # nearest-neighbour step resolution, fully on-device: the
499
+ # schedule is a bind-time fact, so the live conditioning names
500
+ # its baked table without a host round-trip or Python state
501
+ with rf("ad:style"):
502
+ step = (bound.step_conds
503
+ - cond.float()).abs().sum(-1).argmin()
504
+ styles = bound.style_table.index_select(
505
+ 0, step.view(1))[0]
506
+ fin = bound.fin_table.index_select(0, step.view(1))[0]
507
+ styles = stage_styles(styles)
508
+ res = b["res"]
509
+ res.copy_(x2d)
510
+ delta, gate = b["zero"], b["zero"]
511
+ rf_layers = rf("ad:layers")
512
+ rf_layers.__enter__()
513
+ for l in range(L):
514
+ e = table[l]
515
+ norm_project(styles, 2 * l, delta, gate, e, "qkv",
516
+ b["qkv"], b["g1"])
517
+ kr.qkv_split_rope_kvcache_bf16(
518
+ qkv3, bound.rope, nh, kv, hd, P, q_out=b["q"],
519
+ k_cache=b["kc"][l], v_cache=b["vc"][l], max_seq_len=T)
520
+ att2 = attend(l)
521
+ out_project(att2, e, b["dn"])
522
+ norm_project(styles, 2 * l + 1, b["dn"], b["g1"], e, "gu",
523
+ b["gu"], b["g2"])
524
+ down_project(e)
525
+ delta, gate = b["dn"], b["g2"]
526
+ rf_layers.__exit__(None, None, None)
527
+ with rf("ad:tail"):
528
+ res = res.float() + gate.float() * delta.float()
529
+ normed = res * torch.rsqrt(
530
+ res.square().mean(-1, keepdim=True) + eps)
531
+ out = (normed * (1 + fin[0]) + fin[1]).to(torch.bfloat16)
532
+ return bound.out_ctor(last_hidden_state=out.view(1, S, D),
533
+ past_key_values=None)
534
+
535
+ return run
536
+
537
+
538
+ def bind_adarms_fp4_chain(model, root: str,
539
+ probe: Callable[[], Any]) -> dict:
540
+ return bind_adarms_fp8_chain(model, root, probe, band="fp4")
541
+
542
+
543
+ def bind_adarms_fp8_chain(model, root: str,
544
+ probe: Callable[[], Any],
545
+ band: str = "fp8") -> dict:
546
+ """Bind the chain onto the stack at ``root``; adapter contract out.
547
+
548
+ One probe run does all the observation: the suffix calls (smoke
549
+ references), the mask facts, the prefix K/V, and the activation
550
+ amax at every quantizer site. The routed form must track the host
551
+ on **every** probe call above ``SMOKE_FLOOR`` or the whole bind
552
+ refuses — no partial routing. Returns ``{"refused": reason}`` on
553
+ any refusal, with the host untouched.
554
+ """
555
+ try:
556
+ kg = hub_kernel(GEMM_PACKAGE, ">=1")
557
+ kn = hub_kernel(NORM_PACKAGE, ">=1")
558
+ kr = hub_kernel(ROPE_PACKAGE, ">=1")
559
+ kf = hub_kernel(FUSE_PACKAGE, ">=1")
560
+ kg4 = kn4 = None
561
+ if BANDS[band]["packages"]:
562
+ kg4 = hub_kernel(FP4_GEMM_PACKAGE, ">=1")
563
+ kn4 = hub_kernel(FP4_NORM_PACKAGE, ">=1")
564
+ except KernelUnavailable as exc:
565
+ return {"refused": f"adarms_{band}_chain: {exc}"}
566
+ rungs = _attention_rungs()
567
+ gaps = missing_symbols(band=band)
568
+ if gaps:
569
+ return {"refused": f"adarms_fp8_chain missing: {', '.join(gaps)}"}
570
+
571
+ stack = model.get_submodule(root) if root else model
572
+ layers, nh, kv, hd, dim, hidden = _stack_parts(stack)
573
+ if kv != 1:
574
+ return {"refused": f"adarms_fp8_chain: kv_heads {kv} outside "
575
+ "the single-KV band"}
576
+ if not _gelu_tanh_like(layers[0].mlp.act_fn):
577
+ return {"refused": "adarms_fp8_chain: FFN activation is not "
578
+ "tanh-GELU"}
579
+ scalings = {float(ly.self_attn.scaling) for ly in layers}
580
+ if len(scalings) != 1:
581
+ return {"refused": "adarms_fp8_chain: per-layer attention "
582
+ "scaling differs"}
583
+
584
+ bound = BoundAdaRmsFp8Chain()
585
+ bound.kernels = {"kg": kg, "kn": kn, "kr": kr, "kf": kf,
586
+ "kg4": kg4, "kn4": kn4}
587
+ bound.band = band
588
+ bound.scaling = scalings.pop()
589
+ bound.dims = {"nh": nh, "kv": kv, "hd": hd, "dim": dim,
590
+ "hidden": hidden, "layers": len(layers)}
591
+
592
+ # ---- one probe: calls, mask facts, prefix K/V, amax sites ----
593
+ calls: list[dict] = []
594
+ amax: dict[tuple[int, str], float] = {}
595
+
596
+ def note(site):
597
+ def hook(_m, args):
598
+ x = args[0]
599
+ peak = float(x.detach().abs().amax())
600
+ amax[site] = max(amax.get(site, 0.0), peak)
601
+ return hook
602
+
603
+ hooks = []
604
+ for i, ly in enumerate(layers):
605
+ hooks.append(ly.self_attn.q_proj.register_forward_pre_hook(
606
+ note((i, "qkv"))))
607
+ hooks.append(ly.self_attn.o_proj.register_forward_pre_hook(
608
+ note((i, "o"))))
609
+ hooks.append(ly.mlp.gate_proj.register_forward_pre_hook(
610
+ note((i, "gu"))))
611
+ hooks.append(ly.mlp.down_proj.register_forward_pre_hook(
612
+ note((i, "dn"))))
613
+
614
+ # the host calls the stack's ``forward`` directly, so capture is an
615
+ # instance-attribute wrap, not a forward hook
616
+ saved_probe = stack.__dict__.get("forward")
617
+ host_forward = stack.forward
618
+
619
+ def capturing(_self, *args, **kwargs):
620
+ out = host_forward(*args, **kwargs)
621
+ embs = kwargs.get("inputs_embeds")
622
+ cond = kwargs.get("adarms_cond")
623
+ pkv = kwargs.get("past_key_values")
624
+ hidden = getattr(out, "last_hidden_state", None)
625
+ if (embs is not None and cond is not None and pkv is not None
626
+ and hidden is not None
627
+ and embs.dim() == 3 and embs.shape[0] == 1):
628
+ entry = {
629
+ "x": embs.detach().clone(),
630
+ "cond": cond.detach().clone(),
631
+ "mask": kwargs.get("attention_mask"),
632
+ "pos": kwargs.get("position_ids"),
633
+ "out": hidden.detach().clone(),
634
+ "out_type": type(out),
635
+ }
636
+ entry["mask"] = (entry["mask"].detach().clone()
637
+ if entry["mask"] is not None else None)
638
+ entry["pos"] = (entry["pos"].detach().clone()
639
+ if entry["pos"] is not None else None)
640
+ if not any("kv" in c for c in calls):
641
+ entry["kv"] = [
642
+ (_cache_kv(pkv, i)[0].detach().clone(),
643
+ _cache_kv(pkv, i)[1].detach().clone())
644
+ for i in range(len(layers))]
645
+ calls.append(entry)
646
+ return out
647
+
648
+ stack.forward = types.MethodType(capturing, stack)
649
+ try:
650
+ with torch.inference_mode():
651
+ probe()
652
+ finally:
653
+ for hook in hooks:
654
+ hook.remove()
655
+ if saved_probe is not None:
656
+ stack.forward = saved_probe
657
+ else:
658
+ stack.__dict__.pop("forward", None)
659
+
660
+ if not calls:
661
+ return {"refused": "adarms_fp8_chain: probe never made a "
662
+ "suffix call"}
663
+ first = calls[0]
664
+ if first["mask"] is None or first["pos"] is None:
665
+ return {"refused": "adarms_fp8_chain: probe call carried no "
666
+ "mask or positions"}
667
+ S = first["x"].shape[1]
668
+ facts = _mask_facts(first["mask"], S)
669
+ if facts is None:
670
+ return {"refused": "adarms_fp8_chain: mask outside the "
671
+ "[prefix|pad|suffix] band"}
672
+ p_used, p_raw = facts
673
+ pos = first["pos"][0]
674
+ want = torch.arange(p_used, p_used + S, device=pos.device)
675
+ if not torch.equal(pos.to(want.dtype), want):
676
+ return {"refused": "adarms_fp8_chain: positions are not the "
677
+ "contiguous suffix run"}
678
+ for c in calls[1:]:
679
+ if (c["x"].shape != first["x"].shape
680
+ or (c["mask"] is not None
681
+ and c["mask"].shape != first["mask"].shape)):
682
+ return {"refused": "adarms_fp8_chain: probe calls disagree "
683
+ "on shape"}
684
+ if any((i, s) not in amax or amax[(i, s)] <= 0.0
685
+ for i in range(len(layers))
686
+ for s in ("qkv", "o", "gu", "dn")):
687
+ return {"refused": "adarms_fp8_chain: calibration saw a dead "
688
+ "quantizer site"}
689
+
690
+ bound.dims["seq"] = S
691
+ bound.p_used = p_used
692
+ bound.total_keys = p_used + S
693
+ bound.out_ctor = first["out_type"]
694
+
695
+ _style_stack(bound, stack, layers)
696
+ if not _build_rope(bound, stack, first["pos"]):
697
+ return {"refused": "adarms_fp8_chain: rotary table is not "
698
+ "half-duplicated"}
699
+ _quantize(bound, layers, amax)
700
+ _alloc(bound)
701
+
702
+ # ---- the attention ladder: first rung that actually executes ----
703
+ attend, attn_mode = None, None
704
+ rung_trail = []
705
+ for mode, kern in rungs:
706
+ try:
707
+ candidate = _make_attend(bound, mode, kern)
708
+ candidate(0)
709
+ torch.cuda.synchronize()
710
+ except Exception as exc: # noqa: BLE001 — a dead rung, next one
711
+ rung_trail.append(f"{mode}: {type(exc).__name__}")
712
+ continue
713
+ attend, attn_mode = candidate, mode
714
+ break
715
+ if attend is None:
716
+ return {"refused": "adarms_fp8_chain: no attention rung "
717
+ f"executes here ({'; '.join(rung_trail)})"}
718
+ bound.kernels["attend"] = attend
719
+
720
+ half = hd // 2
721
+ kperm = torch.empty(hd, dtype=torch.long, device="cuda")
722
+ kperm[0::2] = torch.arange(half, device="cuda")
723
+ kperm[1::2] = torch.arange(half, hd, device="cuda")
724
+ bound.kperm = kperm
725
+
726
+ # bake one style table per distinct probed step (the step-table
727
+ # form): the run resolves the live conditioning by nearest match
728
+ n_norms = 2 * len(layers) + 1
729
+ step_conds, style_tables, fin_tables = [], [], []
730
+ with torch.no_grad():
731
+ for c in calls:
732
+ cnd = c["cond"].float().cuda()
733
+ if any(torch.allclose(cnd, prev) for prev in step_conds):
734
+ continue
735
+ st = torch.addmm(bound.style_b, cnd, bound.style_w_t)
736
+ step_conds.append(cnd)
737
+ # rows=1 broadcast: the norm kernels accept a single
738
+ # style row, so the table stays one row per norm
739
+ style_tables.append(
740
+ st.view(n_norms, 1, 3 * dim)
741
+ .to(torch.bfloat16).contiguous())
742
+ fin_tables.append(
743
+ st[0, (n_norms - 1) * 3 * dim:].view(3, dim).clone())
744
+ bound.step_conds = torch.cat(step_conds, dim=0)
745
+ bound.style_table = torch.stack(style_tables)
746
+ bound.fin_table = torch.stack(fin_tables)
747
+ prefix_kv = [(k[0, 0, :p_used].contiguous().clone(),
748
+ v[0, 0, :p_used].contiguous().clone())
749
+ for k, v in first["kv"]]
750
+ run = _make_run(bound)
751
+ guard = bound._frt_arm(dtypes=(torch.bfloat16,),
752
+ device=torch.device("cuda"))
753
+ guard.notes["n_layers"] = len(layers)
754
+ guard.notes["suffix_calls"] = len(calls)
755
+ guard.notes["p_used"] = p_used
756
+ guard.notes["attention"] = attn_mode
757
+ if rung_trail:
758
+ guard.notes["attention_fell_through"] = rung_trail
759
+
760
+ # ---- smoke: the routed stack against every captured call ----
761
+ worst = None
762
+ with torch.inference_mode():
763
+ for c in calls:
764
+ got = run(c["x"][0].to(torch.bfloat16), c["cond"], prefix_kv)
765
+ cos = torch.nn.functional.cosine_similarity(
766
+ got.last_hidden_state.float().flatten(),
767
+ c["out"].float().flatten(), dim=0)
768
+ worst = float(cos) if worst is None else min(worst,
769
+ float(cos))
770
+ if worst is None or worst < SMOKE_FLOOR:
771
+ return {"refused": f"adarms_fp8_chain smoke cos {worst} < "
772
+ f"{SMOKE_FLOOR} across {len(calls)} probe "
773
+ "call(s)"}
774
+ guard.notes["smoke_cos"] = round(worst, 6)
775
+
776
+ # ---- route ----
777
+ saved = stack.__dict__.get("forward")
778
+ n_layers = len(layers)
779
+ x_shape = tuple(first["x"].shape)
780
+ mask_shape = tuple(first["mask"].shape)
781
+
782
+ def routed(_self, *args, **kwargs):
783
+ compiling = torch.compiler.is_compiling()
784
+ capturing_now = (False if compiling
785
+ else torch.cuda.is_current_stream_capturing())
786
+ eager = not compiling and not capturing_now
787
+ if eager:
788
+ guard.calls += 1
789
+ embs = kwargs.get("inputs_embeds")
790
+ cond = kwargs.get("adarms_cond")
791
+ pkv = kwargs.get("past_key_values")
792
+ mask = kwargs.get("attention_mask")
793
+ ok = (not args and embs is not None and cond is not None
794
+ and pkv is not None
795
+ and tuple(embs.shape) == x_shape
796
+ and (mask is None or tuple(mask.shape) == mask_shape))
797
+ if not ok:
798
+ if not eager:
799
+ raise RuntimeError(
800
+ "adarms_fp8_chain: out-of-contract call during "
801
+ "capture/compile — fix the eager path first")
802
+ guard.fallbacks += 1
803
+ guard.last_reason = "call outside the routed contract"
804
+ return host_forward(*args, **kwargs)
805
+ prefix = []
806
+ for i in range(n_layers):
807
+ k, v = _cache_kv(pkv, i)
808
+ prefix.append((k[0, 0, :bound.p_used],
809
+ v[0, 0, :bound.p_used]))
810
+ return run(embs[0].to(torch.bfloat16), cond, prefix)
811
+
812
+ def enable() -> None:
813
+ stack.forward = types.MethodType(routed, stack)
814
+
815
+ def disable() -> None:
816
+ if saved is not None:
817
+ stack.forward = saved
818
+ elif "forward" in stack.__dict__:
819
+ del stack.forward
820
+
821
+ def revert() -> None:
822
+ disable()
823
+ bound.table.clear()
824
+ bound.buf.clear()
825
+
826
+ enable()
827
+ return {
828
+ "observed": {f"{root}::adarms_fp8_chain": bound},
829
+ "revert": [revert],
830
+ "toggle": (enable, disable),
831
+ "smoke_cos": worst,
832
+ }