mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
feat(gemini): prefer official reasoning fields, add extra_body(cherry studio) fallback
This commit is contained in:
@@ -33,8 +33,10 @@ func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bo
|
|||||||
out, _ = sjson.SetBytes(out, "model", modelName)
|
out, _ = sjson.SetBytes(out, "model", modelName)
|
||||||
|
|
||||||
// Reasoning effort -> thinkingBudget/include_thoughts
|
// Reasoning effort -> thinkingBudget/include_thoughts
|
||||||
|
// Note: OpenAI official fields take precedence over extra_body.google.thinking_config
|
||||||
re := gjson.GetBytes(rawJSON, "reasoning_effort")
|
re := gjson.GetBytes(rawJSON, "reasoning_effort")
|
||||||
if re.Exists() && util.ModelSupportsThinking(modelName) {
|
hasOfficialThinking := re.Exists()
|
||||||
|
if hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
||||||
switch re.String() {
|
switch re.String() {
|
||||||
case "none":
|
case "none":
|
||||||
out, _ = sjson.DeleteBytes(out, "request.generationConfig.thinkingConfig.include_thoughts")
|
out, _ = sjson.DeleteBytes(out, "request.generationConfig.thinkingConfig.include_thoughts")
|
||||||
@@ -52,6 +54,19 @@ func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cherry Studio extension extra_body.google.thinking_config (effective only when official fields are absent)
|
||||||
|
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
||||||
|
if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
||||||
|
if v := tc.Get("thinking_budget"); v.Exists() {
|
||||||
|
budget := util.NormalizeThinkingBudget(modelName, int(v.Int()))
|
||||||
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
|
}
|
||||||
|
if v := tc.Get("include_thoughts"); v.Exists() {
|
||||||
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Temperature/top_p/top_k
|
// Temperature/top_p/top_k
|
||||||
if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number {
|
if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number {
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.temperature", tr.Num)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.temperature", tr.Num)
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool)
|
|||||||
out, _ = sjson.SetBytes(out, "model", modelName)
|
out, _ = sjson.SetBytes(out, "model", modelName)
|
||||||
|
|
||||||
// Reasoning effort -> thinkingBudget/include_thoughts
|
// Reasoning effort -> thinkingBudget/include_thoughts
|
||||||
|
// Note: OpenAI official fields take precedence over extra_body.google.thinking_config
|
||||||
re := gjson.GetBytes(rawJSON, "reasoning_effort")
|
re := gjson.GetBytes(rawJSON, "reasoning_effort")
|
||||||
if re.Exists() && util.ModelSupportsThinking(modelName) {
|
hasOfficialThinking := re.Exists()
|
||||||
|
if hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
||||||
switch re.String() {
|
switch re.String() {
|
||||||
case "none":
|
case "none":
|
||||||
out, _ = sjson.DeleteBytes(out, "generationConfig.thinkingConfig.include_thoughts")
|
out, _ = sjson.DeleteBytes(out, "generationConfig.thinkingConfig.include_thoughts")
|
||||||
@@ -52,6 +54,20 @@ func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cherry Studio extension extra_body.google.thinking_config (effective only when official fields are absent)
|
||||||
|
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
||||||
|
if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
||||||
|
if v := tc.Get("thinking_budget"); v.Exists() {
|
||||||
|
// Normalize budget to model range
|
||||||
|
budget := util.NormalizeThinkingBudget(modelName, int(v.Int()))
|
||||||
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
|
}
|
||||||
|
if v := tc.Get("include_thoughts"); v.Exists() {
|
||||||
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Temperature/top_p/top_k
|
// Temperature/top_p/top_k
|
||||||
if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number {
|
if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number {
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.temperature", tr.Num)
|
out, _ = sjson.SetBytes(out, "generationConfig.temperature", tr.Num)
|
||||||
|
|||||||
@@ -243,7 +243,10 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte
|
|||||||
out, _ = sjson.Set(out, "generationConfig.stopSequences", sequences)
|
out, _ = sjson.Set(out, "generationConfig.stopSequences", sequences)
|
||||||
}
|
}
|
||||||
|
|
||||||
if reasoningEffort := root.Get("reasoning.effort"); reasoningEffort.Exists() && util.ModelSupportsThinking(modelName) {
|
// OpenAI official reasoning fields take precedence
|
||||||
|
hasOfficialThinking := root.Get("reasoning.effort").Exists()
|
||||||
|
if hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
||||||
|
reasoningEffort := root.Get("reasoning.effort")
|
||||||
switch reasoningEffort.String() {
|
switch reasoningEffort.String() {
|
||||||
case "none":
|
case "none":
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", false)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", false)
|
||||||
@@ -262,5 +265,18 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte
|
|||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cherry Studio extension (applies only when official fields are missing)
|
||||||
|
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
||||||
|
if tc := root.Get("extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
||||||
|
if v := tc.Get("thinking_budget"); v.Exists() {
|
||||||
|
budget := util.NormalizeThinkingBudget(modelName, int(v.Int()))
|
||||||
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
|
}
|
||||||
|
if v := tc.Get("include_thoughts"); v.Exists() {
|
||||||
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return []byte(out)
|
return []byte(out)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user