diff --git a/pkg/openai/keymgr.py b/pkg/openai/keymgr.py index 2b1a52e4..03ce5c3f 100644 --- a/pkg/openai/keymgr.py +++ b/pkg/openai/keymgr.py @@ -21,6 +21,10 @@ class KeysManager: alerted = [] + # 在此list中的都是经超额报错标记过的api-key + # 记录的是key值,仅在运行时有效 + exceeded = [] + def get_using_key(self): return self.using_key @@ -45,15 +49,22 @@ class KeysManager: # 从usage中删除未加载的api-key的记录 # 不删了,也许会运行时添加曾经有记录的api-key - # 根据使用量自动切换到可用的api-key + if 'exceeded_keys' in pkg.utils.context.context and pkg.utils.context.context['exceeded_keys'] is not None: + self.exceeded = pkg.utils.context.context['exceeded_keys'] + + # 根据tested自动切换到可用的api-key # 返回是否切换成功, 切换后的api-key的别名 def auto_switch(self) -> (bool, str): self.dump_fee() for key_name in self.api_key: - if self.get_fee(self.api_key[key_name]) < self.api_key_fee_threshold: + if self.api_key[key_name] not in self.exceeded: self.using_key = self.api_key[key_name] logging.info("使用api-key:" + key_name) return True, key_name + # if self.get_fee(self.api_key[key_name]) < self.api_key_fee_threshold: + # self.using_key = self.api_key[key_name] + # logging.info("使用api-key:" + key_name) + # return True, key_name self.using_key = list(self.api_key.values())[0] logging.info("使用api-key:" + list(self.api_key.keys())[0]) @@ -66,11 +77,19 @@ class KeysManager: # 设置当前使用的api-key使用量超限 # 这是在尝试调用api时发生超限异常时调用的 def set_current_exceeded(self): - md5 = hashlib.md5(self.using_key.encode('utf-8')).hexdigest() + # md5 = hashlib.md5(self.using_key.encode('utf-8')).hexdigest() # self.usage[md5] = self.api_key_usage_threshold - self.fee[md5] = self.api_key_fee_threshold + # self.fee[md5] = self.api_key_fee_threshold + self.exceeded.append(self.using_key) self.dump_fee() + def get_key_name(self, api_key): + """根据api-key获取其别名""" + for key_name in self.api_key: + if self.api_key[key_name] == api_key: + return key_name + return "" + def get_fee(self, api_key): md5 = hashlib.md5(api_key.encode('utf-8')).hexdigest() if md5 not in self.fee: @@ -103,6 +122,7 @@ class KeysManager: pkg.utils.context.get_qqbot_manager().notify_admin("api-key已用完,无未使用的api-key可供切换") self.alerted.append(key_name) return False + return False def dump_fee(self): pkg.utils.context.get_database_manager().dump_api_key_fee(api_keys=self.api_key, fee=self.fee) diff --git a/pkg/openai/manager.py b/pkg/openai/manager.py index e59146d6..2d0c1575 100644 --- a/pkg/openai/manager.py +++ b/pkg/openai/manager.py @@ -30,7 +30,6 @@ class OpenAIInteract: # 请求OpenAI Completion def request_completion(self, prompt, stop): - # print("request") response = openai.Completion.create( prompt=prompt, stop=stop, diff --git a/pkg/qqbot/process.py b/pkg/qqbot/process.py index 8f1222a0..5074b4ce 100644 --- a/pkg/qqbot/process.py +++ b/pkg/qqbot/process.py @@ -186,38 +186,42 @@ def process_message(launcher_type: str, launcher_id: int, text_message: str, mes "..." if len(text_message) > 20 else ""))) session = pkg.openai.session.get_session(session_name) - try: - prefix = "[GPT]" if hasattr(config, "show_prefix") and config.show_prefix else "" - reply = [prefix + session.append(text_message)] - except openai.error.APIConnectionError as e: - mgr.notify_admin("{}会话调用API失败:{}".format(session_name, e)) - reply = ["[bot]err:调用API失败,请重试或联系作者,或等待修复"] - except openai.error.RateLimitError as e: - # 尝试切换api-key - current_tokens_amt = pkg.utils.context.get_openai_manager().key_mgr.get_fee( - pkg.utils.context.get_openai_manager().key_mgr.get_using_key()) - # pkg.utils.context.get_openai_manager().key_mgr.set_current_exceeded() - switched, name = pkg.utils.context.get_openai_manager().key_mgr.auto_switch() - if not switched: - mgr.notify_admin("API调用额度超限({}),请向OpenAI账户充值或在config.py中更换api_key".format( - current_tokens_amt)) - reply = ["[bot]err:API调用额度超额,请联系作者,或等待修复"] - else: - openai.api_key = pkg.utils.context.get_openai_manager().key_mgr.get_using_key() - mgr.notify_admin("API调用额度超限({}),已切换到{}".format(current_tokens_amt, name)) - reply = ["[bot]err:API调用额度超额,已自动切换,请重新发送消息"] - except openai.error.InvalidRequestError as e: - mgr.notify_admin("{}API调用参数错误:{}\n\n这可能是由于config.py中的prompt_submit_length参数或" - "completion_api_params中的max_tokens参数数值过大导致的,请尝试将其降低".format( - session_name, e)) - reply = ["[bot]err:API调用参数错误,请联系作者,或等待修复"] - except openai.error.ServiceUnavailableError as e: - # mgr.notify_admin("{}API调用服务不可用:{}".format(session_name, e)) - reply = ["[bot]err:API调用服务暂不可用,请尝试重试"] - except Exception as e: - logging.exception(e) - reply = ["[bot]err:{}".format(e)] + while True: + try: + prefix = "[GPT]" if hasattr(config, "show_prefix") and config.show_prefix else "" + reply = [prefix + session.append(text_message)] + except openai.error.APIConnectionError as e: + mgr.notify_admin("{}会话调用API失败:{}".format(session_name, e)) + reply = ["[bot]err:调用API失败,请重试或联系作者,或等待修复"] + except openai.error.RateLimitError as e: + # 尝试切换api-key + current_tokens_amt = pkg.utils.context.get_openai_manager().key_mgr.get_fee( + pkg.utils.context.get_openai_manager().key_mgr.get_using_key()) + pkg.utils.context.get_openai_manager().key_mgr.set_current_exceeded() + switched, name = pkg.utils.context.get_openai_manager().key_mgr.auto_switch() + + if not switched: + mgr.notify_admin("API调用额度超限({}),无可用api_key,请向OpenAI账户充值或在config.py中更换api_key".format( + current_tokens_amt)) + reply = ["[bot]err:API调用额度超额,请联系作者,或等待修复"] + else: + openai.api_key = pkg.utils.context.get_openai_manager().key_mgr.get_using_key() + mgr.notify_admin("API调用额度超限({}),接口报错,已切换到{}".format(current_tokens_amt, name)) + reply = ["[bot]err:API调用额度超额,已自动切换,请重新发送消息"] + continue + except openai.error.InvalidRequestError as e: + mgr.notify_admin("{}API调用参数错误:{}\n\n这可能是由于config.py中的prompt_submit_length参数或" + "completion_api_params中的max_tokens参数数值过大导致的,请尝试将其降低".format( + session_name, e)) + reply = ["[bot]err:API调用参数错误,请联系作者,或等待修复"] + except openai.error.ServiceUnavailableError as e: + # mgr.notify_admin("{}API调用服务不可用:{}".format(session_name, e)) + reply = ["[bot]err:API调用服务暂不可用,请尝试重试"] + except Exception as e: + logging.exception(e) + reply = ["[bot]err:{}".format(e)] + break if reply is not None and type(reply[0]) == str: logging.info( diff --git a/pkg/utils/reloader.py b/pkg/utils/reloader.py index 152b3475..fdc919e2 100644 --- a/pkg/utils/reloader.py +++ b/pkg/utils/reloader.py @@ -26,6 +26,7 @@ def reload_all(notify=True): main.stop() # 重载所有模块 + pkg.utils.context.context['exceeded_keys'] = pkg.utils.context.get_openai_manager().key_mgr.exceeded context = pkg.utils.context.context walk(pkg) importlib.reload(__import__('config'))