server: apply format constraint for all thinking parsers when think=false (#15901)
This commit is contained in:
+1
-3
@@ -2766,9 +2766,7 @@ func (s *Server) ChatHandler(c *gin.Context) {
|
||||
// current approach uses the transition from parsed thinking content to
|
||||
// parsed non-thinking content as the signal to turn constraining on
|
||||
|
||||
// TODO(parthsareen): temporary fix for https://github.com/ollama/ollama/issues/15260.
|
||||
// To revisit for other models and have a consistent pattern across models through parsers.
|
||||
forceImmediate := m.Config.Parser == "gemma4" && req.Think != nil && !req.Think.Bool()
|
||||
forceImmediate := builtinParser != nil && builtinParser.HasThinkingSupport() && req.Think != nil && !req.Think.Bool()
|
||||
if req.Format != nil && structuredOutputsState == structuredOutputsState_None && !forceImmediate && ((builtinParser != nil || thinkingState != nil) && slices.Contains(m.Capabilities(), model.CapabilityThinking)) {
|
||||
currentFormat = nil
|
||||
}
|
||||
|
||||
@@ -2811,15 +2811,18 @@ func TestChatWithPromptEndingInThinkTag(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestChatFormatWithThinkFalse verifies that when a model uses a builtin
|
||||
// parser that supports thinking (e.g. gemma4) and the request explicitly
|
||||
// disables thinking (think=false), the format constraint is passed to the
|
||||
// first and only completion call. Previously, format was deferred for all
|
||||
// thinking-capable parsers and only re-applied after an end-of-thinking
|
||||
// transition — a transition that never fires when thinking is off. See
|
||||
// https://github.com/ollama/ollama/issues/15260.
|
||||
// parser that supports thinking and the request explicitly disables thinking
|
||||
// (think=false), the format constraint is passed to the first and only
|
||||
// completion call. Previously, format was deferred for all thinking-capable
|
||||
// parsers and only re-applied after an end-of-thinking transition -- a
|
||||
// transition that never fires when thinking is off. See
|
||||
// https://github.com/ollama/ollama/issues/15260 and
|
||||
// https://github.com/ollama/ollama/issues/14645.
|
||||
func TestChatFormatWithThinkFalse(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
for _, parserName := range []string{"gemma4", "qwen3.5", "qwen3-thinking"} {
|
||||
t.Run(parserName, func(t *testing.T) {
|
||||
mock := &mockRunner{
|
||||
CompletionResponse: llm.CompletionResponse{
|
||||
Done: true,
|
||||
@@ -2876,13 +2879,11 @@ func TestChatFormatWithThinkFalse(t *testing.T) {
|
||||
{Name: "output.weight", Shape: []uint64{1}, WriterTo: bytes.NewReader(make([]byte, 4))},
|
||||
})
|
||||
|
||||
// Use the gemma4 builtin parser — it reports HasThinkingSupport=true, which
|
||||
// adds CapabilityThinking to the model and previously triggered deferral of
|
||||
// the format even when the user passed think=false.
|
||||
modelName := "test-" + parserName + "-parser"
|
||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
||||
Model: "test-gemma4-parser",
|
||||
Model: modelName,
|
||||
Files: map[string]string{"file.gguf": digest},
|
||||
Parser: "gemma4",
|
||||
Parser: parserName,
|
||||
Template: `{{- range .Messages }}{{ .Role }}: {{ .Content }}{{ end }}`,
|
||||
Stream: &stream,
|
||||
})
|
||||
@@ -2916,7 +2917,7 @@ func TestChatFormatWithThinkFalse(t *testing.T) {
|
||||
streamRequest := false
|
||||
think := false
|
||||
w = createRequest(t, s.ChatHandler, api.ChatRequest{
|
||||
Model: "test-gemma4-parser",
|
||||
Model: modelName,
|
||||
Messages: []api.Message{{Role: "user", Content: "Respond in JSON."}},
|
||||
Think: &api.ThinkValue{Value: think},
|
||||
Stream: &streamRequest,
|
||||
@@ -2934,6 +2935,8 @@ func TestChatFormatWithThinkFalse(t *testing.T) {
|
||||
if !bytes.Equal([]byte(format), []byte(requests[0].Format)) {
|
||||
t.Errorf("expected first completion format to match the request format, got %q", string(requests[0].Format))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateUnload(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user