mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-19 10:22:04 +08:00
perf: 结构化插件的表示格式; 优化插件开发接口
This commit is contained in:
@@ -29,12 +29,13 @@ from util import general_utils as gu
|
||||
from util.general_utils import Logger, upload, run_monitor
|
||||
from util.cmd_config import CmdConfig as cc
|
||||
from util.cmd_config import init_astrbot_config_items
|
||||
from . global_object import GlobalObject
|
||||
from .types import *
|
||||
from addons.dashboard.helper import DashBoardHelper
|
||||
from addons.dashboard.server import DashBoardData
|
||||
from cores.database.conn import dbConn
|
||||
from model.platform._message_result import MessageResult
|
||||
|
||||
|
||||
# 用户发言频率
|
||||
user_frequency = {}
|
||||
# 时间默认值
|
||||
@@ -43,7 +44,7 @@ frequency_time = 60
|
||||
frequency_count = 10
|
||||
|
||||
# 版本
|
||||
version = '3.1.6'
|
||||
version = '3.1.7'
|
||||
|
||||
# 语言模型
|
||||
REV_CHATGPT = 'rev_chatgpt'
|
||||
@@ -98,9 +99,6 @@ def init(cfg):
|
||||
_global_object = GlobalObject()
|
||||
_global_object.version = version
|
||||
_global_object.base_config = cfg
|
||||
_global_object.stat['session'] = {}
|
||||
_global_object.stat['message'] = {}
|
||||
_global_object.stat['platform'] = {}
|
||||
_global_object.logger = logger
|
||||
logger.log("AstrBot v"+version, gu.LEVEL_INFO)
|
||||
|
||||
@@ -125,6 +123,7 @@ def init(cfg):
|
||||
llm_instance[REV_CHATGPT] = ProviderRevChatGPT(cfg['rev_ChatGPT'], base_url=cc.get("CHATGPT_BASE_URL", None))
|
||||
llm_command_instance[REV_CHATGPT] = CommandRevChatGPT(llm_instance[REV_CHATGPT], _global_object)
|
||||
chosen_provider = REV_CHATGPT
|
||||
_global_object.llms.append(RegisteredLLM(llm_name=REV_CHATGPT, llm_instance=llm_instance[REV_CHATGPT], origin="internal"))
|
||||
else:
|
||||
input("请退出本程序, 然后在配置文件中填写rev_ChatGPT相关配置")
|
||||
if OPENAI_OFFICIAL in prov:
|
||||
@@ -134,6 +133,7 @@ def init(cfg):
|
||||
from model.command.openai_official import CommandOpenAIOfficial
|
||||
llm_instance[OPENAI_OFFICIAL] = ProviderOpenAIOfficial(cfg['openai'])
|
||||
llm_command_instance[OPENAI_OFFICIAL] = CommandOpenAIOfficial(llm_instance[OPENAI_OFFICIAL], _global_object)
|
||||
_global_object.llms.append(RegisteredLLM(llm_name=OPENAI_OFFICIAL, llm_instance=llm_instance[OPENAI_OFFICIAL], origin="internal"))
|
||||
chosen_provider = OPENAI_OFFICIAL
|
||||
|
||||
# 检查provider设置偏好
|
||||
@@ -184,7 +184,7 @@ def init(cfg):
|
||||
_command = Command(None, _global_object)
|
||||
ok, err = putil.plugin_reload(_global_object.cached_plugins)
|
||||
if ok:
|
||||
logger.log(f"成功载入{len(_global_object.cached_plugins)}个插件", gu.LEVEL_INFO)
|
||||
logger.log(f"成功载入 {len(_global_object.cached_plugins)} 个插件", gu.LEVEL_INFO)
|
||||
else:
|
||||
logger.log(err, gu.LEVEL_ERROR)
|
||||
|
||||
@@ -244,7 +244,7 @@ def run_qqchan_bot(cfg: dict, global_object: GlobalObject):
|
||||
try:
|
||||
from model.platform.qq_official import QQOfficial
|
||||
qqchannel_bot = QQOfficial(cfg=cfg, message_handler=oper_msg, global_object=global_object)
|
||||
global_object.platform_qqchan = qqchannel_bot
|
||||
global_object.platforms.append(RegisteredPlatform(platform_name="qq_official", platform_instance=qqchannel_bot, origin="internal"))
|
||||
qqchannel_bot.run()
|
||||
except BaseException as e:
|
||||
logger.log("启动QQ频道机器人时出现错误, 原因如下: " + str(e), gu.LEVEL_CRITICAL, tag="QQ频道")
|
||||
@@ -272,7 +272,7 @@ def run_gocq_bot(cfg: dict, _global_object: GlobalObject):
|
||||
break
|
||||
try:
|
||||
qq_gocq = QQGOCQ(cfg=cfg, message_handler=oper_msg, global_object=_global_object)
|
||||
_global_object.platform_qq = qq_gocq
|
||||
_global_object.platforms.append(RegisteredPlatform(platform_name="gocq", platform_instance=qq_gocq, origin="internal"))
|
||||
qq_gocq.run()
|
||||
except BaseException as e:
|
||||
input("启动QQ机器人出现错误"+str(e))
|
||||
@@ -317,7 +317,7 @@ async def oper_msg(message: Union[GroupMessage, FriendMessage, GuildMessage, Nak
|
||||
message: 消息对象
|
||||
session_id: 该消息源的唯一识别号
|
||||
role: member | admin
|
||||
platform: 平台(gocq, qqchan)
|
||||
platform: str 所注册的平台的名称。如果没有注册,将抛出一个异常。
|
||||
"""
|
||||
global chosen_provider, _global_object
|
||||
message_str = ''
|
||||
@@ -326,6 +326,16 @@ async def oper_msg(message: Union[GroupMessage, FriendMessage, GuildMessage, Nak
|
||||
hit = False # 是否命中指令
|
||||
command_result = () # 调用指令返回的结果
|
||||
|
||||
# 获取平台实例
|
||||
reg_platform: RegisteredPlatform = None
|
||||
for p in _global_object.platforms:
|
||||
if p.platform_name == platform:
|
||||
reg_platform = p
|
||||
break
|
||||
if not reg_platform:
|
||||
_global_object.logger.log(f"未找到平台 {platform} 的实例。", gu.LEVEL_ERROR)
|
||||
raise Exception(f"未找到平台 {platform} 的实例。")
|
||||
|
||||
# 统计数据,如频道消息量
|
||||
await record_message(platform, session_id)
|
||||
|
||||
@@ -365,7 +375,7 @@ async def oper_msg(message: Union[GroupMessage, FriendMessage, GuildMessage, Nak
|
||||
message_str,
|
||||
session_id,
|
||||
role,
|
||||
platform,
|
||||
reg_platform,
|
||||
message,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
from model.platform.qq_official import QQOfficial, NakuruGuildMessage
|
||||
from model.platform.qq_gocq import QQGOCQ
|
||||
from model.provider.provider import Provider
|
||||
from addons.dashboard.server import DashBoardData
|
||||
from nakuru import (
|
||||
GroupMessage,
|
||||
FriendMessage,
|
||||
GuildMessage,
|
||||
)
|
||||
from typing import Union
|
||||
|
||||
class GlobalObject:
|
||||
'''
|
||||
存放一些公用的数据,用于在不同模块(如core与command)之间传递
|
||||
'''
|
||||
version: str
|
||||
nick: str # gocq 的昵称
|
||||
base_config: dict # config.json
|
||||
cached_plugins: dict # 缓存的插件
|
||||
web_search: bool # 是否开启了网页搜索
|
||||
reply_prefix: str
|
||||
admin_qq: str
|
||||
admin_qqchan: str
|
||||
unique_session: bool
|
||||
cnt_total: int
|
||||
platform_qq: QQGOCQ
|
||||
platform_qqchan: QQOfficial
|
||||
default_personality: dict
|
||||
dashboard_data: DashBoardData
|
||||
stat: dict
|
||||
logger: None
|
||||
|
||||
def __init__(self):
|
||||
self.nick = None # gocq 的昵称
|
||||
self.base_config = None # config.yaml
|
||||
self.cached_plugins = {} # 缓存的插件
|
||||
self.web_search = False # 是否开启了网页搜索
|
||||
self.reply_prefix = None
|
||||
self.admin_qq = "123456"
|
||||
self.admin_qqchan = "123456"
|
||||
self.unique_session = False
|
||||
self.cnt_total = 0
|
||||
self.platform_qq = None
|
||||
self.platform_qqchan = None
|
||||
self.default_personality = None
|
||||
self.dashboard_data = None
|
||||
self.stat = {}
|
||||
|
||||
|
||||
class AstrMessageEvent():
|
||||
message_str: str # 纯消息字符串
|
||||
message_obj: Union[GroupMessage, FriendMessage, GuildMessage, NakuruGuildMessage] # 消息对象
|
||||
gocq_platform: QQGOCQ
|
||||
qq_sdk_platform: QQOfficial
|
||||
platform: str # `gocq` 或 `qqchan`
|
||||
role: str # `admin` 或 `member`
|
||||
global_object: GlobalObject # 一些公用数据
|
||||
session_id: int # 会话id (可能是群id,也可能是某个user的id。取决于是否开启了 unique_session)
|
||||
|
||||
def __init__(self, message_str: str,
|
||||
message_obj: Union[GroupMessage, FriendMessage, GuildMessage, NakuruGuildMessage],
|
||||
gocq_platform: QQGOCQ,
|
||||
qq_sdk_platform: QQOfficial,
|
||||
platform: str,
|
||||
role: str,
|
||||
global_object: GlobalObject,
|
||||
llm_provider: Provider = None,
|
||||
session_id: int = None):
|
||||
self.message_str = message_str
|
||||
self.message_obj = message_obj
|
||||
self.gocq_platform = gocq_platform
|
||||
self.qq_sdk_platform = qq_sdk_platform
|
||||
self.platform = platform
|
||||
self.role = role
|
||||
self.global_object = global_object
|
||||
self.llm_provider = llm_provider
|
||||
self.session_id = session_id
|
||||
|
||||
class CommandResult():
|
||||
'''
|
||||
用于在Command中返回多个值
|
||||
'''
|
||||
def __init__(self, hit: bool, success: bool, message_chain: list, command_name: str = "unknown_command") -> None:
|
||||
self.hit = hit
|
||||
self.success = success
|
||||
self.message_chain = message_chain
|
||||
self.command_name = command_name
|
||||
|
||||
def _result_tuple(self):
|
||||
return (self.success, self.message_chain, self.command_name)
|
||||
140
cores/qqbot/types.py
Normal file
140
cores/qqbot/types.py
Normal file
@@ -0,0 +1,140 @@
|
||||
from model.platform.qq_official import NakuruGuildMessage
|
||||
from model.provider.provider import Provider as LLMProvider
|
||||
from model.platform._platfrom import Platform
|
||||
from nakuru import (
|
||||
GroupMessage,
|
||||
FriendMessage,
|
||||
GuildMessage,
|
||||
)
|
||||
from typing import Union, List, ClassVar
|
||||
from types import ModuleType
|
||||
from enum import Enum
|
||||
from dataclasses import dataclass
|
||||
|
||||
class PluginType(Enum):
|
||||
PLATFORM = 'platfrom' # 平台类插件。
|
||||
LLM = 'llm' # 大语言模型类插件
|
||||
COMMON = 'common' # 其他插件
|
||||
|
||||
@dataclass
|
||||
class PluginMetadata:
|
||||
'''
|
||||
插件的元数据。
|
||||
'''
|
||||
# required
|
||||
plugin_name: str
|
||||
plugin_type: PluginType
|
||||
author: str # 插件作者
|
||||
desc: str # 插件简介
|
||||
version: str # 插件版本
|
||||
|
||||
# optional
|
||||
repo: str = None # 插件仓库地址
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"PluginMetadata({self.plugin_name}, {self.plugin_type}, {self.desc}, {self.version}, {self.repo})"
|
||||
|
||||
@dataclass
|
||||
class RegisteredPlugin:
|
||||
'''
|
||||
注册在 AstrBot 中的插件。
|
||||
'''
|
||||
metadata: PluginMetadata
|
||||
plugin_instance: object
|
||||
module_path: str
|
||||
module: ModuleType
|
||||
root_dir_name: str
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"RegisteredPlugin({self.metadata}, {self.module_path}, {self.root_dir_name})"
|
||||
|
||||
RegisteredPlugins = List[RegisteredPlugin]
|
||||
|
||||
@dataclass
|
||||
class RegisteredPlatform:
|
||||
'''
|
||||
注册在 AstrBot 中的平台。平台应当实现 Platform 接口。
|
||||
'''
|
||||
platform_name: str
|
||||
platform_instance: Platform
|
||||
origin: str = None # 注册来源
|
||||
|
||||
@dataclass
|
||||
class RegisteredLLM:
|
||||
'''
|
||||
注册在 AstrBot 中的大语言模型调用。大语言模型应当实现 LLMProvider 接口。
|
||||
'''
|
||||
llm_name: str
|
||||
llm_instance: LLMProvider
|
||||
origin: str = None # 注册来源
|
||||
|
||||
class GlobalObject:
|
||||
'''
|
||||
存放一些公用的数据,用于在不同模块(如core与command)之间传递
|
||||
'''
|
||||
version: str # 机器人版本
|
||||
nick: str # 用户定义的机器人的别名
|
||||
base_config: dict # config.json 中导出的配置
|
||||
cached_plugins: List[RegisteredPlugin] # 加载的插件
|
||||
platforms: List[RegisteredPlatform]
|
||||
llms: List[RegisteredLLM]
|
||||
|
||||
web_search: bool # 是否开启了网页搜索
|
||||
reply_prefix: str # 回复前缀
|
||||
unique_session: bool # 是否开启了独立会话
|
||||
cnt_total: int # 总消息数
|
||||
default_personality: dict
|
||||
dashboard_data = None
|
||||
logger: None
|
||||
|
||||
def __init__(self):
|
||||
self.nick = None # gocq 的昵称
|
||||
self.base_config = None # config.yaml
|
||||
self.cached_plugins = [] # 缓存的插件
|
||||
self.web_search = False # 是否开启了网页搜索
|
||||
self.reply_prefix = None
|
||||
self.unique_session = False
|
||||
self.cnt_total = 0
|
||||
self.platforms = []
|
||||
self.llms = []
|
||||
self.default_personality = None
|
||||
self.dashboard_data = None
|
||||
self.stat = {}
|
||||
|
||||
class AstrMessageEvent():
|
||||
'''
|
||||
消息事件。
|
||||
'''
|
||||
context: GlobalObject # 一些公用数据
|
||||
message_str: str # 纯消息字符串
|
||||
message_obj: Union[GroupMessage, FriendMessage, GuildMessage, NakuruGuildMessage] # 消息对象
|
||||
platform: RegisteredPlatform # 来源平台
|
||||
role: str # 基本身份。`admin` 或 `member`
|
||||
session_id: int # 会话 id
|
||||
|
||||
def __init__(self,
|
||||
message_str: str,
|
||||
message_obj: Union[GroupMessage, FriendMessage, GuildMessage, NakuruGuildMessage],
|
||||
platform: RegisteredPlatform,
|
||||
role: str,
|
||||
context: GlobalObject,
|
||||
session_id: str = None):
|
||||
self.context = context
|
||||
self.message_str = message_str
|
||||
self.message_obj = message_obj
|
||||
self.platform = platform
|
||||
self.role = role
|
||||
self.session_id = session_id
|
||||
|
||||
class CommandResult():
|
||||
'''
|
||||
用于在Command中返回多个值
|
||||
'''
|
||||
def __init__(self, hit: bool, success: bool, message_chain: list, command_name: str = "unknown_command") -> None:
|
||||
self.hit = hit
|
||||
self.success = success
|
||||
self.message_chain = message_chain
|
||||
self.command_name = command_name
|
||||
|
||||
def _result_tuple(self):
|
||||
return (self.success, self.message_chain, self.command_name)
|
||||
Reference in New Issue
Block a user