From d5fa98f2e002f6ad0b2c89e1647f16e7d1913686 Mon Sep 17 00:00:00 2001 From: "Laisky.Cai" Date: Mon, 27 Jan 2025 03:34:27 +0000 Subject: [PATCH] fix: translate error messages and comments to English for consistency --- controller/auth/lark.go | 6 +- controller/auth/oidc.go | 17 ++-- controller/misc.go | 14 ++-- controller/option.go | 12 +-- controller/token.go | 4 +- controller/user.go | 8 +- middleware/auth.go | 4 +- middleware/distributor.go | 6 +- model/redemption.go | 3 +- model/token.go | 2 +- monitor/channel.go | 12 +-- monitor/manage.go | 2 +- relay/adaptor/aiproxy/main.go | 2 +- relay/adaptor/ali/image.go | 8 +- relay/adaptor/cohere/model.go | 16 ++-- relay/adaptor/tencent/model.go | 82 ++++++++++--------- relay/billing/ratio/model.go | 5 +- relay/controller/helper.go | 2 +- web/default/src/components/ChannelsTable.js | 52 ++++++------ .../src/components/OperationSetting.js | 26 +++--- web/default/src/components/PersonalSetting.js | 2 +- web/default/src/components/SystemSetting.js | 66 +++++++-------- web/default/src/components/TokensTable.js | 8 +- web/default/src/components/UsersTable.js | 10 +-- web/default/src/pages/Token/EditToken.js | 14 ++-- 25 files changed, 197 insertions(+), 186 deletions(-) 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' - /> - - + - -
- {/**/} - DeleteDisableChannel + Delete disabled channels } on='click' @@ -627,7 +627,7 @@ const ChannelsTable = () => { } /> - + diff --git a/web/default/src/components/OperationSetting.js b/web/default/src/components/OperationSetting.js index 7a721cef..213eab29 100644 --- a/web/default/src/components/OperationSetting.js +++ b/web/default/src/components/OperationSetting.js @@ -247,24 +247,24 @@ const OperationSetting = () => { { deleteHistoryLogs().then(); - }}>Clear History Logs - -
+ }}>Clear History Logs + +
Monitoring Settings -
- +
+ { min='0' placeholder='Email will be sent to remind users when the quota is below this' /> - - + + { /> - - { + + { submitConfig('monitor').then(); }}>Save Monitoring Settings diff --git a/web/default/src/components/PersonalSetting.js b/web/default/src/components/PersonalSetting.js index dd2f8b2d..f124eae4 100644 --- a/web/default/src/components/PersonalSetting.js +++ b/web/default/src/components/PersonalSetting.js @@ -249,7 +249,7 @@ const PersonalSetting = () => { } { status.lark_client_id && ( - + ) } @@ -336,7 +336,7 @@ const SystemSetting = () => { @@ -349,12 +349,12 @@ const SystemSetting = () => {
- 配置邮箱域名白名单 - 用以防止恶意Users利用临时邮箱批量Sign up + Configure Email Domain Whitelist + To prevent malicious users from using temporary emails to sign up in bulk
{ { options={EmailDomainWhitelist} /> { submitNewRestrictedDomain(); - }}>填入 + }}>Add } onKeyDown={(e) => { if (e.key === 'Enter') { @@ -387,14 +387,14 @@ const SystemSetting = () => { } }} autoComplete='new-password' - placeholder='Enter新的允许的邮箱域名' + placeholder='Enter new allowed email domain' value={restrictedDomainInput} onChange={(e, { value }) => { setRestrictedDomainInput(value); }} /> - 保存邮箱域名白名单Settings + Save Email Domain Whitelist Settings
Configure SMTP @@ -428,7 +428,7 @@ const SystemSetting = () => { {
Configure GitHub OAuth App - To support login & registration via GitHub, + To support login & registration via GitHub, Click here @@ -459,7 +459,7 @@ const SystemSetting = () => {
Fill in the Homepage URL {inputs.ServerAddress} - ,Fill in the Authorization callback URL{' '} + , Fill in the Authorization callback URL{' '} {`${inputs.ServerAddress}/oauth/github`} @@ -486,18 +486,18 @@ const SystemSetting = () => {
- 配置飞书授权Log in + Configure Lark OAuth - 用以支持通过飞书进行Log inSign up, + To support login & registration via Lark, Click here - Management你的飞书应用 + Manage your Lark App
- 主页链接填 {inputs.ServerAddress} - ,重定向 URL 填{' '} + Fill in the Homepage URL {inputs.ServerAddress} + , Fill in the Redirect URL{' '} {`${inputs.ServerAddress}/oauth/lark`} @@ -520,13 +520,13 @@ const SystemSetting = () => { /> - 保存飞书 OAuth Settings + Save Lark OAuth Settings
Configure WeChat Server - To support login & registration via WeChat, + To support login & registration via WeChat, {
{
- 配置 Message Pusher + Configure Message Pusher - 用以推送报警信息, + To push alert messages, Click here - 了解 Message Pusher + Learn about Message Pusher
{ /> - 保存 Message Pusher Settings + Save Message Pusher Settings
Configure Turnstile - To support user verification, + To support user verification, Click here diff --git a/web/default/src/components/TokensTable.js b/web/default/src/components/TokensTable.js index 13d333ac..e1fb79dc 100644 --- a/web/default/src/components/TokensTable.js +++ b/web/default/src/components/TokensTable.js @@ -422,12 +422,12 @@ const TokensTable = () => { { Add New User { { { { setExpiredTime(0, 0, 0, 1); }}>Expires after one minute
- Note that the quota of the token is only used to limit the maximum quota usage of the token itself, and the actual usage is limited by the remaining quota of the account. + Note that the token's quota is only used to limit the maximum usage of the token itself, and the actual usage is limited by the remaining quota of the account.