2023-01-13 16:49:56 +08:00
|
|
|
|
import logging
|
|
|
|
|
|
2023-11-13 21:59:23 +08:00
|
|
|
|
from ..plugin import host
|
|
|
|
|
from ..utils import context
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
2023-01-14 23:35:03 +08:00
|
|
|
|
PersonMessageReceived = "person_message_received"
|
2023-01-13 23:13:54 +08:00
|
|
|
|
"""收到私聊消息时,在判断是否应该响应前触发
|
|
|
|
|
kwargs:
|
|
|
|
|
launcher_type: str 发起对象类型(group/person)
|
|
|
|
|
launcher_id: int 发起对象ID(群号/QQ号)
|
|
|
|
|
sender_id: int 发送者ID(QQ号)
|
|
|
|
|
message_chain: mirai.models.message.MessageChain 消息链
|
|
|
|
|
"""
|
|
|
|
|
|
2023-01-14 23:35:03 +08:00
|
|
|
|
GroupMessageReceived = "group_message_received"
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""收到群聊消息时,在判断是否应该响应前触发(所有群消息)
|
|
|
|
|
kwargs:
|
|
|
|
|
launcher_type: str 发起对象类型(group/person)
|
|
|
|
|
launcher_id: int 发起对象ID(群号/QQ号)
|
|
|
|
|
sender_id: int 发送者ID(QQ号)
|
|
|
|
|
message_chain: mirai.models.message.MessageChain 消息链
|
|
|
|
|
"""
|
2023-01-13 23:13:54 +08:00
|
|
|
|
|
2023-01-14 23:35:03 +08:00
|
|
|
|
PersonNormalMessageReceived = "person_normal_message_received"
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""判断为应该处理的私聊普通消息时触发
|
|
|
|
|
kwargs:
|
|
|
|
|
launcher_type: str 发起对象类型(group/person)
|
|
|
|
|
launcher_id: int 发起对象ID(群号/QQ号)
|
|
|
|
|
sender_id: int 发送者ID(QQ号)
|
|
|
|
|
text_message: str 消息文本
|
2023-01-15 20:37:23 +08:00
|
|
|
|
|
|
|
|
|
returns (optional):
|
|
|
|
|
alter: str 修改后的消息文本
|
2023-01-15 22:41:47 +08:00
|
|
|
|
reply: list 回复消息组件列表
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""
|
2023-01-13 23:13:54 +08:00
|
|
|
|
|
2023-01-14 23:35:03 +08:00
|
|
|
|
PersonCommandSent = "person_command_sent"
|
2024-01-12 16:48:47 +08:00
|
|
|
|
"""判断为应该处理的私聊命令时触发
|
2023-01-13 23:26:52 +08:00
|
|
|
|
kwargs:
|
|
|
|
|
launcher_type: str 发起对象类型(group/person)
|
|
|
|
|
launcher_id: int 发起对象ID(群号/QQ号)
|
|
|
|
|
sender_id: int 发送者ID(QQ号)
|
2024-01-12 16:48:47 +08:00
|
|
|
|
command: str 命令
|
2023-01-14 22:36:48 +08:00
|
|
|
|
params: list[str] 参数列表
|
2024-01-12 16:48:47 +08:00
|
|
|
|
text_message: str 完整命令文本
|
2023-01-13 23:26:52 +08:00
|
|
|
|
is_admin: bool 是否为管理员
|
2023-01-15 13:57:05 +08:00
|
|
|
|
|
|
|
|
|
returns (optional):
|
2024-01-12 16:48:47 +08:00
|
|
|
|
alter: str 修改后的完整命令文本
|
2023-01-15 13:57:05 +08:00
|
|
|
|
reply: list 回复消息组件列表
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""
|
2023-01-13 23:13:54 +08:00
|
|
|
|
|
2023-01-14 23:35:03 +08:00
|
|
|
|
GroupNormalMessageReceived = "group_normal_message_received"
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""判断为应该处理的群聊普通消息时触发
|
|
|
|
|
kwargs:
|
|
|
|
|
launcher_type: str 发起对象类型(group/person)
|
|
|
|
|
launcher_id: int 发起对象ID(群号/QQ号)
|
|
|
|
|
sender_id: int 发送者ID(QQ号)
|
|
|
|
|
text_message: str 消息文本
|
2023-01-15 20:37:23 +08:00
|
|
|
|
|
|
|
|
|
returns (optional):
|
|
|
|
|
alter: str 修改后的消息文本
|
2023-01-15 22:41:47 +08:00
|
|
|
|
reply: list 回复消息组件列表
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""
|
2023-01-13 23:13:54 +08:00
|
|
|
|
|
2023-01-14 23:35:03 +08:00
|
|
|
|
GroupCommandSent = "group_command_sent"
|
2024-01-12 16:48:47 +08:00
|
|
|
|
"""判断为应该处理的群聊命令时触发
|
2023-01-13 23:26:52 +08:00
|
|
|
|
kwargs:
|
|
|
|
|
launcher_type: str 发起对象类型(group/person)
|
|
|
|
|
launcher_id: int 发起对象ID(群号/QQ号)
|
|
|
|
|
sender_id: int 发送者ID(QQ号)
|
2024-01-12 16:48:47 +08:00
|
|
|
|
command: str 命令
|
2023-01-14 22:36:48 +08:00
|
|
|
|
params: list[str] 参数列表
|
2024-01-12 16:48:47 +08:00
|
|
|
|
text_message: str 完整命令文本
|
2023-01-14 22:36:48 +08:00
|
|
|
|
is_admin: bool 是否为管理员
|
2023-01-15 20:37:23 +08:00
|
|
|
|
|
|
|
|
|
returns (optional):
|
2024-01-12 16:48:47 +08:00
|
|
|
|
alter: str 修改后的完整命令文本
|
2023-01-15 20:37:23 +08:00
|
|
|
|
reply: list 回复消息组件列表
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""
|
2023-01-13 23:13:54 +08:00
|
|
|
|
|
2023-01-15 13:57:05 +08:00
|
|
|
|
NormalMessageResponded = "normal_message_responded"
|
|
|
|
|
"""获取到对普通消息的文字响应时触发
|
|
|
|
|
kwargs:
|
|
|
|
|
launcher_type: str 发起对象类型(group/person)
|
|
|
|
|
launcher_id: int 发起对象ID(群号/QQ号)
|
|
|
|
|
sender_id: int 发送者ID(QQ号)
|
|
|
|
|
session: pkg.openai.session.Session 会话对象
|
|
|
|
|
prefix: str 回复文字消息的前缀
|
|
|
|
|
response_text: str 响应文本
|
2023-08-01 14:31:38 +08:00
|
|
|
|
finish_reason: str 响应结束原因
|
2023-08-02 18:01:02 +08:00
|
|
|
|
funcs_called: list[str] 此次响应中调用的函数列表
|
2023-01-15 13:57:05 +08:00
|
|
|
|
|
|
|
|
|
returns (optional):
|
2023-01-15 20:37:23 +08:00
|
|
|
|
prefix: str 修改后的回复文字消息的前缀
|
2023-01-15 13:57:05 +08:00
|
|
|
|
reply: list 替换回复消息组件列表
|
|
|
|
|
"""
|
|
|
|
|
|
2023-01-14 23:35:03 +08:00
|
|
|
|
SessionFirstMessageReceived = "session_first_message_received"
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""会话被第一次交互时触发
|
|
|
|
|
kwargs:
|
|
|
|
|
session_name: str 会话名称(<launcher_type>_<launcher_id>)
|
|
|
|
|
session: pkg.openai.session.Session 会话对象
|
|
|
|
|
default_prompt: str 预设值
|
|
|
|
|
"""
|
2023-01-13 23:13:54 +08:00
|
|
|
|
|
2023-01-14 22:36:48 +08:00
|
|
|
|
SessionExplicitReset = "session_reset"
|
|
|
|
|
"""会话被用户手动重置时触发,此事件不支持阻止默认行为
|
2023-01-13 23:26:52 +08:00
|
|
|
|
kwargs:
|
|
|
|
|
session_name: str 会话名称(<launcher_type>_<launcher_id>)
|
|
|
|
|
session: pkg.openai.session.Session 会话对象
|
|
|
|
|
"""
|
2023-01-13 23:13:54 +08:00
|
|
|
|
|
2023-01-13 16:49:56 +08:00
|
|
|
|
SessionExpired = "session_expired"
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""会话过期时触发
|
|
|
|
|
kwargs:
|
|
|
|
|
session_name: str 会话名称(<launcher_type>_<launcher_id>)
|
|
|
|
|
session: pkg.openai.session.Session 会话对象
|
2023-01-14 22:36:48 +08:00
|
|
|
|
session_expire_time: int 已设置的会话过期时间(秒)
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""
|
2023-01-13 23:13:54 +08:00
|
|
|
|
|
2023-01-13 16:49:56 +08:00
|
|
|
|
KeyExceeded = "key_exceeded"
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""api-key超额时触发
|
|
|
|
|
kwargs:
|
|
|
|
|
key_name: str 超额的api-key名称
|
|
|
|
|
usage: dict 超额的api-key使用情况
|
2023-01-14 22:36:48 +08:00
|
|
|
|
exceeded_keys: list[str] 超额的api-key列表
|
2023-01-13 23:26:52 +08:00
|
|
|
|
"""
|
2023-01-13 23:13:54 +08:00
|
|
|
|
|
2023-01-13 16:49:56 +08:00
|
|
|
|
KeySwitched = "key_switched"
|
2023-01-14 22:36:48 +08:00
|
|
|
|
"""api-key超额切换成功时触发,此事件不支持阻止默认行为
|
2023-01-13 23:26:52 +08:00
|
|
|
|
kwargs:
|
|
|
|
|
key_name: str 切换成功的api-key名称
|
|
|
|
|
key_list: list[str] api-key列表
|
|
|
|
|
"""
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
2023-07-31 17:21:09 +08:00
|
|
|
|
PromptPreProcessing = "prompt_pre_processing"
|
|
|
|
|
"""每回合调用接口前对prompt进行预处理时触发,此事件不支持阻止默认行为
|
|
|
|
|
kwargs:
|
|
|
|
|
session_name: str 会话名称(<launcher_type>_<launcher_id>)
|
|
|
|
|
default_prompt: list 此session使用的情景预设内容
|
|
|
|
|
prompt: list 此session现有的prompt内容
|
|
|
|
|
text_message: str 用户发送的消息文本
|
|
|
|
|
|
|
|
|
|
returns (optional):
|
|
|
|
|
default_prompt: list 修改后的情景预设内容
|
|
|
|
|
prompt: list 修改后的prompt内容
|
|
|
|
|
text_message: str 修改后的消息文本
|
|
|
|
|
"""
|
|
|
|
|
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
2023-07-29 16:51:19 +08:00
|
|
|
|
def on(*args, **kwargs):
|
2023-01-14 22:36:48 +08:00
|
|
|
|
"""注册事件监听器
|
|
|
|
|
"""
|
2023-07-29 16:51:19 +08:00
|
|
|
|
return Plugin.on(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
def func(*args, **kwargs):
|
2023-07-29 17:10:47 +08:00
|
|
|
|
"""注册内容函数,声明此函数为一个内容函数,在对话中将发送此函数给GPT以供其调用
|
|
|
|
|
此函数可以具有任意的参数,但必须按照[此文档](https://github.com/RockChinQ/CallingGPT/wiki/1.-Function-Format#function-format)
|
|
|
|
|
所述的格式编写函数的docstring。
|
|
|
|
|
此功能仅支持在使用gpt-3.5或gpt-4系列模型时使用。
|
2023-07-29 16:51:19 +08:00
|
|
|
|
"""
|
|
|
|
|
return Plugin.func(*args, **kwargs)
|
2023-01-14 22:36:48 +08:00
|
|
|
|
|
|
|
|
|
|
2023-01-16 23:40:59 +08:00
|
|
|
|
__current_registering_plugin__ = ""
|
|
|
|
|
|
|
|
|
|
|
2023-07-31 17:46:30 +08:00
|
|
|
|
def require_ver(ge: str, le: str="v999.9.9") -> bool:
|
|
|
|
|
"""插件版本要求装饰器
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
ge (str): 最低版本要求
|
|
|
|
|
le (str, optional): 最高版本要求
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
bool: 是否满足要求, False时为无法获取版本号,True时为满足要求,报错为不满足要求
|
|
|
|
|
"""
|
|
|
|
|
qchatgpt_version = ""
|
|
|
|
|
|
|
|
|
|
from pkg.utils.updater import get_current_tag, compare_version_str
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
qchatgpt_version = get_current_tag() # 从updater模块获取版本号
|
|
|
|
|
except:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if compare_version_str(qchatgpt_version, ge) < 0 or \
|
|
|
|
|
(compare_version_str(qchatgpt_version, le) > 0):
|
|
|
|
|
raise Exception("QChatGPT 版本不满足要求,某些功能(可能是由插件提供的)无法正常使用。(要求版本:{}-{},但当前版本:{})".format(ge, le, qchatgpt_version))
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
2023-01-13 16:49:56 +08:00
|
|
|
|
class Plugin:
|
2023-03-05 15:39:13 +08:00
|
|
|
|
"""插件基类"""
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
|
|
|
|
host: host.PluginHost
|
|
|
|
|
"""插件宿主,提供插件的一些基础功能"""
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def on(cls, event):
|
|
|
|
|
"""事件处理器装饰器
|
|
|
|
|
|
|
|
|
|
:param
|
|
|
|
|
event: 事件类型
|
|
|
|
|
:return:
|
|
|
|
|
None
|
|
|
|
|
"""
|
2023-02-25 20:29:21 +08:00
|
|
|
|
global __current_registering_plugin__
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
2023-07-29 17:10:47 +08:00
|
|
|
|
def wrapper(func):
|
|
|
|
|
plugin_hooks = host.__plugins__[__current_registering_plugin__]["hooks"]
|
2023-07-28 19:03:02 +08:00
|
|
|
|
|
2023-07-29 17:10:47 +08:00
|
|
|
|
if event not in plugin_hooks:
|
|
|
|
|
plugin_hooks[event] = []
|
|
|
|
|
plugin_hooks[event].append(func)
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
2023-07-29 17:10:47 +08:00
|
|
|
|
# print("registering hook: p='{}', e='{}', f={}".format(__current_registering_plugin__, event, func))
|
2023-02-25 20:29:21 +08:00
|
|
|
|
|
2023-07-29 17:10:47 +08:00
|
|
|
|
host.__plugins__[__current_registering_plugin__]["hooks"] = plugin_hooks
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
2023-07-29 17:10:47 +08:00
|
|
|
|
return func
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
2023-07-29 17:10:47 +08:00
|
|
|
|
return wrapper
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
2023-07-29 16:51:19 +08:00
|
|
|
|
@classmethod
|
|
|
|
|
def func(cls, name: str=None):
|
|
|
|
|
"""内容函数装饰器
|
|
|
|
|
"""
|
|
|
|
|
global __current_registering_plugin__
|
|
|
|
|
from CallingGPT.entities.namespace import get_func_schema
|
|
|
|
|
|
|
|
|
|
def wrapper(func):
|
|
|
|
|
|
|
|
|
|
function_schema = get_func_schema(func)
|
|
|
|
|
function_schema['name'] = __current_registering_plugin__ + '-' + (func.__name__ if name is None else name)
|
|
|
|
|
|
2023-07-29 17:10:47 +08:00
|
|
|
|
function_schema['enabled'] = True
|
|
|
|
|
|
2023-07-29 16:51:19 +08:00
|
|
|
|
host.__function_inst_map__[function_schema['name']] = function_schema['function']
|
|
|
|
|
|
|
|
|
|
del function_schema['function']
|
|
|
|
|
|
|
|
|
|
# logging.debug("registering content function: p='{}', f='{}', s={}".format(__current_registering_plugin__, func, function_schema))
|
|
|
|
|
|
|
|
|
|
host.__callable_functions__.append(
|
|
|
|
|
function_schema
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return func
|
|
|
|
|
|
|
|
|
|
return wrapper
|
|
|
|
|
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
|
|
|
|
def register(name: str, description: str, version: str, author: str):
|
|
|
|
|
"""注册插件, 此函数作为装饰器使用
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
name (str): 插件名称
|
|
|
|
|
description (str): 插件描述
|
|
|
|
|
version (str): 插件版本
|
|
|
|
|
author (str): 插件作者
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
None
|
|
|
|
|
"""
|
|
|
|
|
global __current_registering_plugin__
|
|
|
|
|
|
|
|
|
|
__current_registering_plugin__ = name
|
2023-02-19 11:46:12 +08:00
|
|
|
|
# print("registering plugin: n='{}', d='{}', v={}, a='{}'".format(name, description, version, author))
|
2023-01-13 16:49:56 +08:00
|
|
|
|
host.__plugins__[name] = {
|
|
|
|
|
"name": name,
|
|
|
|
|
"description": description,
|
|
|
|
|
"version": version,
|
|
|
|
|
"author": author,
|
2023-01-16 23:40:59 +08:00
|
|
|
|
"hooks": {},
|
|
|
|
|
"path": host.__current_module_path__,
|
|
|
|
|
"enabled": True,
|
2023-01-16 23:47:57 +08:00
|
|
|
|
"instance": None,
|
2023-01-13 16:49:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def wrapper(cls: Plugin):
|
|
|
|
|
cls.name = name
|
|
|
|
|
cls.description = description
|
|
|
|
|
cls.version = version
|
|
|
|
|
cls.author = author
|
2023-11-13 21:59:23 +08:00
|
|
|
|
cls.host = context.get_plugin_host()
|
2023-01-16 23:40:59 +08:00
|
|
|
|
cls.enabled = True
|
|
|
|
|
cls.path = host.__current_module_path__
|
2023-01-13 16:49:56 +08:00
|
|
|
|
|
|
|
|
|
# 存到插件列表
|
|
|
|
|
host.__plugins__[name]["class"] = cls
|
|
|
|
|
|
|
|
|
|
logging.info("插件注册完成: n='{}', d='{}', v={}, a='{}' ({})".format(name, description, version, author, cls))
|
|
|
|
|
|
|
|
|
|
return cls
|
|
|
|
|
|
|
|
|
|
return wrapper
|