From c72d963f45c82168994a6004c04159cba0b35575 Mon Sep 17 00:00:00 2001 From: RockYang Date: Mon, 18 Mar 2024 15:37:46 +0800 Subject: [PATCH] feat: The 'chat_models' field of user table, holds the model IDS in place of the model values --- api/core/types/config.go | 40 +++++++++--------- api/handler/admin/chat_model_handler.go | 26 ++++++------ api/handler/admin/config_handler.go | 8 +++- api/handler/admin/user_handler.go | 2 +- api/handler/chat_model_handler.go | 4 +- api/store/vo/user.go | 2 +- database/update-v4.0.0.sql | 2 +- web/src/assets/css/chat-plus.css | 1 + web/src/assets/css/chat-plus.styl | 3 +- web/src/views/ChatPlus.vue | 2 +- web/src/views/admin/ChatModel.vue | 1 + web/src/views/admin/SysConfig.vue | 55 +++++++++++-------------- web/src/views/admin/Users.vue | 3 +- 13 files changed, 73 insertions(+), 76 deletions(-) diff --git a/api/core/types/config.go b/api/core/types/config.go index 5d1c6cb7..e48a6e6d 100644 --- a/api/core/types/config.go +++ b/api/core/types/config.go @@ -131,30 +131,30 @@ const XunFei = Platform("XunFei") const QWen = Platform("QWen") type SystemConfig struct { - Title string `json:"title"` - AdminTitle string `json:"admin_title"` - Logo string `json:"logo"` - InitPower int `json:"init_power"` // 新用户注册赠送算力值 - DailyPower int `json:"daily_power"` // 每日赠送算力 - InvitePower int `json:"invite_power"` // 邀请新用户赠送算力值 - VipMonthPower int `json:"vip_month_power"` // VIP 会员每月赠送的算力值 + Title string `json:"title,omitempty"` + AdminTitle string `json:"admin_title,omitempty"` + Logo string `json:"logo,omitempty"` + InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值 + DailyPower int `json:"daily_power,omitempty"` // 每日赠送算力 + InvitePower int `json:"invite_power,omitempty"` // 邀请新用户赠送算力值 + VipMonthPower int `json:"vip_month_power,omitempty"` // VIP 会员每月赠送的算力值 - RegisterWays []string `json:"register_ways"` // 注册方式:支持手机,邮箱注册 - EnabledRegister bool `json:"enabled_register"` // 是否开放注册 + RegisterWays []string `json:"register_ways,omitempty"` // 注册方式:支持手机,邮箱注册 + EnabledRegister bool `json:"enabled_register,omitempty"` // 是否开放注册 - RewardImg string `json:"reward_img"` // 众筹收款二维码地址 - EnabledReward bool `json:"enabled_reward"` // 启用众筹功能 - PowerPrice float64 `json:"power_price"` // 算力单价 + RewardImg string `json:"reward_img,omitempty"` // 众筹收款二维码地址 + EnabledReward bool `json:"enabled_reward,omitempty"` // 启用众筹功能 + PowerPrice float64 `json:"power_price,omitempty"` // 算力单价 - OrderPayTimeout int `json:"order_pay_timeout"` //订单支付超时时间 - DefaultModels []string `json:"default_models"` // 默认开通的 AI 模型 + OrderPayTimeout int `json:"order_pay_timeout,omitempty"` //订单支付超时时间 + DefaultModels []int `json:"default_models,omitempty"` // 默认开通的 AI 模型 - MjPower int `json:"mj_power"` // MJ 绘画消耗算力 - SdPower int `json:"sd_power"` // SD 绘画消耗算力 - DallPower int `json:"dall_power"` // DALLE3 绘图消耗算力 + MjPower int `json:"mj_power,omitempty"` // MJ 绘画消耗算力 + SdPower int `json:"sd_power,omitempty"` // SD 绘画消耗算力 + 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"` - ContextDeep int `json:"context_deep"` + EnableContext bool `json:"enable_context,omitempty"` + ContextDeep int `json:"context_deep,omitempty"` } diff --git a/api/handler/admin/chat_model_handler.go b/api/handler/admin/chat_model_handler.go index a1bd0c73..b3477bf5 100644 --- a/api/handler/admin/chat_model_handler.go +++ b/api/handler/admin/chat_model_handler.go @@ -26,18 +26,18 @@ func NewChatModelHandler(app *core.AppServer, db *gorm.DB) *ChatModelHandler { func (h *ChatModelHandler) Save(c *gin.Context) { var data struct { - Id uint `json:"id"` - Name string `json:"name"` - Value string `json:"value"` - Enabled bool `json:"enabled"` - SortNum int `json:"sort_num"` - Open bool `json:"open"` - Platform string `json:"platform"` - Power int `json:"power"` - MaxTokens int `json:"max_tokens"` // 最大响应长度 - MaxContext int `json:"max_context"` // 最大上下文长度 - Temperature string `json:"temperature"` // 模型温度 - CreatedAt int64 `json:"created_at"` + Id uint `json:"id"` + Name string `json:"name"` + Value string `json:"value"` + Enabled bool `json:"enabled"` + SortNum int `json:"sort_num"` + Open bool `json:"open"` + Platform string `json:"platform"` + Power int `json:"power"` + MaxTokens int `json:"max_tokens"` // 最大响应长度 + MaxContext int `json:"max_context"` // 最大上下文长度 + Temperature float32 `json:"temperature"` // 模型温度 + CreatedAt int64 `json:"created_at"` } if err := c.ShouldBindJSON(&data); err != nil { resp.ERROR(c, types.InvalidArgs) @@ -53,7 +53,7 @@ func (h *ChatModelHandler) Save(c *gin.Context) { Open: data.Open, MaxTokens: data.MaxTokens, MaxContext: data.MaxContext, - Temperature: float32(utils.Str2Float(data.Temperature)), + Temperature: data.Temperature, Power: data.Power} item.Id = data.Id if item.Id > 0 { diff --git a/api/handler/admin/config_handler.go b/api/handler/admin/config_handler.go index 08c939ba..54dbd9dd 100644 --- a/api/handler/admin/config_handler.go +++ b/api/handler/admin/config_handler.go @@ -25,8 +25,12 @@ func NewConfigHandler(app *core.AppServer, db *gorm.DB) *ConfigHandler { func (h *ConfigHandler) Update(c *gin.Context) { var data struct { - Key string `json:"key"` - Config map[string]interface{} `json:"config"` + Key string `json:"key"` + Config struct { + types.SystemConfig + Content string `json:"content,omitempty"` + Updated bool `json:"updated,omitempty"` + } `json:"config"` } if err := c.ShouldBindJSON(&data); err != nil { diff --git a/api/handler/admin/user_handler.go b/api/handler/admin/user_handler.go index b9213da6..99f91013 100644 --- a/api/handler/admin/user_handler.go +++ b/api/handler/admin/user_handler.go @@ -72,7 +72,7 @@ func (h *UserHandler) Save(c *gin.Context) { Password string `json:"password"` Username string `json:"username"` ChatRoles []string `json:"chat_roles"` - ChatModels []string `json:"chat_models"` + ChatModels []int `json:"chat_models"` ExpiredTime string `json:"expired_time"` Status bool `json:"status"` Vip bool `json:"vip"` diff --git a/api/handler/chat_model_handler.go b/api/handler/chat_model_handler.go index cc8cfa61..31fd90a0 100644 --- a/api/handler/chat_model_handler.go +++ b/api/handler/chat_model_handler.go @@ -32,7 +32,7 @@ func (h *ChatModelHandler) List(c *gin.Context) { return } - var models []string + var models []int err = utils.JsonDecode(user.ChatModels, &models) if err != nil { resp.ERROR(c, "当前用户没有订阅任何模型") @@ -41,7 +41,7 @@ func (h *ChatModelHandler) List(c *gin.Context) { // 查询用户有权限访问的模型以及所有开放的模型 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) if res.Error == nil { for _, item := range items { diff --git a/api/store/vo/user.go b/api/store/vo/user.go index 0ba66169..560f57db 100644 --- a/api/store/vo/user.go +++ b/api/store/vo/user.go @@ -8,7 +8,7 @@ type User struct { Salt string `json:"salt"` // 密码盐 Power int `json:"power"` // 剩余算力 ChatRoles []string `json:"chat_roles"` // 聊天角色集合 - ChatModels []string `json:"chat_models"` // AI模型集合 + ChatModels []int `json:"chat_models"` // AI模型集合 ExpiredTime int64 `json:"expired_time"` // 账户到期时间 Status bool `json:"status"` // 当前状态 LastLoginAt int64 `json:"last_login_at"` // 最后登录时间 diff --git a/database/update-v4.0.0.sql b/database/update-v4.0.0.sql index 9779ecc1..5ba56249 100644 --- a/database/update-v4.0.0.sql +++ b/database/update-v4.0.0.sql @@ -30,7 +30,7 @@ DROP `total_tokens`, DROP `img_calls`; 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 = '用户算力消费日志'; diff --git a/web/src/assets/css/chat-plus.css b/web/src/assets/css/chat-plus.css index 0484a244..a7376918 100644 --- a/web/src/assets/css/chat-plus.css +++ b/web/src/assets/css/chat-plus.css @@ -142,6 +142,7 @@ color: #fff; } #app .common-layout .el-main .chat-head .chat-config .el-select { + max-width: 150px; margin-right: 10px; } #app .common-layout .el-main .chat-head .chat-config .role-select { diff --git a/web/src/assets/css/chat-plus.styl b/web/src/assets/css/chat-plus.styl index 5f9f4df5..a0e4d4ac 100644 --- a/web/src/assets/css/chat-plus.styl +++ b/web/src/assets/css/chat-plus.styl @@ -181,7 +181,7 @@ $borderColor = #4676d0; } .el-select { - //max-width 150px; + max-width 150px; margin-right 10px; } @@ -202,6 +202,7 @@ $borderColor = #4676d0; .is-circle { margin-left 5px + .iconfont { margin-right 0 } diff --git a/web/src/views/ChatPlus.vue b/web/src/views/ChatPlus.vue index 62a8c360..d8dfebfc 100644 --- a/web/src/views/ChatPlus.vue +++ b/web/src/views/ChatPlus.vue @@ -82,7 +82,7 @@
- 聊天角色: + { + item.value.temperature = parseFloat(item.value.temperature) if (valid) { showDialog.value = false httpPost('/api/admin/model/save', item.value).then((res) => { diff --git a/web/src/views/admin/SysConfig.vue b/web/src/views/admin/SysConfig.vue index ebfc0d00..ef52efd7 100644 --- a/web/src/views/admin/SysConfig.vue +++ b/web/src/views/admin/SysConfig.vue @@ -36,7 +36,14 @@ - + +
+ +
+ 如果设置0表示不赠送,用户享受完免费算力额度之后就不能再发起对话了。如果设置为N,则系统每天将算力值小于N的用户自动补充到N。注意,此功能要配合XXL-JOB启用。 +
+
+
@@ -167,12 +174,12 @@ -
+
-
-
会话上下文深度:在老会话中继续会话,默认加载多少条聊天记录作为上下文。如果设置为 - 0 - 则不加载聊天记录,仅仅使用当前角色的上下文。该配置参数最好设置需要为偶数,否则将无法兼容百度的 API。 +
会话上下文深度:在老会话中继续会话,默认加载多少条聊天记录作为上下文。如果设置为 + 0 + 则不加载聊天记录,仅仅使用当前角色的上下文。该配置参数最好设置需要为偶数,否则将无法兼容百度的 API。 +
@@ -202,17 +209,6 @@ import 'md-editor-v3/lib/style.css'; const activeName = ref('basic') 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 systemFormRef = ref(null) const chatFormRef = ref(null) @@ -226,14 +222,6 @@ onMounted(() => { }).catch(e => { 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 => { notice.value = res.data['content'] @@ -361,12 +349,6 @@ const onUploadImg = (files, callback) => { padding-left 10px; } - .tip { - color #c1c1c1 - font-size 12px; - line-height 1.5; - } - .el-icon { font-size 16px margin-left 10px @@ -378,6 +360,15 @@ const onUploadImg = (files, callback) => { position relative top 3px } + + .tip-input-line { + .tip { + margin-top 10px + color #c1c1c1 + font-size 12px; + line-height 1.5; + } + } } } diff --git a/web/src/views/admin/Users.vue b/web/src/views/admin/Users.vue index e7b6e63b..168a1c8d 100644 --- a/web/src/views/admin/Users.vue +++ b/web/src/views/admin/Users.vue @@ -116,7 +116,7 @@ v-for="item in models" :key="item.id" :label="item.name" - :value="item.value" + :value="item.id" /> @@ -297,7 +297,6 @@ const saveUser = function () { } const handleSelectionChange = function (rows) { - // TODO: 批量删除操作 console.log(rows) }