diff --git a/server/handler_chat.go b/server/handler_chat.go index a4b78a1e..eab8dc5b 100644 --- a/server/handler_chat.go +++ b/server/handler_chat.go @@ -215,7 +215,7 @@ func (s *Server) sendMessage(ctx context.Context, session types.ChatSession, rol logger.Infof("API Key %s is deactivated", apiKey) // 移除当前 API key for i, v := range s.Config.Chat.ApiKeys { - if v == apiKey { + if v.Value == apiKey { s.Config.Chat.ApiKeys = append(s.Config.Chat.ApiKeys[:i], s.Config.Chat.ApiKeys[i+1:]...) } } @@ -313,30 +313,26 @@ func (s *Server) sendMessage(ctx context.Context, session types.ChatSession, rol // 随机获取一个 API Key,如果请求失败,则更换 API Key 重试 func (s *Server) getApiKey(failedKey string) string { - var keys = make([]string, 0) - for _, v := range s.Config.Chat.ApiKeys { + var keys = make([]types.APIKey, 0) + for _, key := range s.Config.Chat.ApiKeys { // 过滤掉刚刚失败的 Key - if v == failedKey { + if key.Value == failedKey { continue } - // 获取 API Key 的上次调用时间,控制调用频率 - var lastAccess int64 - if t, ok := s.ApiKeyAccessStat[v]; ok { - lastAccess = t - } - // 保持每分钟访问不超过 15 次 - if time.Now().Unix()-lastAccess <= 4 { + // 保持每分钟访问不超过 15 次,控制调用频率 + if key.LastUsed > 0 && time.Now().Unix()-key.LastUsed <= 4 { continue } - keys = append(keys, v) + keys = append(keys, key) } + // 从可用的 Key 中随机选一个 rand.NewSource(time.Now().UnixNano()) if len(keys) > 0 { key := keys[rand.Intn(len(keys))] - s.ApiKeyAccessStat[key] = time.Now().Unix() - return key + key.LastUsed = time.Now().Unix() + return key.Value } return "" } diff --git a/server/server.go b/server/server.go index 900db3ba..2d5afef0 100644 --- a/server/server.go +++ b/server/server.go @@ -41,7 +41,6 @@ type Server struct { // 保存 Websocket 会话 Username, 每个 Username 只能连接一次 // 防止第三方直接连接 socket 调用 OpenAI API ChatSession map[string]types.ChatSession //map[sessionId]User - ApiKeyAccessStat map[string]int64 // 记录每个 API Key 的最后访问之间,保持在 15/min 之内 ChatClients map[string]*WsClient // Websocket 连接集合 ReqCancelFunc map[string]context.CancelFunc // HttpClient 请求取消 handle function DebugMode bool // 是否开启调试模式 @@ -70,7 +69,6 @@ func NewServer(configPath string) (*Server, error) { ChatSession: make(map[string]types.ChatSession), ChatClients: make(map[string]*WsClient), ReqCancelFunc: make(map[string]context.CancelFunc), - ApiKeyAccessStat: make(map[string]int64), }, nil } diff --git a/types/config.go b/types/config.go index 6b7d642e..d1aaa49d 100644 --- a/types/config.go +++ b/types/config.go @@ -37,7 +37,7 @@ type Manager struct { // Chat configs struct type Chat struct { ApiURL string - ApiKeys []string + ApiKeys []APIKey Model string Temperature float32 MaxTokens int @@ -45,6 +45,11 @@ type Chat struct { ChatContextExpireTime int // 聊天上下文过期时间,单位:秒 } +type APIKey struct { + Value string `json:"value"` // Key value + LastUsed int64 `json:"last_used"` // 最后使用时间 +} + // Session configs struct type Session struct { SecretKey string // session encryption key diff --git a/utils/config.go b/utils/config.go index c8060425..c6c594bc 100644 --- a/utils/config.go +++ b/utils/config.go @@ -30,7 +30,7 @@ func NewDefaultConfig() *types.Config { }, Chat: types.Chat{ ApiURL: "https://api.openai.com/v1/chat/completions", - ApiKeys: []string{""}, + ApiKeys: make([]types.APIKey, 0), Model: "gpt-3.5-turbo", MaxTokens: 1024, Temperature: 0.9, diff --git a/web/src/views/admin/SysConfig.vue b/web/src/views/admin/SysConfig.vue index 72c2d1a0..28d98784 100644 --- a/web/src/views/admin/SysConfig.vue +++ b/web/src/views/admin/SysConfig.vue @@ -29,19 +29,75 @@ + + +
+ + + +
+
+ + +
+ + + +
+
+
+ + + + + - Create + 保存 + API KEY 管理 + + + 新增 + + + + + + + + + + + + + + +