launch: add thinking capability detection to opencode (#15434)
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/ollama/ollama/cmd/internal/fileutil"
|
||||
"github.com/ollama/ollama/envconfig"
|
||||
@@ -278,6 +279,25 @@ func buildModelEntries(modelList []LaunchModel) map[string]any {
|
||||
"output": []string{"text"},
|
||||
}
|
||||
}
|
||||
if model.HasCapability("thinking") {
|
||||
entry["reasoning"] = true
|
||||
if openCodeModelSupportsThinkingLevels(model) {
|
||||
entry["options"] = map[string]any{"reasoningEffort": "medium"}
|
||||
entry["variants"] = map[string]any{
|
||||
"low": map[string]any{"reasoningEffort": "low"},
|
||||
"medium": map[string]any{"reasoningEffort": "medium"},
|
||||
"high": map[string]any{"reasoningEffort": "high"},
|
||||
"max": map[string]any{"reasoningEffort": "max"},
|
||||
}
|
||||
} else {
|
||||
entry["variants"] = map[string]any{
|
||||
"none": map[string]any{"reasoningEffort": "none"},
|
||||
"low": map[string]any{"disabled": true},
|
||||
"medium": map[string]any{"disabled": true},
|
||||
"high": map[string]any{"disabled": true},
|
||||
}
|
||||
}
|
||||
}
|
||||
if model.MaxOutputTokens > 0 {
|
||||
limit := make(map[string]any)
|
||||
if model.ContextLength > 0 {
|
||||
@@ -290,3 +310,20 @@ func buildModelEntries(modelList []LaunchModel) map[string]any {
|
||||
}
|
||||
return models
|
||||
}
|
||||
|
||||
func openCodeModelSupportsThinkingLevels(model LaunchModel) bool {
|
||||
for _, family := range append([]string{model.Details.Family}, model.Details.Families...) {
|
||||
if normalizeOpenCodeModelFamily(family) == "gptoss" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Contains(normalizeOpenCodeModelFamily(model.Name), "gptoss")
|
||||
}
|
||||
|
||||
func normalizeOpenCodeModelFamily(s string) string {
|
||||
s = strings.ToLower(s)
|
||||
s = strings.ReplaceAll(s, "-", "")
|
||||
s = strings.ReplaceAll(s, "_", "")
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/ollama/ollama/api"
|
||||
"github.com/ollama/ollama/types/model"
|
||||
)
|
||||
|
||||
@@ -174,6 +175,54 @@ func TestOpenCodeEdit(t *testing.T) {
|
||||
t.Fatalf("modalities.output = %v, want [text]", output)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("thinking model gets on off reasoning variants", func(t *testing.T) {
|
||||
models := buildModelEntries([]LaunchModel{{Name: "thinking-model", Capabilities: []model.Capability{model.CapabilityThinking}}})
|
||||
entry, _ := models["thinking-model"].(map[string]any)
|
||||
|
||||
if entry["reasoning"] != true {
|
||||
t.Fatalf("reasoning = %v, want true", entry["reasoning"])
|
||||
}
|
||||
variants, _ := entry["variants"].(map[string]any)
|
||||
none, _ := variants["none"].(map[string]any)
|
||||
if none["reasoningEffort"] != "none" {
|
||||
t.Fatalf("variants.none.reasoningEffort = %v, want none", none["reasoningEffort"])
|
||||
}
|
||||
for _, level := range []string{"low", "medium", "high"} {
|
||||
variant, _ := variants[level].(map[string]any)
|
||||
if variant["disabled"] != true {
|
||||
t.Fatalf("variants.%s.disabled = %v, want true", level, variant["disabled"])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("gpt oss gets reasoning level variants", func(t *testing.T) {
|
||||
models := buildModelEntries([]LaunchModel{{Name: "gpt-oss:120b-cloud", Capabilities: []model.Capability{model.CapabilityThinking}}})
|
||||
entry, _ := models["gpt-oss:120b-cloud"].(map[string]any)
|
||||
options, _ := entry["options"].(map[string]any)
|
||||
|
||||
if options["reasoningEffort"] != "medium" {
|
||||
t.Fatalf("options.reasoningEffort = %v, want medium", options["reasoningEffort"])
|
||||
}
|
||||
variants, _ := entry["variants"].(map[string]any)
|
||||
for _, level := range []string{"low", "medium", "high", "max"} {
|
||||
variant, _ := variants[level].(map[string]any)
|
||||
if variant["reasoningEffort"] != level {
|
||||
t.Fatalf("variants.%s.reasoningEffort = %v, want %s", level, variant["reasoningEffort"], level)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("gpt oss family gets reasoning level variants", func(t *testing.T) {
|
||||
models := buildModelEntries([]LaunchModel{{Name: "reasoning-model", Capabilities: []model.Capability{model.CapabilityThinking}, Details: api.ModelDetails{Families: []string{"gptoss"}}}})
|
||||
entry, _ := models["reasoning-model"].(map[string]any)
|
||||
variants, _ := entry["variants"].(map[string]any)
|
||||
max, _ := variants["max"].(map[string]any)
|
||||
|
||||
if max["reasoningEffort"] != "max" {
|
||||
t.Fatalf("variants.max.reasoningEffort = %v, want max", max["reasoningEffort"])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestBuildModelEntries(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user