Explorar o código

Merge pull request #3120 from nekohy/main

feats: repair the thinking of claude to openrouter convert
Seefs hai 2 meses
pai
achega
cd1d43ae47
Modificáronse 4 ficheiros con 38 adicións e 10 borrados
  1. 14 0
      dto/claude.go
  2. 1 0
      relay/channel/openai/adaptor.go
  3. 1 0
      relay/channel/openrouter/dto.go
  4. 22 10
      service/convert.go

+ 14 - 0
dto/claude.go

@@ -218,6 +218,11 @@ type ClaudeRequest struct {
 	ServiceTier string `json:"service_tier,omitempty"`
 }
 
+// OutputConfigForEffort just for extract effort
+type OutputConfigForEffort struct {
+	Effort string `json:"effort,omitempty"`
+}
+
 // createClaudeFileSource 根据数据内容创建正确类型的 FileSource
 func createClaudeFileSource(data string) *types.FileSource {
 	if strings.HasPrefix(data, "http://") || strings.HasPrefix(data, "https://") {
@@ -409,6 +414,15 @@ func (c *ClaudeRequest) GetTools() []any {
 	}
 }
 
+func (c *ClaudeRequest) GetEfforts() string {
+	var OutputConfig OutputConfigForEffort
+	if err := json.Unmarshal(c.OutputConfig, &OutputConfig); err == nil {
+		effort := OutputConfig.Effort
+		return effort
+	}
+	return ""
+}
+
 // ProcessTools 处理工具列表,支持类型断言
 func ProcessTools(tools []any) ([]*Tool, []*ClaudeWebSearchTool) {
 	var normalTools []*Tool

+ 1 - 0
relay/channel/openai/adaptor.go

@@ -298,6 +298,7 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
 				}
 
 				reasoning := openrouter.RequestReasoning{
+					Enabled:   true,
 					MaxTokens: *thinking.BudgetTokens,
 				}
 

+ 1 - 0
relay/channel/openrouter/dto.go

@@ -3,6 +3,7 @@ package openrouter
 import "encoding/json"
 
 type RequestReasoning struct {
+	Enabled bool `json:"enabled"`
 	// One of the following (not both):
 	Effort    string `json:"effort,omitempty"`     // Can be "high", "medium", or "low" (OpenAI-style)
 	MaxTokens int    `json:"max_tokens,omitempty"` // Specific token limit (Anthropic-style)

+ 22 - 10
service/convert.go

@@ -34,22 +34,34 @@ func ClaudeToOpenAIRequest(claudeRequest dto.ClaudeRequest, info *relaycommon.Re
 
 	isOpenRouter := info.ChannelType == constant.ChannelTypeOpenRouter
 
-	if claudeRequest.Thinking != nil && claudeRequest.Thinking.Type == "enabled" {
-		if isOpenRouter {
-			reasoning := openrouter.RequestReasoning{
-				MaxTokens: claudeRequest.Thinking.GetBudgetTokens(),
+	if isOpenRouter {
+		if effort := claudeRequest.GetEfforts(); effort != "" {
+			effortBytes, _ := json.Marshal(effort)
+			openAIRequest.Verbosity = effortBytes
+		}
+		if claudeRequest.Thinking != nil {
+			var reasoning openrouter.RequestReasoning
+			if claudeRequest.Thinking.Type == "enabled" {
+				reasoning = openrouter.RequestReasoning{
+					Enabled:   true,
+					MaxTokens: claudeRequest.Thinking.GetBudgetTokens(),
+				}
+			} else if claudeRequest.Thinking.Type == "adaptive" {
+				reasoning = openrouter.RequestReasoning{
+					Enabled: true,
+				}
 			}
 			reasoningJSON, err := json.Marshal(reasoning)
 			if err != nil {
 				return nil, fmt.Errorf("failed to marshal reasoning: %w", err)
 			}
 			openAIRequest.Reasoning = reasoningJSON
-		} else {
-			thinkingSuffix := "-thinking"
-			if strings.HasSuffix(info.OriginModelName, thinkingSuffix) &&
-				!strings.HasSuffix(openAIRequest.Model, thinkingSuffix) {
-				openAIRequest.Model = openAIRequest.Model + thinkingSuffix
-			}
+		}
+	} else {
+		thinkingSuffix := "-thinking"
+		if strings.HasSuffix(info.OriginModelName, thinkingSuffix) &&
+			!strings.HasSuffix(openAIRequest.Model, thinkingSuffix) {
+			openAIRequest.Model = openAIRequest.Model + thinkingSuffix
 		}
 	}