parser/renderer: add Ornith 9B renderer/parser support (#16920)
This commit is contained in:
@@ -54,6 +54,8 @@ func ParserForName(name string) Parser {
|
|||||||
p = &Qwen3Parser{hasThinkingSupport: true, defaultThinking: true}
|
p = &Qwen3Parser{hasThinkingSupport: true, defaultThinking: true}
|
||||||
case "qwen3.5":
|
case "qwen3.5":
|
||||||
p = &Qwen35Parser{}
|
p = &Qwen35Parser{}
|
||||||
|
case "ornith":
|
||||||
|
p = &Qwen35Parser{}
|
||||||
case "qwen3-coder":
|
case "qwen3-coder":
|
||||||
p = &Qwen3CoderParser{}
|
p = &Qwen3CoderParser{}
|
||||||
case "qwen3-vl-instruct":
|
case "qwen3-vl-instruct":
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ func TestBuiltInParsersStillWork(t *testing.T) {
|
|||||||
{"lfm2"},
|
{"lfm2"},
|
||||||
{"lfm2-thinking"},
|
{"lfm2-thinking"},
|
||||||
{"qwen3.5"},
|
{"qwen3.5"},
|
||||||
|
{"ornith"},
|
||||||
{"harmony"},
|
{"harmony"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
model/renderers/ornith.go
Normal file
16
model/renderers/ornith.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package renderers
|
||||||
|
|
||||||
|
type OrnithRenderer struct {
|
||||||
|
Qwen35Renderer
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOrnithRenderer() Renderer {
|
||||||
|
return &OrnithRenderer{
|
||||||
|
Qwen35Renderer: Qwen35Renderer{
|
||||||
|
isThinking: true,
|
||||||
|
alwaysRenderAssistantThinkBlock: true,
|
||||||
|
emitEmptyThinkOnNoThink: true,
|
||||||
|
useImgTags: RenderImgTags,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
74
model/renderers/ornith_test.go
Normal file
74
model/renderers/ornith_test.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package renderers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ollama/ollama/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOrnithRendererMatchesAssistantHistoryThinkBlocks(t *testing.T) {
|
||||||
|
msgs := []api.Message{
|
||||||
|
{Role: "user", Content: "Say hello."},
|
||||||
|
{Role: "assistant", Content: "Hello."},
|
||||||
|
{Role: "user", Content: "Now say bye."},
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := RenderWithRenderer("ornith", msgs, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("render failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := `<|im_start|>user
|
||||||
|
Say hello.<|im_end|>
|
||||||
|
<|im_start|>assistant
|
||||||
|
<think>
|
||||||
|
|
||||||
|
</think>
|
||||||
|
|
||||||
|
Hello.<|im_end|>
|
||||||
|
<|im_start|>user
|
||||||
|
Now say bye.<|im_end|>
|
||||||
|
<|im_start|>assistant
|
||||||
|
<think>
|
||||||
|
`
|
||||||
|
if got != want {
|
||||||
|
t.Fatalf("unexpected Ornith render\n--- got ---\n%q\n--- want ---\n%q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrnithRendererKeepsAssistantThinkBlocksWhenThinkingDisabled(t *testing.T) {
|
||||||
|
msgs := []api.Message{
|
||||||
|
{Role: "user", Content: "Say hello."},
|
||||||
|
{
|
||||||
|
Role: "assistant",
|
||||||
|
Thinking: "Keep it short.",
|
||||||
|
Content: "Hello.",
|
||||||
|
},
|
||||||
|
{Role: "user", Content: "Now say bye."},
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := RenderWithRenderer("ornith", msgs, nil, &api.ThinkValue{Value: false})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("render failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := `<|im_start|>user
|
||||||
|
Say hello.<|im_end|>
|
||||||
|
<|im_start|>assistant
|
||||||
|
<think>
|
||||||
|
Keep it short.
|
||||||
|
</think>
|
||||||
|
|
||||||
|
Hello.<|im_end|>
|
||||||
|
<|im_start|>user
|
||||||
|
Now say bye.<|im_end|>
|
||||||
|
<|im_start|>assistant
|
||||||
|
<think>
|
||||||
|
|
||||||
|
</think>
|
||||||
|
|
||||||
|
`
|
||||||
|
if got != want {
|
||||||
|
t.Fatalf("unexpected Ornith render with thinking disabled\n--- got ---\n%q\n--- want ---\n%q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,8 +39,9 @@ Reminder:
|
|||||||
type Qwen35Renderer struct {
|
type Qwen35Renderer struct {
|
||||||
isThinking bool
|
isThinking bool
|
||||||
|
|
||||||
emitEmptyThinkOnNoThink bool
|
alwaysRenderAssistantThinkBlock bool
|
||||||
useImgTags bool
|
emitEmptyThinkOnNoThink bool
|
||||||
|
useImgTags bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Qwen35Renderer) LeadingBOS() string {
|
func (r *Qwen35Renderer) LeadingBOS() string {
|
||||||
@@ -140,9 +141,10 @@ func (r *Qwen35Renderer) Render(messages []api.Message, tools []api.Tool, think
|
|||||||
if message.Role == "user" || (message.Role == "system" && i != 0) {
|
if message.Role == "user" || (message.Role == "system" && i != 0) {
|
||||||
sb.WriteString(imStartTag + message.Role + "\n" + content + imEndTag + "\n")
|
sb.WriteString(imStartTag + message.Role + "\n" + content + imEndTag + "\n")
|
||||||
} else if message.Role == "assistant" {
|
} else if message.Role == "assistant" {
|
||||||
contentReasoning, content := splitQwen35ReasoningContent(content, message.Thinking, isThinking)
|
renderAssistantThinkBlock := r.alwaysRenderAssistantThinkBlock || (isThinking && i > lastQueryIndex)
|
||||||
|
contentReasoning, content := splitQwen35ReasoningContent(content, message.Thinking, renderAssistantThinkBlock)
|
||||||
|
|
||||||
if isThinking && i > lastQueryIndex {
|
if renderAssistantThinkBlock {
|
||||||
sb.WriteString(imStartTag + message.Role + "\n<think>\n" + contentReasoning + "\n</think>\n\n" + content)
|
sb.WriteString(imStartTag + message.Role + "\n<think>\n" + contentReasoning + "\n</think>\n\n" + content)
|
||||||
} else {
|
} else {
|
||||||
sb.WriteString(imStartTag + message.Role + "\n" + content)
|
sb.WriteString(imStartTag + message.Role + "\n" + content)
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ func rendererForName(name string) Renderer {
|
|||||||
case "qwen3.5":
|
case "qwen3.5":
|
||||||
renderer := &Qwen35Renderer{isThinking: true, emitEmptyThinkOnNoThink: true, useImgTags: RenderImgTags}
|
renderer := &Qwen35Renderer{isThinking: true, emitEmptyThinkOnNoThink: true, useImgTags: RenderImgTags}
|
||||||
return renderer
|
return renderer
|
||||||
|
case "ornith":
|
||||||
|
return newOrnithRenderer()
|
||||||
case "cogito":
|
case "cogito":
|
||||||
renderer := &CogitoRenderer{isThinking: true}
|
renderer := &CogitoRenderer{isThinking: true}
|
||||||
return renderer
|
return renderer
|
||||||
|
|||||||
Reference in New Issue
Block a user