mirror of https://github.com/ollama/ollama
Add DeepSeek3Renderer with variant support
- Add DeepSeek3Renderer struct with IsThinking and Variant fields - Add Deepseek31 variant constant for DeepSeek v3.1 template support - Include deepseek31.jinja template for proper rendering - Update renderer factory to use new DeepSeek3Renderer structure - All tests pass locally with new renderer implementation
This commit is contained in:
parent
43ff6ba343
commit
786d9d06db
|
|
@ -0,0 +1,121 @@
|
||||||
|
package renderers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ollama/ollama/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeepSeek3Variant int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Deepseek31 DeepSeek3Variant = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeepSeek3Renderer struct {
|
||||||
|
IsThinking bool
|
||||||
|
Variant DeepSeek3Variant
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DeepSeek3Renderer) 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
|
||||||
|
thinking := r.IsThinking && (thinkValue != nil && thinkValue.Bool())
|
||||||
|
|
||||||
|
// extract system messages first
|
||||||
|
var systemPrompt strings.Builder
|
||||||
|
isFirstSystemPrompt := true
|
||||||
|
|
||||||
|
for _, message := range messages {
|
||||||
|
if message.Role == "system" {
|
||||||
|
if isFirstSystemPrompt {
|
||||||
|
systemPrompt.WriteString(message.Content)
|
||||||
|
isFirstSystemPrompt = false
|
||||||
|
} else {
|
||||||
|
systemPrompt.WriteString("\n\n" + message.Content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.WriteString("<|begin▁of▁sentence|>" + systemPrompt.String())
|
||||||
|
|
||||||
|
// state tracking
|
||||||
|
isTool := false
|
||||||
|
isLastUser := false
|
||||||
|
|
||||||
|
for _, message := range messages {
|
||||||
|
switch message.Role {
|
||||||
|
case "user":
|
||||||
|
isTool = false
|
||||||
|
isLastUser = true
|
||||||
|
sb.WriteString("<|User|>" + message.Content)
|
||||||
|
|
||||||
|
case "assistant":
|
||||||
|
if len(message.ToolCalls) > 0 {
|
||||||
|
if isLastUser {
|
||||||
|
sb.WriteString("<|Assistant|></think>")
|
||||||
|
}
|
||||||
|
isLastUser = false
|
||||||
|
isTool = false
|
||||||
|
|
||||||
|
if message.Content != "" {
|
||||||
|
sb.WriteString(message.Content)
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.WriteString("<|tool▁calls▁begin|>")
|
||||||
|
for _, toolCall := range message.ToolCalls {
|
||||||
|
sb.WriteString("<|tool▁call▁begin|>" + toolCall.Function.Name + "<|tool▁sep|>")
|
||||||
|
|
||||||
|
argsJSON, _ := json.Marshal(toolCall.Function.Arguments)
|
||||||
|
sb.WriteString(string(argsJSON))
|
||||||
|
sb.WriteString("<|tool▁call▁end|>")
|
||||||
|
}
|
||||||
|
sb.WriteString("<|tool▁calls▁end|><|end▁of▁sentence|>")
|
||||||
|
} else {
|
||||||
|
if isLastUser {
|
||||||
|
sb.WriteString("<|Assistant|>")
|
||||||
|
// message["prefix"] is defined and message["prefix"] and thinking
|
||||||
|
// message.Thinking != "" represents message["prefix"] being defined
|
||||||
|
if message.Thinking != "" && thinking {
|
||||||
|
sb.WriteString("<think>")
|
||||||
|
} else {
|
||||||
|
sb.WriteString("</think>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isLastUser = false
|
||||||
|
|
||||||
|
content := message.Content
|
||||||
|
if isTool {
|
||||||
|
sb.WriteString(content + "<|end▁of▁sentence|>")
|
||||||
|
isTool = false
|
||||||
|
} else {
|
||||||
|
if strings.Contains(content, "</think>") {
|
||||||
|
parts := strings.SplitN(content, "</think>", 2)
|
||||||
|
if len(parts) > 1 {
|
||||||
|
content = parts[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.WriteString(content + "<|end▁of▁sentence|>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case "tool":
|
||||||
|
isLastUser = false
|
||||||
|
isTool = true
|
||||||
|
sb.WriteString("<|tool▁output▁begin|>" + message.Content + "<|tool▁output▁end|>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isLastUser && !isTool {
|
||||||
|
sb.WriteString("<|Assistant|>")
|
||||||
|
if thinking {
|
||||||
|
sb.WriteString("<think>")
|
||||||
|
} else {
|
||||||
|
sb.WriteString("</think>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.String(), nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
{%- if not add_generation_prompt is defined -%}
|
||||||
|
{%- set add_generation_prompt = false -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if not thinking is defined -%}
|
||||||
|
{%- set thinking = false -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set ns = namespace(is_first=false, is_tool=false, system_prompt="", is_first_sp=true, is_last_user=false) -%}
|
||||||
|
{%- for message in messages -%}
|
||||||
|
{%- if message["role"] == "system" -%}
|
||||||
|
{%- if ns.is_first_sp -%}
|
||||||
|
{%- set ns.system_prompt = ns.system_prompt + message["content"] -%}
|
||||||
|
{%- set ns.is_first_sp = false -%}
|
||||||
|
{%- else -%}
|
||||||
|
{%- set ns.system_prompt = ns.system_prompt + "\n\n" + message["content"] -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{{- bos_token -}}
|
||||||
|
{{- ns.system_prompt -}}
|
||||||
|
{%- for message in messages -%}
|
||||||
|
{%- if message["role"] == "user" -%}
|
||||||
|
{%- set ns.is_tool = false -%}
|
||||||
|
{%- set ns.is_first = false -%}
|
||||||
|
{%- set ns.is_last_user = true -%}
|
||||||
|
{{- "<|User|>" + message["content"] -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if message["role"] == "assistant" and message["tool_calls"] is defined and message["tool_calls"] is not none -%}
|
||||||
|
{%- if ns.is_last_user -%}
|
||||||
|
{{- "<|Assistant|></think>" -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set ns.is_last_user = false -%}
|
||||||
|
{%- set ns.is_first = false -%}
|
||||||
|
{%- set ns.is_tool = false -%}
|
||||||
|
{%- for tool in message["tool_calls"] -%}
|
||||||
|
{%- if not ns.is_first -%}
|
||||||
|
{%- if message["content"] is none -%}
|
||||||
|
{{- "<|tool▁calls▁begin|><|tool▁call▁begin|>" + tool["function"]["name"] + "<|tool▁sep|>" + tool["function"]["arguments"] + "<|tool▁call▁end|>" -}}
|
||||||
|
{%- else -%}
|
||||||
|
{{- message["content"] + "<|tool▁calls▁begin|><|tool▁call▁begin|>" + tool["function"]["name"] + "<|tool▁sep|>" + tool["function"]["arguments"] + "<|tool▁call▁end|>" -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set ns.is_first = true -%}
|
||||||
|
{%- else -%}
|
||||||
|
{{- "<|tool▁call▁begin|>" + tool["function"]["name"] + "<|tool▁sep|>" + tool["function"]["arguments"] + "<|tool▁call▁end|>" -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{{- "<|tool▁calls▁end|><|end▁of▁sentence|>" -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if message["role"] == "assistant" and (message["tool_calls"] is not defined or message["tool_calls"] is none) -%}
|
||||||
|
{%- if ns.is_last_user -%}
|
||||||
|
{{- "<|Assistant|>" -}}
|
||||||
|
{%- if message["prefix"] is defined and message["prefix"] and thinking -%}
|
||||||
|
{{- "<think>" -}}
|
||||||
|
{%- else -%}
|
||||||
|
{{- "</think>" -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set ns.is_last_user = false -%}
|
||||||
|
{%- if ns.is_tool -%}
|
||||||
|
{{- message["content"] + "<|end▁of▁sentence|>" -}}
|
||||||
|
{%- set ns.is_tool = false -%}
|
||||||
|
{%- else -%}
|
||||||
|
{%- set content = message["content"] -%}
|
||||||
|
{%- if "</think>" in content -%}
|
||||||
|
{%- set content = content.split("</think>", 1)[1] -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{{- content + "<|end▁of▁sentence|>" -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if message["role"] == "tool" -%}
|
||||||
|
{%- set ns.is_last_user = false -%}
|
||||||
|
{%- set ns.is_tool = true -%}
|
||||||
|
{{- "<|tool▁output▁begin|>" + message["content"] + "<|tool▁output▁end|>" -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- if add_generation_prompt and ns.is_last_user and not ns.is_tool -%}
|
||||||
|
{{- "<|Assistant|>" -}}
|
||||||
|
{%- if not thinking -%}
|
||||||
|
{{- "</think>" -}}
|
||||||
|
{%- else -%}
|
||||||
|
{{- "<think>" -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
Loading…
Reference in New Issue