Skip to content

test: cover the second hybrid-attention VLM architecture (LFM2VL) - #52

Merged
solderzzc merged 1 commit into
mainfrom
test/vlm-lfm2vl-unit-tests
Aug 15, 2026
Merged

test: cover the second hybrid-attention VLM architecture (LFM2VL)#52
solderzzc merged 1 commit into
mainfrom
test/vlm-lfm2vl-unit-tests

Conversation

@solderzzc

Copy link
Copy Markdown
Member

Companion to #51. Follow-up to #49/#50MLXVLM/Models/LFM2VL.swift was the other largest remaining zero-coverage file in the model layer.

What's different about it

Its hybrid mechanism differs from Qwen35's fixed-period one: layers are attention only at explicit indices, full_attn_idxs (or derived from layer_types), and a short causal convolution (LFM2ShortConv) everywhere else — a sparser, more arbitrary pattern than a modulus. Setting full_attn_idxs: [1] over 2 layers makes layer 0 the conv block and layer 1 the attention block, so both branches of LFM2DecoderLayer build and run.

newCache reads fullAttnIdxs independently of how the layers were built to decide MambaCache vs KVCacheSimple per layer, so the forward-pass test calls it directly (model.newCache(parameters: nil)) rather than assuming construction and cache selection stay in agreement — that agreement is exactly what this exercises.

The vision half carries the same silent constraint as Qwen3VL's tower (#50): num_patches must be a perfect square, since a grid side is derived via sqrt.

Verification

MLXVLM/Models/LFM2VL.swift: 0% → 34.9% line coverage
Full suite: 120 tests, 21 suites, passing (112 before, +8 across this PR and its Qwen35 sibling)

🤖 Generated with Claude Code

Follow-up to #49/#50. MLXVLM/Models/LFM2VL.swift was, alongside Qwen35.swift,
one of the largest remaining zero-coverage files in the model layer.

Its hybrid mechanism differs from Qwen35's fixed-period one: layers are
attention only at explicit indices, full_attn_idxs (or derived from
layer_types), and a short causal convolution (LFM2ShortConv) everywhere
else — a sparser, more arbitrary pattern than a modulus. Setting
full_attn_idxs: [1] over 2 layers makes layer 0 the conv block and layer 1 the
attention block, so both branches of LFM2DecoderLayer build and run.

newCache reads fullAttnIdxs independently of how the layers were built to
decide MambaCache versus KVCacheSimple per layer, so the forward-pass test uses
it directly (model.newCache(parameters: nil)) rather than assuming construction
and cache selection stay in agreement — that agreement is exactly what this
exercises.

The vision half carries the same silent constraint as Qwen3VL's tower (#50):
num_patches must be a perfect square, since a grid side is derived via sqrt.

Verified with coverage: MLXVLM/Models/LFM2VL.swift moves from 0% to 34.9% line
coverage. Full suite: 120 tests, 21 suites, passing (112 before, +8 across this
PR and its sibling for Qwen35).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@solderzzc
solderzzc merged commit c09851f into main Aug 15, 2026
6 checks passed
@solderzzc
solderzzc deleted the test/vlm-lfm2vl-unit-tests branch August 15, 2026 21:14
solderzzc added a commit to SharpAI/SwiftLM that referenced this pull request Aug 15, 2026
…149)

Points at c09851f, which carries both:

- SharpAI/mlx-swift-lm#51 — the hybrid full-attention/GatedDeltaNet split in
  MLXVLM/Models/Qwen35.swift, gated by a fixed period (full_attention_interval)
- SharpAI/mlx-swift-lm#52 — the hybrid attention/short-conv split in
  MLXVLM/Models/LFM2VL.swift, gated by explicit layer indices (full_attn_idxs)

Both were, alongside Gemma4 (#147) and Qwen3VL (#148), among the largest
zero-coverage files in the model layer. Coverage: Qwen35 0% → 66.4%,
LFM2VL 0% → 34.9%.

No SwiftLM-side code changes; verified the umbrella builds clean against the
bumped pointer.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant