From fef7ae048ba08cce8e8d4cbd4c07f589930e26d6 Mon Sep 17 00:00:00 2001 From: "Laisky.Cai" Date: Wed, 12 Feb 2025 00:34:25 +0800 Subject: [PATCH] feat: support gemini-2.0-flash (#2055) * feat: support gemini-2.0-flash - Enhance model support by adding new entries and refining checks for system instruction compatibility. - Update logging display behavior and adjust default quotas for better user experience. - Revamp pricing structures in the billing system to reflect current model values and deprecate outdated entries. - Streamline code by replacing hardcoded values with configurations for maintainability. * feat: add new Gemini 2.0 flash models to adapter and billing ratio * fix: update GetRequestURL to support gemini-1.5 model in versioning --- relay/adaptor/gemini/adaptor.go | 14 ++++----- relay/adaptor/gemini/constants.go | 36 ++++++++++++++++++++++-- relay/adaptor/gemini/main.go | 9 +++++- relay/adaptor/gemini/model.go | 9 +++--- relay/adaptor/vertexai/gemini/adapter.go | 10 ++++--- relay/billing/ratio/model.go | 27 ++++++++++++------ web/default/src/helpers/utils.js | 2 +- 7 files changed, 76 insertions(+), 31 deletions(-) diff --git a/relay/adaptor/gemini/adaptor.go b/relay/adaptor/gemini/adaptor.go index e6e4d051..84083f60 100644 --- a/relay/adaptor/gemini/adaptor.go +++ b/relay/adaptor/gemini/adaptor.go @@ -5,9 +5,10 @@ import ( "fmt" "io" "net/http" + "strings" "github.com/gin-gonic/gin" - + "github.com/songquanpeng/one-api/common/config" "github.com/songquanpeng/one-api/common/helper" channelhelper "github.com/songquanpeng/one-api/relay/adaptor" "github.com/songquanpeng/one-api/relay/adaptor/openai" @@ -20,17 +21,12 @@ type Adaptor struct { } func (a *Adaptor) Init(meta *meta.Meta) { - } func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) { - var defaultVersion string - switch meta.ActualModelName { - case "gemini-2.0-flash-exp", - "gemini-2.0-flash-thinking-exp", - "gemini-2.0-flash-thinking-exp-01-21": - defaultVersion = "v1beta" - default: + defaultVersion := config.GeminiVersion + if strings.Contains(meta.ActualModelName, "gemini-2.0") || + strings.Contains(meta.ActualModelName, "gemini-1.5") { defaultVersion = "v1beta" } diff --git a/relay/adaptor/gemini/constants.go b/relay/adaptor/gemini/constants.go index 381d0c12..cbc2c82c 100644 --- a/relay/adaptor/gemini/constants.go +++ b/relay/adaptor/gemini/constants.go @@ -4,8 +4,38 @@ package gemini var ModelList = []string{ "gemini-pro", "gemini-1.0-pro", - "gemini-1.5-flash", "gemini-1.5-pro", + // "gemma-2-2b-it", "gemma-2-9b-it", "gemma-2-27b-it", + "gemini-1.5-flash", "gemini-1.5-flash-8b", + "gemini-1.5-pro", "gemini-1.5-pro-experimental", "text-embedding-004", "aqa", - "gemini-2.0-flash-exp", - "gemini-2.0-flash-thinking-exp", "gemini-2.0-flash-thinking-exp-01-21", + "gemini-2.0-flash", "gemini-2.0-flash-exp", + "gemini-2.0-flash-lite-preview-02-05", + "gemini-2.0-flash-thinking-exp-01-21", + "gemini-2.0-pro-exp-02-05", +} + +// ModelsSupportSystemInstruction is the list of models that support system instruction. +// +// https://cloud.google.com/vertex-ai/generative-ai/docs/learn/prompts/system-instructions +var ModelsSupportSystemInstruction = []string{ + // "gemini-1.0-pro-002", + // "gemini-1.5-flash", "gemini-1.5-flash-001", "gemini-1.5-flash-002", + // "gemini-1.5-flash-8b", + // "gemini-1.5-pro", "gemini-1.5-pro-001", "gemini-1.5-pro-002", + // "gemini-1.5-pro-experimental", + "gemini-2.0-flash", "gemini-2.0-flash-exp", + "gemini-2.0-flash-thinking-exp-01-21", +} + +// IsModelSupportSystemInstruction check if the model support system instruction. +// +// Because the main version of Go is 1.20, slice.Contains cannot be used +func IsModelSupportSystemInstruction(model string) bool { + for _, m := range ModelsSupportSystemInstruction { + if m == model { + return true + } + } + + return false } diff --git a/relay/adaptor/gemini/main.go b/relay/adaptor/gemini/main.go index 3aa4974b..29637296 100644 --- a/relay/adaptor/gemini/main.go +++ b/relay/adaptor/gemini/main.go @@ -132,9 +132,16 @@ func ConvertRequest(textRequest model.GeneralOpenAIRequest) *ChatRequest { } // Converting system prompt to prompt from user for the same reason if content.Role == "system" { - content.Role = "user" shouldAddDummyModelMessage = true + if IsModelSupportSystemInstruction(textRequest.Model) { + geminiRequest.SystemInstruction = &content + geminiRequest.SystemInstruction.Role = "" + continue + } else { + content.Role = "user" + } } + geminiRequest.Contents = append(geminiRequest.Contents, content) // If a system message is the last message, we need to add a dummy model message to make gemini happy diff --git a/relay/adaptor/gemini/model.go b/relay/adaptor/gemini/model.go index 720cb65d..c3acae60 100644 --- a/relay/adaptor/gemini/model.go +++ b/relay/adaptor/gemini/model.go @@ -1,10 +1,11 @@ package gemini type ChatRequest struct { - Contents []ChatContent `json:"contents"` - SafetySettings []ChatSafetySettings `json:"safety_settings,omitempty"` - GenerationConfig ChatGenerationConfig `json:"generation_config,omitempty"` - Tools []ChatTools `json:"tools,omitempty"` + Contents []ChatContent `json:"contents"` + SafetySettings []ChatSafetySettings `json:"safety_settings,omitempty"` + GenerationConfig ChatGenerationConfig `json:"generation_config,omitempty"` + Tools []ChatTools `json:"tools,omitempty"` + SystemInstruction *ChatContent `json:"system_instruction,omitempty"` } type EmbeddingRequest struct { diff --git a/relay/adaptor/vertexai/gemini/adapter.go b/relay/adaptor/vertexai/gemini/adapter.go index 1240ea5b..f5b245d8 100644 --- a/relay/adaptor/vertexai/gemini/adapter.go +++ b/relay/adaptor/vertexai/gemini/adapter.go @@ -16,10 +16,12 @@ import ( var ModelList = []string{ "gemini-pro", "gemini-pro-vision", - "gemini-1.5-pro-001", "gemini-1.5-flash-001", - "gemini-1.5-pro-002", "gemini-1.5-flash-002", - "gemini-2.0-flash-exp", - "gemini-2.0-flash-thinking-exp", "gemini-2.0-flash-thinking-exp-01-21", + "gemini-exp-1206", + "gemini-1.5-pro-001", "gemini-1.5-pro-002", + "gemini-1.5-flash-001", "gemini-1.5-flash-002", + "gemini-2.0-flash-exp", "gemini-2.0-flash-001", + "gemini-2.0-flash-lite-preview-02-05", + "gemini-2.0-flash-thinking-exp-01-21", } type Adaptor struct { diff --git a/relay/billing/ratio/model.go b/relay/billing/ratio/model.go index a0d57e26..25e4629d 100644 --- a/relay/billing/ratio/model.go +++ b/relay/billing/ratio/model.go @@ -115,15 +115,24 @@ var ModelRatio = map[string]float64{ "bge-large-en": 0.002 * RMB, "tao-8k": 0.002 * RMB, // https://ai.google.dev/pricing - "gemini-pro": 1, // $0.00025 / 1k characters -> $0.001 / 1k tokens - "gemini-1.0-pro": 1, - "gemini-1.5-pro": 1, - "gemini-1.5-pro-001": 1, - "gemini-1.5-flash": 1, - "gemini-1.5-flash-001": 1, - "gemini-2.0-flash-exp": 1, - "gemini-2.0-flash-thinking-exp": 1, - "gemini-2.0-flash-thinking-exp-01-21": 1, + // https://cloud.google.com/vertex-ai/generative-ai/pricing + // "gemma-2-2b-it": 0, + // "gemma-2-9b-it": 0, + // "gemma-2-27b-it": 0, + "gemini-pro": 0.25 * MILLI_USD, // $0.00025 / 1k characters -> $0.001 / 1k tokens + "gemini-1.0-pro": 0.125 * MILLI_USD, + "gemini-1.5-pro": 1.25 * MILLI_USD, + "gemini-1.5-pro-001": 1.25 * MILLI_USD, + "gemini-1.5-pro-experimental": 1.25 * MILLI_USD, + "gemini-1.5-flash": 0.075 * MILLI_USD, + "gemini-1.5-flash-001": 0.075 * MILLI_USD, + "gemini-1.5-flash-8b": 0.0375 * MILLI_USD, + "gemini-2.0-flash-exp": 0.075 * MILLI_USD, + "gemini-2.0-flash": 0.15 * MILLI_USD, + "gemini-2.0-flash-001": 0.15 * MILLI_USD, + "gemini-2.0-flash-lite-preview-02-05": 0.075 * MILLI_USD, + "gemini-2.0-flash-thinking-exp-01-21": 0.075 * MILLI_USD, + "gemini-2.0-pro-exp-02-05": 1.25 * MILLI_USD, "aqa": 1, // https://open.bigmodel.cn/pricing "glm-zero-preview": 0.01 * RMB, diff --git a/web/default/src/helpers/utils.js b/web/default/src/helpers/utils.js index eb935843..0b995409 100644 --- a/web/default/src/helpers/utils.js +++ b/web/default/src/helpers/utils.js @@ -224,4 +224,4 @@ export function getChannelModels(type) { return channelModels[type]; } return []; -} \ No newline at end of file +}