From 209a14c26ff78ac8a6bbe92014475b421710732a Mon Sep 17 00:00:00 2001 From: RandyZhang Date: Sat, 10 May 2025 15:09:05 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E5=A2=9E=E5=8A=A0vertex=20embedding?= =?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81=EF=BC=8C=E4=BF=AE=E6=94=B9vertex?= =?UTF-8?q?=E7=9A=84=E6=A8=A1=E5=9E=8Badapter=E5=8C=B9=E9=85=8D=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- relay/adaptor/gemini/main.go | 14 +++ relay/adaptor/vertexai/adaptor.go | 15 ++- relay/adaptor/vertexai/embedding/adapter.go | 107 ++++++++++++++++++++ relay/adaptor/vertexai/embedding/model.go | 45 ++++++++ relay/adaptor/vertexai/model/model.go | 13 +++ relay/adaptor/vertexai/registry.go | 41 ++++---- 6 files changed, 217 insertions(+), 18 deletions(-) create mode 100644 relay/adaptor/vertexai/embedding/adapter.go create mode 100644 relay/adaptor/vertexai/embedding/model.go create mode 100644 relay/adaptor/vertexai/model/model.go diff --git a/relay/adaptor/gemini/main.go b/relay/adaptor/gemini/main.go index 29637296..579ba30a 100644 --- a/relay/adaptor/gemini/main.go +++ b/relay/adaptor/gemini/main.go @@ -435,3 +435,17 @@ func EmbeddingHandler(c *gin.Context, resp *http.Response) (*model.ErrorWithStat _, err = c.Writer.Write(jsonResponse) return nil, &fullTextResponse.Usage } + +func EmbeddingResponseHandler(c *gin.Context, statusCode int, resp *openai.EmbeddingResponse) (*model.ErrorWithStatusCode, *model.Usage) { + jsonResponse, err := json.Marshal(resp) + if err != nil { + return openai.ErrorWrapper(err, "marshal_response_body_failed", http.StatusInternalServerError), nil + } + c.Writer.Header().Set("Content-Type", "application/json") + c.Writer.WriteHeader(statusCode) + _, err = c.Writer.Write(jsonResponse) + if err != nil { + return openai.ErrorWrapper(err, "write_response_body_failed", http.StatusInternalServerError), nil + } + return nil, &resp.Usage +} diff --git a/relay/adaptor/vertexai/adaptor.go b/relay/adaptor/vertexai/adaptor.go index 3fab4a45..afae18a1 100644 --- a/relay/adaptor/vertexai/adaptor.go +++ b/relay/adaptor/vertexai/adaptor.go @@ -61,12 +61,15 @@ func (a *Adaptor) GetChannelName() string { func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) { suffix := "" - if strings.HasPrefix(meta.ActualModelName, "gemini") { + modelType := PredictModelType(meta.ActualModelName) + if modelType == VertexAIGemini { if meta.IsStream { suffix = "streamGenerateContent?alt=sse" } else { suffix = "generateContent" } + } else if modelType == VertexAIEmbedding { + suffix = "predict" } else { if meta.IsStream { suffix = "streamRawPredict?alt=sse" @@ -115,3 +118,13 @@ func (a *Adaptor) ConvertImageRequest(request *model.ImageRequest) (any, error) func (a *Adaptor) DoRequest(c *gin.Context, meta *meta.Meta, requestBody io.Reader) (*http.Response, error) { return channelhelper.DoRequestHelper(a, c, meta, requestBody) } + +func PredictModelType(model string) VertexAIModelType { + if strings.HasPrefix(model, "gemini-") { + return VertexAIGemini + } + if strings.HasPrefix(model, "text-embedding") || strings.HasPrefix(model, "text-multilingual-embedding") { + return VertexAIEmbedding + } + return VertexAIClaude +} diff --git a/relay/adaptor/vertexai/embedding/adapter.go b/relay/adaptor/vertexai/embedding/adapter.go new file mode 100644 index 00000000..17004928 --- /dev/null +++ b/relay/adaptor/vertexai/embedding/adapter.go @@ -0,0 +1,107 @@ +package vertexai + +import ( + "encoding/json" + "io" + "net/http" + "strings" + + "github.com/songquanpeng/one-api/relay/adaptor/gemini" + "github.com/songquanpeng/one-api/relay/adaptor/openai" + model2 "github.com/songquanpeng/one-api/relay/adaptor/vertexai/model" + + "github.com/gin-gonic/gin" + "github.com/pkg/errors" + + "github.com/songquanpeng/one-api/relay/meta" + "github.com/songquanpeng/one-api/relay/model" +) + +var ModelList = []string{ + "textembedding-gecko-multilingual@001", "text-multilingual-embedding-002", +} + +type Adaptor struct { + model string + task EmbeddingTaskType +} + +var _ model2.InnerAIAdapter = (*Adaptor)(nil) + +func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, request *model.GeneralOpenAIRequest) (any, error) { + if request == nil { + return nil, errors.New("request is nil") + } + inputs := request.ParseInput() + if len(inputs) == 0 { + return nil, errors.New("request is nil") + } + parts := strings.Split(request.Model, "|") + if len(parts) >= 2 { + a.task = EmbeddingTaskType(parts[1]) + } else { + a.task = EmbeddingTaskTypeSemanticSimilarity + } + a.model = parts[0] + instances := make([]EmbeddingInstance, len(inputs)) + for i, input := range inputs { + instances[i] = EmbeddingInstance{ + Content: input, + TaskType: a.task, + } + } + + embeddingRequest := EmbeddingRequest{ + Instances: instances, + Parameters: EmbeddingParams{ + OutputDimensionality: request.Dimensions, + }, + } + + return embeddingRequest, nil +} + +func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta *meta.Meta) (usage *model.Usage, err *model.ErrorWithStatusCode) { + err, usage = EmbeddingHandler(c, a.model, resp) + return +} + +func EmbeddingHandler(c *gin.Context, modelName string, resp *http.Response) (*model.ErrorWithStatusCode, *model.Usage) { + var vertexEmbeddingResponse EmbeddingResponse + responseBody, err := io.ReadAll(resp.Body) + if resp.StatusCode != http.StatusOK { + return openai.ErrorWrapper(err, "read_response_body_failed", http.StatusInternalServerError), nil + } + if err != nil { + return openai.ErrorWrapper(err, "read_response_body_failed", http.StatusInternalServerError), nil + } + err = resp.Body.Close() + if err != nil { + return openai.ErrorWrapper(err, "close_response_body_failed", http.StatusInternalServerError), nil + } + err = json.Unmarshal(responseBody, &vertexEmbeddingResponse) + if err != nil { + return openai.ErrorWrapper(err, "unmarshal_response_body_failed", http.StatusInternalServerError), nil + } + + openaiResp := &openai.EmbeddingResponse{ + Model: modelName, + Data: make([]openai.EmbeddingResponseItem, 0, len(vertexEmbeddingResponse.Predictions)), + Usage: model.Usage{ + TotalTokens: 0, + }, + } + + for i, pred := range vertexEmbeddingResponse.Predictions { + openaiResp.Data = append(openaiResp.Data, openai.EmbeddingResponseItem{ + Index: i, + Embedding: pred.Embeddings.Values, + }) + } + + for _, pred := range vertexEmbeddingResponse.Predictions { + openaiResp.Usage.TotalTokens += pred.Embeddings.Statistics.TokenCount + } + + return gemini.EmbeddingResponseHandler(c, resp.StatusCode, openaiResp) +} diff --git a/relay/adaptor/vertexai/embedding/model.go b/relay/adaptor/vertexai/embedding/model.go new file mode 100644 index 00000000..7e5f86fa --- /dev/null +++ b/relay/adaptor/vertexai/embedding/model.go @@ -0,0 +1,45 @@ +package vertexai + +type EmbeddingTaskType string + +const ( + EmbeddingTaskTypeRetrievalQuery EmbeddingTaskType = "RETRIEVAL_QUERY" + EmbeddingTaskTypeRetrievalDocument EmbeddingTaskType = "RETRIEVAL_DOCUMENT" + EmbeddingTaskTypeSemanticSimilarity EmbeddingTaskType = "SEMANTIC_SIMILARITY" + EmbeddingTaskTypeClassification EmbeddingTaskType = "CLASSIFICATION" + EmbeddingTaskTypeClustering EmbeddingTaskType = "CLUSTERING" + EmbeddingTaskTypeQuestionAnswering EmbeddingTaskType = "QUESTION_ANSWERING" + EmbeddingTaskTypeFactVerification EmbeddingTaskType = "FACT_VERIFICATION" + EmbeddingTaskTypeCodeRetrievalQuery EmbeddingTaskType = "CODE_RETRIEVAL_QUERY" +) + +type EmbeddingRequest struct { + Instances []EmbeddingInstance `json:"instances"` + Parameters EmbeddingParams `json:"parameters"` +} + +type EmbeddingInstance struct { + Content string `json:"content"` + TaskType EmbeddingTaskType `json:"task_type,omitempty"` + Title string `json:"title,omitempty"` +} + +type EmbeddingParams struct { + AutoTruncate bool `json:"autoTruncate,omitempty"` + OutputDimensionality int `json:"outputDimensionality,omitempty"` + // Texts []string `json:"texts,omitempty"` +} + +type EmbeddingResponse struct { + Predictions []struct { + Embeddings EmbeddingData `json:"embeddings"` + } `json:"predictions"` +} + +type EmbeddingData struct { + Statistics struct { + Truncated bool `json:"truncated"` + TokenCount int `json:"token_count"` + } `json:"statistics"` + Values []float64 `json:"values"` +} diff --git a/relay/adaptor/vertexai/model/model.go b/relay/adaptor/vertexai/model/model.go new file mode 100644 index 00000000..a39d38c2 --- /dev/null +++ b/relay/adaptor/vertexai/model/model.go @@ -0,0 +1,13 @@ +package model + +import ( + "github.com/gin-gonic/gin" + "github.com/songquanpeng/one-api/relay/meta" + "github.com/songquanpeng/one-api/relay/model" + "net/http" +) + +type InnerAIAdapter interface { + ConvertRequest(c *gin.Context, relayMode int, request *model.GeneralOpenAIRequest) (any, error) + DoResponse(c *gin.Context, resp *http.Response, meta *meta.Meta) (usage *model.Usage, err *model.ErrorWithStatusCode) +} diff --git a/relay/adaptor/vertexai/registry.go b/relay/adaptor/vertexai/registry.go index 41099f02..bc2fef50 100644 --- a/relay/adaptor/vertexai/registry.go +++ b/relay/adaptor/vertexai/registry.go @@ -1,20 +1,18 @@ package vertexai import ( - "net/http" - - "github.com/gin-gonic/gin" claude "github.com/songquanpeng/one-api/relay/adaptor/vertexai/claude" + embedding "github.com/songquanpeng/one-api/relay/adaptor/vertexai/embedding" gemini "github.com/songquanpeng/one-api/relay/adaptor/vertexai/gemini" - "github.com/songquanpeng/one-api/relay/meta" - "github.com/songquanpeng/one-api/relay/model" + "github.com/songquanpeng/one-api/relay/adaptor/vertexai/model" ) type VertexAIModelType int const ( - VerterAIClaude VertexAIModelType = iota + 1 - VerterAIGemini + VertexAIClaude VertexAIModelType = iota + 1 + VertexAIGemini + VertexAIEmbedding ) var modelMapping = map[string]VertexAIModelType{} @@ -23,28 +21,37 @@ var modelList = []string{} func init() { modelList = append(modelList, claude.ModelList...) for _, model := range claude.ModelList { - modelMapping[model] = VerterAIClaude + modelMapping[model] = VertexAIClaude } modelList = append(modelList, gemini.ModelList...) for _, model := range gemini.ModelList { - modelMapping[model] = VerterAIGemini + modelMapping[model] = VertexAIGemini + } + + modelList = append(modelList, embedding.ModelList...) + for _, model := range embedding.ModelList { + modelMapping[model] = VertexAIEmbedding } } -type innerAIAdapter interface { - ConvertRequest(c *gin.Context, relayMode int, request *model.GeneralOpenAIRequest) (any, error) - DoResponse(c *gin.Context, resp *http.Response, meta *meta.Meta) (usage *model.Usage, err *model.ErrorWithStatusCode) -} - -func GetAdaptor(model string) innerAIAdapter { +func GetAdaptor(model string) model.InnerAIAdapter { adaptorType := modelMapping[model] switch adaptorType { - case VerterAIClaude: + case VertexAIClaude: return &claude.Adaptor{} - case VerterAIGemini: + case VertexAIGemini: return &gemini.Adaptor{} + case VertexAIEmbedding: + return &embedding.Adaptor{} default: + adaptorType = PredictModelType(model) + switch adaptorType { + case VertexAIGemini: + return &gemini.Adaptor{} + case VertexAIEmbedding: + return &embedding.Adaptor{} + } return nil } } From 4907952fd13dd7640f3e89e260b1446b733f31da Mon Sep 17 00:00:00 2001 From: RandyZhang Date: Mon, 12 May 2025 18:23:40 +0800 Subject: [PATCH 2/7] support vertex embedding task_type --- relay/adaptor/vertexai/adaptor.go | 10 +++++-- relay/adaptor/vertexai/embedding/adapter.go | 29 ++++++++++++++------- relay/adaptor/vertexai/embedding/model.go | 1 + 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/relay/adaptor/vertexai/adaptor.go b/relay/adaptor/vertexai/adaptor.go index afae18a1..ae0d8c9d 100644 --- a/relay/adaptor/vertexai/adaptor.go +++ b/relay/adaptor/vertexai/adaptor.go @@ -78,13 +78,19 @@ func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) { } } + model := meta.ActualModelName + if strings.Contains(model, "?") { + // TODO: Maybe fix meta.ActualModelName? + model = strings.Split(model, "?")[0] + } + if meta.BaseURL != "" { return fmt.Sprintf( "%s/v1/projects/%s/locations/%s/publishers/google/models/%s:%s", meta.BaseURL, meta.Config.VertexAIProjectID, meta.Config.Region, - meta.ActualModelName, + model, suffix, ), nil } @@ -93,7 +99,7 @@ func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) { meta.Config.Region, meta.Config.VertexAIProjectID, meta.Config.Region, - meta.ActualModelName, + model, suffix, ), nil } diff --git a/relay/adaptor/vertexai/embedding/adapter.go b/relay/adaptor/vertexai/embedding/adapter.go index 17004928..47cd88fa 100644 --- a/relay/adaptor/vertexai/embedding/adapter.go +++ b/relay/adaptor/vertexai/embedding/adapter.go @@ -4,6 +4,7 @@ import ( "encoding/json" "io" "net/http" + "net/url" "strings" "github.com/songquanpeng/one-api/relay/adaptor/gemini" @@ -23,11 +24,26 @@ var ModelList = []string{ type Adaptor struct { model string - task EmbeddingTaskType } var _ model2.InnerAIAdapter = (*Adaptor)(nil) +func (a *Adaptor) parseEmbeddingTaskType(model string) (string, EmbeddingTaskType) { + modelTaskType := EmbeddingTaskTypeNone + if strings.Contains(model, "?") { + parts := strings.Split(model, "?") + modelName := parts[0] + if len(parts) >= 2 { + modelOptions, err := url.ParseQuery(parts[1]) + if err == nil { + modelTaskType = EmbeddingTaskType(modelOptions.Get("task_type")) + } + } + return modelName, modelTaskType + } + return model, modelTaskType +} + func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, request *model.GeneralOpenAIRequest) (any, error) { if request == nil { return nil, errors.New("request is nil") @@ -36,18 +52,13 @@ func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, request *model.G if len(inputs) == 0 { return nil, errors.New("request is nil") } - parts := strings.Split(request.Model, "|") - if len(parts) >= 2 { - a.task = EmbeddingTaskType(parts[1]) - } else { - a.task = EmbeddingTaskTypeSemanticSimilarity - } - a.model = parts[0] + modelName, modelTaskType := a.parseEmbeddingTaskType(request.Model) + a.model = modelName instances := make([]EmbeddingInstance, len(inputs)) for i, input := range inputs { instances[i] = EmbeddingInstance{ Content: input, - TaskType: a.task, + TaskType: modelTaskType, } } diff --git a/relay/adaptor/vertexai/embedding/model.go b/relay/adaptor/vertexai/embedding/model.go index 7e5f86fa..e9079569 100644 --- a/relay/adaptor/vertexai/embedding/model.go +++ b/relay/adaptor/vertexai/embedding/model.go @@ -3,6 +3,7 @@ package vertexai type EmbeddingTaskType string const ( + EmbeddingTaskTypeNone EmbeddingTaskType = "" EmbeddingTaskTypeRetrievalQuery EmbeddingTaskType = "RETRIEVAL_QUERY" EmbeddingTaskTypeRetrievalDocument EmbeddingTaskType = "RETRIEVAL_DOCUMENT" EmbeddingTaskTypeSemanticSimilarity EmbeddingTaskType = "SEMANTIC_SIMILARITY" From 94f3223fd74829555e831b5a011c6a88da25b7f9 Mon Sep 17 00:00:00 2001 From: RandyZhang Date: Thu, 15 May 2025 16:00:42 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=94=AF=E6=8C=81vertexai=20gemini?= =?UTF-8?q?=E7=9A=84thinking=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- relay/adaptor/gemini/model.go | 24 ++++++++------ relay/adaptor/vertexai/gemini/adapter.go | 41 ++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/relay/adaptor/gemini/model.go b/relay/adaptor/gemini/model.go index c3acae60..6469e45f 100644 --- a/relay/adaptor/gemini/model.go +++ b/relay/adaptor/gemini/model.go @@ -65,13 +65,19 @@ type ChatTools struct { FunctionDeclarations any `json:"function_declarations,omitempty"` } -type ChatGenerationConfig struct { - ResponseMimeType string `json:"responseMimeType,omitempty"` - ResponseSchema any `json:"responseSchema,omitempty"` - Temperature *float64 `json:"temperature,omitempty"` - TopP *float64 `json:"topP,omitempty"` - TopK float64 `json:"topK,omitempty"` - MaxOutputTokens int `json:"maxOutputTokens,omitempty"` - CandidateCount int `json:"candidateCount,omitempty"` - StopSequences []string `json:"stopSequences,omitempty"` +type ThinkingConfig struct { + IncludeThoughts bool `json:"includeThoughts"` + ThinkingBudget int `json:"thinkingBudget"` +} + +type ChatGenerationConfig struct { + ResponseMimeType string `json:"responseMimeType,omitempty"` + ResponseSchema any `json:"responseSchema,omitempty"` + Temperature *float64 `json:"temperature,omitempty"` + TopP *float64 `json:"topP,omitempty"` + TopK float64 `json:"topK,omitempty"` + MaxOutputTokens int `json:"maxOutputTokens,omitempty"` + CandidateCount int `json:"candidateCount,omitempty"` + StopSequences []string `json:"stopSequences,omitempty"` + ThinkingConfig *ThinkingConfig `json:"thinkingConfig,omitempty"` } diff --git a/relay/adaptor/vertexai/gemini/adapter.go b/relay/adaptor/vertexai/gemini/adapter.go index f5b245d8..abdd13c7 100644 --- a/relay/adaptor/vertexai/gemini/adapter.go +++ b/relay/adaptor/vertexai/gemini/adapter.go @@ -2,6 +2,9 @@ package vertexai import ( "net/http" + "net/url" + "strconv" + "strings" "github.com/gin-gonic/gin" "github.com/pkg/errors" @@ -27,13 +30,47 @@ var ModelList = []string{ type Adaptor struct { } +func (a *Adaptor) parseGeminiChatGenerationThinking(model string) (string, *gemini.ThinkingConfig) { + thinkingConfig := &gemini.ThinkingConfig{ + IncludeThoughts: false, + ThinkingBudget: 0, + } + modelName := model + if strings.Contains(model, "?") { + parts := strings.Split(model, "?") + _modelName := parts[0] + if len(parts) >= 2 { + modelOptions, err := url.ParseQuery(parts[1]) + if err != nil && modelOptions != nil { + modelName = _modelName + enableThinking := modelOptions.Has("thinking") + if enableThinking { + thinkingConfig.IncludeThoughts = true + } + thinkingBudget := modelOptions.Get("thinking_budget") + if thinkingBudget != "" { + thinkingBudgetInt, err := strconv.Atoi(thinkingBudget) + if err != nil { + thinkingConfig.ThinkingBudget = thinkingBudgetInt + } + } + } + } + } + return modelName, thinkingConfig +} + func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, request *model.GeneralOpenAIRequest) (any, error) { if request == nil { return nil, errors.New("request is nil") } - + modelName, thinkingConfig := a.parseGeminiChatGenerationThinking(request.Model) + request.Model = modelName geminiRequest := gemini.ConvertRequest(*request) - c.Set(ctxkey.RequestModel, request.Model) + if thinkingConfig != nil { + geminiRequest.GenerationConfig.ThinkingConfig = thinkingConfig + } + c.Set(ctxkey.RequestModel, modelName) c.Set(ctxkey.ConvertedRequest, geminiRequest) return geminiRequest, nil } From cb4ee5e86a70d53e6fd8636ad983a7b73ca44d11 Mon Sep 17 00:00:00 2001 From: RandyZhang Date: Thu, 15 May 2025 16:12:56 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E4=BF=AE=E5=A4=8Denable=E5=BC=80=E5=90=AF?= =?UTF-8?q?=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- relay/adaptor/vertexai/gemini/adapter.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/relay/adaptor/vertexai/gemini/adapter.go b/relay/adaptor/vertexai/gemini/adapter.go index abdd13c7..3e91e844 100644 --- a/relay/adaptor/vertexai/gemini/adapter.go +++ b/relay/adaptor/vertexai/gemini/adapter.go @@ -41,16 +41,16 @@ func (a *Adaptor) parseGeminiChatGenerationThinking(model string) (string, *gemi _modelName := parts[0] if len(parts) >= 2 { modelOptions, err := url.ParseQuery(parts[1]) - if err != nil && modelOptions != nil { + if err == nil && modelOptions != nil { modelName = _modelName - enableThinking := modelOptions.Has("thinking") - if enableThinking { - thinkingConfig.IncludeThoughts = true + hasThinkingFlag := modelOptions.Has("thinking") + if hasThinkingFlag { + thinkingConfig.IncludeThoughts = modelOptions.Get("thinking") == "1" } thinkingBudget := modelOptions.Get("thinking_budget") if thinkingBudget != "" { thinkingBudgetInt, err := strconv.Atoi(thinkingBudget) - if err != nil { + if err == nil { thinkingConfig.ThinkingBudget = thinkingBudgetInt } } From 703859214b3c43e0cfc87b5c1b74dd60a4fea6bb Mon Sep 17 00:00:00 2001 From: RandyZhang Date: Thu, 15 May 2025 21:55:36 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9thinking=20config?= =?UTF-8?q?=E7=9A=84=E8=AE=BE=E7=BD=AE=EF=BC=8C=E5=90=8C=E6=97=B6=E5=85=BC?= =?UTF-8?q?=E5=AE=B9gemini-2.5=E5=92=8Cgemini-2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- relay/adaptor/gemini/model.go | 2 +- relay/adaptor/vertexai/gemini/adapter.go | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/relay/adaptor/gemini/model.go b/relay/adaptor/gemini/model.go index 6469e45f..96dee113 100644 --- a/relay/adaptor/gemini/model.go +++ b/relay/adaptor/gemini/model.go @@ -79,5 +79,5 @@ type ChatGenerationConfig struct { MaxOutputTokens int `json:"maxOutputTokens,omitempty"` CandidateCount int `json:"candidateCount,omitempty"` StopSequences []string `json:"stopSequences,omitempty"` - ThinkingConfig *ThinkingConfig `json:"thinkingConfig,omitempty"` + ThinkingConfig *ThinkingConfig `json:"thinkingConfig"` } diff --git a/relay/adaptor/vertexai/gemini/adapter.go b/relay/adaptor/vertexai/gemini/adapter.go index 3e91e844..bf28a84c 100644 --- a/relay/adaptor/vertexai/gemini/adapter.go +++ b/relay/adaptor/vertexai/gemini/adapter.go @@ -57,7 +57,17 @@ func (a *Adaptor) parseGeminiChatGenerationThinking(model string) (string, *gemi } } } - return modelName, thinkingConfig + if strings.HasPrefix(modelName, "gemini-2.5") { + // 目前2.5的模型支持传递thinking config,且默认开启了thinking,不希望进入thinking模式需要显式传递thinkingConfig来关闭 + return modelName, thinkingConfig + } else { + // 其他模型暂时不支持 + if thinkingConfig != nil && (thinkingConfig.IncludeThoughts || thinkingConfig.ThinkingBudget > 0) { + // 为了后续一旦有其他模型支持了thinking,这里指定可以指定参数开启 + return modelName, thinkingConfig + } + return modelName, nil + } } func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, request *model.GeneralOpenAIRequest) (any, error) { From 3e9f5ad0c74f4bfd1681b1e34e514df2fcd30ae0 Mon Sep 17 00:00:00 2001 From: RandyZhang Date: Tue, 20 May 2025 17:15:10 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=90=8D=EF=BC=8C=E9=98=B2=E6=AD=A2=E8=BF=94=E5=9B=9E=E7=9A=84?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E5=90=8D=E4=B8=BA=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- relay/adaptor/vertexai/embedding/adapter.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/relay/adaptor/vertexai/embedding/adapter.go b/relay/adaptor/vertexai/embedding/adapter.go index 47cd88fa..b9f5b1f1 100644 --- a/relay/adaptor/vertexai/embedding/adapter.go +++ b/relay/adaptor/vertexai/embedding/adapter.go @@ -23,7 +23,6 @@ var ModelList = []string{ } type Adaptor struct { - model string } var _ model2.InnerAIAdapter = (*Adaptor)(nil) @@ -52,8 +51,7 @@ func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, request *model.G if len(inputs) == 0 { return nil, errors.New("request is nil") } - modelName, modelTaskType := a.parseEmbeddingTaskType(request.Model) - a.model = modelName + _, modelTaskType := a.parseEmbeddingTaskType(request.Model) instances := make([]EmbeddingInstance, len(inputs)) for i, input := range inputs { instances[i] = EmbeddingInstance{ @@ -73,7 +71,11 @@ func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, request *model.G } func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta *meta.Meta) (usage *model.Usage, err *model.ErrorWithStatusCode) { - err, usage = EmbeddingHandler(c, a.model, resp) + modelName := "" + if meta != nil { + modelName = meta.ActualModelName + } + err, usage = EmbeddingHandler(c, modelName, resp) return } From 55155e0fb624246a21489665b3b973e7fe82e26d Mon Sep 17 00:00:00 2001 From: RandyZhang Date: Thu, 29 May 2025 10:08:17 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E8=B0=83=E6=95=B4Google=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E7=9A=84Token=E8=BF=87=E6=9C=9F=E6=97=B6=E9=97=B4=EF=BC=8C?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E4=BB=8EToken=E8=AE=A4=E8=AF=81=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E4=B8=AD=E8=8E=B7=E5=8F=96=E8=BF=87=E6=9C=9F=E6=97=B6?= =?UTF-8?q?=E9=97=B4=EF=BC=8C=E5=A6=82=E6=9E=9C=E4=B8=8D=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E4=BC=9A=E9=80=89=E6=8B=A9=E9=BB=98=E8=AE=A4=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- relay/adaptor/vertexai/token.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/relay/adaptor/vertexai/token.go b/relay/adaptor/vertexai/token.go index 0a5e0aad..b007711a 100644 --- a/relay/adaptor/vertexai/token.go +++ b/relay/adaptor/vertexai/token.go @@ -57,6 +57,17 @@ func getToken(ctx context.Context, channelId int, adcJson string) (string, error } _ = resp - Cache.Set(cacheKey, resp.AccessToken, cache.DefaultExpiration) + // 使用响应中的过期时间,如果获取失败则使用默认时间 + expiration := cache.DefaultExpiration + if resp.ExpireTime != nil { + _expiration := time.Until(resp.ExpireTime.AsTime()) + // 提前10分钟过期,避免边界情况 + _expiration = _expiration - 10*time.Minute + if _expiration > 0 { + expiration = _expiration + } + } + + Cache.Set(cacheKey, resp.AccessToken, expiration) return resp.AccessToken, nil }