olmo3_think.go 2.25 KB
Newer Older
1
2
3
4
5
6
7
8
package renderers

import (
	"strings"

	"github.com/ollama/ollama/api"
)

9
10
type Olmo3ThinkVariant int

11
const (
12
13
14
15
	// Olmo3Think32B is for allenai/Olmo-3-32B-Think
	Olmo3Think32B Olmo3ThinkVariant = iota
	// Olmo31Think is for allenai/Olmo-3-7B-Think and allenai/Olmo-3.1-32B-Think (includes model info)
	Olmo31Think
16
17
)

18
19
20
21
22
const (
	olmo3ThinkFunctionsSuffix  = " You do not currently have access to any functions. <functions></functions>"
	olmo3Think32BSystemMessage = "You are a helpful AI assistant."
	olmo31ThinkSystemMessage   = "You are Olmo, a helpful AI assistant built by Ai2. Your date cutoff is December 2024, and your model weights are available at https://huggingface.co/allenai."
)
23

24
25
type Olmo3ThinkRenderer struct {
	Variant Olmo3ThinkVariant
26
27
}

28
func (r *Olmo3ThinkRenderer) Render(messages []api.Message, _ []api.Tool, _ *api.ThinkValue) (string, error) {
29
30
31
32
33
34
35
36
37
38
39
	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
		}
40
41
42
43
		// Skip tool messages - Think models don't support tools
		if message.Role == "tool" {
			continue
		}
44
45
46
47
48
		filteredMessages = append(filteredMessages, message)
	}

	sb.WriteString("<|im_start|>system\n")

49
50
51
	if systemMessage != nil {
		sb.WriteString(systemMessage.Content)
		sb.WriteString(olmo3ThinkFunctionsSuffix)
52
	} else {
53
54
55
56
57
58
59
		// Default system message varies by variant
		switch r.Variant {
		case Olmo3Think32B:
			sb.WriteString(olmo3Think32BSystemMessage)
		default: // Olmo3Think7B, Olmo31Think use same template - diverges from HF but confirmed difference from team
			sb.WriteString(olmo31ThinkSystemMessage)
		}
60
61
	}

62
	sb.WriteString("<|im_end|>\n")
63

64
	for _, message := range filteredMessages {
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
		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)
			}
			sb.WriteString("<|im_end|>\n")
		}
	}

80
81
	// Always add generation prompt with <think> tag for thinking models
	sb.WriteString("<|im_start|>assistant\n<think>")
82
83
84

	return sb.String(), nil
}