Commit 18b74fa41 for llama.cpp
commit 18b74fa41dcac1f55ae1371fe58153f7225941f6
Author: Seungjun Bae <linkedlatch@gmail.com>
Date: Mon Nov 16 03:45:17 2026 +0900
model : read qwen3vl output head size from the tensor (#32349)
Allows Qwen3-ForcedAligner, whose output head (5000 timestamp classes) is smaller than the vocab.
diff --git a/src/models/qwen3vl.cpp b/src/models/qwen3vl.cpp
index 480e570dc..ed9fe6507 100644
--- a/src/models/qwen3vl.cpp
+++ b/src/models/qwen3vl.cpp
@@ -13,14 +13,20 @@ void llama_model_qwen3vl::load_arch_hparams(llama_model_loader & ml) {
}
}
-void llama_model_qwen3vl::load_arch_tensors(llama_model_loader &) {
+void llama_model_qwen3vl::load_arch_tensors(llama_model_loader & ml) {
LLAMA_LOAD_LOCALS;
+ // the output head can be smaller than the vocab (Qwen3-TTS codec head, Qwen3-ForcedAligner timestamp head)
int64_t n_vocab_out = n_vocab;
- if (arch == LLM_ARCH_QWEN3TTS) {
+ if (const ggml_tensor * meta = ml.get_tensor_meta(tn(LLM_TENSOR_OUTPUT, "weight").str().c_str())) {
+ n_vocab_out = meta->ne[1];
+ } else if (arch == LLM_ARCH_QWEN3TTS) {
// [TAG_LLAMA_N_VOCAB_OUT]
n_vocab_out = 3072;
}
+ if (n_vocab_out < 1 || n_vocab_out > n_vocab) {
+ throw std::runtime_error(format("tensor 'output.weight' has invalid head size %lld (vocab size %lld)", (long long) n_vocab_out, (long long) n_vocab));
+ }
tok_embd = create_tensor(tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, 0);
@@ -164,7 +170,7 @@ llama_model_qwen3vl::graph::graph(const llm_graph_params & params) : llm_graph_c
int64_t n_vocab_in = model.tok_embd->ne[1];
int64_t n_vocab_out = model.output->ne[1];
if (n_vocab_in > n_vocab_out) {
- // case: Qwen3TTS model with codec_head as output
+ // case: output head smaller than vocab, see load_arch_tensors
GGML_ASSERT(model.output_norm);
int64_t pad = n_vocab_in - n_vocab_out;