feat: 支持多key切换
This commit is contained in:
+8
-1
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user