Skip to content

Add LFM2.5-VL multimodal support - #507

Open
justinchuby wants to merge 1 commit into
mainfrom
justinchuby-add-lfm25-vl-support
Open

Add LFM2.5-VL multimodal support#507
justinchuby wants to merge 1 commit into
mainfrom
justinchuby-add-lfm25-vl-support

Conversation

@justinchuby

Copy link
Copy Markdown
Member

Summary

Adds production Mobius support for LiquidAI/LFM2.5-VL-3B (model_type=lfm2_vl) at immutable revision 5a414ead75d45db003906d06fb62bd5b6846cec0.

The implementation exports a standardized three-model package:

  • vision_encoder: SigLIP2 NaFlex patch embeddings, dynamic antialiased position interpolation, masked vision attention, pixel-unshuffle, and the LFM2-VL projector
  • embedding: token embedding plus image-feature substitution, including zero-image cached decode
  • decoder: existing LFM2 hybrid short-convolution/full-attention decoder with convolution and KV cache reuse

It also pins revisions through configuration, weights, tokenizer/processor assets, CLI/runtime export, and golden generation; adds ORT GenAI metadata for hybrid cache names/layer types; and preserves the upstream adaptive-tiling processor contract.

Architecture and integration checklist

  • Extract composite LFM2-VL text, NaFlex vision, and projector configuration
  • Register lfm2_vl with the lfm2-vl three-model task
  • Use public Mobius components and onnx_ir only (no protobuf APIs)
  • Route all decoder, vision, projector, tied LM-head, and embedding weights
  • Emit standardized decoder, vision_encoder, and embedding keys
  • Preserve pixel_values, pixel_attention_mask, and spatial_shapes processor inputs
  • Emit hybrid layer_types, convolution cache names/size, image token ID, and past_present_share_buffer=false
  • Add immutable --revision CLI plumbing across config, weights, assets, processor, and golden calls
  • Add real nonzero-image L4/L5 goldens using pipeline-cat-chonk.jpeg

Validation evidence

Environment: Windows, NVIDIA RTX A1000 8 GB (driver 573.44), ONNX Runtime 1.26.0, ONNX Runtime GenAI 0.15.2, Transformers 5.14.1.

L1 / weight alignment / L3 synthetic parity

$env:PYTHONPATH=(Resolve-Path src).Path
python -m pytest src\mobius\components\_siglip2_naflex_test.py src\mobius\models\lfm2_vl_test.py tests\build_graph_test.py tests\weight_alignment_test.py -q -k "lfm2_vl or naflex" --tb=short

Result: 18 passed. This includes ONNX graph/checker coverage, complete three-package Hugging Face weight alignment, NaFlex vision/projector full-tensor parity (rtol=atol=1e-4), embedding fusion, and LFM2 prefill plus cached-decode full-logit parity (rtol=atol=1e-4).

L2 / YAML schema

python -m pytest tests\yaml_schema_test.py -q --tb=short
python -m pytest tests\yaml_schema_test.py tests\arch_validation_test.py -q -k "lfm2_5 or lfm2_vl" --tb=short

Results: 247 passed schema tests; 2 passed targeted schema/full pinned-config graph tests.

L4 CUDA prefill (bf16)

$env:MOBIUS_TEST_DEVICE='cuda'
$env:MOBIUS_TEST_BUILD_EP='onnx-standard'
python -m pytest tests\e2e_golden_test.py -m golden -k "lfm2_5-vl-3b" -v --tb=short -s

Result: 1 passed in 244.47s. Executes real processor → ONNX NaFlex vision/projector → ONNX embedding fusion → ONNX hybrid decoder on CUDAExecutionProvider and matches the pinned upstream prefill golden.

L5 CUDA cached deterministic generation (bf16)

$env:MOBIUS_TEST_DEVICE='cuda'
$env:MOBIUS_TEST_BUILD_EP='onnx-standard'
python -m pytest tests\e2e_golden_test.py -m generation -k "lfm2_5-vl-3b" -v --tb=short -s

Result: 1 passed in 264.92s. Exact 15-token cached decode:

[41, 10299, 5140, 355, 11759, 383, 278, 10409, 415, 267, 34204, 5097, 435, 22, 124900]

Decoded: A brown cat is walking on the snow with a fence behind it.

Float16 CUDA parity

The same L4 and L5 commands with the case dtype temporarily set to float16 both passed (244.35s and 244.15s) with the same exact 15-token sequence. The committed canonical golden case remains bf16.

CLI and runtime metadata

python -m mobius build --model 'LiquidAI/LFM2.5-VL-3B' --revision '5a414ead75d45db003906d06fb62bd5b6846cec0' --dtype bf16 --ep onnx-standard --runtime ort-genai <output-dir>

Result: successful export of decoder/model.onnx, vision_encoder/model.onnx, embedding/model.onnx, genai_config.json, pinned tokenizer/chat-template assets, and upstream processor_config.json. Intrinsic checks verified all referenced files, 30 hybrid layer types, convolution cache size 2, NaFlex input mapping, token IDs, and non-shared cache buffers.

Formatting, lint, and broad regression

lintrunner format --output oneline <all changed paths>
lintrunner -a --output oneline <all changed paths>

Result: passed with no findings.

The broad non-integration suite completed with 3967 passed, 58 skipped. Five unrelated existing numerical tests failed: one GGUF Q4_0 dequantization parity case, two decomposed softcap-attention parity cases, and two Qwen-Image CUDA low-precision parity cases. No LFM2-VL or revision/runtime-metadata test failed.

Explicit waivers / runtime notes

  • ORT GenAI 0.15.2 model loading: exported metadata is internally valid, but the released runtime rejects the required NaFlex pixel_attention_mask vision input as an unknown schema key. Current ORT GenAI cannot represent LFM2-VL adaptive patch masking; direct three-stage ONNX execution is fully covered by CUDA L4/L5. The upstream processor_config.json is intentionally preserved rather than emitting incorrect simplified transforms.
  • CUDA-specialized custom convolution graph: MOBIUS_TEST_BUILD_EP=cuda triggers an ONNX Runtime 1.26.0 optimizer failure because CausalConvWithState has no provider assignment. The portable onnx-standard graph runs all three stages through CUDAExecutionProvider and passes L4/L5; this is the validated deployment path for the current runtime.
  • Real fp32 CUDA checkpoint: the 3B checkpoint requires over 12 GB for fp32 parameters before activations, exceeding the available 8 GB GPU. Full-tensor fp32 synthetic vision/projector and decoder prefill/cached-decode parity passes; real-checkpoint CUDA gates cover bf16 and fp16.

Review

  • Independent specialist diff review completed
  • No high-confidence correctness, architecture, weight-routing, revision, cache, or metadata findings remained

Implement the SigLIP2 NaFlex vision tower, projector, embedding fusion, and hybrid LFM2 decoder package for LiquidAI/LFM2.5-VL-3B. Pin Hugging Face revisions through export and golden workflows, emit ORT GenAI metadata, and add architecture, alignment, parity, CUDA golden, and generation coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Justin Chu <justinchu@microsoft.com>
@justinchuby
justinchuby requested review from a team and a lite review from Copilot August 17, 2026 17:47
@github-actions

Copy link
Copy Markdown

Performance Comparison

Comparing 781bbe85fa779e

Model Metric Baseline Current Delta
bert (feature-extraction) model_size_bytes 359 KB 359 KB +0.0%
bert (feature-extraction) num_nodes 60 60 +0.0%
falcon model_size_bytes 364 KB 364 KB +0.0%
falcon num_nodes 66 66 +0.0%
gemma2 model_size_bytes 428 KB 428 KB +0.0%
gemma2 num_nodes 105 105 +0.0%
gpt2 model_size_bytes 388 KB 388 KB +0.0%
gpt2 num_nodes 54 54 +0.0%
llama model_size_bytes 425 KB 425 KB +0.0%
llama num_nodes 60 60 +0.0%
llama (static-cache) model_size_bytes 425 KB 425 KB +0.0%
llama (static-cache) num_nodes 56 56 +0.0%
mamba (ssm-text-generation) model_size_bytes 296 KB 296 KB +0.0%
mamba (ssm-text-generation) num_nodes 94 94 +0.0%
phi3 model_size_bytes 421 KB 421 KB +0.0%
phi3 num_nodes 58 58 +0.0%
phi3 (static-cache) model_size_bytes 421 KB 421 KB +0.0%
phi3 (static-cache) num_nodes 54 54 +0.0%
qwen2 model_size_bytes 425 KB 425 KB +0.0%
qwen2 num_nodes 60 60 +0.0%
qwen2 (static-cache) model_size_bytes 425 KB 425 KB +0.0%
qwen2 (static-cache) num_nodes 56 56 +0.0%
qwen3_5_moe (hybrid-text-generation) model_size_bytes 506 KB 506 KB +0.0%
qwen3_5_moe (hybrid-text-generation) num_nodes 264 264 +0.0%
qwen3_5_text (hybrid-text-generation) model_size_bytes 458 KB 458 KB +0.0%
qwen3_5_text (hybrid-text-generation) num_nodes 126 126 +0.0%
qwen3_5_vl (hybrid-qwen-vl) model_size_bytes 977 KB 977 KB +0.0%
qwen3_5_vl (hybrid-qwen-vl) num_nodes 428 428 +0.0%
t5 (seq2seq) model_size_bytes 836 KB 836 KB +0.0%
t5 (seq2seq) num_nodes 166 166 +0.0%
whisper (speech-to-text) model_size_bytes 1008 KB 1008 KB +0.0%
whisper (speech-to-text) num_nodes 128 128 +0.0%

No performance regressions.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class Mobius support for LiquidAI’s lfm2_vl multimodal family by introducing a dedicated 3-model split (vision encoder + embedding fusion + hybrid decoder), along with revision pinning across CLI/export/golden generation and ORT GenAI metadata updates.

Changes:

  • Introduces Lfm2VlForConditionalGeneration + Lfm2VlTask to export a standardized decoder / vision_encoder / embedding ModelPackage for lfm2_vl.
  • Adds SigLIP2 NaFlex tower + LFM2-VL pixel-unshuffle projector implementation and parity tests vs Transformers.
  • Threads immutable --revision through CLI, ORT GenAI auto-export/artifacts, torch reference loading, and adds L4/L5 goldens for the real checkpoint.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/weight_alignment_test.py Adds HF key-alignment coverage for the lfm2_vl three-model initializer layout.
tests/e2e_golden_test.py Extends hybrid-cache handling for conv layer types and tightens L5 length mismatch behavior when exact match is required.
tests/cli_test.py Verifies --revision is propagated through CLI build plumbing (including diffusers detection).
tests/_test_configs.py Adds a tiny lfm2_vl config fixture for graph construction/unit tests.
testdata/golden/vision-language/lfm2_5-vl-3b.json Adds pinned L4 golden output for real-image vision-language prefill.
testdata/golden/vision-language/lfm2_5-vl-3b_generation.json Adds pinned L5 deterministic generation golden (exact token sequence + text).
testdata/cases/vision-language/lfm2_5-vl-3b.yaml Adds an end-to-end L4+L5 golden test case pinned to an immutable HF revision.
src/mobius/tasks/_vision_language_3model.py Introduces Lfm2VlTask implementing NaFlex vision I/O + hybrid decoder cache export.
src/mobius/tasks/init.py Exports and registers the new lfm2-vl task name → Lfm2VlTask.
src/mobius/models/lfm2.py Refactors LFM2 config defaults + projection-key rename helpers; adds inputs_embeds path to the LFM2 backbone.
src/mobius/models/lfm2_vl.py New LFM2-VL 3-model split implementation (NaFlex tower + projector + embedding fusion + hybrid decoder) and weight routing.
src/mobius/models/lfm2_vl_test.py Adds config extraction, graph contract checks, HF parity tests, and weight-routing tests for LFM2-VL.
src/mobius/models/init.py Exposes Lfm2VlForConditionalGeneration from the public models API.
src/mobius/integrations/ort_genai/genai_config.py Enables LFM2 hybrid-cache metadata generation for lfm2_vl.
src/mobius/integrations/ort_genai/genai_config_test.py Adds a targeted test asserting hybrid-cache metadata for lfm2_vl.
src/mobius/integrations/ort_genai/auto_export.py Adds lfm2_vl model type support, preserves processor_config.json for LFM2-VL, and threads revision through remote fetches.
src/mobius/integrations/ort_genai/auto_export_test.py Tests that auto-export pins revision for both build and artifact generation, including tokenizer/config fetching.
src/mobius/components/_siglip2_naflex.py New SigLIP2 NaFlex tower (pre-patchified input, dynamic antialiased position interpolation, mask handling).
src/mobius/components/_siglip2_naflex_test.py Adds parity and parameter-name tests for the SigLIP2 NaFlex tower.
src/mobius/components/init.py Exports NaFlex tower symbols from the public components API.
src/mobius/_testing/torch_reference.py Adds revision plumbing to reference multimodal HF loading (tokenizer/processor/config/weights).
src/mobius/_registry.py Registers lfm2_vl model_type → module/task/config class mapping and updates default model IDs/categorization.
src/mobius/_configs/per_model/_lfm2_vl_vision.py Adds NaFlex-specific vision extraction hook for composite LFM2-VL configs.
src/mobius/_configs/per_model/init.py Imports the new per-model LFM2-VL vision hook for registration.
src/mobius/_configs/_base.py Introduces Lfm2VlConfig (projector + composite lifting) in the config system.
src/mobius/_configs/init.py Exports Lfm2VlConfig from the public configs API.
src/mobius/main.py Adds --revision CLI flag and propagates it through build/export paths.
scripts/generate_golden.py Threads pinned revision through golden generation for both text-only and multimodal cases.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants