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 管理
+
+
+ 新增
+
+
+
+
+
+
+
+
+ {{scope.row['last_used']}}
+ 未使用
+
+
+
+
+ Edit
+ Delete
+
+
+
+
+