From 26bd8b403a8db04e684e4006523885385a2305a2 Mon Sep 17 00:00:00 2001 From: Colibri Developer Date: Sun, 19 Jul 2026 13:39:11 -0600 Subject: [PATCH] fix(engine): filter non-EOS stop tokens in serve mode to prevent premature halt on tool calls GLM-5.2's config defines three stop tokens: <|endoftext|>, <|user|>, and <|observation|>. In serve mode, when the model generates blocks, int4-quantized logit noise can cause argmax to pick a <|user|> or <|observation|> token ID, immediately stopping generation. The <|user|> and <|observation|> tokens are role markers handled by the Python API server, not the C engine. Filter them out in stops_arm() when SERVE=1, keeping only <|endoftext|> as the stop token. - Add SERVE-mode guard in stops_arm() that retains only the EOS token - Log the number of filtered tokens for diagnostics --- c/glm.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/c/glm.c b/c/glm.c index 00c7076..3237c0a 100644 --- a/c/glm.c +++ b/c/glm.c @@ -4115,6 +4115,19 @@ static void stops_arm(const Cfg *c, int tok_eos){ g_nstop=0; for(int i=0;in_stop;i++) g_stop[g_nstop++]=c->stop_ids[i]; if(tok_eos>=0 && !is_stop(tok_eos)) g_stop[g_nstop++]=tok_eos; + /* In serve mode (API), keep only <|endoftext|> as a stop token. The tokens + * <|user|> and <|observation|> are role markers that the Python server + * handles — keeping them as stop tokens causes the engine to halt + * prematurely when the model tries to emit blocks, because + * int4-quantized logits can be noisy enough that argmax picks a stop-token + * ID instead of the correct tool-call token. (#401) */ + if(getenv("SERVE")){ + int kept=0; + for(int i=0;i