diff --git a/api/core/types/config.go b/api/core/types/config.go index 3bea5a71..4c5bc2c8 100644 --- a/api/core/types/config.go +++ b/api/core/types/config.go @@ -115,11 +115,10 @@ type ChatConfig struct { Baidu ModelAPIConfig `json:"baidu"` XunFei ModelAPIConfig `json:"xun_fei"` - EnableContext bool `json:"enable_context"` // 是否开启聊天上下文 - EnableHistory bool `json:"enable_history"` // 是否允许保存聊天记录 - ContextDeep int `json:"context_deep"` // 上下文深度 - DallApiURL string `json:"dall_api_url"` // dall-e3 绘图 API 地址 - DallImgNum int `json:"dall_img_num"` // dall-e3 出图数量 + EnableContext bool `json:"enable_context"` // 是否开启聊天上下文 + EnableHistory bool `json:"enable_history"` // 是否允许保存聊天记录 + ContextDeep int `json:"context_deep"` // 上下文深度 + DallImgNum int `json:"dall_img_num"` // dall-e3 出图数量 } type Platform string @@ -143,7 +142,6 @@ type InviteReward struct { type ModelAPIConfig struct { Temperature float32 `json:"temperature"` MaxTokens int `json:"max_tokens"` - ApiKey string `json:"api_key"` } type SystemConfig struct { diff --git a/api/handler/admin/api_key_handler.go b/api/handler/admin/api_key_handler.go index 19cf0179..63a147f3 100644 --- a/api/handler/admin/api_key_handler.go +++ b/api/handler/admin/api_key_handler.go @@ -27,6 +27,7 @@ func (h *ApiKeyHandler) Save(c *gin.Context) { var data struct { Id uint `json:"id"` Platform string `json:"platform"` + Name string `json:"name"` Type string `json:"type"` Value string `json:"value"` ApiURL string `json:"api_url"` @@ -48,6 +49,7 @@ func (h *ApiKeyHandler) Save(c *gin.Context) { apiKey.ApiURL = data.ApiURL apiKey.Enabled = data.Enabled apiKey.UseProxy = data.UseProxy + apiKey.Name = data.Name res := h.db.Save(&apiKey) if res.Error != nil { resp.ERROR(c, "更新数据库失败!") diff --git a/api/handler/chatimpl/chat_handler.go b/api/handler/chatimpl/chat_handler.go index 95cb50af..6b1bf80e 100644 --- a/api/handler/chatimpl/chat_handler.go +++ b/api/handler/chatimpl/chat_handler.go @@ -448,8 +448,9 @@ func (h *ChatHandler) doRequest(ctx context.Context, req types.ApiRequest, platf request = request.WithContext(ctx) request.Header.Set("Content-Type", "application/json") - proxyURL := h.App.Config.ProxyURL - if proxyURL != "" && platform == types.OpenAI { // 使用代理 + var proxyURL string + if h.App.Config.ProxyURL != "" && apiKey.UseProxy { // 使用代理 + proxyURL = h.App.Config.ProxyURL proxy, _ := url.Parse(proxyURL) client = &http.Client{ Transport: &http.Transport{ diff --git a/api/handler/function_handler.go b/api/handler/function_handler.go index ca78589a..de35dfdb 100644 --- a/api/handler/function_handler.go +++ b/api/handler/function_handler.go @@ -231,15 +231,10 @@ func (h *FunctionHandler) Dall3(c *gin.Context) { // translate prompt const translatePromptTemplate = "Translate the following painting prompt words into English keyword phrases. Without any explanation, directly output the keyword phrases separated by commas. The content to be translated is: [%s]" - pt, err := utils.OpenAIRequest(fmt.Sprintf(translatePromptTemplate, params["prompt"]), apiKey, h.App.Config.ProxyURL) + pt, err := utils.OpenAIRequest(h.db, fmt.Sprintf(translatePromptTemplate, params["prompt"]), h.App.Config.ProxyURL) if err == nil { prompt = pt } - - apiURL := chatConfig.DallApiURL - if utils.IsEmptyValue(apiURL) { - apiURL = "https://api.openai.com/v1/images/generations" - } imgNum := chatConfig.DallImgNum if imgNum <= 0 { imgNum = 1 @@ -247,11 +242,12 @@ func (h *FunctionHandler) Dall3(c *gin.Context) { var res imgRes var errRes ErrRes var request *req.Request - if strings.Contains(apiURL, "api.openai.com") { + if apiKey.UseProxy && h.proxyURL != "" { request = req.C().SetProxyURL(h.proxyURL).R() } else { request = req.C().R() } + logger.Debugf("Sending %s request, ApiURL:%s, ApiKey:%s, PROXY: %s", apiKey.Platform, apiKey.ApiURL, apiKey.Value, h.proxyURL) r, err := request.SetHeader("Content-Type", "application/json"). SetHeader("Authorization", "Bearer "+apiKey.Value). SetBody(imgReq{ @@ -261,7 +257,7 @@ func (h *FunctionHandler) Dall3(c *gin.Context) { Size: "1024x1024", }). SetErrorResult(&errRes). - SetSuccessResult(&res).Post(apiURL) + SetSuccessResult(&res).Post(apiKey.ApiURL) if r.IsErrorState() { resp.ERROR(c, "请求 OpenAI API 失败: "+errRes.Error.Message) return diff --git a/api/handler/prompt_handler.go b/api/handler/prompt_handler.go index c05d28af..2d01fad3 100644 --- a/api/handler/prompt_handler.go +++ b/api/handler/prompt_handler.go @@ -3,11 +3,8 @@ package handler import ( "chatplus/core" "chatplus/core/types" - "chatplus/store/model" "chatplus/utils" "chatplus/utils/resp" - "fmt" - "github.com/gin-gonic/gin" "gorm.io/gorm" ) @@ -36,7 +33,7 @@ func (h *PromptHandler) Rewrite(c *gin.Context) { return } - content, err := h.request(data.Prompt, rewritePromptTemplate) + content, err := utils.OpenAIRequest(h.db, data.Prompt, rewritePromptTemplate) if err != nil { resp.ERROR(c, err.Error()) return @@ -54,7 +51,7 @@ func (h *PromptHandler) Translate(c *gin.Context) { return } - content, err := h.request(data.Prompt, translatePromptTemplate) + content, err := utils.OpenAIRequest(h.db, data.Prompt, translatePromptTemplate) if err != nil { resp.ERROR(c, err.Error()) return @@ -62,14 +59,3 @@ func (h *PromptHandler) Translate(c *gin.Context) { resp.SUCCESS(c, content) } - -func (h *PromptHandler) request(prompt string, promptTemplate string) (string, error) { - // 获取 OpenAI 的 API KEY - var apiKey model.ApiKey - res := h.db.Where("platform = ?", types.OpenAI).Where("type = ?", "chat").Where("enabled = ?", true).First(&apiKey) - if res.Error != nil { - return "", fmt.Errorf("error with fetch OpenAI API KEY:%v", res.Error) - } - - return utils.OpenAIRequest(fmt.Sprintf(promptTemplate, prompt), apiKey, h.App.Config.ProxyURL) -} diff --git a/api/handler/user_handler.go b/api/handler/user_handler.go index 6f5e01f2..8f4f584a 100644 --- a/api/handler/user_handler.go +++ b/api/handler/user_handler.go @@ -303,7 +303,7 @@ func (h *UserHandler) ProfileUpdate(c *gin.Context) { } h.db.First(&user, user.Id) user.Avatar = data.Avatar - user.ChatConfig = utils.JsonEncode(data.ChatConfig) + user.Nickname = data.Nickname res := h.db.Updates(&user) if res.Error != nil { resp.ERROR(c, "更新用户信息失败") diff --git a/api/store/model/api_key.go b/api/store/model/api_key.go index b79d3ff7..109cec77 100644 --- a/api/store/model/api_key.go +++ b/api/store/model/api_key.go @@ -4,6 +4,7 @@ package model type ApiKey struct { BaseModel Platform string + Name string Type string // 用途 chat => 聊天,img => 绘图 Value string // API Key 的值 ApiURL string // 当前 KEY 的 API 地址 diff --git a/api/store/vo/api_key.go b/api/store/vo/api_key.go index c3c985d7..d32233f3 100644 --- a/api/store/vo/api_key.go +++ b/api/store/vo/api_key.go @@ -4,6 +4,7 @@ package vo type ApiKey struct { BaseVo Platform string `json:"platform"` + Name string `json:"name"` Type string `json:"type"` Value string `json:"value"` // API Key 的值 ApiURL string `json:"api_url"` diff --git a/api/utils/net.go b/api/utils/net.go index d8cc8614..288c4f12 100644 --- a/api/utils/net.go +++ b/api/utils/net.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "github.com/imroc/req/v3" + "gorm.io/gorm" "io" "net/http" "net/url" @@ -86,7 +87,13 @@ type apiErrRes struct { } `json:"error"` } -func OpenAIRequest(prompt string, apiKey model.ApiKey, proxy string) (string, error) { +func OpenAIRequest(db *gorm.DB, prompt string, proxy string) (string, error) { + var apiKey model.ApiKey + res := db.Where("platform = ?", types.OpenAI).Where("type = ?", "chat").Where("enabled = ?", true).First(&apiKey) + if res.Error != nil { + return "", fmt.Errorf("error with fetch OpenAI API KEY:%v", res.Error) + } + messages := make([]interface{}, 1) messages[0] = types.Message{ Role: "user", diff --git a/database/update-v3.2.4.sql b/database/update-v3.2.4.sql index 620126d1..99279408 100644 --- a/database/update-v3.2.4.sql +++ b/database/update-v3.2.4.sql @@ -3,4 +3,5 @@ ALTER TABLE `chatgpt_rewards` ADD `exchange` VARCHAR(255) NOT NULL COMMENT '兑 ALTER TABLE `chatgpt_api_keys` ADD `api_url` VARCHAR(255) NULL COMMENT 'API 地址' AFTER `last_used_at`, ADD `enabled` TINYINT(1) NULL COMMENT '是否启用' AFTER `api_url`; ALTER TABLE `chatgpt_api_keys` DROP INDEX `value`; ALTER TABLE `chatgpt_mj_jobs` ADD UNIQUE(`task_id`); -ALTER TABLE `chatgpt_api_keys` ADD `use_proxy` TINYINT(1) NULL COMMENT '是否使用代理访问' AFTER `enabled`; \ No newline at end of file +ALTER TABLE `chatgpt_api_keys` ADD `use_proxy` TINYINT(1) NULL COMMENT '是否使用代理访问' AFTER `enabled`; +ALTER TABLE `chatgpt_api_keys` ADD `name` VARCHAR(30) NULL COMMENT '名称' AFTER `platform`; \ No newline at end of file diff --git a/web/src/components/UserProfile.vue b/web/src/components/UserProfile.vue index 4957d411..fa121d1f 100644 --- a/web/src/components/UserProfile.vue +++ b/web/src/components/UserProfile.vue @@ -15,7 +15,7 @@ - {{ user['nickname'] }} + {{ user.mobile }} @@ -44,16 +44,6 @@ {{ dateFormat(user['expired_time']) }} - - - - - - - - - - 保存 @@ -78,7 +68,6 @@ const user = ref({ mobile: '', calls: 0, tokens: 0, - chat_config: {api_keys: {OpenAI: "", Azure: "", ChatGLM: ""}} }) const vipImg = ref("/images/vip.png") @@ -87,7 +76,6 @@ onMounted(() => { // 获取最新用户信息 httpGet('/api/user/profile').then(res => { user.value = res.data - user.value.chat_config.api_keys = res.data.chat_config.api_keys ?? {OpenAI: "", Azure: "", ChatGLM: ""} }).catch(e => { ElMessage.error("获取用户信息失败:" + e.message) }); diff --git a/web/src/views/admin/ApiKey.vue b/web/src/views/admin/ApiKey.vue index 6275104b..5adb7e6f 100644 --- a/web/src/views/admin/ApiKey.vue +++ b/web/src/views/admin/ApiKey.vue @@ -8,7 +8,16 @@ - + + + +