Skip to content

feat(step3): Step-3.5/3.7-Flash family scaffold + config decoders#16

Merged
TheTom merged 2 commits into
devfrom
tom/wip/step3
Jun 23, 2026
Merged

feat(step3): Step-3.5/3.7-Flash family scaffold + config decoders#16
TheTom merged 2 commits into
devfrom
tom/wip/step3

Conversation

@TheTom

@TheTom TheTom commented May 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Claim the Step-3 family namespace in FFAI and wire the loader so a Step-3.5-Flash / Step-3.7-Flash checkpoint is recognized end-to-end. The matching GPU kernels are merged in metaltile (#242). Concrete forward + per-layer code lands in follow-ups — every load path validates the config, then throws Step3Error.notYetImplemented. The scaffold gives a stable type surface to land the forward paths against without churning dispatch.

What's in the box

File Role
Sources/FFAI/Models/Step3.swift Family entry — enum Step3 (modelTypes / architectures / VL architectures / variant dispatch), Step3Variant protocol, Step3Error
Sources/FFAI/Models/Text/Step3Text.swift Step3TextConfig decoder (per-layer overrides for the hybrid stack), Step3Hybrid variant, placeholder Step3Model
Sources/FFAI/Models/Vision/Step3Vision.swift Step3VLVisionConfig decoder (Perception-Encoder ViT + downsamplers + projector), enum Step3VL orchestrator
Sources/FFAI/Loader/Model.swift New dispatch arm — VL architectures hand off to Step3VL.load, matching the Gemma4VL / Qwen3VL pattern

File layout follows the per-family convention (Models/<Family>.swift + Models/Text/<Family>Text.swift + Models/Vision/<Family>Vision.swift), as in Gemma 4 / Qwen 3.

Architecture surface decoded by this scaffold

Text backbone — 45-layer hybrid: [full, swa, swa, swa] pattern (12 full-attention + 33 sliding-window-512); asymmetric GQA per layer-type (full = 64 q-heads / SWA = 96, both 8 KV, head_dim 128); partial RoPE on full-attn only (factor 0.5) with per-layer-type RoPE base + YARN scoped to the full-attn type; MoE on layers 3-44 (288 experts, top-8, +1 shared) with a sigmoid + router-bias gate (DeepSeek-V3 style); per-layer clamped SwiGLU; head-wise attention output gate.

Vision tower — Perception-Encoder: 47 layers, hidden 1536, head_dim 96, patch 14, 2D RoPE + abs pos-embed, quick-GELU, LayerScale; post-encoder 2× stride-2 conv shrink → 169 patch tokens; vit_large_projector maps hidden*4 → text.hidden.

Tests

Step3RecognitionTests (CI-runnable, no checkpoint): family recognition by model_type / architecture, the hybrid full/sliding config-decode, and the default-generation-parameters convention.

Next steps (separate PRs)

  1. Step3Hybrid forward — layer stack, hybrid full/SWA KV cache, sigmoid+bias MoE router, clamped-SwiGLU (kernels merged in metaltile #242).
  2. Head-wise attention gate wired into the forward path (ffai_attn_head_gate, metaltile #242).
  3. Perception-Encoder forward + projector over the existing conv2d / sdpa_bidirectional / rope_2d surface.
  4. Text-only Step-3 dispatch arm once Step3Model conforms to LanguageModel (only the VL arm is wired today).

Merge sequencing

Targets dev (rebased 2026-06-10). dev's tip is currently red from the metaltile binding drift (ffai_sdpa_decode_d{64,256}_* grew has_sink/sink_logit); this branch carries the interim 6-site Ops.swift fix so its CI builds green against current bindings. #17 carries the same fix — whichever merges first makes the other's copy a no-op on rebase.

@TheTom TheTom changed the title WIP: Step-3 family scaffold (Step-3.5-Flash / Step-3.7-Flash) wip(step3): family scaffold (Step-3.5-Flash / Step-3.7-Flash) May 30, 2026
@TheTom TheTom changed the title wip(step3): family scaffold (Step-3.5-Flash / Step-3.7-Flash) feat(step3): family scaffold (WIP — Step-3.5-Flash / Step-3.7-Flash) May 30, 2026
@github-actions github-actions Bot added the feature New feature or capability label May 30, 2026
@TheTom

TheTom commented May 30, 2026

Copy link
Copy Markdown
Contributor Author

Accompanying metaltile kernels PR: 0xClandestine/metaltile#242 — ships the three net-new primitives this scaffold's forward path will call into (mt_clamped_swiglu, ffai_attn_head_gate, ffai_moe_router_sigmoid_bias). Reviewing them in tandem lets us lock the kernel surface before the FFAI forward-path PR fans out.

@ekryski
ekryski marked this pull request as draft June 3, 2026 23:29
@TheTom TheTom changed the title feat(step3): family scaffold (WIP — Step-3.5-Flash / Step-3.7-Flash) feat(step3): Step-3.5/3.7-Flash family scaffold + config decoders Jun 4, 2026
@TheTom
TheTom force-pushed the tom/wip/step3 branch 2 times, most recently from 7a57f8e to d10a964 Compare June 10, 2026 13:53
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

Commit message hygiene check

All commit messages and PR text are clean. ✅

@TheTom
TheTom changed the base branch from main to dev June 10, 2026 13:53
@TheTom
TheTom marked this pull request as ready for review June 10, 2026 13:53
TheTom added 2 commits June 22, 2026 22:28
…ard yet)

Claim the Step-3 family namespace and wire the loader so a Step-3.5-Flash
or Step-3.7-Flash checkpoint is recognized end-to-end. Concrete forward
+ per-layer code lands in follow-ups; today every load path throws
`Step3Error.notYetImplemented` after the architecture is validated.

### Architecture surface decoded by this scaffold

- **45-layer hybrid text decoder** with a `[full, swa, swa, swa]`
  layer-type pattern repeating (12 full-attn + 33 sliding-window-512).
  GQA per-layer-type — full-attn carries 64 q-heads, SWA carries 96
  q-heads (decoded into `perLayerHeads` overrides), shared 8 KV groups
  at `head_dim=128`.
- **Partial RoPE on full-attn only** (`partial_rotary_factors=0.5`).
  Per-layer-type RoPE base (5M full / 10K SWA) handled via
  `perLayerRopeTheta`. **YARN scaling scoped to selected layer-types**
  via `yarn_only_types` — read into `yarnLayerTypes`.
- **MoE on layers 3-44** (288 experts, top-k=8, intermediate=1280, one
  always-on shared expert at dim=1280). Dense MLP on layers 0-2 with
  intermediate=11264. **Sigmoid + router-bias gate** (DeepSeek-V3
  style) routed via `routerBias`/`routerNormTopK`/`routerScalingFactor`.
- **Clamped SwiGLU** (gpt-oss-style activation clip,
  `clip(silu(g), max=L) * clip(x, -L, L)`) per-layer via
  `perLayerSwigluLimit` + `perLayerSharedSwigluLimit`. Sparse map —
  only the layers with a non-zero limit get entries.
- **Head-wise attention output gate** (`use_head_wise_attn_gate`) —
  flagged in config; new op needed at forward time.
- **Perception-Encoder vision tower** (47 layers, hidden=1536, 16
  heads, head_dim=96, patch=14, image=728). 2D RoPE + additive abs
  pos-embed, quick-GELU, LayerScale (`ls_init_value=0.1`), pre-norm.
  Two stride-2 Conv2d downsamplers shrink 52×52 → 13×13 = 169 patch
  tokens; final projector maps `hidden*4 → text.hidden`.

### Files

- `Sources/FFAI/Models/Step3.swift` — family entry (`enum Step3`,
  `Step3Variant` protocol, `Step3Error`). Lists the
  text-only/conditional architecture strings + the VL subset.
- `Sources/FFAI/Models/Text/Step3Text.swift` — `Step3TextConfig`
  decoder (verbose per-layer overrides), `Step3Hybrid` variant that
  decodes the config then throws `notYetImplemented`, and the
  placeholder `Step3Model` type.
- `Sources/FFAI/Models/Vision/Step3Vision.swift` — `Step3VLVisionConfig`
  decoder + `enum Step3VL` orchestrator. Same pattern: decode +
  variant lookup + throw.
- `Sources/FFAI/Loader/Model.swift` — new dispatch arm that hands
  Step-3 VL architectures to `Step3VL.load`, matching the
  Gemma4VL/Qwen3VL/Qwen3VLMoe shape directly above it.

### Compile

The three new files compile clean against the rest of FFAI. The
`Sources/FFAI/Ops/Ops.swift` build error on this branch is a
pre-existing main-branch regen drift (`ffai_sdpa_decode_d{64,256,512}_*`
grew `has_sink: UInt32` + `sink_logit: Float` constexpr params in the
generated `MetalTileSwift/Generated/MetalTileKernels.swift`, and the
sdpaDecode hand-written dispatch sites weren't updated). Unblocking
that is its own PR.

### Next

1. Forward path on Step3Hybrid — wire the layer stack, hybrid
   KV-cache, sigmoid+bias MoE router, clamped-SwiGLU per-layer.
2. Head-wise attention gate Op (small new metaltile kernel or fuse
   into o_proj input).
3. Perception-Encoder vision tower forward + projector.
4. Text-only Step-3 dispatch arm in the loader (today only the VL
   arm is wired since `Step3Model` doesn't yet conform to
   `LanguageModel`).
…on smoke test

- Reword the WIP status/doc comments to factual phrasing (the scaffold
  state — forward stubbed, throws notYetImplemented — is unchanged).
- Drop the model-specific default maxTokens on Step3 + Step3Hybrid (falls
  to the GenerationParameters default), mirroring the DSv4 review fix.
- Add Step3RecognitionTests (CI-runnable, no checkpoint): family
  recognition, hybrid full/sliding config-decode, and default-params
  convention.
@TheTom
TheTom merged commit e05f46e into dev Jun 23, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant