feat: 支持多key切换

This commit is contained in:
Soulter
2022-12-17 14:39:37 +08:00
parent b59df0774e
commit 1076b264d9
4 changed files with 106 additions and 9 deletions
View File
+8 -1
View File
@@ -1,5 +1,11 @@
openai:
# 注意:在1.7版本已支持多key自动切换,方法:
# key:
# - xxxxx
# - xxxxxx
# 在下方非注释的地方使用以上格式
key:
-
chatGPTConfigs:
engine: text-davinci-003
max_tokens: 800
@@ -8,6 +14,7 @@ openai:
frequency_penalty: 0.4
presence_penalty: 0.3
total_tokens_limit: 700
qqbot:
appid:
token:
@@ -16,7 +23,7 @@ qqbot:
uniqueSessionMode: false
# QChannelBot 的版本
version: 1.6 beta
version: 1.7 beta
# [Beta] 转储历史记录时间间隔(分钟)
dump_history_interval: 10
+78 -5
View File
@@ -1,19 +1,46 @@
import openai
import yaml
from util.errors.errors import PromptExceededError
import json
import time
inst = None
class ChatGPT:
def __init__(self):
self.key_list = []
with open("./configs/config.yaml", 'r', encoding='utf-8') as ymlfile:
cfg = yaml.safe_load(ymlfile)
if cfg['openai']['key'] != '':
print("读取ChatGPT Key成功")
openai.api_key = cfg['openai']['key']
self.key_list = cfg['openai']['key']
print(f"Key列表: {self.key_list}")
# openai.api_key = cfg['openai']['key']
else:
print("请先去完善ChatGPT的Key。详情请前往https://beta.openai.com/account/api-keys")
with open("chatgpt_key_record", 'r', encoding='utf-8') as keyfile:
try:
self.key_stat = json.load(keyfile)
except Exception as e:
print(e)
self.key_stat = {}
finally:
for key in self.key_list:
if key not in self.key_stat:
self.key_stat[key] = {'exceed': False, 'used': 0}
if openai.api_key is None:
print("切换")
openai.api_key = key
else:
if self.key_stat[key]['exceed']:
print(f"Key: {key} 已超额")
continue
else:
openai.api_key = key
print(f"使用Key: {key}, 已使用token: {self.key_stat[key]['used']}")
break
self.save_key_record()
chatGPT_configs = cfg['openai']['chatGPTConfigs']
print(f'加载ChatGPTConfigs: {chatGPT_configs}')
@@ -23,21 +50,67 @@ class ChatGPT:
inst = self
def chat(self, prompt):
print("[OpenAI API]收到")
try:
response = openai.Completion.create(
prompt=prompt,
**self.chatGPT_configs
)
except(openai.error.InvalidRequestError) as e:
raise PromptExceededError("OpenAI遇到错误:输入了一个不合法的请求。\n"+str(e))
# except(openai.error.InvalidRequestError) as e:
# raise PromptExceededError("OpenAI遇到错误:输入了一个不合法的请求。\n"+str(e))
except Exception as e:
print(e)
if 'You exceeded' in str(e):
print("当前Key已超额,正在切换")
self.key_stat[openai.api_key]['exceed'] = True
self.save_key_record()
response, is_switched = self.handle_switch_key(prompt)
if not is_switched:
# 所有Key都超额
raise e
# print(response['usage'])
self.key_stat[openai.api_key]['used'] += response['usage']['total_tokens']
self.save_key_record()
print("[ChatGPT] "+response["choices"][0]["text"])
return response["choices"][0]["text"].strip(), response['usage']['total_tokens']
def handle_switch_key(self, prompt):
while True:
is_all_exceed = True
for key in self.key_stat:
if not self.key_stat[key]['exceed']:
is_all_exceed = False
openai.api_key = key
print(f"切换到Key: {key}, 已使用token: {self.key_stat[key]['used']}")
try:
response = openai.Completion.create(
prompt=prompt,
**self.chatGPT_configs
)
return response, True
except Exception as e:
print(e)
if 'You exceeded' in str(e):
print("当前Key已超额,正在切换")
self.key_stat[openai.api_key]['exceed'] = True
self.save_key_record()
time.sleep(1)
continue
if is_all_exceed:
print("所有Key已超额")
return None, False
def getConfigs(self):
return self.openai_configs
def save_key_record(self):
with open("chatgpt_key_record", 'w', encoding='utf-8') as f:
json.dump(self.key_stat, f)
def get_key_stat(self):
return self.key_stat
def get_key_list(self):
return self.key_list
def getInst() -> ChatGPT:
global inst
+20 -3
View File
@@ -85,7 +85,7 @@ def dump_history():
db = dbConn()
while True:
try:
print("转储历史记录...")
# print("转储历史记录...")
for key in session_dict:
# print("TEST: "+str(db.get_session(key)))
data = session_dict[key]
@@ -96,7 +96,7 @@ def dump_history():
db.update_session(key, json.dumps(data_json))
else:
db.insert_session(key, json.dumps(data_json))
print("转储历史记录完毕")
# print("转储历史记录完毕")
except BaseException as e:
print(e)
# 每隔10分钟转储一次
@@ -278,7 +278,24 @@ def oper_msg(message, at=False, loop=None):
if k == "key":
continue
chatgpt_cfg_str += f"{k}: {v}"
send_qq_msg(message, f"ChatGPT配置:\n - {chatgpt_cfg_str}\n QQChannelChatGPT 版本: {version}")
key_stat = chatgpt.get_key_stat()
key_list = chatgpt.get_key_list()
chatgpt_cfg_str += '\n\n配额使用情况:\n'
index = 1
max = 900000
for key in key_list:
if key in key_stat:
if key_stat[key]['exceed']:
chatgpt_cfg_str += f"#{index}: 已寄\n"
index += 1
continue
# chatgpt_cfg_str += f"#{index}: {round(key_stat[key]['used']/max*100, 2)}%\n"
chatgpt_cfg_str += f"#{index}: {key_stat[key]['used']}/{max}\n"
index += 1
chatgpt_cfg_str += '\n注: 配额情况在某些极端情况下具有一定的不准确性。\n'
print("生成...")
send_qq_msg(message, f"ChatGPT配置:\n {chatgpt_cfg_str}\n QQChannelChatGPT 版本: {version}")
return
if qq_msg == "/count":
try: