launch: add thinking capability detection to opencode (#15434)

This commit is contained in:
Eva H
2026-06-18 10:45:16 -07:00
committed by GitHub
parent e1f7f9cbdb
commit 07ed752353
3 changed files with 109 additions and 19 deletions

View File

@@ -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
}

View File

@@ -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) {