Просмотр исходного кода

feats: repair the thinking of claude to openrouter convert

Nekohy 2 месяцев назад
Родитель
Сommit
a4629f2630
4 измененных файлов с 37 добавлено и 7 удалено
  1. 14 0
      dto/claude.go
  2. 1 0
      relay/channel/openai/adaptor.go
  3. 1 0
      relay/channel/openrouter/dto.go
  4. 21 7
      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)

+ 21 - 7
service/convert.go

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