Compare commits

..

5 Commits

Author SHA1 Message Date
JustSong
519cb030f7 chore: update input label 2023-05-16 16:23:07 +08:00
JustSong
58fe923c85 perf: use max_tokens to reduce token consuming 2023-05-16 16:22:25 +08:00
JustSong
c9ac5e391f feat: support max_tokens now (#52) 2023-05-16 16:18:35 +08:00
JustSong
69cf1de7bd feat: disable operations for root user (close #76) 2023-05-16 15:38:03 +08:00
JustSong
4d6172a242 feat: able to set pre consumed quota now 2023-05-16 13:57:01 +08:00
6 changed files with 48 additions and 17 deletions

View File

@@ -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 = ""

View File

@@ -210,11 +210,12 @@ func testChannel(channel *model.Channel, request *ChatRequest) error {
func buildTestRequest(c *gin.Context) *ChatRequest { func buildTestRequest(c *gin.Context) *ChatRequest {
model_ := c.Query("model") model_ := c.Query("model")
testRequest := &ChatRequest{ testRequest := &ChatRequest{
Model: model_, Model: model_,
MaxTokens: 1,
} }
testMessage := Message{ testMessage := Message{
Role: "user", Role: "user",
Content: "echo hi", Content: "hi",
} }
testRequest.Messages = append(testRequest.Messages, testMessage) testRequest.Messages = append(testRequest.Messages, testMessage)
return testRequest return testRequest

View File

@@ -21,14 +21,16 @@ type Message struct {
} }
type ChatRequest struct { type ChatRequest struct {
Model string `json:"model"` Model string `json:"model"`
Messages []Message `json:"messages"` Messages []Message `json:"messages"`
MaxTokens int `json:"max_tokens"`
} }
type TextRequest struct { type TextRequest struct {
Model string `json:"model"` Model string `json:"model"`
Messages []Message `json:"messages"` Messages []Message `json:"messages"`
Prompt string `json:"prompt"` Prompt string `json:"prompt"`
MaxTokens int `json:"max_tokens"`
//Stream bool `json:"stream"` //Stream bool `json:"stream"`
} }
@@ -128,7 +130,17 @@ 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)
} }
preConsumedQuota := 500 // TODO: make this configurable, take ratio into account var promptText string
for _, message := range textRequest.Messages {
promptText += fmt.Sprintf("%s: %s\n", message.Role, message.Content)
}
promptTokens := countToken(promptText) + 3
preConsumedTokens := common.PreConsumedQuota
if textRequest.MaxTokens != 0 {
preConsumedTokens = promptTokens + textRequest.MaxTokens
}
ratio := common.GetModelRatio(textRequest.Model)
preConsumedQuota := int(float64(preConsumedTokens) * ratio)
if consumeQuota { if consumeQuota {
err := model.PreConsumeTokenQuota(tokenId, preConsumedQuota) err := model.PreConsumeTokenQuota(tokenId, preConsumedQuota)
if err != nil { if err != nil {
@@ -175,16 +187,11 @@ func relayHelper(c *gin.Context) error {
completionRatio = 2 completionRatio = 2
} }
if isStream { if isStream {
var promptText string
for _, message := range textRequest.Messages {
promptText += fmt.Sprintf("%s: %s\n", message.Role, message.Content)
}
completionText := fmt.Sprintf("%s: %s\n", "assistant", streamResponseText) completionText := fmt.Sprintf("%s: %s\n", "assistant", streamResponseText)
quota = countToken(promptText) + countToken(completionText)*completionRatio + 3 quota = promptTokens + countToken(completionText)*completionRatio
} 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)
quotaDelta := quota - preConsumedQuota quotaDelta := quota - preConsumedQuota
err := model.PostConsumeTokenQuota(tokenId, quotaDelta) err := model.PostConsumeTokenQuota(tokenId, quotaDelta)

View File

@@ -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":

View File

@@ -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
@@ -321,7 +336,7 @@ const SystemSetting = () => {
</Header> </Header>
<Form.Group widths={3}> <Form.Group widths={3}>
<Form.Input <Form.Input
label='最长应时间' label='最长应时间'
name='ChannelDisableThreshold' name='ChannelDisableThreshold'
onChange={handleInputChange} onChange={handleInputChange}
autoComplete='new-password' autoComplete='new-password'

View File

@@ -234,6 +234,7 @@ const UsersTable = () => {
onClick={() => { onClick={() => {
manageUser(user.username, 'promote', idx); manageUser(user.username, 'promote', idx);
}} }}
disabled={user.role === 100}
> >
提升 提升
</Button> </Button>
@@ -243,12 +244,13 @@ const UsersTable = () => {
onClick={() => { onClick={() => {
manageUser(user.username, 'demote', idx); manageUser(user.username, 'demote', idx);
}} }}
disabled={user.role === 100}
> >
降级 降级
</Button> </Button>
<Popup <Popup
trigger={ trigger={
<Button size='small' negative> <Button size='small' negative disabled={user.role === 100}>
删除 删除
</Button> </Button>
} }
@@ -274,6 +276,7 @@ const UsersTable = () => {
idx idx
); );
}} }}
disabled={user.role === 100}
> >
{user.status === 1 ? '禁用' : '启用'} {user.status === 1 ? '禁用' : '启用'}
</Button> </Button>
@@ -281,6 +284,7 @@ const UsersTable = () => {
size={'small'} size={'small'}
as={Link} as={Link}
to={'/user/edit/' + user.id} to={'/user/edit/' + user.id}
disabled={user.role === 100}
> >
编辑 编辑
</Button> </Button>