Compare commits

...

1 Commits

Author SHA1 Message Date
Jeffrey Morgan 9dc851630c Handle Gemma4 BOS override in llama server 2026-05-30 23:30:46 -07:00
2 changed files with 26 additions and 2 deletions
+8 -1
View File
@@ -241,7 +241,14 @@ func (s *llamaServerRunner) tokenizerAddsBOS() bool {
return false
}
return s.ggml.KV().Bool("tokenizer.ggml.add_bos_token")
kv := s.ggml.KV()
if kv.Bool("tokenizer.ggml.add_bos_token") {
return true
}
// llama.cpp forces add_bos on for Gemma4 at load time, even for older GGUFs
// whose tokenizer.ggml.add_bos_token metadata is false.
return kv.String("tokenizer.ggml.pre") == "gemma4"
}
func (s *llamaServerRunner) completionPromptForRequest(ctx context.Context, req CompletionRequest) (any, error) {
+18 -1
View File
@@ -981,6 +981,7 @@ func TestLlamaServerCompletionBOSOwnership(t *testing.T) {
name string
leadingBOS string
tokenizerAddsBOS bool
ggmlKV ggml.KV
prompt string
wantPrompt string
}{
@@ -1020,6 +1021,20 @@ func TestLlamaServerCompletionBOSOwnership(t *testing.T) {
prompt: "<bos>hello<bos>",
wantPrompt: "hello<bos>",
},
{
name: "gemma4 llama.cpp runtime bos override",
leadingBOS: "<bos>",
ggmlKV: ggml.KV{
"general.architecture": "gemma4",
"tokenizer.ggml.pre": "gemma4",
"tokenizer.ggml.add_bos_token": false,
"tokenizer.ggml.bos_token_id": uint32(2),
"tokenizer.ggml.eos_token_id": uint32(1),
"tokenizer.ggml.unknown_token_id": uint32(0),
},
prompt: "<bos><|turn>user\nhello<turn|>\n<|turn>model\n",
wantPrompt: "<|turn>user\nhello<turn|>\n<|turn>model\n",
},
}
for _, tt := range tests {
@@ -1053,7 +1068,9 @@ func TestLlamaServerCompletionBOSOwnership(t *testing.T) {
sem: semaphore.NewWeighted(1),
options: api.Options{Runner: api.Runner{NumCtx: 2048}},
}
if tt.tokenizerAddsBOS {
if tt.ggmlKV != nil {
runner.ggml = loadTestGGML(t, tt.ggmlKV)
} else if tt.tokenizerAddsBOS {
runner.ggml = loadTestGGML(t, ggml.KV{
"general.architecture": "gemma3",
"tokenizer.ggml.add_bos_token": true,