package renderers import ( "encoding/json" "strings" "github.com/ollama/ollama/api" ) const ( olmo3ThinkDefaultSystemMessage = "You are OLMo, a helpful function-calling AI assistant built by Ai2. Your date cutoff is November 2024, and your model weights are available at https://huggingface.co/allenai." olmo3ThinkNoFunctionsMessage = " You do not currently have access to any functions." ) type Olmo3ThinkRenderer struct{} type olmo3ThinkToolCall struct { ID string `json:"id,omitempty"` Type string `json:"type,omitempty"` Function olmo3ThinkToolCallFunc `json:"function"` } type olmo3ThinkToolCallFunc struct { Name string `json:"name"` Arguments string `json:"arguments"` } func (r *Olmo3ThinkRenderer) Render(messages []api.Message, tools []api.Tool, _ *api.ThinkValue) (string, error) { var sb strings.Builder var systemMessage *api.Message filteredMessages := make([]api.Message, 0, len(messages)) for i, message := range messages { if message.Role == "system" { if systemMessage == nil { systemMessage = &messages[i] } continue } filteredMessages = append(filteredMessages, message) } systemContent := olmo3ThinkDefaultSystemMessage if systemMessage != nil { systemContent = systemMessage.Content } sb.WriteString("<|im_start|>system\n") sb.WriteString(systemContent) if len(tools) > 0 { functionsJSON, err := marshalWithSpaces(tools) if err != nil { return "", err } sb.WriteString(" ") sb.WriteString(string(functionsJSON)) sb.WriteString("") } else { sb.WriteString(olmo3ThinkNoFunctionsMessage) sb.WriteString(" ") } sb.WriteString("<|im_end|>\n") for i, message := range filteredMessages { lastMessage := i == len(filteredMessages)-1 switch message.Role { case "user": sb.WriteString("<|im_start|>user\n") sb.WriteString(message.Content) sb.WriteString("<|im_end|>\n") case "assistant": sb.WriteString("<|im_start|>assistant\n") if message.Content != "" { sb.WriteString(message.Content) } if len(message.ToolCalls) > 0 { toolCalls := make([]olmo3ThinkToolCall, len(message.ToolCalls)) for j, tc := range message.ToolCalls { argsJSON, err := json.Marshal(tc.Function.Arguments) if err != nil { return "", err } toolCalls[j] = olmo3ThinkToolCall{ ID: tc.ID, Type: "function", Function: olmo3ThinkToolCallFunc{ Name: tc.Function.Name, Arguments: string(argsJSON), }, } } toolCallsJSON, err := marshalWithSpaces(toolCalls) if err != nil { return "", err } sb.WriteString("") sb.WriteString(string(toolCallsJSON)) sb.WriteString("") } if !lastMessage { sb.WriteString("<|im_end|>\n") } case "tool": sb.WriteString("<|im_start|>environment\n") sb.WriteString(message.Content) sb.WriteString("<|im_end|>\n") } } needsGenerationPrompt := true if len(filteredMessages) > 0 { lastMsg := filteredMessages[len(filteredMessages)-1] if lastMsg.Role == "assistant" && len(lastMsg.ToolCalls) == 0 && lastMsg.Content != "" { needsGenerationPrompt = false } } if needsGenerationPrompt { sb.WriteString("<|im_start|>assistant\n") } return sb.String(), nil }