支持添加多个 ChatGPT API 代理地址

This commit is contained in:
RockYang
2023-03-26 21:10:40 +08:00
parent fe91b0f784
commit 6a38de7eaa
6 changed files with 99 additions and 21 deletions

View File

@@ -66,6 +66,7 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
} else {
context = s.Config.ChatRoles[role].Context
}
logger.Infof("会话上下文:%+v", context)
r.Messages = append(context, types.Message{
Role: "user",
Content: text,
@@ -78,17 +79,6 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
// 创建 HttpClient 请求对象
var client *http.Client
if s.Config.ProxyURL == "" {
client = &http.Client{}
} else { // 使用代理
uri := url.URL{}
proxy, _ := uri.Parse(s.Config.ProxyURL)
client = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxy),
},
}
}
request, err := http.NewRequest(http.MethodPost, s.Config.Chat.ApiURL, bytes.NewBuffer(requestBody))
if err != nil {
return err
@@ -98,7 +88,20 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
var retryCount = 3
var response *http.Response
var failedKey = ""
var failedProxyURL = ""
for retryCount > 0 {
proxyURL := s.getProxyURL(failedProxyURL)
if proxyURL == "" {
client = &http.Client{}
} else { // 使用代理
uri := url.URL{}
proxy, _ := uri.Parse(proxyURL)
client = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxy),
},
}
}
apiKey := s.getApiKey(failedKey)
if apiKey == "" {
logger.Info("Too many requests, all Api Key is not available")
@@ -113,6 +116,7 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
} else {
logger.Error(err)
failedKey = apiKey
failedProxyURL = proxyURL
}
retryCount--
}
@@ -214,6 +218,28 @@ func (s *Server) getApiKey(failedKey string) string {
return ""
}
// 获取一个可用的代理
func (s *Server) getProxyURL(failedProxyURL string) string {
if len(s.Config.ProxyURL) == 0 {
return ""
}
if len(s.Config.ProxyURL) == 1 || failedProxyURL == "" {
return s.Config.ProxyURL[0]
}
for i, v := range s.Config.ProxyURL {
if failedProxyURL == v {
if i == len(s.Config.ProxyURL)-1 {
return s.Config.ProxyURL[0]
} else {
return s.Config.ProxyURL[i+1]
}
}
}
return ""
}
// 回复客户端消息
func replyMessage(message types.WsMessage, client Client) {
msg, err := json.Marshal(message)

View File

@@ -19,11 +19,6 @@ func (s *Server) ConfigSetHandle(c *gin.Context) {
return
}
// proxy URL
if proxy, ok := data["proxy"]; ok {
s.Config.ProxyURL = proxy
}
// Model
if model, ok := data["model"]; ok {
s.Config.Chat.Model = model
@@ -268,3 +263,57 @@ func (s *Server) UpdateChatRole(c *gin.Context) {
c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg})
}
// AddProxy 添加一个代理
func (s *Server) AddProxy(c *gin.Context) {
var data map[string]string
err := json.NewDecoder(c.Request.Body).Decode(&data)
if err != nil {
logger.Errorf("Error decode json data: %s", err.Error())
c.JSON(http.StatusBadRequest, nil)
return
}
if proxy, ok := data["proxy"]; ok {
if !utils.ContainsItem(s.Config.ProxyURL, proxy) {
s.Config.ProxyURL = append(s.Config.ProxyURL, proxy)
}
}
// 保存配置文件
err = types.SaveConfig(s.Config, s.ConfigPath)
if err != nil {
c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "Failed to save config file"})
return
}
c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg, Data: s.Config.ProxyURL})
}
func (s *Server) RemoveProxy(c *gin.Context) {
var data map[string]string
err := json.NewDecoder(c.Request.Body).Decode(&data)
if err != nil {
logger.Errorf("Error decode json data: %s", err.Error())
c.JSON(http.StatusBadRequest, nil)
return
}
if proxy, ok := data["proxy"]; ok {
for i, v := range s.Config.ProxyURL {
if v == proxy {
s.Config.ProxyURL = append(s.Config.ProxyURL[:i], s.Config.ProxyURL[i+1:]...)
break
}
}
}
// 保存配置文件
err = types.SaveConfig(s.Config, s.ConfigPath)
if err != nil {
c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "Failed to save config file"})
return
}
c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg, Data: s.Config.ProxyURL})
}

View File

@@ -81,6 +81,8 @@ func (s *Server) Run(webRoot embed.FS, path string, debug bool) {
engine.POST("api/config/apikey/remove", s.RemoveApiKey)
engine.POST("api/config/apikey/list", s.ListApiKeys)
engine.POST("api/config/role/set", s.UpdateChatRole)
engine.POST("api/config/proxy/add", s.AddProxy)
engine.POST("api/config/proxy/remove", s.RemoveProxy)
engine.NoRoute(func(c *gin.Context) {
if c.Request.URL.Path == "/favicon.ico" {