mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-21 05:40:51 +08:00
fix: clamp reasoning_effort to valid OpenAI-format values
CPA-internal thinking levels like 'xhigh' and 'minimal' are not accepted by OpenAI-format providers (MiniMax, etc.). The OpenAI applier now maps non-standard levels to the nearest valid reasoning_effort value before writing to the request body: xhigh → high minimal → low auto → medium
This commit is contained in:
@@ -10,10 +10,53 @@ import (
|
|||||||
|
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/registry"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/registry"
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/thinking"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/thinking"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"github.com/tidwall/sjson"
|
"github.com/tidwall/sjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// validReasoningEffortLevels contains the standard values accepted by the
|
||||||
|
// OpenAI reasoning_effort field. Provider-specific extensions (xhigh, minimal,
|
||||||
|
// auto) are NOT in this set and must be clamped before use.
|
||||||
|
var validReasoningEffortLevels = map[string]struct{}{
|
||||||
|
"none": {},
|
||||||
|
"low": {},
|
||||||
|
"medium": {},
|
||||||
|
"high": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// clampReasoningEffort maps any thinking level string to a value that is safe
|
||||||
|
// to send as OpenAI reasoning_effort. Non-standard CPA-internal values are
|
||||||
|
// mapped to the nearest standard equivalent.
|
||||||
|
//
|
||||||
|
// Mapping rules:
|
||||||
|
// - none / low / medium / high → returned as-is (already valid)
|
||||||
|
// - xhigh → "high" (nearest lower standard level)
|
||||||
|
// - minimal → "low" (nearest higher standard level)
|
||||||
|
// - auto → "medium" (reasonable default)
|
||||||
|
// - anything else → "medium" (safe default)
|
||||||
|
func clampReasoningEffort(level string) string {
|
||||||
|
if _, ok := validReasoningEffortLevels[level]; ok {
|
||||||
|
return level
|
||||||
|
}
|
||||||
|
var clamped string
|
||||||
|
switch level {
|
||||||
|
case string(thinking.LevelXHigh):
|
||||||
|
clamped = string(thinking.LevelHigh)
|
||||||
|
case string(thinking.LevelMinimal):
|
||||||
|
clamped = string(thinking.LevelLow)
|
||||||
|
case string(thinking.LevelAuto):
|
||||||
|
clamped = string(thinking.LevelMedium)
|
||||||
|
default:
|
||||||
|
clamped = string(thinking.LevelMedium)
|
||||||
|
}
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"original": level,
|
||||||
|
"clamped": clamped,
|
||||||
|
}).Debug("openai: reasoning_effort clamped to nearest valid standard value")
|
||||||
|
return clamped
|
||||||
|
}
|
||||||
|
|
||||||
// Applier implements thinking.ProviderApplier for OpenAI models.
|
// Applier implements thinking.ProviderApplier for OpenAI models.
|
||||||
//
|
//
|
||||||
// OpenAI-specific behavior:
|
// OpenAI-specific behavior:
|
||||||
@@ -58,7 +101,7 @@ func (a *Applier) Apply(body []byte, config thinking.ThinkingConfig, modelInfo *
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.Mode == thinking.ModeLevel {
|
if config.Mode == thinking.ModeLevel {
|
||||||
result, _ := sjson.SetBytes(body, "reasoning_effort", string(config.Level))
|
result, _ := sjson.SetBytes(body, "reasoning_effort", clampReasoningEffort(string(config.Level)))
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +122,7 @@ func (a *Applier) Apply(body []byte, config thinking.ThinkingConfig, modelInfo *
|
|||||||
return body, nil
|
return body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result, _ := sjson.SetBytes(body, "reasoning_effort", effort)
|
result, _ := sjson.SetBytes(body, "reasoning_effort", clampReasoningEffort(effort))
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +157,7 @@ func applyCompatibleOpenAI(body []byte, config thinking.ThinkingConfig) ([]byte,
|
|||||||
return body, nil
|
return body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result, _ := sjson.SetBytes(body, "reasoning_effort", effort)
|
result, _ := sjson.SetBytes(body, "reasoning_effort", clampReasoningEffort(effort))
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user