Files
ollama/model/parsers/parsers.go
2025-10-14 01:13:54 -07:00

74 lines
2.0 KiB
Go

package parsers
import (
"github.com/ollama/ollama/api"
"github.com/ollama/ollama/harmony"
)
type Parser interface {
// Init initializes the parser with tools and optional last message for chat prefill
// Returns processed tools if the parser needs to modify them (e.g., harmony renames them)
Init(tools []api.Tool, lastMessage *api.Message) []api.Tool
// Add processes streamed content and returns parsed content, thinking, and tool calls
// The done flag indicates if this is the last chunk (used for draining accumulators)
Add(s string, done bool) (content string, thinking string, calls []api.ToolCall, err error)
HasToolSupport() bool
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{}
return parser
case "qwen3-vl-instruct":
parser := &Qwen3VLParser{hasThinkingSupport: false}
return parser
case "passthrough":
return &PassthroughParser{}
case "harmony":
return harmony.NewHarmonyMessageHandler()
default:
return nil
}
}
type PassthroughParser struct{}
func (p *PassthroughParser) Init(tools []api.Tool, lastMessage *api.Message) []api.Tool {
return tools // passthrough doesn't modify tools
}
func (p *PassthroughParser) Add(s string, done bool) (content string, thinking string, calls []api.ToolCall, err error) {
return s, "", nil, nil
}
func (p *PassthroughParser) HasToolSupport() bool {
return false
}
func (p *PassthroughParser) HasThinkingSupport() bool {
return false
}