mirror of
				https://github.com/songquanpeng/one-api.git
				synced 2025-11-04 15:53:42 +08:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			v0.3.0-alp
			...
			v0.3.0-alp
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					4d6172a242 | ||
| 
						 | 
					8afdc56b11 | 
@@ -54,6 +54,7 @@ var QuotaForNewUser = 0
 | 
				
			|||||||
var ChannelDisableThreshold = 5.0
 | 
					var ChannelDisableThreshold = 5.0
 | 
				
			||||||
var AutomaticDisableChannelEnabled = false
 | 
					var AutomaticDisableChannelEnabled = false
 | 
				
			||||||
var QuotaRemindThreshold = 1000
 | 
					var QuotaRemindThreshold = 1000
 | 
				
			||||||
 | 
					var PreConsumedQuota = 500
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var RootUserEmail = ""
 | 
					var RootUserEmail = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -128,6 +128,14 @@ func relayHelper(c *gin.Context) error {
 | 
				
			|||||||
		model_ = strings.TrimSuffix(model_, "-0314")
 | 
							model_ = strings.TrimSuffix(model_, "-0314")
 | 
				
			||||||
		fullRequestURL = fmt.Sprintf("%s/openai/deployments/%s/%s", baseURL, model_, task)
 | 
							fullRequestURL = fmt.Sprintf("%s/openai/deployments/%s/%s", baseURL, model_, task)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						ratio := common.GetModelRatio(textRequest.Model)
 | 
				
			||||||
 | 
						preConsumedQuota := int(float64(common.PreConsumedQuota) * ratio)
 | 
				
			||||||
 | 
						if consumeQuota {
 | 
				
			||||||
 | 
							err := model.PreConsumeTokenQuota(tokenId, preConsumedQuota)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	req, err := http.NewRequest(c.Request.Method, fullRequestURL, c.Request.Body)
 | 
						req, err := http.NewRequest(c.Request.Method, fullRequestURL, c.Request.Body)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -177,9 +185,9 @@ func relayHelper(c *gin.Context) error {
 | 
				
			|||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				quota = textResponse.Usage.PromptTokens + textResponse.Usage.CompletionTokens*completionRatio
 | 
									quota = textResponse.Usage.PromptTokens + textResponse.Usage.CompletionTokens*completionRatio
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			ratio := common.GetModelRatio(textRequest.Model)
 | 
					 | 
				
			||||||
			quota = int(float64(quota) * ratio)
 | 
								quota = int(float64(quota) * ratio)
 | 
				
			||||||
			err := model.DecreaseTokenQuota(tokenId, quota)
 | 
								quotaDelta := quota - preConsumedQuota
 | 
				
			||||||
 | 
								err := model.PostConsumeTokenQuota(tokenId, quotaDelta)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				common.SysError("Error consuming token remain quota: " + err.Error())
 | 
									common.SysError("Error consuming token remain quota: " + err.Error())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,7 +111,7 @@ func TokenAuth() func(c *gin.Context) {
 | 
				
			|||||||
		c.Set("id", token.UserId)
 | 
							c.Set("id", token.UserId)
 | 
				
			||||||
		c.Set("token_id", token.Id)
 | 
							c.Set("token_id", token.Id)
 | 
				
			||||||
		requestURL := c.Request.URL.String()
 | 
							requestURL := c.Request.URL.String()
 | 
				
			||||||
		consumeQuota := !token.UnlimitedQuota
 | 
							consumeQuota := true
 | 
				
			||||||
		if strings.HasPrefix(requestURL, "/v1/models") {
 | 
							if strings.HasPrefix(requestURL, "/v1/models") {
 | 
				
			||||||
			consumeQuota = false
 | 
								consumeQuota = false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,6 +55,7 @@ func InitOptionMap() {
 | 
				
			|||||||
	common.OptionMap["TurnstileSecretKey"] = ""
 | 
						common.OptionMap["TurnstileSecretKey"] = ""
 | 
				
			||||||
	common.OptionMap["QuotaForNewUser"] = strconv.Itoa(common.QuotaForNewUser)
 | 
						common.OptionMap["QuotaForNewUser"] = strconv.Itoa(common.QuotaForNewUser)
 | 
				
			||||||
	common.OptionMap["QuotaRemindThreshold"] = strconv.Itoa(common.QuotaRemindThreshold)
 | 
						common.OptionMap["QuotaRemindThreshold"] = strconv.Itoa(common.QuotaRemindThreshold)
 | 
				
			||||||
 | 
						common.OptionMap["PreConsumedQuota"] = strconv.Itoa(common.PreConsumedQuota)
 | 
				
			||||||
	common.OptionMap["ModelRatio"] = common.ModelRatio2JSONString()
 | 
						common.OptionMap["ModelRatio"] = common.ModelRatio2JSONString()
 | 
				
			||||||
	common.OptionMap["TopUpLink"] = common.TopUpLink
 | 
						common.OptionMap["TopUpLink"] = common.TopUpLink
 | 
				
			||||||
	common.OptionMapRWMutex.Unlock()
 | 
						common.OptionMapRWMutex.Unlock()
 | 
				
			||||||
@@ -159,6 +160,8 @@ func updateOptionMap(key string, value string) (err error) {
 | 
				
			|||||||
		common.QuotaForNewUser, _ = strconv.Atoi(value)
 | 
							common.QuotaForNewUser, _ = strconv.Atoi(value)
 | 
				
			||||||
	case "QuotaRemindThreshold":
 | 
						case "QuotaRemindThreshold":
 | 
				
			||||||
		common.QuotaRemindThreshold, _ = strconv.Atoi(value)
 | 
							common.QuotaRemindThreshold, _ = strconv.Atoi(value)
 | 
				
			||||||
 | 
						case "PreConsumedQuota":
 | 
				
			||||||
 | 
							common.PreConsumedQuota, _ = strconv.Atoi(value)
 | 
				
			||||||
	case "ModelRatio":
 | 
						case "ModelRatio":
 | 
				
			||||||
		err = common.UpdateModelRatioByJSONString(value)
 | 
							err = common.UpdateModelRatioByJSONString(value)
 | 
				
			||||||
	case "TopUpLink":
 | 
						case "TopUpLink":
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -130,7 +130,23 @@ func DeleteTokenById(id int, userId int) (err error) {
 | 
				
			|||||||
	return token.Delete()
 | 
						return token.Delete()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func DecreaseTokenQuota(tokenId int, quota int) (err error) {
 | 
					func IncreaseTokenQuota(id int, quota int) (err error) {
 | 
				
			||||||
 | 
						if quota < 0 {
 | 
				
			||||||
 | 
							return errors.New("quota 不能为负数!")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = DB.Model(&Token{}).Where("id = ?", id).Update("remain_quota", gorm.Expr("remain_quota + ?", quota)).Error
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DecreaseTokenQuota(id int, quota int) (err error) {
 | 
				
			||||||
 | 
						if quota < 0 {
 | 
				
			||||||
 | 
							return errors.New("quota 不能为负数!")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = DB.Model(&Token{}).Where("id = ?", id).Update("remain_quota", gorm.Expr("remain_quota - ?", quota)).Error
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func PreConsumeTokenQuota(tokenId int, quota int) (err error) {
 | 
				
			||||||
	if quota < 0 {
 | 
						if quota < 0 {
 | 
				
			||||||
		return errors.New("quota 不能为负数!")
 | 
							return errors.New("quota 不能为负数!")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -138,7 +154,7 @@ func DecreaseTokenQuota(tokenId int, quota int) (err error) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if token.RemainQuota < quota {
 | 
						if !token.UnlimitedQuota && token.RemainQuota < quota {
 | 
				
			||||||
		return errors.New("令牌额度不足")
 | 
							return errors.New("令牌额度不足")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	userQuota, err := GetUserQuota(token.UserId)
 | 
						userQuota, err := GetUserQuota(token.UserId)
 | 
				
			||||||
@@ -163,17 +179,42 @@ func DecreaseTokenQuota(tokenId int, quota int) (err error) {
 | 
				
			|||||||
			if email != "" {
 | 
								if email != "" {
 | 
				
			||||||
				topUpLink := fmt.Sprintf("%s/topup", common.ServerAddress)
 | 
									topUpLink := fmt.Sprintf("%s/topup", common.ServerAddress)
 | 
				
			||||||
				err = common.SendEmail(prompt, email,
 | 
									err = common.SendEmail(prompt, email,
 | 
				
			||||||
					fmt.Sprintf("%s,剩余额度为 %d,为了不影响您的使用,请及时充值。<br/>充值链接:<a href='%s'>%s</a>", prompt, userQuota-quota, topUpLink, topUpLink))
 | 
										fmt.Sprintf("%s,当前剩余额度为 %d,为了不影响您的使用,请及时充值。<br/>充值链接:<a href='%s'>%s</a>", prompt, userQuota, topUpLink, topUpLink))
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					common.SysError("发送邮件失败:" + err.Error())
 | 
										common.SysError("发送邮件失败:" + err.Error())
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}()
 | 
							}()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = DB.Model(&Token{}).Where("id = ?", tokenId).Update("remain_quota", gorm.Expr("remain_quota - ?", quota)).Error
 | 
						if !token.UnlimitedQuota {
 | 
				
			||||||
	if err != nil {
 | 
							err = DecreaseTokenQuota(tokenId, quota)
 | 
				
			||||||
		return err
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = DecreaseUserQuota(token.UserId, quota)
 | 
						err = DecreaseUserQuota(token.UserId, quota)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func PostConsumeTokenQuota(tokenId int, quota int) (err error) {
 | 
				
			||||||
 | 
						token, err := GetTokenById(tokenId)
 | 
				
			||||||
 | 
						if quota > 0 {
 | 
				
			||||||
 | 
							err = DecreaseUserQuota(token.UserId, quota)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = IncreaseUserQuota(token.UserId, -quota)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !token.UnlimitedQuota {
 | 
				
			||||||
 | 
							if quota > 0 {
 | 
				
			||||||
 | 
								err = DecreaseTokenQuota(tokenId, quota)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								err = IncreaseTokenQuota(tokenId, -quota)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,7 @@ const SystemSetting = () => {
 | 
				
			|||||||
    RegisterEnabled: '',
 | 
					    RegisterEnabled: '',
 | 
				
			||||||
    QuotaForNewUser: 0,
 | 
					    QuotaForNewUser: 0,
 | 
				
			||||||
    QuotaRemindThreshold: 0,
 | 
					    QuotaRemindThreshold: 0,
 | 
				
			||||||
 | 
					    PreConsumedQuota: 0,
 | 
				
			||||||
    ModelRatio: '',
 | 
					    ModelRatio: '',
 | 
				
			||||||
    TopUpLink: '',
 | 
					    TopUpLink: '',
 | 
				
			||||||
    AutomaticDisableChannelEnabled: '',
 | 
					    AutomaticDisableChannelEnabled: '',
 | 
				
			||||||
@@ -98,6 +99,7 @@ const SystemSetting = () => {
 | 
				
			|||||||
      name === 'TurnstileSecretKey' ||
 | 
					      name === 'TurnstileSecretKey' ||
 | 
				
			||||||
      name === 'QuotaForNewUser' ||
 | 
					      name === 'QuotaForNewUser' ||
 | 
				
			||||||
      name === 'QuotaRemindThreshold' ||
 | 
					      name === 'QuotaRemindThreshold' ||
 | 
				
			||||||
 | 
					      name === 'PreConsumedQuota' ||
 | 
				
			||||||
      name === 'ModelRatio' ||
 | 
					      name === 'ModelRatio' ||
 | 
				
			||||||
      name === 'TopUpLink'
 | 
					      name === 'TopUpLink'
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
@@ -119,6 +121,9 @@ const SystemSetting = () => {
 | 
				
			|||||||
    if (originInputs['QuotaRemindThreshold'] !== inputs.QuotaRemindThreshold) {
 | 
					    if (originInputs['QuotaRemindThreshold'] !== inputs.QuotaRemindThreshold) {
 | 
				
			||||||
      await updateOption('QuotaRemindThreshold', inputs.QuotaRemindThreshold);
 | 
					      await updateOption('QuotaRemindThreshold', inputs.QuotaRemindThreshold);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (originInputs['PreConsumedQuota'] !== inputs.PreConsumedQuota) {
 | 
				
			||||||
 | 
					      await updateOption('PreConsumedQuota', inputs.PreConsumedQuota);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (originInputs['ModelRatio'] !== inputs.ModelRatio) {
 | 
					    if (originInputs['ModelRatio'] !== inputs.ModelRatio) {
 | 
				
			||||||
      if (!verifyJSON(inputs.ModelRatio)) {
 | 
					      if (!verifyJSON(inputs.ModelRatio)) {
 | 
				
			||||||
        showError('模型倍率不是合法的 JSON 字符串');
 | 
					        showError('模型倍率不是合法的 JSON 字符串');
 | 
				
			||||||
@@ -272,7 +277,7 @@ const SystemSetting = () => {
 | 
				
			|||||||
          <Header as='h3'>
 | 
					          <Header as='h3'>
 | 
				
			||||||
            运营设置
 | 
					            运营设置
 | 
				
			||||||
          </Header>
 | 
					          </Header>
 | 
				
			||||||
          <Form.Group widths={3}>
 | 
					          <Form.Group widths={4}>
 | 
				
			||||||
            <Form.Input
 | 
					            <Form.Input
 | 
				
			||||||
              label='新用户初始配额'
 | 
					              label='新用户初始配额'
 | 
				
			||||||
              name='QuotaForNewUser'
 | 
					              name='QuotaForNewUser'
 | 
				
			||||||
@@ -302,6 +307,16 @@ const SystemSetting = () => {
 | 
				
			|||||||
              min='0'
 | 
					              min='0'
 | 
				
			||||||
              placeholder='低于此额度时将发送邮件提醒用户'
 | 
					              placeholder='低于此额度时将发送邮件提醒用户'
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
 | 
					            <Form.Input
 | 
				
			||||||
 | 
					              label='请求预扣费额度'
 | 
				
			||||||
 | 
					              name='PreConsumedQuota'
 | 
				
			||||||
 | 
					              onChange={handleInputChange}
 | 
				
			||||||
 | 
					              autoComplete='new-password'
 | 
				
			||||||
 | 
					              value={inputs.PreConsumedQuota}
 | 
				
			||||||
 | 
					              type='number'
 | 
				
			||||||
 | 
					              min='0'
 | 
				
			||||||
 | 
					              placeholder='请求结束后多退少补'
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
          </Form.Group>
 | 
					          </Form.Group>
 | 
				
			||||||
          <Form.Group widths='equal'>
 | 
					          <Form.Group widths='equal'>
 | 
				
			||||||
            <Form.TextArea
 | 
					            <Form.TextArea
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user