Skip to main content

flashdreams-integrations

Navigate the FlashDreams package layout and integration architecture: core vs infra vs recipes vs workspace integrations, Transformer/Encoder/StreamingDecoder/Pipeline config contracts, AR caches, CP, CFG, KV cache, CUDA graph wrapping, runner registration, and test placement. Use when adding or editing built-in recipes under flashdreams/flashdreams/recipes/, plugin packages under integrations/, model configs, pipeline wiring, or when the user asks where code belongs. The template recipe is the reference design.

Source facts

Repository
NVIDIA/flashdreams
Last source activity
September 3, 2026 at 05:46
Detected SKILL.md language
English
Stars
516
Forks
64

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
flashdreams-integrations
description
Navigate the FlashDreams package layout and integration architecture: core vs infra vs recipes vs workspace integrations, Transformer/Encoder/StreamingDecoder/Pipeline config contracts, AR caches, CP, CFG, KV cache, CUDA graph wrapping, runner registration, and test placement. Use when adding or editing built-in recipes under flashdreams/flashdreams/recipes/, plugin packages under integrations/, model configs, pipeline wiring, or when the user asks where code belongs. The template recipe is the reference design.
# flashdreams integration architecture A map of how `flashdreams/` is organized and how a single rollout flows through the framework. Read once before adding a built-in recipe under `flashdreams/flashdreams/recipes/`, adding a workspace integration under `integrations/`, or restructuring an existing one. Keep docstrings consistent with the `python-docstring-style` skill. > For the **step-by-step procedure** of doing an integration end-to-end (scope → scaffold → recipe → checkpoint remap → conditioners → runner → verify → perf), see the **`integrate-a-model`** skill. This skill is the *map*; that one is the *route*. > **The fastest way to learn this codebase is to clone the structure of `flashdreams/flashdreams/recipes/template/`.** It is the reference integration — every contract this skill describes is wired up there in its minimal form. Skim it side-by-side with this document. ## TL;DR - Three layers, strict dependency direction: `core` -> `infra` -> recipes/integrations. `infra` and `core` never import from `integrations`. Recipes and integrations may reuse sibling recipe code when the dependency stays explicit and model-owned. - An integration = a `Pipeline` that owns a `DiffusionModel` + optional `Encoder` / `StreamingDecoder`. The `DiffusionModel` owns a `Transformer` + a `Scheduler`. You author the integration-specific subclasses of these and ship one **module-level literal** `StreamInferencePipelineConfig` per variant in `config.py`. No `build_*(...)` factories — variants derive from a base via `derive_config(BASE, ...)`. - Every config sets `name: str` (a stable slug). The per-integration `<NAME>_CONFIGS: dict[str, StreamInferencePipelineConfig]` dict is keyed by `name`. There is no central pipeline-config registry — pipelines are reachable via direct per-integration imports. Integrations that ship a `Runner` (see §5) self-register their slugs into `flashdreams.configs.registry._SUPPORTED_RUNNERS` (read it via `supported_runners()`), which is the only registry the `flashdreams-run` CLI dispatches over. - Per-rollout state lives in nested `*Cache` dataclasses that mirror the same containment tree. - Lifecycle: `pipeline.initialize_cache(...)` once, then a loop of `pipeline.generate(ar_idx, ...)` + `pipeline.finalize(ar_idx, ...)`. - Two shape regimes, separated by `transformer.patchify_and_maybe_split_cp`: pre-patchify `[B, C, T, H, W]` outside, post-patchify `[B, L/cp, C]` inside. ## 1. Codebase layout ``` flashdreams/ ├── core/ reusable numerical primitives (no integration-specific code, no infra deps) ├── infra/ framework contracts + orchestration (ABCs, base configs, pipeline glue) └── integrations/ concrete model bindings that satisfy the infra contracts ``` | Layer | Owns | Imports from | |----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| | `core/` | `attention/` (`NativeAttention`, `RingAttention`, `BlockKVCache`, `RotaryPositionEmbedding3D`, `apply_rope_freqs`), `checkpoint/load.py`, `distributed/` (`split_inputs_cp`, `cat_outputs_cp`, `*_object_list`), `io/` | nothing in flashdreams | | `infra/` | `config` (`InstantiateConfig`, `derive_config`), `pipeline` (`StreamInferencePipeline*`), `diffusion.{model, scheduler, transformer}` (ABCs + base impls), `encoder` (`Encoder` + `StreamingEncoder` + `StreamingVideoEncoder` + `NullEncoder`), `decoder` (`StreamingDecoder` + `StreamingVideoDecoder`), `compile`, `cuda_graph`, `profiler` | `core` | | `integrations/<name>/` | concrete model: `transformer/`, optional `encoder.py` / `decoder.py` / `pipeline.py`, `config.py` builders | `core`, `infra` | ### Where does this code go? | Question | Layer | |---------------------------------------------------------|------------------------------------| | New attention kernel or shared CUDA utility | `core/` | | Reusable text/CLIP encoder any integration could use | `infra/encoder/<kind>/` | | New ABC or generic orchestrator | `infra/` | | Model-specific DiT, control encoder, or VAE | `integrations/<name>/` | | CLI runner config + ``run()`` body | `integrations/<name>/runner.py` | If you're tempted to add an integration-specific branch in `infra/` or `core/` — expose a config slot or override hook instead. ## 2. What a pipeline contains The whole framework is built around three nested objects: pipeline, diffusion model, transformer. Each layer (a) holds the next layer down and (b) holds a per-rollout cache that mirrors the same shape. ```mermaid flowchart TB classDef infra fill:#d6f5d6,stroke:#2e7d32,color:#1b5e20 classDef integration fill:#fddede,stroke:#c62828,color:#b71c1c subgraph PIPE["StreamInferencePipeline (infra)"] ENC["encoder<br/>(per-AR-step, optional)"]:::integration DM["DiffusionModel (infra)"]:::infra DEC["decoder<br/>(optional)"]:::integration end subgraph DM_INNER[" "] TF["YourTransformer (integration)<br/>+ context_encoder slot<br/>+ rope_adapter (built per rollout)"]:::integration SCH["Scheduler (infra)<br/>FlowMatch / UniPC"]:::infra end subgraph TF_INNER[" "] NET["YourDiT network (integration)<br/>blocks + KV caches"]:::integration end PIPE --> DM DM --> TF DM --> SCH TF --> NET ``` **Containment, top-down:** - `StreamInferencePipeline` (use as-is in most cases) - `encoder: StreamingEncoder | None` (optional; per-AR-step control like HDMap, camera, first-frame VAE) - `diffusion_model: DiffusionModel` - `transformer: YourTransformer` ← you write this - `network: YourDiT` ← you write this - `context_encoder: Encoder` (one-shot encoder slot — text / CLIP-image / `NullEncoder`) - `rope_adapter: RotaryPositionEmbedding3D` (built per rollout, lives on the cache) - `scheduler: FlowMatchScheduler | UniPCScheduler` (pick from `infra.diffusion.scheduler`) - `decoder: StreamingDecoder | None` (optional; latent → pixels). Use `StreamingVideoDecoder` when the decoder is a pixel-video VAE. **The per-rollout cache mirrors that tree** (`StreamInferencePipelineCache` → `transformer_cache` → `network_cache`). Each level forwards `before_update` / `after_update` to the level below. ### One-shot context vs per-AR-step control input There are **two encoder slots**, and they take different base classes. Confusing them is the most common pitfall. | Slot | Runs | Base class | Input | Disable | |-----------------------------------------------|-------------------------------------|-----------------------------|------------------------------------|---------------------| | `transformer.context_encoder` (one-shot) | once, in `initialize_autoregressive_cache` | `Encoder` (stateless) | text prompts, reference image | `NullEncoderConfig()` | | `pipeline.encoder` (per-AR-step) | every AR step, in `pipeline.generate` | `StreamingEncoder` (stateful, has cache) | per-step control (HDMap, camera, hand-crafted control latent) | `encoder=None` | Text encoders (subclass `Encoder`) go on `context_encoder`. Per-AR-step controls (subclass `StreamingEncoder`) go on `pipeline.encoder`. Putting a text encoder on the per-AR-step slot reruns it every step; putting a streaming encoder on the one-shot slot drops its cache. The decoder slot (`pipeline.decoder`) takes a `StreamingDecoder` (stateful, `forward(input, ar_idx, cache)`). Use `StreamingVideoDecoder` for pixel-video VAEs (WAN VAE, TAEHV) — it adds the spatial / temporal compression contracts the pipeline needs to size pixel I/O. Stateless decoders just return an empty `StreamingDecoderCache` from `initialize_autoregressive_cache` and ignore `autoregressive_index` / `cache` in `forward` (see `template/decoder.py`). **Where the per-AR-step control tensor flows.** This is the path a new control input (HDMap, camera trajectory, ...) takes through the framework. Defining a new control = author one `StreamingEncoder` subclass under `integrations/<name>/encoder.py` and consume the `control` arg inside your network's forward. ``` user passes raw control as `pipeline.generate(ar_idx, cache, input=hdmap)` │ [B, C_ctrl, T, H, W] ▼ pipeline.encoder.forward(input, ar_idx, cache.encoder_cache) ← integrations/<name>/encoder.py │ [B, C_latent, T, H, W] (still pre-patchify; same T/H/W as the noisy latent) ▼ diffusion_model.generate(ar_idx, transformer_cache, input=encoded) │ ├── transformer.patchify_and_maybe_split_cp(encoded) │ [B, L/cp, C] │ └── scheduler loop: transformer.predict_flow(noisy, t, cache, input=patchified_control) └── network.forward(noisy, ..., control=patchified_control) └── x = input_proj(noisy) + input_proj(control) # additive bias ``` Two corollaries: - **The encoder's output shape must match the noisy latent's pre-patchify shape** so the same `patchify_and_maybe_split_cp` call works on both, and so the network can fuse them as an additive bias on the per-token channel dim. - **`encoder=None` round-trips `input=None` end-to-end.** Your network's `forward` should treat `control=None` as "skip the control bias" — `flashdreams/flashdreams/recipes/template/transformer/network.py` is the reference. This lets the same integration support both controlled and uncontrolled rollouts without a separate config. ## 3. Anatomy of an integration A minimum viable built-in recipe (what `flashdreams/flashdreams/recipes/template/` ships) is **3 files and 4 classes**: ``` flashdreams/flashdreams/recipes/<name>/ ├── transformer/ │ ├── __init__.py YourTransformerConfig + YourTransformerCache + YourTransformer │ └── network.py YourDiTConfig + YourDiTCache + YourDiT └── config.py module-level literal StreamInferencePipelineConfig per variant <NAME>_CONFIGS: dict[str, StreamInferencePipelineConfig] ``` Add files only when you actually need them: | File | When to add | |---------------------|---------------------------------------------------------------------| | `encoder.py` | integration needs a per-AR-step control input | | `decoder.py` | integration owns the latent → pixel stage | | `pipeline.py` | rare — only when `pipeline.initialize_cache(...)` needs a custom signature (e.g. derive per-rollout `(height, width)` from an input image, accept text strings instead of pre-encoded embeddings) | | `transformer/impl/` | network is large enough to split (`modules.py`, `network.py`, ...) | | `config/` | many shipped variants — split `config.py` into a package |
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub