Commit 78e05b8e by CaIon

Merge branch 'main' into private

parents b106799a 8c5fd7b7
...@@ -11,11 +11,10 @@ import ( ...@@ -11,11 +11,10 @@ import (
"net/http" "net/http"
"one-api/common" "one-api/common"
"one-api/model" "one-api/model"
"strings"
) )
func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode { func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
imageModel := "dall-e"
tokenId := c.GetInt("token_id") tokenId := c.GetInt("token_id")
channelType := c.GetInt("channel") channelType := c.GetInt("channel")
channelId := c.GetInt("channel_id") channelId := c.GetInt("channel_id")
...@@ -31,14 +30,21 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode ...@@ -31,14 +30,21 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode
} }
} }
if imageRequest.Model == "" {
imageRequest.Model = "dall-e"
}
// Prompt validation // Prompt validation
if imageRequest.Prompt == "" { if imageRequest.Prompt == "" {
return errorWrapper(errors.New("prompt is required"), "required_field_missing", http.StatusBadRequest) return errorWrapper(errors.New("prompt is required"), "required_field_missing", http.StatusBadRequest)
} }
if strings.Contains(imageRequest.Size, "×") {
return errorWrapper(errors.New("size an unexpected error occurred in the parameter, please use 'x' instead of the multiplication sign '×'"), "invalid_field_value", http.StatusBadRequest)
}
// Not "256x256", "512x512", or "1024x1024" // Not "256x256", "512x512", or "1024x1024"
if imageRequest.Size != "" && imageRequest.Size != "256x256" && imageRequest.Size != "512x512" && imageRequest.Size != "1024x1024" { if imageRequest.Size != "" && imageRequest.Size != "256x256" && imageRequest.Size != "512x512" && imageRequest.Size != "1024x1024" &&
return errorWrapper(errors.New("size must be one of 256x256, 512x512, or 1024x1024"), "invalid_field_value", http.StatusBadRequest) (imageRequest.Model == "dall-e-3" && (imageRequest.Size != "1024x1792" && imageRequest.Size != "1792x1024")) {
return errorWrapper(errors.New("size must be one of 256x256, 512x512, or 1024x1024, dall-e-3 1024x1792 or 1792x1024"), "invalid_field_value", http.StatusBadRequest)
} }
// N should between 1 and 10 // N should between 1 and 10
...@@ -55,8 +61,8 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode ...@@ -55,8 +61,8 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode
if err != nil { if err != nil {
return errorWrapper(err, "unmarshal_model_mapping_failed", http.StatusInternalServerError) return errorWrapper(err, "unmarshal_model_mapping_failed", http.StatusInternalServerError)
} }
if modelMap[imageModel] != "" { if modelMap[imageRequest.Model] != "" {
imageModel = modelMap[imageModel] imageRequest.Model = modelMap[imageRequest.Model]
isModelMapped = true isModelMapped = true
} }
} }
...@@ -77,7 +83,7 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode ...@@ -77,7 +83,7 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode
requestBody = c.Request.Body requestBody = c.Request.Body
} }
modelRatio := common.GetModelRatio(imageModel) modelRatio := common.GetModelRatio(imageRequest.Model)
groupRatio := common.GetGroupRatio(group) groupRatio := common.GetGroupRatio(group)
ratio := modelRatio * groupRatio ratio := modelRatio * groupRatio
userQuota, err := model.CacheGetUserQuota(userId) userQuota, err := model.CacheGetUserQuota(userId)
...@@ -90,8 +96,19 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode ...@@ -90,8 +96,19 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode
sizeRatio = 1.125 sizeRatio = 1.125
} else if imageRequest.Size == "1024x1024" { } else if imageRequest.Size == "1024x1024" {
sizeRatio = 1.25 sizeRatio = 1.25
} else if imageRequest.Size == "1024x1792" || imageRequest.Size == "1792x1024" {
sizeRatio = 2.5
}
qualityRatio := 1.0
if imageRequest.Model == "dall-e-3" && imageRequest.Quality == "hd" {
qualityRatio = 2.0
if imageRequest.Size == "1024×1792" || imageRequest.Size == "1792×1024" {
qualityRatio = 1.5
}
} }
quota := int(ratio*sizeRatio*1000) * imageRequest.N
quota := int(ratio*sizeRatio*qualityRatio*1000) * imageRequest.N
if consumeQuota && userQuota-quota < 0 { if consumeQuota && userQuota-quota < 0 {
return errorWrapper(errors.New("user quota is not enough"), "insufficient_user_quota", http.StatusForbidden) return errorWrapper(errors.New("user quota is not enough"), "insufficient_user_quota", http.StatusForbidden)
...@@ -120,7 +137,6 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode ...@@ -120,7 +137,6 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode
return errorWrapper(err, "close_request_body_failed", http.StatusInternalServerError) return errorWrapper(err, "close_request_body_failed", http.StatusInternalServerError)
} }
var textResponse ImageResponse var textResponse ImageResponse
defer func(ctx context.Context) { defer func(ctx context.Context) {
if consumeQuota { if consumeQuota {
err := model.PostConsumeTokenQuota(tokenId, quota) err := model.PostConsumeTokenQuota(tokenId, quota)
...@@ -134,7 +150,7 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode ...@@ -134,7 +150,7 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode
if quota != 0 { if quota != 0 {
tokenName := c.GetString("token_name") tokenName := c.GetString("token_name")
logContent := fmt.Sprintf("模型倍率 %.2f,分组倍率 %.2f", modelRatio, groupRatio) logContent := fmt.Sprintf("模型倍率 %.2f,分组倍率 %.2f", modelRatio, groupRatio)
model.RecordConsumeLog(ctx, userId, channelId, 0, 0, imageModel, tokenName, quota, logContent, tokenId) model.RecordConsumeLog(ctx, userId, channelId, 0, 0, imageRequest.Model, tokenName, quota, logContent, tokenId)
model.UpdateUserUsedQuotaAndRequestCount(userId, quota) model.UpdateUserUsedQuotaAndRequestCount(userId, quota)
channelId := c.GetInt("channel_id") channelId := c.GetInt("channel_id")
model.UpdateChannelUsedQuota(channelId, quota) model.UpdateChannelUsedQuota(channelId, quota)
......
...@@ -85,6 +85,8 @@ type TextRequest struct { ...@@ -85,6 +85,8 @@ type TextRequest struct {
} }
type ImageRequest struct { type ImageRequest struct {
Model string `json:"model"`
Quality string `json:"quality"`
Prompt string `json:"prompt"` Prompt string `json:"prompt"`
N int `json:"n"` N int `json:"n"`
Size string `json:"size"` Size string `json:"size"`
......
...@@ -17,6 +17,7 @@ type Redemption struct { ...@@ -17,6 +17,7 @@ type Redemption struct {
CreatedTime int64 `json:"created_time" gorm:"bigint"` CreatedTime int64 `json:"created_time" gorm:"bigint"`
RedeemedTime int64 `json:"redeemed_time" gorm:"bigint"` RedeemedTime int64 `json:"redeemed_time" gorm:"bigint"`
Count int `json:"count" gorm:"-:all"` // only for api request Count int `json:"count" gorm:"-:all"` // only for api request
UsedUserId int `json:"used_user_id"`
} }
func GetAllRedemptions(startIdx int, num int) ([]*Redemption, error) { func GetAllRedemptions(startIdx int, num int) ([]*Redemption, error) {
...@@ -69,6 +70,7 @@ func Redeem(key string, userId int) (quota int, err error) { ...@@ -69,6 +70,7 @@ func Redeem(key string, userId int) (quota int, err error) {
} }
redemption.RedeemedTime = common.GetTimestamp() redemption.RedeemedTime = common.GetTimestamp()
redemption.Status = common.RedemptionCodeStatusUsed redemption.Status = common.RedemptionCodeStatusUsed
redemption.UsedUserId = userId
err = tx.Save(redemption).Error err = tx.Save(redemption).Error
return err return err
}) })
......
import React, {useEffect, useState} from 'react'; import React, {useEffect, useState} from 'react';
import {Label} from 'semantic-ui-react'; import {Label} from 'semantic-ui-react';
import {API, isAdmin, showError, timestamp2string} from '../helpers'; import {API, copy, isAdmin, showError, showSuccess, timestamp2string} from '../helpers';
import {Table, Avatar, Tag, Form, Button, Layout, Select, Popover, Modal} from '@douyinfe/semi-ui'; import {Table, Avatar, Tag, Form, Button, Layout, Select, Popover, Modal} from '@douyinfe/semi-ui';
import {ITEMS_PER_PAGE} from '../constants'; import {ITEMS_PER_PAGE} from '../constants';
...@@ -106,7 +106,9 @@ const LogsTable = () => { ...@@ -106,7 +106,9 @@ const LogsTable = () => {
return ( return (
record.type === 0 || record.type === 2 ? record.type === 0 || record.type === 2 ?
<div> <div>
{<Tag color='grey' size='large'> {text} </Tag>} <Tag color='grey' size='large' onClick={()=>{
copyText(text)
}}> {text} </Tag>
</div> </div>
: :
<></> <></>
...@@ -131,7 +133,9 @@ const LogsTable = () => { ...@@ -131,7 +133,9 @@ const LogsTable = () => {
return ( return (
record.type === 0 || record.type === 2 ? record.type === 0 || record.type === 2 ?
<div> <div>
{<Tag color={stringToColor(text)} size='large'> {text} </Tag>} <Tag color={stringToColor(text)} size='large' onClick={()=>{
copyText(text)
}}> {text} </Tag>
</div> </div>
: :
<></> <></>
...@@ -329,6 +333,15 @@ const LogsTable = () => { ...@@ -329,6 +333,15 @@ const LogsTable = () => {
await loadLogs(0); await loadLogs(0);
}; };
const copyText = async (text) => {
if (await copy(text)) {
showSuccess('已复制:' + text);
} else {
// setSearchKeyword(text);
Modal.error({ title: '无法复制到剪贴板,请手动复制', content: text });
}
}
useEffect(() => { useEffect(() => {
refresh().then(); refresh().then();
}, [logType]); }, [logType]);
...@@ -397,7 +410,7 @@ const LogsTable = () => { ...@@ -397,7 +410,7 @@ const LogsTable = () => {
<Form.Input field="model_name" label='模型名称' style={{width: 176}} value={model_name} <Form.Input field="model_name" label='模型名称' style={{width: 176}} value={model_name}
placeholder='可选值' placeholder='可选值'
name='model_name' name='model_name'
onChange={value => handlePageChange(value, 'model_name')}/> onChange={value => handleInputChange(value, 'model_name')}/>
<Form.DatePicker field="start_timestamp" label='起始时间' style={{width: 272}} <Form.DatePicker field="start_timestamp" label='起始时间' style={{width: 272}}
value={start_timestamp} type='dateTime' value={start_timestamp} type='dateTime'
name='start_timestamp' name='start_timestamp'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment