diff --git a/controller/auth/lark.go b/controller/auth/lark.go index 43977d54..35f269e9 100644 --- a/controller/auth/lark.go +++ b/controller/auth/lark.go @@ -53,7 +53,7 @@ func getLarkUserInfoByCode(code string) (*LarkUser, error) { res, err := client.Do(req) if err != nil { logger.SysLog(err.Error()) - return nil, errors.New("None法连接至飞书服务器,请稍后Retry!") + return nil, errors.New("Unable to connect to Lark server, please try again later!") } defer res.Body.Close() var oAuthResponse LarkOAuthResponse @@ -69,7 +69,7 @@ func getLarkUserInfoByCode(code string) (*LarkUser, error) { res2, err := client.Do(req) if err != nil { logger.SysLog(err.Error()) - return nil, errors.New("None法连接至飞书服务器,请稍后Retry!") + return nil, errors.New("Unable to connect to Lark server, please try again later!") } var larkUser LarkUser err = json.NewDecoder(res2.Body).Decode(&larkUser) @@ -168,7 +168,7 @@ func LarkBind(c *gin.Context) { if model.IsLarkIdAlreadyTaken(user.LarkId) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "该飞书账户已被Bind", + "message": "This Lark account has already been bound", }) return } diff --git a/controller/auth/oidc.go b/controller/auth/oidc.go index 6eafecb8..b82c7a08 100644 --- a/controller/auth/oidc.go +++ b/controller/auth/oidc.go @@ -5,15 +5,16 @@ import ( "encoding/json" "errors" "fmt" + "net/http" + "strconv" + "time" + "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "github.com/songquanpeng/one-api/common/config" "github.com/songquanpeng/one-api/common/logger" "github.com/songquanpeng/one-api/controller" "github.com/songquanpeng/one-api/model" - "net/http" - "strconv" - "time" ) type OidcResponse struct { @@ -60,7 +61,7 @@ func getOidcUserInfoByCode(code string) (*OidcUser, error) { res, err := client.Do(req) if err != nil { logger.SysLog(err.Error()) - return nil, errors.New("None法连接至 OIDC 服务器,请稍后Retry!") + return nil, errors.New("Unable to connect to the OIDC server, please try again later!") } defer res.Body.Close() var oidcResponse OidcResponse @@ -76,7 +77,7 @@ func getOidcUserInfoByCode(code string) (*OidcUser, error) { res2, err := client.Do(req) if err != nil { logger.SysLog(err.Error()) - return nil, errors.New("None法连接至 OIDC 服务器,请稍后Retry!") + return nil, errors.New("Unable to connect to the OIDC server, please try again later!") } var oidcUser OidcUser err = json.NewDecoder(res2.Body).Decode(&oidcUser) @@ -104,7 +105,7 @@ func OidcAuth(c *gin.Context) { if !config.OidcEnabled { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "Administrator未开启通过 OIDC Log in以及Sign up", + "message": "Administrator has not enabled OIDC Log in and Sign up", }) return } @@ -173,7 +174,7 @@ func OidcBind(c *gin.Context) { if !config.OidcEnabled { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "Administrator未开启通过 OIDC Log in以及Sign up", + "message": "The administrator has turned off new user registration", }) return } @@ -192,7 +193,7 @@ func OidcBind(c *gin.Context) { if model.IsOidcIdAlreadyTaken(user.OidcId) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "该 OIDC 账户已被Bind", + "message": "This OIDC account has already been bound", }) return } diff --git a/controller/misc.go b/controller/misc.go index 633a0354..7af4af30 100644 --- a/controller/misc.go +++ b/controller/misc.go @@ -3,14 +3,14 @@ package controller import ( "encoding/json" "fmt" - "github.com/songquanpeng/one-api/common" - "github.com/songquanpeng/one-api/common/config" - "github.com/songquanpeng/one-api/common/message" - "github.com/songquanpeng/one-api/model" "net/http" "strings" "github.com/gin-gonic/gin" + "github.com/songquanpeng/one-api/common" + "github.com/songquanpeng/one-api/common/config" + "github.com/songquanpeng/one-api/common/message" + "github.com/songquanpeng/one-api/model" ) func GetStatus(c *gin.Context) { @@ -100,7 +100,7 @@ func SendEmailVerification(c *gin.Context) { if !allowed { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "AdministratorEnable了邮箱域名白名单,您的Email address的域名不在白名单中", + "message": "Administrator has enabled email domain whitelist, your email domain is not in the whitelist", }) return } @@ -154,8 +154,8 @@ func SendPasswordResetEmail(c *gin.Context) { link := fmt.Sprintf("%s/user/reset?email=%s&token=%s", config.ServerAddress, email, code) subject := fmt.Sprintf("%s Password reset", config.SystemName) content := fmt.Sprintf("
Hello, you are resetting %s password.
"+ - "点击 此处 进行Password reset。
"+ - "如果链接None法点击,请尝试点击下面的链接或将其Copy到浏览器中打开:
%s
Click here to reset your password.
"+ + "If the link cannot be clicked, please try clicking the link below or copy it to your browser to open:
%s
The reset link is valid within %d minutes. If it is not your operation, please ignore it.
", config.SystemName, link, link, common.VerificationValidMinutes) err := message.SendEmail(subject, email, content) if err != nil { diff --git a/controller/option.go b/controller/option.go index 3f16060e..380ad1c6 100644 --- a/controller/option.go +++ b/controller/option.go @@ -2,13 +2,13 @@ package controller import ( "encoding/json" - "github.com/songquanpeng/one-api/common/config" - "github.com/songquanpeng/one-api/common/helper" - "github.com/songquanpeng/one-api/model" "net/http" "strings" "github.com/gin-gonic/gin" + "github.com/songquanpeng/one-api/common/config" + "github.com/songquanpeng/one-api/common/helper" + "github.com/songquanpeng/one-api/model" ) func GetOptions(c *gin.Context) { @@ -47,7 +47,7 @@ func UpdateOption(c *gin.Context) { if !config.ValidThemes[option.Value] { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "None效的主题", + "message": "invalid theme", }) return } @@ -55,7 +55,7 @@ func UpdateOption(c *gin.Context) { if option.Value == "true" && config.GitHubClientId == "" { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "None法Enable GitHub OAuth,请先填入 GitHub Client Id 以及 GitHub Client Secret!", + "message": "Unable to enable GitHub OAuth, please fill in the GitHub Client Id and GitHub Client Secret first!", }) return } @@ -63,7 +63,7 @@ func UpdateOption(c *gin.Context) { if option.Value == "true" && len(config.EmailDomainWhitelist) == 0 { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "None法Enable邮箱域名限制,请先填入限制的邮箱域名!", + "message": "Unable to enable email domain restriction, please fill in the restricted email domains first!", }) return } diff --git a/controller/token.go b/controller/token.go index 7822b722..19557fc7 100644 --- a/controller/token.go +++ b/controller/token.go @@ -162,7 +162,7 @@ func AddToken(c *gin.Context) { if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": fmt.Sprintf("参数Error:%s", err.Error()), + "message": fmt.Sprintf("invalid token: %s", err.Error()), }) return } @@ -336,7 +336,7 @@ func UpdateToken(c *gin.Context) { if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": fmt.Sprintf("参数Error:%s", err.Error()), + "message": fmt.Sprintf("invalid token: %s", err.Error()), }) return } diff --git a/controller/user.go b/controller/user.go index dd2762b2..b6fac67e 100644 --- a/controller/user.go +++ b/controller/user.go @@ -271,7 +271,7 @@ func GetUserDashboard(c *gin.Context) { if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "None法获取Statistics", + "message": "Failed to get user dashboard data: " + err.Error(), "data": nil, }) return @@ -415,7 +415,7 @@ func UpdateUser(c *gin.Context) { if myRole <= updatedUser.Role && myRole != model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "None权将其他Users权限等级Promote到大于Equals自己的权限等级", + "message": "No permission to promote other users to a permission level greater than or equal to your own", }) return } @@ -529,7 +529,7 @@ func DeleteSelf(c *gin.Context) { if user.Role == model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "不能DeleteSuper administrator账户", + "message": "Cannot delete super administrator account", }) return } @@ -813,7 +813,7 @@ func AdminTopUp(c *gin.Context) { return } if req.Remark == "" { - req.Remark = fmt.Sprintf("通过 API Recharge %s", common.LogQuota(int64(req.Quota))) + req.Remark = fmt.Sprintf("Recharged via API %s", common.LogQuota(int64(req.Quota))) } model.RecordTopupLog(req.UserId, req.Remark, req.Quota) c.JSON(http.StatusOK, gin.H{ diff --git a/middleware/auth.go b/middleware/auth.go index 8fc62027..f3a1f1c7 100644 --- a/middleware/auth.go +++ b/middleware/auth.go @@ -107,7 +107,7 @@ func TokenAuth() func(c *gin.Context) { } if token.Subnet != nil && *token.Subnet != "" { if !network.IsIpInSubnets(ctx, c.ClientIP(), *token.Subnet) { - abortWithMessage(c, http.StatusForbidden, fmt.Sprintf("该API Keys只能在指定网段使用:%s,当前 ip:%s", *token.Subnet, c.ClientIP())) + abortWithMessage(c, http.StatusForbidden, fmt.Sprintf("This API key can only be used in the specified subnet: %s, current IP: %s", *token.Subnet, c.ClientIP())) return } } @@ -129,7 +129,7 @@ func TokenAuth() func(c *gin.Context) { if token.Models != nil && *token.Models != "" { c.Set(ctxkey.AvailableModels, *token.Models) if requestModel != "" && !isModelInList(requestModel, *token.Models) { - abortWithMessage(c, http.StatusForbidden, fmt.Sprintf("该API KeysNone权使用Model:%s", requestModel)) + abortWithMessage(c, http.StatusForbidden, fmt.Sprintf("This API key does not have permission to use the model: %s", requestModel)) return } } diff --git a/middleware/distributor.go b/middleware/distributor.go index 8098c307..2cac55cd 100644 --- a/middleware/distributor.go +++ b/middleware/distributor.go @@ -30,12 +30,12 @@ func Distribute() func(c *gin.Context) { if ok { id, err := strconv.Atoi(channelId.(string)) if err != nil { - abortWithMessage(c, http.StatusBadRequest, "None效的Channel Id") + abortWithMessage(c, http.StatusBadRequest, "Invalid Channel Id") return } channel, err = model.GetChannelById(id, true) if err != nil { - abortWithMessage(c, http.StatusBadRequest, "None效的Channel Id") + abortWithMessage(c, http.StatusBadRequest, "Invalid Channel Id") return } if channel.Status != model.ChannelStatusEnabled { @@ -47,7 +47,7 @@ func Distribute() func(c *gin.Context) { var err error channel, err = model.CacheGetRandomSatisfiedChannel(userGroup, requestModel, false) if err != nil { - message := fmt.Sprintf("当前Group %s 下对于Model %s No available channels", userGroup, requestModel) + message := fmt.Sprintf("No available channels for Model %s under Group %s", requestModel, userGroup) if channel != nil { logger.SysError(fmt.Sprintf("Channel does not exist: %d", channel.Id)) message = "Database consistency has been broken, please contact the administrator" diff --git a/model/redemption.go b/model/redemption.go index 4f5ae4c9..b3f80947 100644 --- a/model/redemption.go +++ b/model/redemption.go @@ -2,6 +2,7 @@ package model import ( "fmt" + "github.com/pkg/errors" "github.com/songquanpeng/one-api/common" "github.com/songquanpeng/one-api/common/helper" @@ -80,7 +81,7 @@ func Redeem(key string, userId int) (quota int64, err error) { return err }) if err != nil { - return 0, errors.New("Redeem失败," + err.Error()) + return 0, errors.New("Redeem failed, " + err.Error()) } RecordLog(userId, LogTypeTopup, fmt.Sprintf("Recharge %s through redemption code", common.LogQuota(redemption.Quota))) return redemption.Quota, nil diff --git a/model/token.go b/model/token.go index ce281923..621ea15c 100644 --- a/model/token.go +++ b/model/token.go @@ -72,7 +72,7 @@ func ValidateUserToken(key string) (token *Token, err error) { return nil, errors.Wrap(err, "failed to get token by key") } if token.Status == TokenStatusExhausted { - return nil, fmt.Errorf("API Keys %s(#%d)Quota已用尽", token.Name, token.Id) + return nil, fmt.Errorf("API Key %s (#%d) quota has been exhausted", token.Name, token.Id) } else if token.Status == TokenStatusExpired { return nil, errors.New("The token has expired") } diff --git a/monitor/channel.go b/monitor/channel.go index 39705e40..90443965 100644 --- a/monitor/channel.go +++ b/monitor/channel.go @@ -2,6 +2,7 @@ package monitor import ( "fmt" + "github.com/songquanpeng/one-api/common/config" "github.com/songquanpeng/one-api/common/logger" "github.com/songquanpeng/one-api/common/message" @@ -38,9 +39,10 @@ func DisableChannel(channelId int, channelName string, reason string) { func MetricDisableChannel(channelId int, successRate float64) { model.UpdateChannelStatusById(channelId, model.ChannelStatusAutoDisabled) logger.SysLog(fmt.Sprintf("channel #%d has been disabled due to low success rate: %.2f", channelId, successRate*100)) - subject := fmt.Sprintf("Channel #%d 已被Disable", channelId) - content := fmt.Sprintf("该Channel(#%d)在最近 %d 次调用中成功率为 %.2f%%,低于阈值 %.2f%%,因此被System自动Disable。", - channelId, config.MetricQueueSize, successRate*100, config.MetricSuccessRateThreshold*100) + subject := fmt.Sprintf("Channel #%d has been disabled", channelId) + content := fmt.Sprintf("The channel (#%d) has been automatically disabled by the system due to "+ + "a success rate of %.2f%% over the last %d calls, which is below the threshold of %.2f%%.", + channelId, successRate*100, config.MetricQueueSize, config.MetricSuccessRateThreshold*100) notifyRootUser(subject, content) } @@ -48,7 +50,7 @@ func MetricDisableChannel(channelId int, successRate float64) { func EnableChannel(channelId int, channelName string) { model.UpdateChannelStatusById(channelId, model.ChannelStatusEnabled) logger.SysLog(fmt.Sprintf("channel #%d has been enabled", channelId)) - subject := fmt.Sprintf("Channel「%s」(#%d)已被Enable", channelName, channelId) - content := fmt.Sprintf("Channel「%s」(#%d)已被Enable", channelName, channelId) + subject := fmt.Sprintf("Channel %s (#%d) has been enabled", channelName, channelId) + content := fmt.Sprintf("Channel %s (#%d) has been enabled", channelName, channelId) notifyRootUser(subject, content) } diff --git a/monitor/manage.go b/monitor/manage.go index 268d3924..a0a4166b 100644 --- a/monitor/manage.go +++ b/monitor/manage.go @@ -35,7 +35,7 @@ func ShouldDisableChannel(err *model.Error, statusCode int) bool { strings.Contains(lowerMessage, "balance") || strings.Contains(lowerMessage, "permission denied") || strings.Contains(lowerMessage, "organization has been restricted") || // groq - strings.Contains(lowerMessage, "已欠费") { + strings.Contains(lowerMessage, "overdue payment") { return true } return false diff --git a/relay/adaptor/aiproxy/main.go b/relay/adaptor/aiproxy/main.go index 03eeefa4..8403e7a1 100644 --- a/relay/adaptor/aiproxy/main.go +++ b/relay/adaptor/aiproxy/main.go @@ -38,7 +38,7 @@ func aiProxyDocuments2Markdown(documents []LibraryDocument) string { if len(documents) == 0 { return "" } - content := "\n\n参考文档:\n" + content := "\n\nReference Documents:\n" for i, document := range documents { content += fmt.Sprintf("%d. [%s](%s)\n", i+1, document.Title, document.URL) } diff --git a/relay/adaptor/ali/image.go b/relay/adaptor/ali/image.go index a251d4d8..e86f496e 100644 --- a/relay/adaptor/ali/image.go +++ b/relay/adaptor/ali/image.go @@ -148,18 +148,18 @@ func responseAli2OpenAIImage(response *TaskResponse, responseFormat string) *ope for _, data := range response.Output.Results { var b64Json string if responseFormat == "b64_json" { - // 读取 data.Url 的图片数据并转存到 b64Json + // Read the image data from data.Url and store it in b64Json imageData, err := getImageData(data.Url) if err != nil { - // 处理获取图片数据失败的情况 + // Handle the case where getting image data fails logger.SysError("getImageData Error getting image data: " + err.Error()) continue } - // 将图片数据转为 Base64 编码的字符串 + // Convert the image data to a Base64 encoded string b64Json = Base64Encode(imageData) } else { - // 如果 responseFormat 不是 "b64_json",则直接使用 data.B64Image + // If responseFormat is not "b64_json", use data.B64Image directly b64Json = data.B64Image } diff --git a/relay/adaptor/cohere/model.go b/relay/adaptor/cohere/model.go index c613c3d9..adabee59 100644 --- a/relay/adaptor/cohere/model.go +++ b/relay/adaptor/cohere/model.go @@ -2,23 +2,23 @@ package cohere type Request struct { Message string `json:"message" required:"true"` - Model string `json:"model,omitempty"` // Default值为"command-r" - Stream bool `json:"stream,omitempty"` // Default值为false + Model string `json:"model,omitempty"` // default to "command-r" + Stream bool `json:"stream,omitempty"` // default to false Preamble string `json:"preamble,omitempty"` ChatHistory []ChatMessage `json:"chat_history,omitempty"` ConversationID string `json:"conversation_id,omitempty"` - PromptTruncation string `json:"prompt_truncation,omitempty"` // Default值为"AUTO" + PromptTruncation string `json:"prompt_truncation,omitempty"` // default to "AUTO" Connectors []Connector `json:"connectors,omitempty"` Documents []Document `json:"documents,omitempty"` - Temperature *float64 `json:"temperature,omitempty"` // Default值为0.3 + Temperature *float64 `json:"temperature,omitempty"` // default to 0.3 MaxTokens int `json:"max_tokens,omitempty"` MaxInputTokens int `json:"max_input_tokens,omitempty"` - K int `json:"k,omitempty"` // Default值为0 - P *float64 `json:"p,omitempty"` // Default值为0.75 + K int `json:"k,omitempty"` // default to 0 + P *float64 `json:"p,omitempty"` // default to 0.75 Seed int `json:"seed,omitempty"` StopSequences []string `json:"stop_sequences,omitempty"` - FrequencyPenalty *float64 `json:"frequency_penalty,omitempty"` // Default值为0.0 - PresencePenalty *float64 `json:"presence_penalty,omitempty"` // Default值为0.0 + FrequencyPenalty *float64 `json:"frequency_penalty,omitempty"` // default to 0.0 + PresencePenalty *float64 `json:"presence_penalty,omitempty"` // default to 0.0 Tools []Tool `json:"tools,omitempty"` ToolResults []ToolResult `json:"tool_results,omitempty"` } diff --git a/relay/adaptor/tencent/model.go b/relay/adaptor/tencent/model.go index 7f5e7eb2..b34398fb 100644 --- a/relay/adaptor/tencent/model.go +++ b/relay/adaptor/tencent/model.go @@ -6,40 +6,46 @@ type Message struct { } type ChatRequest struct { - // Model name,Optional values包括 hunyuan-lite、hunyuan-standard、hunyuan-standard-256K、hunyuan-pro。 - // 各Model介绍请阅读 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 中的说明。 + // Model name, optional values include hunyuan-lite, hunyuan-standard, hunyuan-standard-256K, hunyuan-pro. + // For descriptions of each model, please read the [Product Overview](https://cloud.tencent.com/document/product/1729/104753). // - // Note: - // 不同的Model计费不同,请根据 [购买指南](https://cloud.tencent.com/document/product/1729/97731) 按需调用。 + // Note: + // Different models have different pricing. Please refer to the [Purchase Guide](https://cloud.tencent.com/document/product/1729/97731) for details. Model *string `json:"Model"` - // Chat上下文信息。 - // 说明: - // 1. 长度最多为 40,按对话Time从旧到新在数Group中排列。 - // 2. Message.Role Optional values:system、user、assistant。 - // 其中,system 角色可选,如存在则必须位于列表的最开始。user 和 assistant 需交替出现(一问一答),以 user 提问开始和结束,且 Content 不能为空。Role 的顺序示例:[system(可选) user assistant user assistant user ...]。 - // 3. Messages 中 Content 总长度不能超过ModelEnter长度上限(可参考 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 文档),超过则会截断最前面的内容,只保留尾部内容。 + // Chat context information. + // Description: + // 1. The maximum length is 40, arranged in the array in chronological order from oldest to newest. + // 2. Message.Role optional values: system, user, assistant. + // Among them, the system role is optional. If it exists, it must be at the beginning of the list. + // User and assistant must alternate (one question and one answer), starting and ending with user, + // and Content cannot be empty. The order of roles is as follows: [system (optional) user assistant user assistant user ...]. + // 3. The total length of Content in Messages cannot exceed the model's length limit + // (refer to the [Product Overview](https://cloud.tencent.com/document/product/1729/104753) document). + // If it exceeds, the earliest content will be truncated, leaving only the latest content. Messages []*Message `json:"Messages"` - // 流式调用开关。 - // 说明: - // 1. 未传值时Default为非流式调用(false)。 - // 2. 流式调用时以 SSE 协议增量返回结果(返回值取 Choices[n].Delta 中的值,需要拼接增量数据才能获得完整结果)。 - // 3. 非流式调用时: - // 调用方式与普通 HTTP 请求None异。 - // 接口响应耗时较长,**如需更低时延建议Settings为 true**。 - // 只返回一次最终结果(返回值取 Choices[n].Message 中的值)。 + // Stream call switch. + // Description: + // 1. If not provided, the default is non-streaming call (false). + // 2. In streaming calls, results are returned incrementally using the SSE protocol + // (the return value is taken from Choices[n].Delta, and incremental data needs to be concatenated to obtain the complete result). + // 3. In non-streaming calls: + // The call method is the same as a regular HTTP request. + // The interface response time is relatively long. **If lower latency is required, it is recommended to set this to true**. + // Only the final result is returned once (the return value is taken from Choices[n].Message). // - // Note: - // 通过 SDK 调用时,流式和非流式调用需用**不同的方式**获取返回值,具体参考 SDK 中的注释或示例(在各语言 SDK 代码仓库的 examples/hunyuan/v20230901/ 目录中)。 + // Note: + // When calling through the SDK, different methods are required to obtain return values for streaming and non-streaming calls. + // Refer to the comments or examples in the SDK (in the examples/hunyuan/v20230901/ directory of each language SDK code repository). Stream *bool `json:"Stream"` - // 说明: - // 1. 影响输出文本的多样性,取值越大,生成文本的多样性越强。 - // 2. 取值区间为 [0.0, 1.0],未传值时使用各Model推荐值。 - // 3. 非必要不建议使用,不合理的取值会影响效果。 + // Description: + // 1. Affects the diversity of the output text. The larger the value, the more diverse the generated text. + // 2. The value range is [0.0, 1.0]. If not provided, the recommended value for each model is used. + // 3. It is not recommended to use this unless necessary, as unreasonable values can affect the results. TopP *float64 `json:"TopP"` - // 说明: - // 1. 较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。 - // 2. 取值区间为 [0.0, 2.0],未传值时使用各Model推荐值。 - // 3. 非必要不建议使用,不合理的取值会影响效果。 + // Description: + // 1. Higher values make the output more random, while lower values make it more focused and deterministic. + // 2. The value range is [0.0, 2.0]. If not provided, the recommended value for each model is used. + // 3. It is not recommended to use this unless necessary, as unreasonable values can affect the results. Temperature *float64 `json:"Temperature"` } @@ -55,19 +61,19 @@ type Usage struct { } type ResponseChoices struct { - FinishReason string `json:"FinishReason,omitempty"` // 流式结束标志位,为 stop 则表示尾包 - Messages Message `json:"Message,omitempty"` // 内容,同步模式返回内容,流模式为 null 输出 content 内容总数最多支持 1024token。 - Delta Message `json:"Delta,omitempty"` // 内容,流模式返回内容,同步模式为 null 输出 content 内容总数最多支持 1024token。 + FinishReason string `json:"FinishReason,omitempty"` // Stream end flag, "stop" indicates the end packet + Messages Message `json:"Message,omitempty"` // Content, returned in synchronous mode, null in stream mode. The total content supports up to 1024 tokens. + Delta Message `json:"Delta,omitempty"` // Content, returned in stream mode, null in synchronous mode. The total content supports up to 1024 tokens. } type ChatResponse struct { - Choices []ResponseChoices `json:"Choices,omitempty"` // 结果 - Created int64 `json:"Created,omitempty"` // unix Time戳的字符串 - Id string `json:"Id,omitempty"` // 会话 id - Usage Usage `json:"Usage,omitempty"` // token 数量 - Error Error `json:"Error,omitempty"` // 错误信息 Note:此字段可能返回 null,表示取不到有效值 - Note string `json:"Note,omitempty"` // 注释 - ReqID string `json:"Req_id,omitempty"` // 唯一请求 Id,每次请求都会返回。用于反馈接口入参 + Choices []ResponseChoices `json:"Choices,omitempty"` // Results + Created int64 `json:"Created,omitempty"` // Unix timestamp string + Id string `json:"Id,omitempty"` // Session ID + Usage Usage `json:"Usage,omitempty"` // Token count + Error Error `json:"Error,omitempty"` // Error information. Note: This field may return null, indicating that no valid value was found. + Note string `json:"Note,omitempty"` // Note + ReqID string `json:"Req_id,omitempty"` // Unique request ID, returned with each request. Used for feedback on interface input parameters. } type ChatResponseP struct { diff --git a/relay/billing/ratio/model.go b/relay/billing/ratio/model.go index 470bd336..613c4881 100644 --- a/relay/billing/ratio/model.go +++ b/relay/billing/ratio/model.go @@ -385,8 +385,9 @@ func GetAudioCompletionRatio(actualModelName string) float64 { // AudioTokensPerSecond is the number of audio tokens per second for each model. var AudioPromptTokensPerSecond = map[string]float64{ - // whisper 的 API 价格是 $0.0001/sec。one-api 的历史倍率为 15,对应 $0.03/kilo_tokens。 - // 那么换算后可得,每秒的 tokens 应该为 0.0001/0.03*1000 = 3.3333 + // Whisper API price is $0.0001/sec. One-api's historical ratio is 15, + // corresponding to $0.03/kilo_tokens. + // After conversion, tokens per second should be 0.0001/0.03*1000 = 3.3333. "whisper-1": 0.0001 / 0.03 * 1000, // gpt-4o-audio series processes 10 tokens per second "gpt-4o-audio-preview": 10, diff --git a/relay/controller/helper.go b/relay/controller/helper.go index 746453af..834487dc 100644 --- a/relay/controller/helper.go +++ b/relay/controller/helper.go @@ -125,7 +125,7 @@ func postConsumeQuota(ctx context.Context, usage *relaymodel.Usage, meta *meta.M } var extraLog string if systemPromptReset { - extraLog = " (NoteSystemPrompt词已被重置)" + extraLog = " (Note: System prompt has been reset)" } logContent := fmt.Sprintf("model rate %.2f, group rate %.2f, completion rate %.2f%s", modelRatio, groupRatio, completionRatio, extraLog) model.RecordConsumeLog(ctx, meta.UserId, meta.ChannelId, promptTokens, completionTokens, textRequest.Model, meta.TokenName, quota, logContent) diff --git a/web/default/src/components/ChannelsTable.js b/web/default/src/components/ChannelsTable.js index f738ef52..9986e2d5 100644 --- a/web/default/src/components/ChannelsTable.js +++ b/web/default/src/components/ChannelsTable.js @@ -203,7 +203,7 @@ const ChannelsTable = () => { trigger={} - content='本Channel被手动Disable' + content='This channel has been manually disabled' basic /> ); @@ -213,7 +213,7 @@ const ChannelsTable = () => { trigger={} - content='本Channel被程序自动Disable' + content='This channel has been automatically disabled by the program' basic /> ); @@ -277,7 +277,7 @@ const ChannelsTable = () => { newChannels[realIdx].response_time = time * 1000; newChannels[realIdx].test_time = Date.now() / 1000; setChannels(newChannels); - showInfo(`Channel ${name} Test成功,Model ${model},耗时 ${time.toFixed(2)}s。`); + showInfo(`Channel ${name} tested successfully with model ${model}, taking ${time.toFixed(2)} seconds.`); } else { showError(message); } @@ -292,7 +292,7 @@ const ChannelsTable = () => { const res = await API.get(`/api/channel/test?scope=${scope}`); const { success, message } = res.data; if (success) { - showInfo('已成功开始TestChannel,请Refresh页面查看结果。'); + showInfo('Successfully started testing channels, please refresh the page to see the results.'); } else { showError(message); } @@ -302,7 +302,7 @@ const ChannelsTable = () => { const res = await API.delete(`/api/channel/disabled`); const { success, message, data } = res.data; if (success) { - showSuccess(`已Delete所有DisableChannel,共计 ${data} 个`); + showSuccess(`Successfully deleted all disabled channels, total ${data} channels`); await refresh(); } else { showError(message); @@ -504,26 +504,26 @@ const ChannelsTable = () => { idx, event.target.value ); - }}> + }}> - } - content='Channel priority - higher value means higher priority' - /> - -{inputs.ServerAddress}
- ,Fill in the Authorization callback URL{' '}
+ , Fill in the Authorization callback URL{' '}
{`${inputs.ServerAddress}/oauth/github`}
{inputs.ServerAddress}
- ,重定向 URL 填{' '}
+ Fill in the Homepage URL {inputs.ServerAddress}
+ , Fill in the Redirect URL{' '}
{`${inputs.ServerAddress}/oauth/lark`}