From 2504818b5af1ae721990ed2ab07e517239ebfbb1 Mon Sep 17 00:00:00 2001 From: Papersnake Date: Fri, 6 Feb 2026 09:12:45 +0800 Subject: [PATCH 1/3] feat: add claude-opus-4-6 --- relay/channel/aws/constants.go | 8 +++++++- relay/channel/claude/constants.go | 2 ++ relay/channel/vertex/adaptor.go | 1 + setting/ratio_setting/cache_ratio.go | 4 ++++ setting/ratio_setting/model_ratio.go | 1 + 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/relay/channel/aws/constants.go b/relay/channel/aws/constants.go index 4b78b3985..848bb7eac 100644 --- a/relay/channel/aws/constants.go +++ b/relay/channel/aws/constants.go @@ -3,7 +3,7 @@ package aws import "strings" var awsModelIDMap = map[string]string{ - "claude-3-sonnet-20240229": "anthropic.claude-3-sonnet-20240229-v1:0", + "claude-3-sonnet-20240229": "anthropic.claude-3-sonnet-20240229-v1:0", "claude-3-opus-20240229": "anthropic.claude-3-opus-20240229-v1:0", "claude-3-haiku-20240307": "anthropic.claude-3-haiku-20240307-v1:0", "claude-3-5-sonnet-20240620": "anthropic.claude-3-5-sonnet-20240620-v1:0", @@ -16,6 +16,7 @@ var awsModelIDMap = map[string]string{ "claude-sonnet-4-5-20250929": "anthropic.claude-sonnet-4-5-20250929-v1:0", "claude-haiku-4-5-20251001": "anthropic.claude-haiku-4-5-20251001-v1:0", "claude-opus-4-5-20251101": "anthropic.claude-opus-4-5-20251101-v1:0", + "claude-opus-4-6": "anthropic.claude-opus-4-6-v1:0", // Nova models "nova-micro-v1:0": "amazon.nova-micro-v1:0", "nova-lite-v1:0": "amazon.nova-lite-v1:0", @@ -79,6 +80,11 @@ var awsModelCanCrossRegionMap = map[string]map[string]bool{ "ap": true, "eu": true, }, + "anthropic.claude-opus-4-6-v1:0": { + "us": true, + "ap": true, + "eu": true, + }, "anthropic.claude-haiku-4-5-20251001-v1:0": { "us": true, "ap": true, diff --git a/relay/channel/claude/constants.go b/relay/channel/claude/constants.go index b5dcc5af4..797d1a90a 100644 --- a/relay/channel/claude/constants.go +++ b/relay/channel/claude/constants.go @@ -20,6 +20,8 @@ var ModelList = []string{ "claude-sonnet-4-5-20250929-thinking", "claude-opus-4-5-20251101", "claude-opus-4-5-20251101-thinking", + "claude-opus-4-6", + "claude-opus-4-6-thinking", } var ChannelName = "claude" diff --git a/relay/channel/vertex/adaptor.go b/relay/channel/vertex/adaptor.go index b9fbd19a4..7c48907ec 100644 --- a/relay/channel/vertex/adaptor.go +++ b/relay/channel/vertex/adaptor.go @@ -42,6 +42,7 @@ var claudeModelMap = map[string]string{ "claude-sonnet-4-5-20250929": "claude-sonnet-4-5@20250929", "claude-haiku-4-5-20251001": "claude-haiku-4-5@20251001", "claude-opus-4-5-20251101": "claude-opus-4-5@20251101", + "claude-opus-4-6": "claude-opus-4-6", } const anthropicVersion = "vertex-2023-10-16" diff --git a/setting/ratio_setting/cache_ratio.go b/setting/ratio_setting/cache_ratio.go index 665c2f593..ec85de11c 100644 --- a/setting/ratio_setting/cache_ratio.go +++ b/setting/ratio_setting/cache_ratio.go @@ -60,6 +60,8 @@ var defaultCacheRatio = map[string]float64{ "claude-sonnet-4-5-20250929-thinking": 0.1, "claude-opus-4-5-20251101": 0.1, "claude-opus-4-5-20251101-thinking": 0.1, + "claude-opus-4-6": 0.1, + "claude-opus-4-6-thinking": 0.1, } var defaultCreateCacheRatio = map[string]float64{ @@ -82,6 +84,8 @@ var defaultCreateCacheRatio = map[string]float64{ "claude-sonnet-4-5-20250929-thinking": 1.25, "claude-opus-4-5-20251101": 1.25, "claude-opus-4-5-20251101-thinking": 1.25, + "claude-opus-4-6": 1.25, + "claude-opus-4-6-thinking": 1.25, } //var defaultCreateCacheRatio = map[string]float64{} diff --git a/setting/ratio_setting/model_ratio.go b/setting/ratio_setting/model_ratio.go index 61f6d044f..e1a2b8ca0 100644 --- a/setting/ratio_setting/model_ratio.go +++ b/setting/ratio_setting/model_ratio.go @@ -142,6 +142,7 @@ var defaultModelRatio = map[string]float64{ "claude-sonnet-4-20250514": 1.5, "claude-sonnet-4-5-20250929": 1.5, "claude-opus-4-5-20251101": 2.5, + "claude-opus-4-6": 2.5, "claude-3-opus-20240229": 7.5, // $15 / 1M tokens "claude-opus-4-20250514": 7.5, "claude-opus-4-1-20250805": 7.5, From ff71786d8d837371f9f40eab41683e5ef89641e8 Mon Sep 17 00:00:00 2001 From: Papersnake Date: Fri, 6 Feb 2026 09:51:15 +0800 Subject: [PATCH 2/3] fix: aws claude --- relay/channel/aws/constants.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relay/channel/aws/constants.go b/relay/channel/aws/constants.go index 848bb7eac..54ab32c8c 100644 --- a/relay/channel/aws/constants.go +++ b/relay/channel/aws/constants.go @@ -16,7 +16,7 @@ var awsModelIDMap = map[string]string{ "claude-sonnet-4-5-20250929": "anthropic.claude-sonnet-4-5-20250929-v1:0", "claude-haiku-4-5-20251001": "anthropic.claude-haiku-4-5-20251001-v1:0", "claude-opus-4-5-20251101": "anthropic.claude-opus-4-5-20251101-v1:0", - "claude-opus-4-6": "anthropic.claude-opus-4-6-v1:0", + "claude-opus-4-6": "anthropic.claude-opus-4-6-v1", // Nova models "nova-micro-v1:0": "amazon.nova-micro-v1:0", "nova-lite-v1:0": "amazon.nova-lite-v1:0", @@ -80,7 +80,7 @@ var awsModelCanCrossRegionMap = map[string]map[string]bool{ "ap": true, "eu": true, }, - "anthropic.claude-opus-4-6-v1:0": { + "anthropic.claude-opus-4-6-v1": { "us": true, "ap": true, "eu": true, From c9f5de7048d6399500d4c3e886400bcda06f3d52 Mon Sep 17 00:00:00 2001 From: Papersnake Date: Fri, 6 Feb 2026 11:01:23 +0800 Subject: [PATCH 3/3] feat: support adaptive thinking --- relay/channel/aws/dto.go | 1 + relay/channel/claude/constants.go | 5 ++++- relay/channel/claude/relay-claude.go | 12 +++++++++++- relay/channel/vertex/dto.go | 4 ++++ relay/claude_handler.go | 12 +++++++++++- setting/ratio_setting/cache_ratio.go | 8 ++++++++ setting/ratio_setting/model_ratio.go | 4 ++++ setting/reasoning/suffix.go | 2 +- 8 files changed, 44 insertions(+), 4 deletions(-) diff --git a/relay/channel/aws/dto.go b/relay/channel/aws/dto.go index b060a593b..4a942714d 100644 --- a/relay/channel/aws/dto.go +++ b/relay/channel/aws/dto.go @@ -26,6 +26,7 @@ type AwsClaudeRequest struct { Tools any `json:"tools,omitempty"` ToolChoice any `json:"tool_choice,omitempty"` Thinking *dto.Thinking `json:"thinking,omitempty"` + OutputConfig json.RawMessage `json:"output_config,omitempty"` } func formatRequest(requestBody io.Reader, requestHeader http.Header) (*AwsClaudeRequest, error) { diff --git a/relay/channel/claude/constants.go b/relay/channel/claude/constants.go index 797d1a90a..2da61d0c7 100644 --- a/relay/channel/claude/constants.go +++ b/relay/channel/claude/constants.go @@ -21,7 +21,10 @@ var ModelList = []string{ "claude-opus-4-5-20251101", "claude-opus-4-5-20251101-thinking", "claude-opus-4-6", - "claude-opus-4-6-thinking", + "claude-opus-4-6-max", + "claude-opus-4-6-high", + "claude-opus-4-6-medium", + "claude-opus-4-6-low", } var ChannelName = "claude" diff --git a/relay/channel/claude/relay-claude.go b/relay/channel/claude/relay-claude.go index 6d90daa08..bdb376edd 100644 --- a/relay/channel/claude/relay-claude.go +++ b/relay/channel/claude/relay-claude.go @@ -17,6 +17,7 @@ import ( "github.com/QuantumNous/new-api/relay/reasonmap" "github.com/QuantumNous/new-api/service" "github.com/QuantumNous/new-api/setting/model_setting" + "github.com/QuantumNous/new-api/setting/reasoning" "github.com/QuantumNous/new-api/types" "github.com/gin-gonic/gin" @@ -141,7 +142,16 @@ func RequestOpenAI2ClaudeMessage(c *gin.Context, textRequest dto.GeneralOpenAIRe claudeRequest.MaxTokens = uint(model_setting.GetClaudeSettings().GetDefaultMaxTokens(textRequest.Model)) } - if model_setting.GetClaudeSettings().ThinkingAdapterEnabled && + if baseModel, effortLevel, ok := reasoning.TrimEffortSuffix(textRequest.Model); ok && effortLevel != "" && + strings.HasPrefix(textRequest.Model, "claude-opus-4-6") { + claudeRequest.Model = baseModel + claudeRequest.Thinking = &dto.Thinking{ + Type: "adaptive", + } + claudeRequest.OutputConfig = json.RawMessage(fmt.Sprintf(`{"effort":"%s"}`, effortLevel)) + claudeRequest.TopP = 0 + claudeRequest.Temperature = common.GetPointer[float64](1.0) + } else if model_setting.GetClaudeSettings().ThinkingAdapterEnabled && strings.HasSuffix(textRequest.Model, "-thinking") { // 因为BudgetTokens 必须大于1024 diff --git a/relay/channel/vertex/dto.go b/relay/channel/vertex/dto.go index 68044ff32..2ddafa31b 100644 --- a/relay/channel/vertex/dto.go +++ b/relay/channel/vertex/dto.go @@ -1,6 +1,8 @@ package vertex import ( + "encoding/json" + "github.com/QuantumNous/new-api/dto" ) @@ -17,6 +19,7 @@ type VertexAIClaudeRequest struct { Tools any `json:"tools,omitempty"` ToolChoice any `json:"tool_choice,omitempty"` Thinking *dto.Thinking `json:"thinking,omitempty"` + OutputConfig json.RawMessage `json:"output_config,omitempty"` } func copyRequest(req *dto.ClaudeRequest, version string) *VertexAIClaudeRequest { @@ -33,5 +36,6 @@ func copyRequest(req *dto.ClaudeRequest, version string) *VertexAIClaudeRequest Tools: req.Tools, ToolChoice: req.ToolChoice, Thinking: req.Thinking, + OutputConfig: req.OutputConfig, } } diff --git a/relay/claude_handler.go b/relay/claude_handler.go index 7e05116da..fe63fcbd8 100644 --- a/relay/claude_handler.go +++ b/relay/claude_handler.go @@ -2,6 +2,7 @@ package relay import ( "bytes" + "encoding/json" "fmt" "io" "net/http" @@ -14,6 +15,7 @@ import ( "github.com/QuantumNous/new-api/relay/helper" "github.com/QuantumNous/new-api/service" "github.com/QuantumNous/new-api/setting/model_setting" + "github.com/QuantumNous/new-api/setting/reasoning" "github.com/QuantumNous/new-api/types" "github.com/gin-gonic/gin" @@ -49,7 +51,15 @@ func ClaudeHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *typ request.MaxTokens = uint(model_setting.GetClaudeSettings().GetDefaultMaxTokens(request.Model)) } - if model_setting.GetClaudeSettings().ThinkingAdapterEnabled && + if baseModel, effortLevel, ok := reasoning.TrimEffortSuffix(request.Model); ok && effortLevel != "" && + strings.HasPrefix(request.Model, "claude-opus-4-6") { + request.Model = baseModel + request.Thinking = &dto.Thinking{ + Type: "adaptive", + } + request.OutputConfig = json.RawMessage(fmt.Sprintf(`{"effort":"%s"}`, effortLevel)) + info.UpstreamModelName = request.Model + } else if model_setting.GetClaudeSettings().ThinkingAdapterEnabled && strings.HasSuffix(request.Model, "-thinking") { if request.Thinking == nil { // 因为BudgetTokens 必须大于1024 diff --git a/setting/ratio_setting/cache_ratio.go b/setting/ratio_setting/cache_ratio.go index ec85de11c..626267537 100644 --- a/setting/ratio_setting/cache_ratio.go +++ b/setting/ratio_setting/cache_ratio.go @@ -62,6 +62,10 @@ var defaultCacheRatio = map[string]float64{ "claude-opus-4-5-20251101-thinking": 0.1, "claude-opus-4-6": 0.1, "claude-opus-4-6-thinking": 0.1, + "claude-opus-4-6-max": 0.1, + "claude-opus-4-6-high": 0.1, + "claude-opus-4-6-medium": 0.1, + "claude-opus-4-6-low": 0.1, } var defaultCreateCacheRatio = map[string]float64{ @@ -86,6 +90,10 @@ var defaultCreateCacheRatio = map[string]float64{ "claude-opus-4-5-20251101-thinking": 1.25, "claude-opus-4-6": 1.25, "claude-opus-4-6-thinking": 1.25, + "claude-opus-4-6-max": 1.25, + "claude-opus-4-6-high": 1.25, + "claude-opus-4-6-medium": 1.25, + "claude-opus-4-6-low": 1.25, } //var defaultCreateCacheRatio = map[string]float64{} diff --git a/setting/ratio_setting/model_ratio.go b/setting/ratio_setting/model_ratio.go index e1a2b8ca0..6b7d70e77 100644 --- a/setting/ratio_setting/model_ratio.go +++ b/setting/ratio_setting/model_ratio.go @@ -143,6 +143,10 @@ var defaultModelRatio = map[string]float64{ "claude-sonnet-4-5-20250929": 1.5, "claude-opus-4-5-20251101": 2.5, "claude-opus-4-6": 2.5, + "claude-opus-4-6-max": 2.5, + "claude-opus-4-6-high": 2.5, + "claude-opus-4-6-medium": 2.5, + "claude-opus-4-6-low": 2.5, "claude-3-opus-20240229": 7.5, // $15 / 1M tokens "claude-opus-4-20250514": 7.5, "claude-opus-4-1-20250805": 7.5, diff --git a/setting/reasoning/suffix.go b/setting/reasoning/suffix.go index da3bdc7d3..fb66c6019 100644 --- a/setting/reasoning/suffix.go +++ b/setting/reasoning/suffix.go @@ -6,7 +6,7 @@ import ( "github.com/samber/lo" ) -var EffortSuffixes = []string{"-high", "-medium", "-low", "-minimal"} +var EffortSuffixes = []string{"-max", "-high", "-medium", "-low", "-minimal"} // TrimEffortSuffix -> modelName level(low) exists func TrimEffortSuffix(modelName string) (string, string, bool) {