Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
ollama
Commits
ddaca643
Commit
ddaca643
authored
Oct 14, 2025
by
Devon Rifkin
Browse files
add registries for parsers/renderers
parent
05982a95
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
222 additions
and
4 deletions
+222
-4
model/parsers/parsers.go
model/parsers/parsers.go
+21
-0
model/parsers/parsers_test.go
model/parsers/parsers_test.go
+97
-0
model/renderers/renderer.go
model/renderers/renderer.go
+36
-2
model/renderers/renderer_test.go
model/renderers/renderer_test.go
+67
-0
server/prompt.go
server/prompt.go
+1
-2
No files found.
model/parsers/parsers.go
View file @
ddaca643
...
...
@@ -16,7 +16,28 @@ type Parser interface {
HasThinkingSupport
()
bool
}
type
ParserConstructor
func
()
Parser
type
ParserRegistry
struct
{
constructors
map
[
string
]
ParserConstructor
}
func
(
r
*
ParserRegistry
)
Register
(
name
string
,
constructor
ParserConstructor
)
{
r
.
constructors
[
name
]
=
constructor
}
var
registry
=
ParserRegistry
{
constructors
:
make
(
map
[
string
]
ParserConstructor
),
}
func
Register
(
name
string
,
constructor
ParserConstructor
)
{
registry
.
Register
(
name
,
constructor
)
}
func
ParserForName
(
name
string
)
Parser
{
if
parser
,
ok
:=
registry
.
constructors
[
name
];
ok
{
return
parser
()
}
switch
name
{
case
"qwen3-coder"
:
parser
:=
&
Qwen3CoderParser
{}
...
...
model/parsers/parsers_test.go
0 → 100644
View file @
ddaca643
package
parsers
import
(
"testing"
"github.com/ollama/ollama/api"
)
type
mockParser
struct
{
name
string
}
func
(
m
*
mockParser
)
Init
(
tools
[]
api
.
Tool
,
lastMessage
*
api
.
Message
)
[]
api
.
Tool
{
return
tools
}
func
(
m
*
mockParser
)
Add
(
s
string
,
done
bool
)
(
content
string
,
thinking
string
,
calls
[]
api
.
ToolCall
,
err
error
)
{
return
"mock:"
+
s
,
""
,
nil
,
nil
}
func
(
m
*
mockParser
)
HasToolSupport
()
bool
{
return
false
}
func
(
m
*
mockParser
)
HasThinkingSupport
()
bool
{
return
false
}
func
TestRegisterCustomParser
(
t
*
testing
.
T
)
{
// Register a custom parser
Register
(
"custom-parser"
,
func
()
Parser
{
return
&
mockParser
{
name
:
"custom"
}
})
// Retrieve it
parser
:=
ParserForName
(
"custom-parser"
)
if
parser
==
nil
{
t
.
Fatal
(
"expected parser to be registered"
)
}
// Test it works
content
,
_
,
_
,
err
:=
parser
.
Add
(
"test"
,
false
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
if
content
!=
"mock:test"
{
t
.
Errorf
(
"expected 'mock:test', got %q"
,
content
)
}
}
func
TestBuiltInParsersStillWork
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
name
string
}{
{
"passthrough"
},
{
"qwen3-coder"
},
{
"harmony"
},
}
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
parser
:=
ParserForName
(
tt
.
name
)
if
parser
==
nil
{
t
.
Fatalf
(
"expected built-in parser %q to exist"
,
tt
.
name
)
}
})
}
}
func
TestOverrideBuiltInParser
(
t
*
testing
.
T
)
{
// Override a built-in parser
Register
(
"passthrough"
,
func
()
Parser
{
return
&
mockParser
{
name
:
"override"
}
})
// Should get the override
parser
:=
ParserForName
(
"passthrough"
)
if
parser
==
nil
{
t
.
Fatal
(
"expected parser to exist"
)
}
// Test it's the override
content
,
_
,
_
,
err
:=
parser
.
Add
(
"test"
,
false
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
if
content
!=
"mock:test"
{
t
.
Errorf
(
"expected 'mock:test' from override, got %q"
,
content
)
}
}
func
TestUnknownParserReturnsNil
(
t
*
testing
.
T
)
{
parser
:=
ParserForName
(
"nonexistent-parser"
)
if
parser
!=
nil
{
t
.
Error
(
"expected nil for unknown parser"
)
}
}
model/renderers/renderer.go
View file @
ddaca643
package
renderers
import
"github.com/ollama/ollama/api"
import
(
"fmt"
"github.com/ollama/ollama/api"
)
type
Renderer
interface
{
Render
(
messages
[]
api
.
Message
,
tools
[]
api
.
Tool
,
think
*
api
.
ThinkValue
)
(
string
,
error
)
}
func
RendererForName
(
name
string
)
Renderer
{
type
(
RendererConstructor
func
()
Renderer
RendererRegistry
struct
{
renderers
map
[
string
]
RendererConstructor
}
)
func
(
r
*
RendererRegistry
)
Register
(
name
string
,
renderer
RendererConstructor
)
{
r
.
renderers
[
name
]
=
renderer
}
var
registry
=
RendererRegistry
{
renderers
:
make
(
map
[
string
]
RendererConstructor
),
}
func
Register
(
name
string
,
renderer
RendererConstructor
)
{
registry
.
Register
(
name
,
renderer
)
}
func
RenderWithRenderer
(
name
string
,
msgs
[]
api
.
Message
,
tools
[]
api
.
Tool
,
think
*
api
.
ThinkValue
)
(
string
,
error
)
{
renderer
:=
rendererForName
(
name
)
if
renderer
==
nil
{
return
""
,
fmt
.
Errorf
(
"unknown renderer %q"
,
name
)
}
return
renderer
.
Render
(
msgs
,
tools
,
think
)
}
func
rendererForName
(
name
string
)
Renderer
{
if
constructor
,
ok
:=
registry
.
renderers
[
name
];
ok
{
return
constructor
()
}
switch
name
{
case
"qwen3-coder"
:
renderer
:=
&
Qwen3CoderRenderer
{}
...
...
model/renderers/renderer_test.go
0 → 100644
View file @
ddaca643
package
renderers
import
(
"testing"
"github.com/ollama/ollama/api"
)
type
mockRenderer
struct
{}
func
(
m
*
mockRenderer
)
Render
(
msgs
[]
api
.
Message
,
tools
[]
api
.
Tool
,
think
*
api
.
ThinkValue
)
(
string
,
error
)
{
return
"mock-output"
,
nil
}
func
TestRegisterCustomRenderer
(
t
*
testing
.
T
)
{
// Register a custom renderer
Register
(
"custom-renderer"
,
func
()
Renderer
{
return
&
mockRenderer
{}
})
// Retrieve and use it
result
,
err
:=
RenderWithRenderer
(
"custom-renderer"
,
nil
,
nil
,
nil
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
if
result
!=
"mock-output"
{
t
.
Errorf
(
"expected 'mock-output', got %q"
,
result
)
}
}
func
TestBuiltInRendererStillWorks
(
t
*
testing
.
T
)
{
// Test that qwen3-coder still works
messages
:=
[]
api
.
Message
{
{
Role
:
"user"
,
Content
:
"Hello"
},
}
result
,
err
:=
RenderWithRenderer
(
"qwen3-coder"
,
messages
,
nil
,
nil
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
if
result
==
""
{
t
.
Error
(
"expected non-empty result from qwen3-coder renderer"
)
}
}
func
TestOverrideBuiltInRenderer
(
t
*
testing
.
T
)
{
// Override the built-in renderer
Register
(
"qwen3-coder"
,
func
()
Renderer
{
return
&
mockRenderer
{}
})
// Should get the override
result
,
err
:=
RenderWithRenderer
(
"qwen3-coder"
,
nil
,
nil
,
nil
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
if
result
!=
"mock-output"
{
t
.
Errorf
(
"expected 'mock-output' from override, got %q"
,
result
)
}
}
func
TestUnknownRendererReturnsError
(
t
*
testing
.
T
)
{
_
,
err
:=
RenderWithRenderer
(
"nonexistent-renderer"
,
nil
,
nil
,
nil
)
if
err
==
nil
{
t
.
Error
(
"expected error for unknown renderer"
)
}
}
server/prompt.go
View file @
ddaca643
...
...
@@ -106,8 +106,7 @@ func chatPrompt(ctx context.Context, m *Model, tokenize tokenizeFunc, opts *api.
func
renderPrompt
(
m
*
Model
,
msgs
[]
api
.
Message
,
tools
[]
api
.
Tool
,
think
*
api
.
ThinkValue
)
(
string
,
error
)
{
if
m
.
Config
.
Renderer
!=
""
{
renderer
:=
renderers
.
RendererForName
(
m
.
Config
.
Renderer
)
rendered
,
err
:=
renderer
.
Render
(
msgs
,
tools
,
think
)
rendered
,
err
:=
renderers
.
RenderWithRenderer
(
m
.
Config
.
Renderer
,
msgs
,
tools
,
think
)
if
err
!=
nil
{
return
""
,
err
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment