mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	feat: The 'chat_models' field of user table, holds the model IDS in place of the model values
This commit is contained in:
		@@ -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"`
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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"`
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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"` // 最后登录时间
 | 
			
		||||
 
 | 
			
		||||
@@ -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 = '用户算力消费日志';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
          }
 | 
			
		||||
 
 | 
			
		||||
@@ -82,7 +82,7 @@
 | 
			
		||||
      <el-main v-loading="loading" element-loading-background="rgba(122, 122, 122, 0.3)">
 | 
			
		||||
        <div class="chat-head">
 | 
			
		||||
          <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-option
 | 
			
		||||
                  v-for="item in roles"
 | 
			
		||||
 
 | 
			
		||||
@@ -266,6 +266,7 @@ const edit = function (row) {
 | 
			
		||||
 | 
			
		||||
const save = function () {
 | 
			
		||||
  formRef.value.validate((valid) => {
 | 
			
		||||
    item.value.temperature = parseFloat(item.value.temperature)
 | 
			
		||||
    if (valid) {
 | 
			
		||||
      showDialog.value = false
 | 
			
		||||
      httpPost('/api/admin/model/save', item.value).then((res) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,14 @@
 | 
			
		||||
            <el-form-item label="VIP每月赠送算力" prop="vip_month_power">
 | 
			
		||||
              <el-input v-model.number="system['vip_month_power']" placeholder="VIP用户每月赠送算力"/>
 | 
			
		||||
            </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-switch v-model="system['enabled_register']"/>
 | 
			
		||||
              <el-tooltip
 | 
			
		||||
@@ -144,7 +151,7 @@
 | 
			
		||||
                        v-for="item in models"
 | 
			
		||||
                        :key="item.id"
 | 
			
		||||
                        :label="item.name"
 | 
			
		||||
                        :value="item.value"
 | 
			
		||||
                        :value="item.id"
 | 
			
		||||
                    />
 | 
			
		||||
                  </el-select>
 | 
			
		||||
                  <div class="info">
 | 
			
		||||
@@ -167,12 +174,12 @@
 | 
			
		||||
              <el-switch v-model="system['enable_context']"/>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <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"/>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="tip" style="margin-top: 10px; ">会话上下文深度:在老会话中继续会话,默认加载多少条聊天记录作为上下文。如果设置为
 | 
			
		||||
                0
 | 
			
		||||
                则不加载聊天记录,仅仅使用当前角色的上下文。该配置参数最好设置需要为偶数,否则将无法兼容百度的 API。
 | 
			
		||||
                <div class="tip">会话上下文深度:在老会话中继续会话,默认加载多少条聊天记录作为上下文。如果设置为
 | 
			
		||||
                  0
 | 
			
		||||
                  则不加载聊天记录,仅仅使用当前角色的上下文。该配置参数最好设置需要为偶数,否则将无法兼容百度的 API。
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item>
 | 
			
		||||
@@ -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;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -116,7 +116,7 @@
 | 
			
		||||
                v-for="item in models"
 | 
			
		||||
                :key="item.id"
 | 
			
		||||
                :label="item.name"
 | 
			
		||||
                :value="item.value"
 | 
			
		||||
                :value="item.id"
 | 
			
		||||
            />
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
@@ -297,7 +297,6 @@ const saveUser = function () {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const handleSelectionChange = function (rows) {
 | 
			
		||||
  // TODO: 批量删除操作
 | 
			
		||||
  console.log(rows)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user