diff --git a/common/config/config.go b/common/config/config.go index 84adcad9..a596664d 100644 --- a/common/config/config.go +++ b/common/config/config.go @@ -132,10 +132,10 @@ var ValidThemes = map[string]bool{ // All duration's unit is seconds // Shouldn't larger then RateLimitKeyExpirationDuration var ( - GlobalApiRateLimitNum = env.Int("GLOBAL_API_RATE_LIMIT", 180) + GlobalApiRateLimitNum = env.Int("GLOBAL_API_RATE_LIMIT", 240) GlobalApiRateLimitDuration int64 = 3 * 60 - GlobalWebRateLimitNum = env.Int("GLOBAL_WEB_RATE_LIMIT", 60) + GlobalWebRateLimitNum = env.Int("GLOBAL_WEB_RATE_LIMIT", 120) GlobalWebRateLimitDuration int64 = 3 * 60 UploadRateLimitNum = 10 diff --git a/common/logger/logger.go b/common/logger/logger.go index c3dcd89d..f725c619 100644 --- a/common/logger/logger.go +++ b/common/logger/logger.go @@ -43,11 +43,19 @@ func SysLog(s string) { _, _ = fmt.Fprintf(gin.DefaultWriter, "[SYS] %v | %s \n", t.Format("2006/01/02 - 15:04:05"), s) } +func SysLogf(format string, a ...any) { + SysLog(fmt.Sprintf(format, a...)) +} + func SysError(s string) { t := time.Now() _, _ = fmt.Fprintf(gin.DefaultErrorWriter, "[SYS] %v | %s \n", t.Format("2006/01/02 - 15:04:05"), s) } +func SysErrorf(format string, a ...any) { + SysError(fmt.Sprintf(format, a...)) +} + func Debug(ctx context.Context, msg string) { if config.DebugEnabled { logHelper(ctx, loggerDEBUG, msg) diff --git a/controller/user.go b/controller/user.go index b433f1fd..05c4d66a 100644 --- a/controller/user.go +++ b/controller/user.go @@ -12,8 +12,6 @@ import ( "github.com/songquanpeng/one-api/common" "github.com/songquanpeng/one-api/common/config" "github.com/songquanpeng/one-api/common/ctxkey" - "github.com/songquanpeng/one-api/common/helper" - "github.com/songquanpeng/one-api/common/logger" "github.com/songquanpeng/one-api/common/random" "github.com/songquanpeng/one-api/model" ) @@ -117,7 +115,6 @@ func Logout(c *gin.Context) { } func Register(c *gin.Context) { - ctx := c.Request.Context() if !config.RegisterEnabled { c.JSON(http.StatusOK, gin.H{ "message": "管理员关闭了新用户注册", @@ -182,28 +179,6 @@ func Register(c *gin.Context) { }) return } - go func() { - err := user.ValidateAndFill() - if err != nil { - logger.Errorf(ctx, "user.ValidateAndFill failed: %v", err) - return - } - cleanToken := model.Token{ - UserId: user.Id, - Name: "default", - Key: random.GenerateKey(), - CreatedTime: helper.GetTimestamp(), - AccessedTime: helper.GetTimestamp(), - ExpiredTime: -1, - RemainQuota: -1, - UnlimitedQuota: true, - } - err = cleanToken.Insert() - if err != nil { - logger.Errorf(ctx, "cleanToken.Insert failed: %v", err) - return - } - }() c.JSON(http.StatusOK, gin.H{ "success": true, "message": "", diff --git a/main.go b/main.go index c2123c0e..dd54d6d9 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ var buildFS embed.FS func main() { logger.SetupLogger() - logger.SysLog(fmt.Sprintf("One API %s started", common.Version)) + logger.SysLogf("One API %s started", common.Version) if os.Getenv("GIN_MODE") != "debug" { gin.SetMode(gin.ReleaseMode) } diff --git a/middleware/distributor.go b/middleware/distributor.go index 9677e26b..70938299 100644 --- a/middleware/distributor.go +++ b/middleware/distributor.go @@ -91,26 +91,28 @@ func SetupContextForSelectedChannel(c *gin.Context, channel *model.Channel, mode c.Set(ctxkey.BaseURL, channel.GetBaseURL()) cfg, _ := channel.LoadConfig() // this is for backward compatibility - switch channel.Type { - case channeltype.Azure: - if cfg.APIVersion == "" { - cfg.APIVersion = channel.Other - } - case channeltype.Xunfei: - if cfg.APIVersion == "" { - cfg.APIVersion = channel.Other - } - case channeltype.Gemini: - if cfg.APIVersion == "" { - cfg.APIVersion = channel.Other - } - case channeltype.AIProxyLibrary: - if cfg.LibraryID == "" { - cfg.LibraryID = channel.Other - } - case channeltype.Ali: - if cfg.Plugin == "" { - cfg.Plugin = channel.Other + if channel.Other != nil { + switch channel.Type { + case channeltype.Azure: + if cfg.APIVersion == "" { + cfg.APIVersion = *channel.Other + } + case channeltype.Xunfei: + if cfg.APIVersion == "" { + cfg.APIVersion = *channel.Other + } + case channeltype.Gemini: + if cfg.APIVersion == "" { + cfg.APIVersion = *channel.Other + } + case channeltype.AIProxyLibrary: + if cfg.LibraryID == "" { + cfg.LibraryID = *channel.Other + } + case channeltype.Ali: + if cfg.Plugin == "" { + cfg.Plugin = *channel.Other + } } } c.Set(ctxkey.Config, cfg) diff --git a/model/channel.go b/model/channel.go index ec52683e..a92f402c 100644 --- a/model/channel.go +++ b/model/channel.go @@ -27,7 +27,7 @@ type Channel struct { TestTime int64 `json:"test_time" gorm:"bigint"` ResponseTime int `json:"response_time"` // in milliseconds BaseURL *string `json:"base_url" gorm:"column:base_url;default:''"` - Other string `json:"other"` // DEPRECATED: please save config to field Config + Other *string `json:"other"` // DEPRECATED: please save config to field Config Balance float64 `json:"balance"` // in USD BalanceUpdatedTime int64 `json:"balance_updated_time" gorm:"bigint"` Models string `json:"models"` diff --git a/model/user.go b/model/user.go index 3cc1f9c0..db7ceba0 100644 --- a/model/user.go +++ b/model/user.go @@ -8,6 +8,7 @@ import ( "github.com/songquanpeng/one-api/common" "github.com/songquanpeng/one-api/common/blacklist" "github.com/songquanpeng/one-api/common/config" + "github.com/songquanpeng/one-api/common/helper" "github.com/songquanpeng/one-api/common/logger" "github.com/songquanpeng/one-api/common/random" "gorm.io/gorm" @@ -141,6 +142,22 @@ func (user *User) Insert(inviterId int) error { RecordLog(inviterId, LogTypeSystem, fmt.Sprintf("邀请用户赠送 %s", common.LogQuota(config.QuotaForInviter))) } } + // create default token + cleanToken := Token{ + UserId: user.Id, + Name: "default", + Key: random.GenerateKey(), + CreatedTime: helper.GetTimestamp(), + AccessedTime: helper.GetTimestamp(), + ExpiredTime: -1, + RemainQuota: -1, + UnlimitedQuota: true, + } + result.Error = cleanToken.Insert() + if result.Error != nil { + // do not block + logger.SysError(fmt.Sprintf("create default token for user %d failed: %s", user.Id, result.Error.Error())) + } return nil } diff --git a/relay/adaptor/gemini/main.go b/relay/adaptor/gemini/main.go index 8d4c2cb9..3feb612f 100644 --- a/relay/adaptor/gemini/main.go +++ b/relay/adaptor/gemini/main.go @@ -244,8 +244,10 @@ func responseGeminiChat2OpenAI(response *ChatResponse) *openai.TextResponse { func streamResponseGeminiChat2OpenAI(geminiResponse *ChatResponse) *openai.ChatCompletionsStreamResponse { var choice openai.ChatCompletionsStreamResponseChoice choice.Delta.Content = geminiResponse.GetResponseText() - choice.FinishReason = &constant.StopFinishReason + //choice.FinishReason = &constant.StopFinishReason var response openai.ChatCompletionsStreamResponse + response.Id = fmt.Sprintf("chatcmpl-%s", random.GetUUID()) + response.Created = helper.GetTimestamp() response.Object = "chat.completion.chunk" response.Model = "gemini" response.Choices = []openai.ChatCompletionsStreamResponseChoice{choice} diff --git a/relay/adaptor/xunfei/adaptor.go b/relay/adaptor/xunfei/adaptor.go index 49e3d2ee..4be1285f 100644 --- a/relay/adaptor/xunfei/adaptor.go +++ b/relay/adaptor/xunfei/adaptor.go @@ -28,14 +28,6 @@ func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) { func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request, meta *meta.Meta) error { adaptor.SetupCommonRequestHeader(c, req, meta) - version := parseAPIVersionByModelName(meta.ActualModelName) - if version == "" { - version = a.meta.Config.APIVersion - } - if version == "" { - version = "v1.1" - } - a.meta.Config.APIVersion = version // check DoResponse for auth part return nil } @@ -70,6 +62,14 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta *meta.Met if a.request == nil { return nil, openai.ErrorWrapper(errors.New("request is nil"), "request_is_nil", http.StatusBadRequest) } + version := parseAPIVersionByModelName(meta.ActualModelName) + if version == "" { + version = a.meta.Config.APIVersion + } + if version == "" { + version = "v1.1" + } + a.meta.Config.APIVersion = version if meta.IsStream { err, usage = StreamHandler(c, meta, *a.request, splits[0], splits[1], splits[2]) } else { diff --git a/relay/adaptor/xunfei/main.go b/relay/adaptor/xunfei/main.go index 4f8d60a9..00122d5e 100644 --- a/relay/adaptor/xunfei/main.go +++ b/relay/adaptor/xunfei/main.go @@ -5,6 +5,7 @@ import ( "crypto/sha256" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -29,11 +30,7 @@ import ( func requestOpenAI2Xunfei(request model.GeneralOpenAIRequest, xunfeiAppId string, domain string) *ChatRequest { messages := make([]Message, 0, len(request.Messages)) - var lastToolCalls []model.Tool for _, message := range request.Messages { - if message.ToolCalls != nil { - lastToolCalls = message.ToolCalls - } messages = append(messages, Message{ Role: message.Role, Content: message.StringContent(), @@ -46,9 +43,10 @@ func requestOpenAI2Xunfei(request model.GeneralOpenAIRequest, xunfeiAppId string xunfeiRequest.Parameter.Chat.TopK = request.N xunfeiRequest.Parameter.Chat.MaxTokens = request.MaxTokens xunfeiRequest.Payload.Message.Text = messages - if len(lastToolCalls) != 0 { - for _, toolCall := range lastToolCalls { - xunfeiRequest.Payload.Functions.Text = append(xunfeiRequest.Payload.Functions.Text, toolCall.Function) + + if strings.HasPrefix(domain, "generalv3") { + xunfeiRequest.Payload.Functions = &Functions{ + Text: request.Tools, } } @@ -204,7 +202,7 @@ func Handler(c *gin.Context, meta *meta.Meta, textRequest model.GeneralOpenAIReq } } if len(xunfeiResponse.Payload.Choices.Text) == 0 { - return openai.ErrorWrapper(err, "xunfei_empty_response_detected", http.StatusInternalServerError), nil + return openai.ErrorWrapper(errors.New("xunfei empty response detected"), "xunfei_empty_response_detected", http.StatusInternalServerError), nil } xunfeiResponse.Payload.Choices.Text[0].Content = content diff --git a/relay/adaptor/xunfei/model.go b/relay/adaptor/xunfei/model.go index 97a43154..681c0c05 100644 --- a/relay/adaptor/xunfei/model.go +++ b/relay/adaptor/xunfei/model.go @@ -9,6 +9,10 @@ type Message struct { Content string `json:"content"` } +type Functions struct { + Text []model.Tool `json:"text,omitempty"` +} + type ChatRequest struct { Header struct { AppId string `json:"app_id"` @@ -26,9 +30,7 @@ type ChatRequest struct { Message struct { Text []Message `json:"text"` } `json:"message"` - Functions struct { - Text []model.Function `json:"text,omitempty"` - } `json:"functions,omitempty"` + Functions *Functions `json:"functions,omitempty"` } `json:"payload"` } diff --git a/web/berry/src/views/Channel/component/EditModal.js b/web/berry/src/views/Channel/component/EditModal.js index 4f7f216d..29bd3de2 100644 --- a/web/berry/src/views/Channel/component/EditModal.js +++ b/web/berry/src/views/Channel/component/EditModal.js @@ -163,7 +163,7 @@ const EditModal = ({ open, channelId, onCancel, onOk }) => { values.other = 'v2.1'; } if (values.key === '') { - if (values.config.ak !== '' && values.config.sk !== '' && values.config.region !== '') { + if (values.config.ak && values.config.sk && values.config.region) { values.key = `${values.config.ak}|${values.config.sk}|${values.config.region}`; } } diff --git a/web/default/src/pages/Channel/EditChannel.js b/web/default/src/pages/Channel/EditChannel.js index ac0fed60..fb80a726 100644 --- a/web/default/src/pages/Channel/EditChannel.js +++ b/web/default/src/pages/Channel/EditChannel.js @@ -181,9 +181,6 @@ const EditChannel = () => { if (localInputs.type === 3 && localInputs.other === '') { localInputs.other = '2024-03-01-preview'; } - if (localInputs.type === 18 && localInputs.other === '') { - localInputs.other = 'v2.1'; - } let res; localInputs.models = localInputs.models.join(','); localInputs.group = localInputs.groups.join(',');