Skip to content

[Models] Serve Qwen3.5/3.6/3.8 text-only GGUF without an mm_proj - #120

Open
laureano-arcanio wants to merge 1 commit into
vllm-project:mainfrom
laureano-arcanio:qwen35-text-only
Open

[Models] Serve Qwen3.5/3.6/3.8 text-only GGUF without an mm_proj#120
laureano-arcanio wants to merge 1 commit into
vllm-project:mainfrom
laureano-arcanio:qwen35-text-only

Conversation

@laureano-arcanio

Copy link
Copy Markdown

Qwen3.5-family GGUF backbones are commonly published without a vision tower, but their HF configs are the multimodal composite ones, so the adapter demanded an mmproj.gguf that would never be used and refused to start otherwise.

Detect a text-only backbone (no vision tensors, no projector sibling and no explicitly configured one) and build it as its text architecture (Qwen3_5ForCausalLM / Qwen3_5MoeForCausalLM) from the config's text half. The architecture is chosen in the config parser, which runs before any model loader exists, so EngineArgs now records the GGUF reference and the explicit mm_proj for it.

Multimodal loads are unchanged: a projector - detected or configured - still selects the ConditionalGeneration architecture.

Tested on an RTX 3090 with Qwen3.8-27B (dense), Qwen3.6-35B-A3B (MoE), Qwen3.5-9B (single file and 3-way split), all Q4_K_M/Q4_K_XL.

Qwen3.5-family GGUF backbones are commonly published without a vision
tower, but their HF configs are the multimodal composite ones, so the
adapter demanded an *mmproj*.gguf that would never be used and refused
to start otherwise.

Detect a text-only backbone (no vision tensors, no projector sibling and
no explicitly configured one) and build it as its text architecture
(Qwen3_5ForCausalLM / Qwen3_5MoeForCausalLM) from the config's text half.
The architecture is chosen in the config parser, which runs before any
model loader exists, so EngineArgs now records the GGUF reference and the
explicit mm_proj for it.

Multimodal loads are unchanged: a projector - detected or configured -
still selects the ConditionalGeneration architecture.

Tested on an RTX 3090 with Qwen3.8-27B (dense), Qwen3.6-35B-A3B (MoE),
Qwen3.5-9B (single file and 3-way split), all Q4_K_M/Q4_K_XL.

@GaryYang77 GaryYang77 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.

Hi, thanks for the PR. I think this is useful so I tried it with vLLM 0.26.0 but ran into a compatibility issue.

The PR worktree is definitely being loaded, but engine init fails with:

TypeError: Invalid type of HuggingFace config.
Expected Qwen3_5Config, found Qwen3_5TextConfig

I checked the model registry in vLLM 0.26.0. Qwen3_5ForCausalLM and Qwen3_5MoeForCausalLM are not registered there; only Qwen3_5ForConditionalGeneration is.

So for the text-only case, this PR changes the config to Qwen3_5TextConfig and sets the architecture to Qwen3_5ForCausalLM, but vLLM 0.26.0 ends up resolving it through the registered Qwen3_5ForConditionalGeneration path. The multimodal processor then expects Qwen3_5Config, which gives the error above.

This seems to be version-dependent. The causal Qwen3.5 architectures were added upstream after 0.26.0 (vllm-project/vllm#50210), but this plugin currently just depends on vllm without a minimum version.

So I think this either needs some compatibility handling for 0.26.0, or the minimum supported vLLM version should be bumped/documented.

It may also be worth adding a small regression test that passes the parsed architecture through vLLM's ModelRegistry. The current parser tests only check that Qwen3_5ForCausalLM is written into the config, so they won't catch cases where that architecture isn't actually registered by the installed vLLM version.

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.

2 participants