feat: The 'chat_models' field of user table, holds the model IDS in place of the model values

This commit is contained in:
RockYang 2024-03-18 15:37:46 +08:00
parent 172d498618
commit c72d963f45
13 changed files with 73 additions and 76 deletions

View File

@ -131,30 +131,30 @@ const XunFei = Platform("XunFei")
const QWen = Platform("QWen") const QWen = Platform("QWen")
type SystemConfig struct { type SystemConfig struct {
Title string `json:"title"` Title string `json:"title,omitempty"`
AdminTitle string `json:"admin_title"` AdminTitle string `json:"admin_title,omitempty"`
Logo string `json:"logo"` Logo string `json:"logo,omitempty"`
InitPower int `json:"init_power"` // 新用户注册赠送算力值 InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值
DailyPower int `json:"daily_power"` // 每日赠送算力 DailyPower int `json:"daily_power,omitempty"` // 每日赠送算力
InvitePower int `json:"invite_power"` // 邀请新用户赠送算力值 InvitePower int `json:"invite_power,omitempty"` // 邀请新用户赠送算力值
VipMonthPower int `json:"vip_month_power"` // VIP 会员每月赠送的算力值 VipMonthPower int `json:"vip_month_power,omitempty"` // VIP 会员每月赠送的算力值
RegisterWays []string `json:"register_ways"` // 注册方式:支持手机,邮箱注册 RegisterWays []string `json:"register_ways,omitempty"` // 注册方式:支持手机,邮箱注册
EnabledRegister bool `json:"enabled_register"` // 是否开放注册 EnabledRegister bool `json:"enabled_register,omitempty"` // 是否开放注册
RewardImg string `json:"reward_img"` // 众筹收款二维码地址 RewardImg string `json:"reward_img,omitempty"` // 众筹收款二维码地址
EnabledReward bool `json:"enabled_reward"` // 启用众筹功能 EnabledReward bool `json:"enabled_reward,omitempty"` // 启用众筹功能
PowerPrice float64 `json:"power_price"` // 算力单价 PowerPrice float64 `json:"power_price,omitempty"` // 算力单价
OrderPayTimeout int `json:"order_pay_timeout"` //订单支付超时时间 OrderPayTimeout int `json:"order_pay_timeout,omitempty"` //订单支付超时时间
DefaultModels []string `json:"default_models"` // 默认开通的 AI 模型 DefaultModels []int `json:"default_models,omitempty"` // 默认开通的 AI 模型
MjPower int `json:"mj_power"` // MJ 绘画消耗算力 MjPower int `json:"mj_power,omitempty"` // MJ 绘画消耗算力
SdPower int `json:"sd_power"` // SD 绘画消耗算力 SdPower int `json:"sd_power,omitempty"` // SD 绘画消耗算力
DallPower int `json:"dall_power"` // DALLE3 绘图消耗算力 DallPower int `json:"dall_power,omitempty"` // DALLE3 绘图消耗算力
WechatCardURL string `json:"wechat_card_url"` // 微信客服地址 WechatCardURL string `json:"wechat_card_url,omitempty"` // 微信客服地址
EnableContext bool `json:"enable_context"` EnableContext bool `json:"enable_context,omitempty"`
ContextDeep int `json:"context_deep"` ContextDeep int `json:"context_deep,omitempty"`
} }

View File

@ -26,18 +26,18 @@ func NewChatModelHandler(app *core.AppServer, db *gorm.DB) *ChatModelHandler {
func (h *ChatModelHandler) Save(c *gin.Context) { func (h *ChatModelHandler) Save(c *gin.Context) {
var data struct { var data struct {
Id uint `json:"id"` Id uint `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Value string `json:"value"` Value string `json:"value"`
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
SortNum int `json:"sort_num"` SortNum int `json:"sort_num"`
Open bool `json:"open"` Open bool `json:"open"`
Platform string `json:"platform"` Platform string `json:"platform"`
Power int `json:"power"` Power int `json:"power"`
MaxTokens int `json:"max_tokens"` // 最大响应长度 MaxTokens int `json:"max_tokens"` // 最大响应长度
MaxContext int `json:"max_context"` // 最大上下文长度 MaxContext int `json:"max_context"` // 最大上下文长度
Temperature string `json:"temperature"` // 模型温度 Temperature float32 `json:"temperature"` // 模型温度
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
} }
if err := c.ShouldBindJSON(&data); err != nil { if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs) resp.ERROR(c, types.InvalidArgs)
@ -53,7 +53,7 @@ func (h *ChatModelHandler) Save(c *gin.Context) {
Open: data.Open, Open: data.Open,
MaxTokens: data.MaxTokens, MaxTokens: data.MaxTokens,
MaxContext: data.MaxContext, MaxContext: data.MaxContext,
Temperature: float32(utils.Str2Float(data.Temperature)), Temperature: data.Temperature,
Power: data.Power} Power: data.Power}
item.Id = data.Id item.Id = data.Id
if item.Id > 0 { if item.Id > 0 {

View File

@ -25,8 +25,12 @@ func NewConfigHandler(app *core.AppServer, db *gorm.DB) *ConfigHandler {
func (h *ConfigHandler) Update(c *gin.Context) { func (h *ConfigHandler) Update(c *gin.Context) {
var data struct { var data struct {
Key string `json:"key"` Key string `json:"key"`
Config map[string]interface{} `json:"config"` Config struct {
types.SystemConfig
Content string `json:"content,omitempty"`
Updated bool `json:"updated,omitempty"`
} `json:"config"`
} }
if err := c.ShouldBindJSON(&data); err != nil { if err := c.ShouldBindJSON(&data); err != nil {

View File

@ -72,7 +72,7 @@ func (h *UserHandler) Save(c *gin.Context) {
Password string `json:"password"` Password string `json:"password"`
Username string `json:"username"` Username string `json:"username"`
ChatRoles []string `json:"chat_roles"` ChatRoles []string `json:"chat_roles"`
ChatModels []string `json:"chat_models"` ChatModels []int `json:"chat_models"`
ExpiredTime string `json:"expired_time"` ExpiredTime string `json:"expired_time"`
Status bool `json:"status"` Status bool `json:"status"`
Vip bool `json:"vip"` Vip bool `json:"vip"`

View File

@ -32,7 +32,7 @@ func (h *ChatModelHandler) List(c *gin.Context) {
return return
} }
var models []string var models []int
err = utils.JsonDecode(user.ChatModels, &models) err = utils.JsonDecode(user.ChatModels, &models)
if err != nil { if err != nil {
resp.ERROR(c, "当前用户没有订阅任何模型") resp.ERROR(c, "当前用户没有订阅任何模型")
@ -41,7 +41,7 @@ func (h *ChatModelHandler) List(c *gin.Context) {
// 查询用户有权限访问的模型以及所有开放的模型 // 查询用户有权限访问的模型以及所有开放的模型
res := h.db.Where("enabled = ?", true).Where( res := h.db.Where("enabled = ?", true).Where(
h.db.Where("value IN ?", models).Or("open =?", true), h.db.Where("id IN ?", models).Or("open =?", true),
).Order("sort_num ASC").Find(&items) ).Order("sort_num ASC").Find(&items)
if res.Error == nil { if res.Error == nil {
for _, item := range items { for _, item := range items {

View File

@ -8,7 +8,7 @@ type User struct {
Salt string `json:"salt"` // 密码盐 Salt string `json:"salt"` // 密码盐
Power int `json:"power"` // 剩余算力 Power int `json:"power"` // 剩余算力
ChatRoles []string `json:"chat_roles"` // 聊天角色集合 ChatRoles []string `json:"chat_roles"` // 聊天角色集合
ChatModels []string `json:"chat_models"` // AI模型集合 ChatModels []int `json:"chat_models"` // AI模型集合
ExpiredTime int64 `json:"expired_time"` // 账户到期时间 ExpiredTime int64 `json:"expired_time"` // 账户到期时间
Status bool `json:"status"` // 当前状态 Status bool `json:"status"` // 当前状态
LastLoginAt int64 `json:"last_login_at"` // 最后登录时间 LastLoginAt int64 `json:"last_login_at"` // 最后登录时间

View File

@ -30,7 +30,7 @@ DROP `total_tokens`,
DROP `img_calls`; DROP `img_calls`;
ALTER TABLE `chatgpt_chat_models` CHANGE `weight` `power` TINYINT NOT NULL COMMENT '消耗算力点数'; ALTER TABLE `chatgpt_chat_models` CHANGE `weight` `power` TINYINT NOT NULL COMMENT '消耗算力点数';
ALTER TABLE `chatgpt_chat_models` ADD `temperature` FLOAT(3,2) NOT NULL DEFAULT '1' COMMENT '模型创意度' AFTER `power`, ADD `max_tokens` INT(11) NOT NULL DEFAULT '1024' COMMENT '最大响应长度' AFTER `temperature`, ADD `max_context` INT(11) NOT NULL DEFAULT '4096' COMMENT '最大上下文长度' AFTER `max_tokens`; ALTER TABLE `chatgpt_chat_models` ADD `temperature` FLOAT(3,1) NOT NULL DEFAULT '1' COMMENT '模型创意度' AFTER `power`, ADD `max_tokens` INT(11) NOT NULL DEFAULT '1024' COMMENT '最大响应长度' AFTER `temperature`, ADD `max_context` INT(11) NOT NULL DEFAULT '4096' COMMENT '最大上下文长度' AFTER `max_tokens`;
CREATE TABLE `chatgpt_plus`.`chatgpt_power_logs` ( `id` INT(11) NOT NULL AUTO_INCREMENT , `user_id` INT(11) NOT NULL COMMENT '用户ID' , `username` VARCHAR(30) NOT NULL COMMENT '用户名' , `type` TINYINT(1) NOT NULL COMMENT '类型1充值2消费3退费' , `amount` SMALLINT(3) NOT NULL COMMENT '算力花费' , `balance` INT(11) NOT NULL COMMENT '余额' , `model` VARCHAR(30) NOT NULL COMMENT '模型' , `remark` VARCHAR(255) NOT NULL COMMENT '备注' , `created_at` DATETIME NOT NULL COMMENT '创建时间' , PRIMARY KEY (`id`)) ENGINE = InnoDB COMMENT = '用户算力消费日志'; CREATE TABLE `chatgpt_plus`.`chatgpt_power_logs` ( `id` INT(11) NOT NULL AUTO_INCREMENT , `user_id` INT(11) NOT NULL COMMENT '用户ID' , `username` VARCHAR(30) NOT NULL COMMENT '用户名' , `type` TINYINT(1) NOT NULL COMMENT '类型1充值2消费3退费' , `amount` SMALLINT(3) NOT NULL COMMENT '算力花费' , `balance` INT(11) NOT NULL COMMENT '余额' , `model` VARCHAR(30) NOT NULL COMMENT '模型' , `remark` VARCHAR(255) NOT NULL COMMENT '备注' , `created_at` DATETIME NOT NULL COMMENT '创建时间' , PRIMARY KEY (`id`)) ENGINE = InnoDB COMMENT = '用户算力消费日志';

View File

@ -142,6 +142,7 @@
color: #fff; color: #fff;
} }
#app .common-layout .el-main .chat-head .chat-config .el-select { #app .common-layout .el-main .chat-head .chat-config .el-select {
max-width: 150px;
margin-right: 10px; margin-right: 10px;
} }
#app .common-layout .el-main .chat-head .chat-config .role-select { #app .common-layout .el-main .chat-head .chat-config .role-select {

View File

@ -181,7 +181,7 @@ $borderColor = #4676d0;
} }
.el-select { .el-select {
//max-width 150px; max-width 150px;
margin-right 10px; margin-right 10px;
} }
@ -202,6 +202,7 @@ $borderColor = #4676d0;
.is-circle { .is-circle {
margin-left 5px margin-left 5px
.iconfont { .iconfont {
margin-right 0 margin-right 0
} }

View File

@ -82,7 +82,7 @@
<el-main v-loading="loading" element-loading-background="rgba(122, 122, 122, 0.3)"> <el-main v-loading="loading" element-loading-background="rgba(122, 122, 122, 0.3)">
<div class="chat-head"> <div class="chat-head">
<div class="chat-config"> <div class="chat-config">
<span class="role-select-label">聊天角色</span> <!-- <span class="role-select-label">聊天角色</span>-->
<el-select v-model="roleId" filterable placeholder="角色" class="role-select" @change="newChat"> <el-select v-model="roleId" filterable placeholder="角色" class="role-select" @change="newChat">
<el-option <el-option
v-for="item in roles" v-for="item in roles"

View File

@ -266,6 +266,7 @@ const edit = function (row) {
const save = function () { const save = function () {
formRef.value.validate((valid) => { formRef.value.validate((valid) => {
item.value.temperature = parseFloat(item.value.temperature)
if (valid) { if (valid) {
showDialog.value = false showDialog.value = false
httpPost('/api/admin/model/save', item.value).then((res) => { httpPost('/api/admin/model/save', item.value).then((res) => {

View File

@ -36,7 +36,14 @@
<el-form-item label="VIP每月赠送算力" prop="vip_month_power"> <el-form-item label="VIP每月赠送算力" prop="vip_month_power">
<el-input v-model.number="system['vip_month_power']" placeholder="VIP用户每月赠送算力"/> <el-input v-model.number="system['vip_month_power']" placeholder="VIP用户每月赠送算力"/>
</el-form-item> </el-form-item>
<el-form-item label="每日赠送算力" prop="daily_power">
<div class="tip-input-line">
<el-input v-model.number="system['daily_power']" placeholder="默认值0"/>
<div class="tip">
如果设置0表示不赠送用户享受完免费算力额度之后就不能再发起对话了如果设置为N则系统每天将算力值小于N的用户自动补充到N注意此功能要配合XXL-JOB启用
</div>
</div>
</el-form-item>
<el-form-item label="开放注册" prop="enabled_register"> <el-form-item label="开放注册" prop="enabled_register">
<el-switch v-model="system['enabled_register']"/> <el-switch v-model="system['enabled_register']"/>
<el-tooltip <el-tooltip
@ -144,7 +151,7 @@
v-for="item in models" v-for="item in models"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.value" :value="item.id"
/> />
</el-select> </el-select>
<div class="info"> <div class="info">
@ -167,12 +174,12 @@
<el-switch v-model="system['enable_context']"/> <el-switch v-model="system['enable_context']"/>
</el-form-item> </el-form-item>
<el-form-item label="会话上下文深度"> <el-form-item label="会话上下文深度">
<div style="width:100%"> <div class="tip-input-line">
<el-input-number v-model="system['context_deep']" :min="0" :max="10"/> <el-input-number v-model="system['context_deep']" :min="0" :max="10"/>
</div> <div class="tip">会话上下文深度在老会话中继续会话默认加载多少条聊天记录作为上下文如果设置为
<div class="tip" style="margin-top: 10px; ">会话上下文深度在老会话中继续会话默认加载多少条聊天记录作为上下文如果设置为 0
0 则不加载聊天记录仅仅使用当前角色的上下文该配置参数最好设置需要为偶数否则将无法兼容百度的 API
则不加载聊天记录仅仅使用当前角色的上下文该配置参数最好设置需要为偶数否则将无法兼容百度的 API </div>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
@ -202,17 +209,6 @@ import 'md-editor-v3/lib/style.css';
const activeName = ref('basic') const activeName = ref('basic')
const system = ref({models: []}) const system = ref({models: []})
const chat = ref({
open_ai: {temperature: 1, max_tokens: 1024},
azure: {temperature: 1, max_tokens: 1024},
chat_gml: {temperature: 0.95, max_tokens: 1024},
baidu: {temperature: 0.95, max_tokens: 1024},
xun_fei: {temperature: 0.5, max_tokens: 1024},
context_deep: 0,
enable_context: true,
enable_history: true,
dall_api_url: "",
})
const loading = ref(true) const loading = ref(true)
const systemFormRef = ref(null) const systemFormRef = ref(null)
const chatFormRef = ref(null) const chatFormRef = ref(null)
@ -226,14 +222,6 @@ onMounted(() => {
}).catch(e => { }).catch(e => {
ElMessage.error("加载系统配置失败: " + e.message) ElMessage.error("加载系统配置失败: " + e.message)
}) })
//
httpGet('/api/admin/config/get?key=chat').then(res => {
chat.value = res.data
}).catch(e => {
ElMessage.error("加载聊天配置失败: " + e.message)
})
// //
httpGet('/api/admin/config/get?key=notice').then(res => { httpGet('/api/admin/config/get?key=notice').then(res => {
notice.value = res.data['content'] notice.value = res.data['content']
@ -361,12 +349,6 @@ const onUploadImg = (files, callback) => {
padding-left 10px; padding-left 10px;
} }
.tip {
color #c1c1c1
font-size 12px;
line-height 1.5;
}
.el-icon { .el-icon {
font-size 16px font-size 16px
margin-left 10px margin-left 10px
@ -378,6 +360,15 @@ const onUploadImg = (files, callback) => {
position relative position relative
top 3px top 3px
} }
.tip-input-line {
.tip {
margin-top 10px
color #c1c1c1
font-size 12px;
line-height 1.5;
}
}
} }
} }

View File

@ -116,7 +116,7 @@
v-for="item in models" v-for="item in models"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.value" :value="item.id"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -297,7 +297,6 @@ const saveUser = function () {
} }
const handleSelectionChange = function (rows) { const handleSelectionChange = function (rows) {
// TODO:
console.log(rows) console.log(rows)
} }