Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
801f95c
Add structures catalog skeleton with decoder_ffn specification
LiangSu8899 Jul 16, 2026
6d8e652
Add parity qualification gate for structures
LiangSu8899 Jul 16, 2026
9b2639e
Add fp8_static implementation of decoder_ffn over Hub kernels
LiangSu8899 Jul 16, 2026
6e6da9b
Add pi05 binding for decoder_ffn
LiangSu8899 Jul 16, 2026
e29e1e5
Support AdaLN gated residual in decoder_ffn
LiangSu8899 Jul 16, 2026
8e31cf9
Add transactional attach and the MLP-seam bind path
LiangSu8899 Jul 16, 2026
ad40b23
Fix bind-time autograd retention in fp8_static
LiangSu8899 Jul 16, 2026
fcaa1b5
Add pi05_prefix binding for decoder_ffn
LiangSu8899 Jul 16, 2026
6b9c849
Add qwen25_15b binding for decoder_ffn
LiangSu8899 Jul 16, 2026
29fa8b0
Compute p99 via kthvalue in parity metrics
LiangSu8899 Jul 16, 2026
182a0a2
Add vision_ffn structure with fp8_static implementation and pi05 binding
LiangSu8899 Jul 16, 2026
157de89
Add structures provider: export host-captured graphs as model runtimes
LiangSu8899 Jul 16, 2026
cad80de
Make MLP-seam modules host-naming agnostic
LiangSu8899 Jul 17, 2026
f90916e
Add bindings for Qwen3-8B, Qwen3-VL-8B, and SmolVLA hosts
LiangSu8899 Jul 17, 2026
3e419b8
Add GR00T N1.6 bindings: Eagle LLM, SigLIP vision, and DiT feed-forward
LiangSu8899 Jul 17, 2026
d49c665
Add weight-only INT8 implementation of decoder_ffn for the decode band
LiangSu8899 Jul 17, 2026
ade6cd8
Route FFN implementations through the kernels' fused BF16 entries
LiangSu8899 Jul 18, 2026
02f8af1
catalog: add stage_pipeline structure kind and vla_tick_pipeline spec
LiangSu8899 Jul 18, 2026
3b730eb
bindings: smolvla_tick — second host on vla_tick_pipeline
LiangSu8899 Jul 18, 2026
8230bff
structures: one-call front door — attach(model, forward)
LiangSu8899 Jul 18, 2026
1eff560
structures: explicit door — get(name).bind(module, calibration)
LiangSu8899 Jul 18, 2026
3ac09ba
structures: capture door — graph a hot stage with swap windows
LiangSu8899 Jul 18, 2026
34688f0
catalog: linear_proj — finest generally-useful region boundary
LiangSu8899 Jul 19, 2026
8fca4bb
impls: linear_proj fp8_static + qualified attention-proj discovery
LiangSu8899 Jul 19, 2026
d18d257
structures: CapturedStage.export — one call to the runtime contract
LiangSu8899 Jul 19, 2026
ec838c6
impls: resolve the hub op at bind time, not inside forward
LiangSu8899 Jul 19, 2026
1deae07
structures: recipe door — declared levers, same-process audit, certif…
LiangSu8899 Jul 19, 2026
33b792b
impls: step-table memoization for step-constant conditioning producers
LiangSu8899 Jul 19, 2026
5846ef3
impls: step-table sibling locator sharing
LiangSu8899 Jul 19, 2026
29b32b3
structures: parity warn band — loose floor while calibration matures
LiangSu8899 Jul 19, 2026
3290deb
structures: lever build-time refusal is an outcome, not an abort
LiangSu8899 Jul 19, 2026
d7ee3b7
structures: qkv_pack — pack sibling projections into one GEMM
LiangSu8899 Jul 20, 2026
81497b4
structures: adaln_producer — step-resolved conditioning norm
LiangSu8899 Jul 20, 2026
565d506
structures: cadence_static — hold slower-cadence work outside the hot…
LiangSu8899 Jul 20, 2026
618d2a4
structures: attention_core — packed-KV attention on the FA2 kernel
LiangSu8899 Jul 20, 2026
c7dfa34
structures: expose the winning arm's captured stage for the absorptio…
LiangSu8899 Jul 20, 2026
34684ed
structures: export SUPPORTED_HEAD_DIMS for qualification checks
LiangSu8899 Jul 20, 2026
774c830
structures: auto-discover and calibrate qkv_pack/adaln_producer in on…
LiangSu8899 Jul 20, 2026
ca22dca
structures: host-family attention adapter with self-verifying fallback
LiangSu8899 Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions flash_rt/structures/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""FlashRT structures — verified, composable model sub-blocks.

A structure is a versioned specification of one model region: boundary
tensors, framework-neutral weight slots, a plain reference implementation
used as ground truth, and qualification gates. This package hosts the
structure catalog and its registry. Implementations, host adapters, and
the qualification harness build on top of these specifications.
"""

from flash_rt.structures.registry import StructureSpec, list_structures, load


def get(name):
"""Explicit door: pull one structure and bind it yourself.

Mirrors ``kernels.get_kernel``: ``get("decoder_ffn").bind(module,
calibration=[...])`` returns a gated drop-in replacement you plug in
where you choose. See :mod:`flash_rt.structures.handle`.
"""
from flash_rt.structures.handle import get as _get

return _get(name)


def capture(fn, **kwargs):
"""Capture door: graph a hot stage with declared swap windows.

See :func:`flash_rt.structures.stages.capture`.
"""
from flash_rt.structures.stages import capture as _capture

return _capture(fn, **kwargs)


def auto_swaps(model, forward, **kwargs):
"""Distribution layer: discover, calibrate, bind — one pass, no
per-seam scaffolding. Returns an :class:`AutoPlan` of swaps.

See :func:`flash_rt.structures.autobuild.auto_swaps`.
"""
from flash_rt.structures.autobuild import auto_swaps as _auto

return _auto(model, forward, **kwargs)


def run_recipe(recipe, model, ctx=None, **kwargs):
"""Recipe door: assemble declared levers, audit same-process on the
graph, certify or refuse — one call, one receipt.

See :mod:`flash_rt.structures.recipe` for ``Recipe``/``Lever``/
``Gates`` and the switch lifecycle.
"""
from flash_rt.structures.recipe import run_recipe as _run

return _run(recipe, model, ctx, **kwargs)


def attach(model, forward, **kwargs):
"""One-call front door: discover, calibrate, gate, activate.

See :func:`flash_rt.structures.frontdoor.attach`. Imported lazily so
that spec-only consumers do not pay for torch-side machinery.
"""
from flash_rt.structures.frontdoor import attach as _attach

return _attach(model, forward, **kwargs)


__all__ = ["StructureSpec", "attach", "capture", "get", "list_structures",
"load", "run_recipe"]
13 changes: 13 additions & 0 deletions flash_rt/structures/adapters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Host-family adapters — where a structure's seam is host-specific.

Importing this package registers the built-in adapters with autobuild.
Attention seams (attention_core) live here because where the attention
math runs differs by host family; a static module pattern cannot find
them, so each family gets a small adapter.
"""
from ..autobuild import register_attention_adapter
from .gemma_attention import GemmaAttentionAdapter

register_attention_adapter(GemmaAttentionAdapter())

__all__ = ["GemmaAttentionAdapter"]
113 changes: 113 additions & 0 deletions flash_rt/structures/adapters/gemma_attention.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""Attention adapter for Gemma-family denoise hosts (pi05 / pi_gemma).

Where the attention math runs is host-specific. In this family the
transformer's own forward calls ``modeling_gemma.eager_attention_forward``
directly, bypassing the config/interface dispatch entirely, so the seam
is that function, not a module. This adapter locates it by capturing one
denoise pass, binds an :mod:`..impls.attention_core` per layer from the
captured shapes and masks, and installs a function-level patch that
routes the fixed denoise shape to the packed-KV kernel while leaving
prefill and any other shape on the host path.

Registering this adapter lets ``autobuild`` pick up the attention_core
structure for this host family with no per-host scaffolding at the call
site — the host still just calls ``auto_swaps``.
"""

from __future__ import annotations

from ..impls.attention_core import bind_attention_core


class GemmaAttentionAdapter:
"""Recognise a Gemma-family denoise host and wire its fa2 seam."""

__name__ = "gemma_attention"

def __call__(self, model, forward):
try:
import transformers.models.gemma.modeling_gemma as mg
except ImportError:
return None
orig = mg.eager_attention_forward

recs = {"q": None, "masks": [], "keys": [], "values": []}

def record(module, query, key, value, attention_mask, **kw):
if query.shape[2] < 128: # denoise (short) vs prefill
recs["q"] = query.detach()
recs["masks"].append(
attention_mask.detach()
if attention_mask is not None else None)
recs["keys"].append(key.detach().clone())
recs["values"].append(value.detach().clone())
return orig(module, query, key, value, attention_mask, **kw)

mg.eager_attention_forward = record
try:
with __import__("torch").no_grad():
forward()
finally:
mg.eager_attention_forward = orig
if recs["q"] is None:
return None # host never called this seam — not our family

n_layers = _infer_layers(model)
if n_layers == 0 or len(recs["keys"]) % n_layers != 0:
return None
steps = len(recs["keys"]) // n_layers
captures = [{
"q": recs["q"],
"keys": [recs["keys"][i + s * n_layers] for s in range(steps)],
"values": [recs["values"][i + s * n_layers]
for s in range(steps)],
"mask": recs["masks"][i],
} for i in range(n_layers)]

bound = bind_attention_core(captures)
if bound is None:
return None # head_dim unsupported → host keeps its path
cores, prefix_update = bound
seq_q = recs["q"].shape[2]
expert = _expert_layers(model)
for i, layer in enumerate(expert):
layer.self_attn._fa2_core = cores[i]

fired = {"n": 0}

def fa2_fn(module, query, key, value, attention_mask, **kw):
if query.shape[2] != seq_q or not hasattr(module, "_fa2_core"):
return orig(module, query, key, value, attention_mask, **kw)
fired["n"] += 1
return module._fa2_core(query, key, value,
scale=kw.get("scaling")), None

mg.eager_attention_forward = fa2_fn
# self-verify the patch actually takes over the seam on the same
# forward that will be captured; if it never fires (the host's
# captured entry uses a different attention shape than the one
# we calibrated on) leave the host untouched rather than install
# a patch that only adds a Python check and blocks fusion
with __import__("torch").no_grad():
forward()
if fired["n"] == 0:
mg.eager_attention_forward = orig
for layer in expert:
if hasattr(layer.self_attn, "_fa2_core"):
del layer.self_attn._fa2_core
return None
# the swap map is empty (the seam is a function, not a module);
# the patch and the per-layer core buffers are the swap
return {}, None


def _infer_layers(model) -> int:
layers = _expert_layers(model)
return len(layers) if layers is not None else 0


def _expert_layers(model):
try:
return model.paligemma_with_expert.gemma_expert.model.layers
except AttributeError:
return None
Loading