diff --git a/model/parsers/nemotron3nano.go b/model/parsers/nemotron3nano.go
index c230b4e7..6e662fba 100644
--- a/model/parsers/nemotron3nano.go
+++ b/model/parsers/nemotron3nano.go
@@ -24,19 +24,18 @@ const (
)
type Nemotron3NanoParser struct {
- state Nemotron3NanoParserState
- buffer strings.Builder
- tools []api.Tool
- HasThinking bool
+ state Nemotron3NanoParserState
+ buffer strings.Builder
+ tools []api.Tool
}
func (p *Nemotron3NanoParser) HasToolSupport() bool { return true }
-func (p *Nemotron3NanoParser) HasThinkingSupport() bool { return p.HasThinking }
+func (p *Nemotron3NanoParser) HasThinkingSupport() bool { return true }
func (p *Nemotron3NanoParser) Init(tools []api.Tool, lastMessage *api.Message, thinkValue *api.ThinkValue) []api.Tool {
p.tools = tools
- // Check both model capability AND request preference
+ // thinking is enabled if user requests it
thinkingEnabled := thinkValue != nil && thinkValue.Bool()
prefill := lastMessage != nil && lastMessage.Role == "assistant"
diff --git a/model/parsers/nemotron3nano_test.go b/model/parsers/nemotron3nano_test.go
index cfe74a31..a4517fc4 100644
--- a/model/parsers/nemotron3nano_test.go
+++ b/model/parsers/nemotron3nano_test.go
@@ -203,7 +203,7 @@ func TestNemotron3NanoParser(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- p := &Nemotron3NanoParser{HasThinking: tt.thinkValue != nil && tt.thinkValue.Bool()}
+ p := &Nemotron3NanoParser{}
p.Init(nil, nil, tt.thinkValue)
content, thinking, calls, err := p.Add(tt.input, false)
@@ -441,7 +441,7 @@ func TestNemotron3NanoParser_Streaming(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- p := &Nemotron3NanoParser{HasThinking: tt.thinkValue != nil && tt.thinkValue.Bool()}
+ p := &Nemotron3NanoParser{}
p.Init(nil, nil, tt.thinkValue)
var allContent string
@@ -488,24 +488,15 @@ func TestNemotron3NanoParser_HasToolSupport(t *testing.T) {
}
func TestNemotron3NanoParser_HasThinkingSupport(t *testing.T) {
- t.Run("with thinking enabled", func(t *testing.T) {
- p := &Nemotron3NanoParser{HasThinking: true}
- if !p.HasThinkingSupport() {
- t.Error("expected HasThinkingSupport to return true")
- }
- })
-
- t.Run("with thinking disabled", func(t *testing.T) {
- p := &Nemotron3NanoParser{HasThinking: false}
- if p.HasThinkingSupport() {
- t.Error("expected HasThinkingSupport to return false")
- }
- })
+ p := &Nemotron3NanoParser{}
+ if !p.HasThinkingSupport() {
+ t.Error("expected HasThinkingSupport to return true")
+ }
}
func TestNemotron3NanoParser_Init(t *testing.T) {
t.Run("starts in thinking state when enabled", func(t *testing.T) {
- p := &Nemotron3NanoParser{HasThinking: true}
+ p := &Nemotron3NanoParser{}
p.Init(nil, nil, &api.ThinkValue{Value: true})
if p.state != Nemotron3NanoCollectingThinking {
t.Errorf("expected state Nemotron3NanoCollectingThinking, got %v", p.state)
@@ -513,7 +504,7 @@ func TestNemotron3NanoParser_Init(t *testing.T) {
})
t.Run("starts in content state when thinking disabled", func(t *testing.T) {
- p := &Nemotron3NanoParser{HasThinking: true}
+ p := &Nemotron3NanoParser{}
p.Init(nil, nil, &api.ThinkValue{Value: false})
if p.state != Nemotron3NanoCollectingContent {
t.Errorf("expected state Nemotron3NanoCollectingContent, got %v", p.state)
@@ -521,7 +512,7 @@ func TestNemotron3NanoParser_Init(t *testing.T) {
})
t.Run("starts in content state when nil thinkValue", func(t *testing.T) {
- p := &Nemotron3NanoParser{HasThinking: true}
+ p := &Nemotron3NanoParser{}
p.Init(nil, nil, nil)
if p.state != Nemotron3NanoCollectingContent {
t.Errorf("expected state Nemotron3NanoCollectingContent, got %v", p.state)
@@ -529,7 +520,7 @@ func TestNemotron3NanoParser_Init(t *testing.T) {
})
t.Run("starts in content state with assistant prefill", func(t *testing.T) {
- p := &Nemotron3NanoParser{HasThinking: true}
+ p := &Nemotron3NanoParser{}
prefill := &api.Message{Role: "assistant", Content: "Starting..."}
p.Init(nil, prefill, &api.ThinkValue{Value: true})
if p.state != Nemotron3NanoCollectingContent {
diff --git a/model/parsers/parsers.go b/model/parsers/parsers.go
index 417261b1..4c7656f9 100644
--- a/model/parsers/parsers.go
+++ b/model/parsers/parsers.go
@@ -63,9 +63,7 @@ func ParserForName(name string) Parser {
case "olmo3-think":
return &Olmo3ThinkParser{}
case "nemotron-3-nano":
- return &Nemotron3NanoParser{HasThinking: false}
- case "nemotron-3-nano-thinking":
- return &Nemotron3NanoParser{HasThinking: true}
+ return &Nemotron3NanoParser{}
default:
return nil
}
diff --git a/model/renderers/nemotron3nano.go b/model/renderers/nemotron3nano.go
index 08074d18..478a59bd 100644
--- a/model/renderers/nemotron3nano.go
+++ b/model/renderers/nemotron3nano.go
@@ -8,15 +8,13 @@ import (
"github.com/ollama/ollama/api"
)
-type Nemotron3NanoRenderer struct {
- IsThinking bool
-}
+type Nemotron3NanoRenderer struct{}
func (r *Nemotron3NanoRenderer) Render(messages []api.Message, tools []api.Tool, thinkValue *api.ThinkValue) (string, error) {
var sb strings.Builder
- // thinking is enabled: model must support it AND user must request it
- enableThinking := r.IsThinking && (thinkValue != nil && thinkValue.Bool())
+ // thinking is enabled if user requests it
+ enableThinking := thinkValue != nil && thinkValue.Bool()
// Extract system message if present
var systemMessage string
diff --git a/model/renderers/nemotron3nano_test.go b/model/renderers/nemotron3nano_test.go
index dad528cc..ca1feb93 100644
--- a/model/renderers/nemotron3nano_test.go
+++ b/model/renderers/nemotron3nano_test.go
@@ -14,7 +14,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
msgs []api.Message
tools []api.Tool
thinkValue *api.ThinkValue
- isThinking bool
expected string
}{
{
@@ -22,7 +21,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
msgs: []api.Message{
{Role: "user", Content: "Hello!"},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n<|im_end|>\n" +
"<|im_start|>user\nHello!<|im_end|>\n" +
@@ -33,7 +31,7 @@ func TestNemotron3NanoRenderer(t *testing.T) {
msgs: []api.Message{
{Role: "user", Content: "Hello!"},
},
- isThinking: false,
+ thinkValue: nil,
expected: "<|im_start|>system\n<|im_end|>\n" +
"<|im_start|>user\nHello!<|im_end|>\n" +
"<|im_start|>assistant\n",
@@ -44,7 +42,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
{Role: "system", Content: "You are a helpful assistant."},
{Role: "user", Content: "Hello!"},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n" +
"<|im_start|>user\nHello!<|im_end|>\n" +
@@ -57,7 +54,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
{Role: "assistant", Content: "Hello! How can I help?"},
{Role: "user", Content: "Tell me a joke"},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n<|im_end|>\n" +
"<|im_start|>user\nHi<|im_end|>\n" +
@@ -86,7 +82,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
},
},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n" +
"# Tools\n\nYou have access to the following functions:\n\n\n" +
@@ -141,7 +136,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
},
},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n" +
"# Tools\n\nYou have access to the following functions:\n\n\n" +
@@ -198,7 +192,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
},
},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n" +
"# Tools\n\nYou have access to the following functions:\n\n\n" +
@@ -228,7 +221,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
{Role: "assistant", Content: "Hello!", Thinking: "Let me think about this..."},
{Role: "user", Content: "How are you?"},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n<|im_end|>\n" +
"<|im_start|>user\nHi<|im_end|>\n" +
@@ -274,7 +266,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
},
},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n" +
"# Tools\n\nYou have access to the following functions:\n\n\n" +
@@ -299,12 +290,11 @@ func TestNemotron3NanoRenderer(t *testing.T) {
"<|im_start|>assistant\n\n",
},
{
- name: "thinking disabled even when model supports it",
+ name: "thinking disabled when user doesn't request it",
msgs: []api.Message{
{Role: "user", Content: "Hello!"},
},
- isThinking: true, // model supports thinking
- thinkValue: nil, // but user didn't request it
+ thinkValue: nil,
expected: "<|im_start|>system\n<|im_end|>\n" +
"<|im_start|>user\nHello!<|im_end|>\n" +
"<|im_start|>assistant\n",
@@ -351,7 +341,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
},
},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n" +
"# Tools\n\nYou have access to the following functions:\n\n\n" +
@@ -390,7 +379,7 @@ func TestNemotron3NanoRenderer(t *testing.T) {
{
name: "empty messages list",
msgs: []api.Message{},
- isThinking: false,
+ thinkValue: nil,
expected: "<|im_start|>system\n<|im_end|>\n<|im_start|>assistant\n",
},
{
@@ -417,7 +406,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
},
},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n" +
"# Tools\n\nYou have access to the following functions:\n\n\n" +
@@ -446,7 +434,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
{Role: "assistant", Thinking: "Deep thoughts here...", Content: ""},
{Role: "user", Content: "What did you think?"},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n<|im_end|>\n" +
"<|im_start|>user\nThink about this<|im_end|>\n" +
@@ -483,7 +470,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
},
},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n" +
"# Tools\n\nYou have access to the following functions:\n\n\n" +
@@ -512,7 +498,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
{Role: "assistant", Content: "To call a tool, use tags with inside."},
{Role: "user", Content: "Thanks!"},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n<|im_end|>\n" +
"<|im_start|>user\nHow do I format a tool call?<|im_end|>\n" +
@@ -546,7 +531,6 @@ func TestNemotron3NanoRenderer(t *testing.T) {
},
},
},
- isThinking: true,
thinkValue: &api.ThinkValue{Value: true},
expected: "<|im_start|>system\n" +
"# Tools\n\nYou have access to the following functions:\n\n\n" +
@@ -572,7 +556,7 @@ func TestNemotron3NanoRenderer(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- renderer := &Nemotron3NanoRenderer{IsThinking: tt.isThinking}
+ renderer := &Nemotron3NanoRenderer{}
rendered, err := renderer.Render(tt.msgs, tt.tools, tt.thinkValue)
if err != nil {
t.Fatal(err)
diff --git a/model/renderers/renderer.go b/model/renderers/renderer.go
index 7c03cf93..657c75a5 100644
--- a/model/renderers/renderer.go
+++ b/model/renderers/renderer.go
@@ -77,11 +77,7 @@ func rendererForName(name string) Renderer {
renderer := &Olmo3ThinkRenderer{Variant: Olmo3Think32B}
return renderer
case "nemotron-3-nano":
- renderer := &Nemotron3NanoRenderer{IsThinking: false}
- return renderer
- case "nemotron-3-nano-thinking":
- renderer := &Nemotron3NanoRenderer{IsThinking: true}
- return renderer
+ return &Nemotron3NanoRenderer{}
default:
return nil
}