Skip to content

Commit 41fbc01

Browse files
committed
fix(sdk): enable thinking mode on the llama.cpp VLM path
Gemma-4 ships an mmproj file so it loads as a VLM and runs through vlm.cpp, which hardcoded enable_thinking=false and dropped special tokens in token_to_piece. Pass enable_thinking through and render special tokens so reasoning channel delimiters reach the caller. Also enable allow_special_tokens for all models on the LLM path so reasoning delimiters are never silently swallowed. Closes qcom-ai-hub/geniex#1208 Signed-off-by: Paul Zhu <paulzhuzx@gmail.com>
1 parent 30c1aef commit 41fbc01

2 files changed

Lines changed: 10 additions & 6 deletions

File tree

sdk/plugins/llama_cpp/src/llm.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,12 @@ int32_t LlamaLlm::create_impl(const geniex_LlmCreateInput* input) {
4848
bool is_gpt_oss_model =
4949
(model_path_lower.find("gpt") != std::string::npos) && (model_path_lower.find("oss") != std::string::npos);
5050

51-
this->allow_special_tokens = is_gpt_oss_model;
51+
// Special tokens must be rendered as text so the FSM in the CLI can
52+
// detect thinking/channel delimiters (e.g. <|channel>/<channel|> for
53+
// Gemma-4, <|channel|> for GPT-OSS). EOS is already intercepted by
54+
// llama_vocab_is_eog() before token_to_piece is called, so enabling
55+
// this globally is safe for all models.
56+
this->allow_special_tokens = true;
5257
if (is_gpt_oss_model) {
5358
tensor_overrides[0] = {"\\.ffn_(up|down|gate)_exps\\.(weight|bias)", ggml_backend_cpu_buffer_type()};
5459
tensor_overrides[1] = {nullptr, nullptr}; // Null terminator

sdk/plugins/llama_cpp/src/vlm.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,7 @@ int32_t LlamaVlm::apply_chat_template(
154154
tmpl_inputs.tools = common_chat_tools_parse_oaicompat(nlohmann::ordered_json::parse(std::string(input->tools)));
155155
}
156156

157-
if (input->enable_thinking) {
158-
GENIEX_LOG_WARN("thinking mode not supported for llama.cpp VLM; ignoring enable_thinking=true");
159-
}
160-
tmpl_inputs.enable_thinking = false;
157+
tmpl_inputs.enable_thinking = input->enable_thinking;
161158
GENIEX_LOG_DEBUG("applying chat template with add_generation_prompt=true, use_jinja={}", tmpl_inputs.use_jinja);
162159

163160
// Apply chat template
@@ -399,7 +396,9 @@ int32_t LlamaVlm::generate(const geniex_VlmGenerateInput* input, geniex_VlmGener
399396
break;
400397
}
401398

402-
int n = llama_token_to_piece(vocab, token, token_buffer, sizeof(token_buffer) - 1, 0, false);
399+
// Render special tokens so reasoning/channel delimiters (e.g. Gemma-4's
400+
// <|channel>/<channel|>) reach the caller; EOS is already handled above.
401+
int n = llama_token_to_piece(vocab, token, token_buffer, sizeof(token_buffer) - 1, 0, true);
403402
if (n < 0) n = 0;
404403
token_buffer[n] = '\0';
405404

0 commit comments

Comments
 (0)