|
|
@@ -12,6 +12,7 @@ import (
|
|
|
"one-api/relay/helper"
|
|
|
"one-api/service"
|
|
|
"one-api/setting/model_setting"
|
|
|
+ "strconv"
|
|
|
"strings"
|
|
|
"unicode/utf8"
|
|
|
|
|
|
@@ -36,6 +37,13 @@ var geminiSupportedMimeTypes = map[string]bool{
|
|
|
"video/flv": true,
|
|
|
}
|
|
|
|
|
|
+// Gemini 允许的思考预算范围
|
|
|
+const (
|
|
|
+ pro25MinBudget = 128
|
|
|
+ pro25MaxBudget = 32768
|
|
|
+ flash25MaxBudget = 24576
|
|
|
+)
|
|
|
+
|
|
|
// Setting safety to the lowest possible values since Gemini is already powerless enough
|
|
|
func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest, info *relaycommon.RelayInfo) (*GeminiChatRequest, error) {
|
|
|
|
|
|
@@ -57,7 +65,40 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest, info *relaycommon
|
|
|
}
|
|
|
|
|
|
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 的旧模型
|
|
|
unsupportedModels := []string{
|
|
|
"gemini-2.5-pro-preview-05-06",
|
|
|
@@ -611,9 +652,9 @@ func getResponseToolCall(item *GeminiPart) *dto.ToolCallResponse {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func responseGeminiChat2OpenAI(response *GeminiChatResponse) *dto.OpenAITextResponse {
|
|
|
+func responseGeminiChat2OpenAI(c *gin.Context, response *GeminiChatResponse) *dto.OpenAITextResponse {
|
|
|
fullTextResponse := dto.OpenAITextResponse{
|
|
|
- Id: fmt.Sprintf("chatcmpl-%s", common.GetUUID()),
|
|
|
+ Id: helper.GetResponseID(c),
|
|
|
Object: "chat.completion",
|
|
|
Created: common.GetTimestamp(),
|
|
|
Choices: make([]dto.OpenAITextResponseChoice, 0, len(response.Candidates)),
|
|
|
@@ -754,7 +795,7 @@ func streamResponseGeminiChat2OpenAI(geminiResponse *GeminiChatResponse) (*dto.C
|
|
|
|
|
|
func GeminiChatStreamHandler(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (*dto.OpenAIErrorWithStatusCode, *dto.Usage) {
|
|
|
// responseText := ""
|
|
|
- id := fmt.Sprintf("chatcmpl-%s", common.GetUUID())
|
|
|
+ id := helper.GetResponseID(c)
|
|
|
createAt := common.GetTimestamp()
|
|
|
var usage = &dto.Usage{}
|
|
|
var imageCount int
|
|
|
@@ -849,7 +890,7 @@ func GeminiChatHandler(c *gin.Context, resp *http.Response, info *relaycommon.Re
|
|
|
StatusCode: resp.StatusCode,
|
|
|
}, nil
|
|
|
}
|
|
|
- fullTextResponse := responseGeminiChat2OpenAI(&geminiResponse)
|
|
|
+ fullTextResponse := responseGeminiChat2OpenAI(c, &geminiResponse)
|
|
|
fullTextResponse.Model = info.UpstreamModelName
|
|
|
usage := dto.Usage{
|
|
|
PromptTokens: geminiResponse.UsageMetadata.PromptTokenCount,
|