mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-08 18:23:45 +08:00
支持添加多个 ChatGPT API 代理地址
This commit is contained in:
@@ -66,6 +66,7 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
|
|||||||
} else {
|
} else {
|
||||||
context = s.Config.ChatRoles[role].Context
|
context = s.Config.ChatRoles[role].Context
|
||||||
}
|
}
|
||||||
|
logger.Infof("会话上下文:%+v", context)
|
||||||
r.Messages = append(context, types.Message{
|
r.Messages = append(context, types.Message{
|
||||||
Role: "user",
|
Role: "user",
|
||||||
Content: text,
|
Content: text,
|
||||||
@@ -78,17 +79,6 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
|
|||||||
|
|
||||||
// 创建 HttpClient 请求对象
|
// 创建 HttpClient 请求对象
|
||||||
var client *http.Client
|
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))
|
request, err := http.NewRequest(http.MethodPost, s.Config.Chat.ApiURL, bytes.NewBuffer(requestBody))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -98,7 +88,20 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
|
|||||||
var retryCount = 3
|
var retryCount = 3
|
||||||
var response *http.Response
|
var response *http.Response
|
||||||
var failedKey = ""
|
var failedKey = ""
|
||||||
|
var failedProxyURL = ""
|
||||||
for retryCount > 0 {
|
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)
|
apiKey := s.getApiKey(failedKey)
|
||||||
if apiKey == "" {
|
if apiKey == "" {
|
||||||
logger.Info("Too many requests, all Api Key is not available")
|
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 {
|
} else {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
failedKey = apiKey
|
failedKey = apiKey
|
||||||
|
failedProxyURL = proxyURL
|
||||||
}
|
}
|
||||||
retryCount--
|
retryCount--
|
||||||
}
|
}
|
||||||
@@ -214,6 +218,28 @@ func (s *Server) getApiKey(failedKey string) string {
|
|||||||
return ""
|
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) {
|
func replyMessage(message types.WsMessage, client Client) {
|
||||||
msg, err := json.Marshal(message)
|
msg, err := json.Marshal(message)
|
||||||
|
|||||||
@@ -19,11 +19,6 @@ func (s *Server) ConfigSetHandle(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// proxy URL
|
|
||||||
if proxy, ok := data["proxy"]; ok {
|
|
||||||
s.Config.ProxyURL = proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
// Model
|
// Model
|
||||||
if model, ok := data["model"]; ok {
|
if model, ok := data["model"]; ok {
|
||||||
s.Config.Chat.Model = model
|
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})
|
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})
|
||||||
|
}
|
||||||
|
|||||||
@@ -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/remove", s.RemoveApiKey)
|
||||||
engine.POST("api/config/apikey/list", s.ListApiKeys)
|
engine.POST("api/config/apikey/list", s.ListApiKeys)
|
||||||
engine.POST("api/config/role/set", s.UpdateChatRole)
|
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) {
|
engine.NoRoute(func(c *gin.Context) {
|
||||||
if c.Request.URL.Path == "/favicon.ico" {
|
if c.Request.URL.Path == "/favicon.ico" {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ func GetDefaultChatRole() map[string]ChatRole {
|
|||||||
Name: "老师",
|
Name: "老师",
|
||||||
Context: []Message{
|
Context: []Message{
|
||||||
{Role: "user", Content: "从现在开始,你将扮演一个老师,你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。"},
|
{Role: "user", Content: "从现在开始,你将扮演一个老师,你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。"},
|
||||||
{Role: "assistant", Content: "好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案。"},
|
{Role: "assistant", Content: "好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案,绝对不直接给出答案。"},
|
||||||
},
|
},
|
||||||
HelloMsg: "师者,传道受业解惑也。",
|
HelloMsg: "师者,传道受业解惑也。",
|
||||||
Icon: "images/avatar/teacher.jpg",
|
Icon: "images/avatar/teacher.jpg",
|
||||||
@@ -108,7 +108,7 @@ func GetDefaultChatRole() map[string]ChatRole {
|
|||||||
},
|
},
|
||||||
HelloMsg: "你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。",
|
HelloMsg: "你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。",
|
||||||
Icon: "images/avatar/seller.jpg",
|
Icon: "images/avatar/seller.jpg",
|
||||||
Enable: true,
|
Enable: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
"english_trainer": {
|
"english_trainer": {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
Listen string
|
Listen string
|
||||||
Session Session
|
Session Session
|
||||||
ProxyURL string
|
ProxyURL []string
|
||||||
Chat Chat
|
Chat Chat
|
||||||
EnableAuth bool // 是否开启鉴权
|
EnableAuth bool // 是否开启鉴权
|
||||||
Tokens []string // 授权的白名单列表 TODO: 后期要存储到 LevelDB 或者 Mysql 数据库
|
Tokens []string // 授权的白名单列表 TODO: 后期要存储到 LevelDB 或者 Mysql 数据库
|
||||||
@@ -43,7 +43,8 @@ type Session struct {
|
|||||||
|
|
||||||
func NewDefaultConfig() *Config {
|
func NewDefaultConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
Listen: "0.0.0.0:5678",
|
Listen: "0.0.0.0:5678",
|
||||||
|
ProxyURL: make([]string, 0),
|
||||||
|
|
||||||
Session: Session{
|
Session: Session{
|
||||||
SecretKey: utils.RandString(64),
|
SecretKey: utils.RandString(64),
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ export default defineComponent({
|
|||||||
reader.onload = () => {
|
reader.onload = () => {
|
||||||
const data = JSON.parse(String(reader.result));
|
const data = JSON.parse(String(reader.result));
|
||||||
// 过滤掉重复的打招呼信息
|
// 过滤掉重复的打招呼信息
|
||||||
if (data['is_hello_msg'] && this.chatData.length > 3) {
|
if (data['is_hello_msg'] && this.chatData.length > 1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user