Compare commits

..

11 Commits

Author SHA1 Message Date
CalciumIon 1888a10394 refactor: Enhance error handling in Gemini request conversion
- Updated `CovertGemini2OpenAI` function to return an error alongside the GeminiChatRequest, improving error reporting for image processing.
- Modified `ConvertRequest` methods in both `adaptor.go` files to handle potential errors from the Gemini conversion, ensuring robust request handling.
- Improved clarity and maintainability of the code by explicitly managing error cases during request conversion.
2024-12-20 21:50:58 +08:00
CalciumIon 0725c8aac9 feat: Add GEMINI_VISION_MAX_IMAGE_NUM configuration
- Introduced `GEMINI_VISION_MAX_IMAGE_NUM` to README files for better user guidance.
- Updated `env.go` to retrieve the maximum image number from environment variables, defaulting to 16.
- Modified image handling logic in `relay-gemini.go` to respect the new configuration, allowing disabling of the limit by setting it to -1.
- Removed hardcoded constant for maximum image number in `constant.go` to streamline configuration management.
2024-12-20 21:36:23 +08:00
Calcium-Ion 1ae143c55a Merge pull request #636 from HynoR/fix/smfix
fix: 修复添加模型切换模式时,初始化空值导致的判断问题
2024-12-20 20:33:01 +08:00
Calcium-Ion d083d1ec33 Merge pull request #641 from HynoR/main
chore: 更新遗漏的gemini模型
2024-12-20 20:32:47 +08:00
Calcium-Ion d61524bee7 Merge pull request #642 from MartialBE/fix_gemini_thinking
fix: 修复gemini thinking在stream下会内容丢失
2024-12-20 20:32:23 +08:00
MartialBE 8504023d03 fix: Fix the issue where Gemini loses content when converting OpenAI format in the stream. 2024-12-20 20:24:49 +08:00
HynoR 105f13b2de chore: 更新gemini模型 2024-12-20 19:17:56 +08:00
HynoR c4c10d29f9 chore: 更新gemini模型 2024-12-20 19:14:53 +08:00
TAKO e95d65207f Merge branch 'Calcium-Ion:main' into fix/smfix 2024-12-20 19:11:32 +08:00
CalciumIon 1dfdb44d7f feat: Add new experimental Gemini versions to ModelList
- Included additional versions: "gemini-2.0-flash-thinking-exp" and "gemini-2.0-flash-thinking-exp-1219".
- Added comments to categorize versions as old, experimental, and flash experimental for better clarity.
2024-12-20 13:26:51 +08:00
HynoR 8170ed6b48 fix: 修复添加模型切换模式时,初始化空值导致的判断问题 2024-12-19 19:08:04 +08:00
8 changed files with 36 additions and 21 deletions
+1
View File
@@ -81,6 +81,7 @@ You can add custom models gpt-4-gizmo-* in channels. These are third-party model
- `UPDATE_TASK`: Update async tasks (Midjourney, Suno), default `true`
- `GEMINI_MODEL_MAP`: Specify Gemini model versions (v1/v1beta), format: "model:version", comma-separated
- `COHERE_SAFETY_SETTING`: Cohere model [safety settings](https://docs.cohere.com/docs/safety-modes#overview), options: `NONE`, `CONTEXTUAL`, `STRICT`, default `NONE`
- `GEMINI_VISION_MAX_IMAGE_NUM`: Gemini model maximum image number, default `16`, set to `-1` to disable
## Deployment
> [!TIP]
+1
View File
@@ -87,6 +87,7 @@
- `UPDATE_TASK`:是否更新异步任务(Midjourney、Suno),默认为 `true`,关闭后将不会更新任务进度。
- `GEMINI_MODEL_MAP`Gemini模型指定版本(v1/v1beta),使用“模型:版本”指定,","分隔,例如:-e GEMINI_MODEL_MAP="gemini-1.5-pro-latest:v1beta,gemini-1.5-pro-001:v1beta",为空则使用默认配置(v1beta)
- `COHERE_SAFETY_SETTING`Cohere模型[安全设置](https://docs.cohere.com/docs/safety-modes#overview),可选值为 `NONE`, `CONTEXTUAL``STRICT`,默认为 `NONE`
- `GEMINI_VISION_MAX_IMAGE_NUM`:Gemini模型最大图片数量,默认为 `16`,设置为 `-1` 则不限制。
## 部署
> [!TIP]
> 最新版Docker镜像:`calciumion/new-api:latest`
+2
View File
@@ -23,6 +23,8 @@ var GeminiModelMap = map[string]string{
"gemini-1.0-pro": "v1",
}
var GeminiVisionMaxImageNum = common.GetEnvOrDefault("GEMINI_VISION_MAX_IMAGE_NUM", 16)
func InitEnv() {
modelVersionMapStr := strings.TrimSpace(os.Getenv("GEMINI_MODEL_MAP"))
if modelVersionMapStr == "" {
+5 -1
View File
@@ -57,7 +57,11 @@ func (a *Adaptor) ConvertRequest(c *gin.Context, info *relaycommon.RelayInfo, re
if request == nil {
return nil, errors.New("request is nil")
}
return CovertGemini2OpenAI(*request), nil
ai, err := CovertGemini2OpenAI(*request)
if err != nil {
return nil, err
}
return ai, nil
}
func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dto.RerankRequest) (any, error) {
+8 -4
View File
@@ -1,14 +1,18 @@
package gemini
const (
GeminiVisionMaxImageNum = 16
)
var ModelList = []string{
// stable version
"gemini-1.5-pro", "gemini-1.5-flash", "gemini-1.5-flash-8b",
// latest version
"gemini-1.5-pro-latest", "gemini-1.5-flash-latest",
// legacy version
"gemini-1.5-pro-exp-0827", "gemini-1.5-flash-exp-0827",
// exp
"gemini-exp-1114", "gemini-exp-1121", "gemini-exp-1206",
// flash exp
"gemini-2.0-flash-exp",
// thinking exp
"gemini-2.0-flash-thinking-exp",
"gemini-2.0-flash-thinking-exp-1219",
}
+14 -9
View File
@@ -17,7 +17,7 @@ import (
)
// Setting safety to the lowest possible values since Gemini is already powerless enough
func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest) *GeminiChatRequest {
func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest) (*GeminiChatRequest, error) {
geminiRequest := GeminiChatRequest{
Contents: make([]GeminiChatContent, 0, len(textRequest.Messages)),
SafetySettings: []GeminiChatSafetySettings{
@@ -108,9 +108,10 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest) *GeminiChatReques
})
} else if part.Type == dto.ContentTypeImageURL {
imageNum += 1
//if imageNum > GeminiVisionMaxImageNum {
// continue
//}
if constant.GeminiVisionMaxImageNum != -1 && imageNum > constant.GeminiVisionMaxImageNum {
return nil, fmt.Errorf("too many images in the message, max allowed is %d", constant.GeminiVisionMaxImageNum)
}
// 判断是否是url
if strings.HasPrefix(part.ImageUrl.(dto.MessageImageUrl).Url, "http") {
// 是url,获取图片的类型和base64编码的数据
@@ -124,7 +125,7 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest) *GeminiChatReques
} else {
_, format, base64String, err := service.DecodeBase64ImageData(part.ImageUrl.(dto.MessageImageUrl).Url)
if err != nil {
continue
return nil, fmt.Errorf("decode base64 image data failed: %s", err.Error())
}
parts = append(parts, GeminiPart{
InlineData: &GeminiInlineData{
@@ -161,7 +162,7 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest) *GeminiChatReques
// shouldAddDummyModelMessage = false
//}
}
return &geminiRequest
return &geminiRequest, nil
}
func (g *GeminiChatResponse) GetResponseText() string {
@@ -236,13 +237,17 @@ func streamResponseGeminiChat2OpenAI(geminiResponse *GeminiChatResponse) *dto.Ch
var choice dto.ChatCompletionsStreamResponseChoice
//choice.Delta.SetContentString(geminiResponse.GetResponseText())
if len(geminiResponse.Candidates) > 0 && len(geminiResponse.Candidates[0].Content.Parts) > 0 {
respFirst := geminiResponse.Candidates[0].Content.Parts[0]
if respFirst.FunctionCall != nil {
respFirstParts := geminiResponse.Candidates[0].Content.Parts
if respFirstParts[0].FunctionCall != nil {
// function response
choice.Delta.ToolCalls = getToolCalls(&geminiResponse.Candidates[0])
} else {
// text response
choice.Delta.SetContentString(respFirst.Text)
var texts []string
for _, part := range respFirstParts {
texts = append(texts, part.Text)
}
choice.Delta.SetContentString(strings.Join(texts, "\n"))
}
}
var response dto.ChatCompletionsStreamResponse
+4 -1
View File
@@ -135,7 +135,10 @@ func (a *Adaptor) ConvertRequest(c *gin.Context, info *relaycommon.RelayInfo, re
c.Set("request_model", request.Model)
return vertexClaudeReq, nil
} else if a.RequestMode == RequestModeGemini {
geminiRequest := gemini.CovertGemini2OpenAI(*request)
geminiRequest, err := gemini.CovertGemini2OpenAI(*request)
if err != nil {
return nil, err
}
c.Set("request_model", request.Model)
return geminiRequest, nil
} else if a.RequestMode == RequestModeLlama {
@@ -75,7 +75,7 @@ export default function ModelSettingsVisualEditor(props) {
output.ModelPrice[model.name] = parseFloat(model.price)
} else {
if (model.ratio !== '') output.ModelRatio[model.name] = parseFloat(model.ratio);
if (model.completionRatio != '') output.CompletionRatio[model.name] = parseFloat(model.completionRatio);
if (model.completionRatio !== '') output.CompletionRatio[model.name] = parseFloat(model.completionRatio);
}
});
@@ -203,11 +203,6 @@ export default function ModelSettingsVisualEditor(props) {
showError('模型名称已存在');
return;
}
// 不允许同时添加固定价格和倍率
if (values.price !== '' && (values.ratio !== '' || values.completionRatio !== '')) {
showError('固定价格和倍率不能同时存在');
return;
}
setModels(prev => [{
name: values.name,
price: values.price || '',