QChatGPT/pkg/qqbot/message.py

135 lines
6.3 KiB
Python
Raw Normal View History

# 普通消息处理模块
import logging
2023-11-13 21:59:23 +08:00
import openai
2023-11-13 21:59:23 +08:00
from ..utils import context
from ..openai import session as openai_session
from ..plugin import host as plugin_host
from ..plugin import models as plugin_models
2023-04-07 13:20:57 +08:00
import tips as tips_custom
def handle_exception(notify_admin: str = "", set_reply: str = "") -> list:
"""处理异常当notify_admin不为空时会通知管理员返回通知用户的消息"""
import config
2023-11-13 21:59:23 +08:00
context.get_qqbot_manager().notify_admin(notify_admin)
if config.hide_exce_info_to_user:
return [tips_custom.alter_tip_message] if tips_custom.alter_tip_message else []
else:
return [set_reply]
def process_normal_message(text_message: str, mgr, config, launcher_type: str,
launcher_id: int, sender_id: int) -> list:
session_name = f"{launcher_type}_{launcher_id}"
logging.info("[{}]发送消息:{}".format(session_name, text_message[:min(20, len(text_message))] + (
"..." if len(text_message) > 20 else "")))
2023-11-13 21:59:23 +08:00
session = openai_session.get_session(session_name)
2023-02-09 14:33:24 +08:00
unexpected_exception_times = 0
max_unexpected_exception_times = 3
reply = []
while True:
2023-02-09 14:33:24 +08:00
if unexpected_exception_times >= max_unexpected_exception_times:
2023-02-09 15:06:47 +08:00
reply = handle_exception(notify_admin=f"{session_name},多次尝试失败。", set_reply=f"[bot]多次尝试失败,请重试或联系管理员")
2023-02-09 14:33:24 +08:00
break
try:
prefix = "[GPT]" if config.show_prefix else ""
text, finish_reason, funcs = session.query(text_message)
# 触发插件事件
args = {
"launcher_type": launcher_type,
"launcher_id": launcher_id,
"sender_id": sender_id,
"session": session,
"prefix": prefix,
"response_text": text,
"finish_reason": finish_reason,
"funcs_called": funcs,
}
2023-11-13 21:59:23 +08:00
event = plugin_host.emit(plugin_models.NormalMessageResponded, **args)
2023-01-15 20:37:23 +08:00
if event.get_return_value("prefix") is not None:
prefix = event.get_return_value("prefix")
if event.get_return_value("reply") is not None:
2023-01-15 21:13:44 +08:00
reply = event.get_return_value("reply")
if not event.is_prevented_default():
2023-03-15 22:47:20 +08:00
reply = [prefix + text]
2023-11-10 10:13:50 +08:00
except openai.APIConnectionError as e:
2023-02-09 15:05:00 +08:00
err_msg = str(e)
if err_msg.__contains__('Error communicating with OpenAI'):
2023-08-06 12:17:04 +08:00
reply = handle_exception("{}会话调用API失败:{}\n您的网络无法访问OpenAI接口或网络代理不正常".format(session_name, e),
2023-02-09 15:05:00 +08:00
"[bot]err:调用API失败请重试或联系管理员或等待修复")
else:
reply = handle_exception("{}会话调用API失败:{}".format(session_name, e), "[bot]err:调用API失败请重试或联系管理员或等待修复")
2023-11-10 10:13:50 +08:00
except openai.RateLimitError as e:
logging.debug(type(e))
2023-01-25 22:51:09 +08:00
logging.debug(e.error['message'])
2023-01-14 22:36:48 +08:00
2023-01-25 22:51:09 +08:00
if 'message' in e.error and e.error['message'].__contains__('You exceeded your current quota'):
# 尝试切换api-key
2023-11-13 21:59:23 +08:00
current_key_name = context.get_openai_manager().key_mgr.get_key_name(
context.get_openai_manager().key_mgr.using_key
2023-01-25 22:51:09 +08:00
)
2023-11-13 21:59:23 +08:00
context.get_openai_manager().key_mgr.set_current_exceeded()
2023-01-14 22:36:48 +08:00
2023-01-25 22:51:09 +08:00
# 触发插件事件
args = {
'key_name': current_key_name,
2023-11-13 21:59:23 +08:00
'usage': context.get_openai_manager().audit_mgr
.get_usage(context.get_openai_manager().key_mgr.get_using_key_md5()),
'exceeded_keys': context.get_openai_manager().key_mgr.exceeded,
2023-01-25 22:51:09 +08:00
}
event = plugin_host.emit(plugin_models.KeyExceeded, **args)
if not event.is_prevented_default():
2023-11-13 21:59:23 +08:00
switched, name = context.get_openai_manager().key_mgr.auto_switch()
2023-01-25 22:51:09 +08:00
if not switched:
reply = handle_exception(
2023-02-09 15:05:00 +08:00
"api-key调用额度超限({}),无可用api_key,请向OpenAI账户充值或在config.py中更换api_key如果你认为这是误判请尝试重启程序。".format(
current_key_name), "[bot]err:API调用额度超额请联系管理员或等待修复")
2023-01-25 22:51:09 +08:00
else:
2023-11-13 21:59:23 +08:00
openai.api_key = context.get_openai_manager().key_mgr.get_using_key()
2023-01-25 22:51:09 +08:00
mgr.notify_admin("api-key调用额度超限({}),接口报错,已切换到{}".format(current_key_name, name))
reply = ["[bot]err:API调用额度超额已自动切换请重新发送消息"]
continue
elif 'message' in e.error and e.error['message'].__contains__('You can retry your request'):
# 重试
2023-02-09 14:33:24 +08:00
unexpected_exception_times += 1
continue
elif 'message' in e.error and e.error['message']\
.__contains__('The server had an error while processing your request'):
# 重试
unexpected_exception_times += 1
continue
2023-01-25 22:51:09 +08:00
else:
reply = handle_exception("{}会话调用API失败:{}".format(session_name, e),
"[bot]err:RateLimitError,请重试或联系作者,或等待修复")
2023-11-10 10:13:50 +08:00
except openai.BadRequestError as e:
2023-06-08 13:49:20 +08:00
if config.auto_reset and "This model's maximum context length is" in str(e):
2023-07-07 16:35:37 +08:00
session.reset(persist=True)
reply = [tips_custom.session_auto_reset_message]
else:
reply = handle_exception("{}API调用参数错误:{}\n".format(
session_name, e), "[bot]err:API调用参数错误请联系管理员或等待修复")
2023-11-10 10:13:50 +08:00
except openai.APIStatusError as e:
2023-02-09 15:05:00 +08:00
reply = handle_exception("{}API调用服务不可用:{}".format(session_name, e), "[bot]err:API调用服务不可用请重试或联系管理员或等待修复")
except Exception as e:
logging.exception(e)
reply = handle_exception("{}会话处理异常:{}".format(session_name, e), "[bot]err:{}".format(e))
break
return reply