Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
1e1a6aae
authored
Jun 15, 2025
by
RedwindA
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: implement thinking budget control in model name
parent
1c4819b2
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
69 additions
and
9 deletions
+69
-9
relay/channel/gemini/adaptor.go
+5
-2
relay/channel/gemini/relay-gemini.go
+42
-1
setting/operation_setting/model-ratio.go
+15
-3
web/src/i18n/locales/en.json
+3
-0
web/src/pages/Setting/Model/SettingGeminiModel.js
+4
-3
No files found.
relay/channel/gemini/adaptor.go
View file @
1e1a6aae
...
@@ -72,8 +72,11 @@ func (a *Adaptor) Init(info *relaycommon.RelayInfo) {
...
@@ -72,8 +72,11 @@ func (a *Adaptor) Init(info *relaycommon.RelayInfo) {
func
(
a
*
Adaptor
)
GetRequestURL
(
info
*
relaycommon
.
RelayInfo
)
(
string
,
error
)
{
func
(
a
*
Adaptor
)
GetRequestURL
(
info
*
relaycommon
.
RelayInfo
)
(
string
,
error
)
{
if
model_setting
.
GetGeminiSettings
()
.
ThinkingAdapterEnabled
{
if
model_setting
.
GetGeminiSettings
()
.
ThinkingAdapterEnabled
{
// suffix -thinking and -nothinking
// 新增逻辑:处理 -thinking-<budget> 格式
if
strings
.
HasSuffix
(
info
.
OriginModelName
,
"-thinking"
)
{
if
strings
.
Contains
(
info
.
OriginModelName
,
"-thinking-"
)
{
parts
:=
strings
.
Split
(
info
.
UpstreamModelName
,
"-thinking-"
)
info
.
UpstreamModelName
=
parts
[
0
]
}
else
if
strings
.
HasSuffix
(
info
.
OriginModelName
,
"-thinking"
)
{
// 旧的适配
info
.
UpstreamModelName
=
strings
.
TrimSuffix
(
info
.
UpstreamModelName
,
"-thinking"
)
info
.
UpstreamModelName
=
strings
.
TrimSuffix
(
info
.
UpstreamModelName
,
"-thinking"
)
}
else
if
strings
.
HasSuffix
(
info
.
OriginModelName
,
"-nothinking"
)
{
}
else
if
strings
.
HasSuffix
(
info
.
OriginModelName
,
"-nothinking"
)
{
info
.
UpstreamModelName
=
strings
.
TrimSuffix
(
info
.
UpstreamModelName
,
"-nothinking"
)
info
.
UpstreamModelName
=
strings
.
TrimSuffix
(
info
.
UpstreamModelName
,
"-nothinking"
)
...
...
relay/channel/gemini/relay-gemini.go
View file @
1e1a6aae
...
@@ -12,6 +12,7 @@ import (
...
@@ -12,6 +12,7 @@ import (
"one-api/relay/helper"
"one-api/relay/helper"
"one-api/service"
"one-api/service"
"one-api/setting/model_setting"
"one-api/setting/model_setting"
"strconv"
"strings"
"strings"
"unicode/utf8"
"unicode/utf8"
...
@@ -36,6 +37,13 @@ var geminiSupportedMimeTypes = map[string]bool{
...
@@ -36,6 +37,13 @@ var geminiSupportedMimeTypes = map[string]bool{
"video/flv"
:
true
,
"video/flv"
:
true
,
}
}
// Gemini 允许的思考预算范围
const
(
pro25MinBudget
=
128
pro25MaxBudget
=
32768
flash25MaxBudget
=
24576
)
// Setting safety to the lowest possible values since Gemini is already powerless enough
// Setting safety to the lowest possible values since Gemini is already powerless enough
func
CovertGemini2OpenAI
(
textRequest
dto
.
GeneralOpenAIRequest
,
info
*
relaycommon
.
RelayInfo
)
(
*
GeminiChatRequest
,
error
)
{
func
CovertGemini2OpenAI
(
textRequest
dto
.
GeneralOpenAIRequest
,
info
*
relaycommon
.
RelayInfo
)
(
*
GeminiChatRequest
,
error
)
{
...
@@ -57,7 +65,40 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest, info *relaycommon
...
@@ -57,7 +65,40 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest, info *relaycommon
}
}
if
model_setting
.
GetGeminiSettings
()
.
ThinkingAdapterEnabled
{
if
model_setting
.
GetGeminiSettings
()
.
ThinkingAdapterEnabled
{
if
strings
.
HasSuffix
(
info
.
OriginModelName
,
"-thinking"
)
{
// 新增逻辑:处理 -thinking-<budget> 格式
if
strings
.
Contains
(
info
.
OriginModelName
,
"-thinking-"
)
{
parts
:=
strings
.
SplitN
(
info
.
OriginModelName
,
"-thinking-"
,
2
)
if
len
(
parts
)
==
2
&&
parts
[
1
]
!=
""
{
if
budgetTokens
,
err
:=
strconv
.
Atoi
(
parts
[
1
]);
err
==
nil
{
// 从模型名称成功解析预算
isNew25Pro
:=
strings
.
HasPrefix
(
info
.
OriginModelName
,
"gemini-2.5-pro"
)
&&
!
strings
.
HasPrefix
(
info
.
OriginModelName
,
"gemini-2.5-pro-preview-05-06"
)
&&
!
strings
.
HasPrefix
(
info
.
OriginModelName
,
"gemini-2.5-pro-preview-03-25"
)
if
isNew25Pro
{
// 新的2.5pro模型:ThinkingBudget范围为128-32768
if
budgetTokens
<
pro25MinBudget
{
budgetTokens
=
pro25MinBudget
}
else
if
budgetTokens
>
pro25MaxBudget
{
budgetTokens
=
pro25MaxBudget
}
}
else
{
// 其他模型:ThinkingBudget范围为0-24576
if
budgetTokens
<
0
{
budgetTokens
=
0
}
else
if
budgetTokens
>
flash25MaxBudget
{
budgetTokens
=
flash25MaxBudget
}
}
geminiRequest
.
GenerationConfig
.
ThinkingConfig
=
&
GeminiThinkingConfig
{
ThinkingBudget
:
common
.
GetPointer
(
budgetTokens
),
IncludeThoughts
:
true
,
}
}
// 如果解析失败,则不设置ThinkingConfig,静默处理
}
}
else
if
strings
.
HasSuffix
(
info
.
OriginModelName
,
"-thinking"
)
{
// 保留旧逻辑以兼容
// 硬编码不支持 ThinkingBudget 的旧模型
// 硬编码不支持 ThinkingBudget 的旧模型
unsupportedModels
:=
[]
string
{
unsupportedModels
:=
[]
string
{
"gemini-2.5-pro-preview-05-06"
,
"gemini-2.5-pro-preview-05-06"
,
...
...
setting/operation_setting/model-ratio.go
View file @
1e1a6aae
...
@@ -142,6 +142,11 @@ var defaultModelRatio = map[string]float64{
...
@@ -142,6 +142,11 @@ var defaultModelRatio = map[string]float64{
"gemini-2.5-flash-preview-04-17"
:
0.075
,
"gemini-2.5-flash-preview-04-17"
:
0.075
,
"gemini-2.5-flash-preview-04-17-thinking"
:
0.075
,
"gemini-2.5-flash-preview-04-17-thinking"
:
0.075
,
"gemini-2.5-flash-preview-04-17-nothinking"
:
0.075
,
"gemini-2.5-flash-preview-04-17-nothinking"
:
0.075
,
"gemini-2.5-flash-preview-05-20"
:
0.075
,
"gemini-2.5-flash-preview-05-20-thinking"
:
0.075
,
"gemini-2.5-flash-preview-05-20-nothinking"
:
0.075
,
"gemini-2.5-flash-thinking-*"
:
0.075
,
// 用于为后续所有2.5 flash thinking budget 模型设置默认倍率
"gemini-2.5-pro-thinking-*"
:
0.625
,
// 用于为后续所有2.5 pro thinking budget 模型设置默认倍率
"text-embedding-004"
:
0.001
,
"text-embedding-004"
:
0.001
,
"chatglm_turbo"
:
0.3572
,
// ¥0.005 / 1k tokens
"chatglm_turbo"
:
0.3572
,
// ¥0.005 / 1k tokens
"chatglm_pro"
:
0.7143
,
// ¥0.01 / 1k tokens
"chatglm_pro"
:
0.7143
,
// ¥0.01 / 1k tokens
...
@@ -345,7 +350,14 @@ func UpdateModelRatioByJSONString(jsonStr string) error {
...
@@ -345,7 +350,14 @@ func UpdateModelRatioByJSONString(jsonStr string) error {
func
GetModelRatio
(
name
string
)
(
float64
,
bool
)
{
func
GetModelRatio
(
name
string
)
(
float64
,
bool
)
{
modelRatioMapMutex
.
RLock
()
modelRatioMapMutex
.
RLock
()
defer
modelRatioMapMutex
.
RUnlock
()
defer
modelRatioMapMutex
.
RUnlock
()
// 处理带有思考预算的模型名称,方便统一定价
handleThinkingBudgetModel
:=
func
(
prefix
,
wildcard
string
)
{
if
strings
.
HasPrefix
(
name
,
prefix
)
&&
strings
.
Contains
(
name
,
"-thinking-"
)
{
name
=
wildcard
}
}
handleThinkingBudgetModel
(
"gemini-2.5-flash"
,
"gemini-2.5-flash-thinking-*"
)
handleThinkingBudgetModel
(
"gemini-2.5-pro"
,
"gemini-2.5-pro-thinking-*"
)
if
strings
.
HasPrefix
(
name
,
"gpt-4-gizmo"
)
{
if
strings
.
HasPrefix
(
name
,
"gpt-4-gizmo"
)
{
name
=
"gpt-4-gizmo-*"
name
=
"gpt-4-gizmo-*"
}
}
...
@@ -470,9 +482,9 @@ func getHardcodedCompletionModelRatio(name string) (float64, bool) {
...
@@ -470,9 +482,9 @@ func getHardcodedCompletionModelRatio(name string) (float64, bool) {
return
4
,
true
return
4
,
true
}
else
if
strings
.
HasPrefix
(
name
,
"gemini-2.0"
)
{
}
else
if
strings
.
HasPrefix
(
name
,
"gemini-2.0"
)
{
return
4
,
true
return
4
,
true
}
else
if
strings
.
HasPrefix
(
name
,
"gemini-2.5-pro
-preview"
)
{
}
else
if
strings
.
HasPrefix
(
name
,
"gemini-2.5-pro
"
)
{
// 移除preview来增加兼容性,这里假设正式版的倍率和preview一致
return
8
,
true
return
8
,
true
}
else
if
strings
.
HasPrefix
(
name
,
"gemini-2.5-flash
-preview"
)
{
}
else
if
strings
.
HasPrefix
(
name
,
"gemini-2.5-flash
"
)
{
// 同上
if
strings
.
HasSuffix
(
name
,
"-nothinking"
)
{
if
strings
.
HasSuffix
(
name
,
"-nothinking"
)
{
return
4
,
false
return
4
,
false
}
else
{
}
else
{
...
...
web/src/i18n/locales/en.json
View file @
1e1a6aae
...
@@ -1373,6 +1373,9 @@
...
@@ -1373,6 +1373,9 @@
"示例"
:
"Example"
,
"示例"
:
"Example"
,
"缺省 MaxTokens"
:
"Default MaxTokens"
,
"缺省 MaxTokens"
:
"Default MaxTokens"
,
"启用Claude思考适配(-thinking后缀)"
:
"Enable Claude thinking adaptation (-thinking suffix)"
,
"启用Claude思考适配(-thinking后缀)"
:
"Enable Claude thinking adaptation (-thinking suffix)"
,
"启用Gemini思考后缀适配"
:
"Enable Gemini thinking suffix adaptation"
,
"适配-thinking、-thinking-预算数字和-nothinking后缀"
:
"Adapt -thinking, -thinking-budgetNumber, and -nothinking suffixes"
,
"思考预算占比"
:
"Thinking budget ratio"
,
"Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比"
:
"Claude thinking adaptation BudgetTokens = MaxTokens * BudgetTokens percentage"
,
"Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比"
:
"Claude thinking adaptation BudgetTokens = MaxTokens * BudgetTokens percentage"
,
"思考适配 BudgetTokens 百分比"
:
"Thinking adaptation BudgetTokens percentage"
,
"思考适配 BudgetTokens 百分比"
:
"Thinking adaptation BudgetTokens percentage"
,
"0.1-1之间的小数"
:
"Decimal between 0.1 and 1"
,
"0.1-1之间的小数"
:
"Decimal between 0.1 and 1"
,
...
...
web/src/pages/Setting/Model/SettingGeminiModel.js
View file @
1e1a6aae
...
@@ -173,7 +173,8 @@ export default function SettingGeminiModel(props) {
...
@@ -173,7 +173,8 @@ export default function SettingGeminiModel(props) {
<
Text
>
<
Text
>
{
t
(
{
t
(
"和Claude不同,默认情况下Gemini的思考模型会自动决定要不要思考,就算不开启适配模型也可以正常使用,"
+
"和Claude不同,默认情况下Gemini的思考模型会自动决定要不要思考,就算不开启适配模型也可以正常使用,"
+
"如果您需要计费,推荐设置无后缀模型价格按思考价格设置"
"如果您需要计费,推荐设置无后缀模型价格按思考价格设置。"
+
"支持使用 gemini-2.5-pro-preview-06-05-thinking-128 格式来精确传递思考预算。"
)}
)}
<
/Text
>
<
/Text
>
<
/Col
>
<
/Col
>
...
@@ -183,7 +184,7 @@ export default function SettingGeminiModel(props) {
...
@@ -183,7 +184,7 @@ export default function SettingGeminiModel(props) {
<
Form
.
Switch
<
Form
.
Switch
label
=
{
t
(
'启用Gemini思考后缀适配'
)}
label
=
{
t
(
'启用Gemini思考后缀适配'
)}
field
=
{
'gemini.thinking_adapter_enabled'
}
field
=
{
'gemini.thinking_adapter_enabled'
}
extraText
=
{
"适配-thinking和-nothinking后缀"
}
extraText
=
{
t
(
'适配 -thinking、-thinking-预算数字 和 -nothinking 后缀'
)
}
onChange
=
{(
value
)
=>
onChange
=
{(
value
)
=>
setInputs
({
setInputs
({
...
inputs
,
...
inputs
,
...
@@ -205,7 +206,7 @@ export default function SettingGeminiModel(props) {
...
@@ -205,7 +206,7 @@ export default function SettingGeminiModel(props) {
<
Row
>
<
Row
>
<
Col
xs
=
{
24
}
sm
=
{
12
}
md
=
{
8
}
lg
=
{
8
}
xl
=
{
8
}
>
<
Col
xs
=
{
24
}
sm
=
{
12
}
md
=
{
8
}
lg
=
{
8
}
xl
=
{
8
}
>
<
Form
.
InputNumber
<
Form
.
InputNumber
label
=
{
t
(
'
请求模型带-thinking后缀的BudgetTokens数(超出24576的部分将被忽略)
'
)}
label
=
{
t
(
'
思考预算占比
'
)}
field
=
{
'gemini.thinking_adapter_budget_tokens_percentage'
}
field
=
{
'gemini.thinking_adapter_budget_tokens_percentage'
}
initValue
=
{
''
}
initValue
=
{
''
}
extraText
=
{
t
(
'0.1-1之间的小数'
)}
extraText
=
{
t
(
'0.1-1之间的小数'
)}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment