@@ -25,7 +25,7 @@ available_setting = { | |||
"single_chat_reply_suffix": "", # 私聊时自动回复的后缀,\n 可以换行 | |||
"group_chat_prefix": ["@bot"], # 群聊时包含该前缀则会触发机器人回复 | |||
"group_chat_reply_prefix": "", # 群聊时自动回复的前缀 | |||
"group_chat_reply_suffix": "", # 群聊时自动回复的后缀,\n 可以换行 | |||
"group_chat_reply_suffix": "", # 群聊时自动回复的后缀,\n 可以换行 | |||
"group_chat_keyword": [], # 群聊时包含该关键词则会触发机器人回复 | |||
"group_at_off": False, # 是否关闭群聊时@bot的触发 | |||
"group_name_white_list": ["ChatGPT测试群", "ChatGPT测试群2"], # 开启自动回复的群名称列表 | |||
@@ -37,7 +37,8 @@ available_setting = { | |||
"image_create_size": "256x256", # 图片大小,可选有 256x256, 512x512, 1024x1024 | |||
# chatgpt会话参数 | |||
"expires_in_seconds": 3600, # 无操作会话的过期时间 | |||
"character_desc": "你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。", # 人格描述 | |||
# 人格描述 | |||
"character_desc": "你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。", | |||
"conversation_max_tokens": 1000, # 支持上下文记忆的最多字符数 | |||
# chatgpt限流配置 | |||
"rate_limit_chatgpt": 20, # chatgpt的调用频率限制 | |||
@@ -228,3 +229,26 @@ def subscribe_msg(): | |||
trigger_prefix = conf().get("single_chat_prefix", [""])[0] | |||
msg = conf().get("subscribe_msg", "") | |||
return msg.format(trigger_prefix=trigger_prefix) | |||
# global plugin config | |||
plugin_config = {} | |||
def write_plugin_config(pconf: dict): | |||
""" | |||
写入插件全局配置 | |||
:param pconf: 全量插件配置 | |||
""" | |||
global plugin_config | |||
for k in pconf: | |||
plugin_config[k.lower()] = pconf[k] | |||
def pconf(plugin_name: str) -> dict: | |||
""" | |||
根据插件名称获取配置 | |||
:param plugin_name: 插件名称 | |||
:return: 该插件的配置项 | |||
""" | |||
return plugin_config.get(plugin_name.lower()) |
@@ -33,7 +33,7 @@ class Banwords(Plugin): | |||
json.dump(conf, f, indent=4) | |||
else: | |||
with open(config_path, "r") as f: | |||
conf = json.load(f) | |||
conf = super().load_config() or json.load(f) | |||
self.searchr = WordsSearch() | |||
self.action = conf["action"] | |||
banwords_path = os.path.join(curdir, "banwords.txt") | |||
@@ -36,7 +36,7 @@ class BDunit(Plugin): | |||
raise Exception("config.json not found") | |||
else: | |||
with open(config_path, "r") as f: | |||
conf = json.load(f) | |||
conf = super().load_config() or json.load(f) | |||
self.service_id = conf["service_id"] | |||
self.api_key = conf["api_key"] | |||
self.secret_key = conf["secret_key"] | |||
@@ -0,0 +1,24 @@ | |||
{ | |||
"godcmd": { | |||
"password": "", | |||
"admin_users": [] | |||
}, | |||
"banwords": { | |||
"action": "replace", | |||
"reply_filter": true, | |||
"reply_action": "ignore" | |||
}, | |||
"tool": { | |||
"tools": [ | |||
"python", | |||
"url-get", | |||
"terminal", | |||
"meteo-weather" | |||
], | |||
"kwargs": { | |||
"top_k_results": 2, | |||
"no_default": false, | |||
"model_name": "gpt-3.5-turbo" | |||
} | |||
} | |||
} |
@@ -187,7 +187,7 @@ class Godcmd(Plugin): | |||
json.dump(gconf, f, indent=4) | |||
else: | |||
with open(config_path, "r") as f: | |||
gconf = json.load(f) | |||
gconf = super().load_config() or json.load(f) | |||
if gconf["password"] == "": | |||
self.temp_password = "".join(random.sample(string.digits, 4)) | |||
logger.info("[Godcmd] 因未设置口令,本次的临时口令为%s。" % self.temp_password) | |||
@@ -1,6 +1,16 @@ | |||
import os | |||
from config import pconf | |||
class Plugin: | |||
def __init__(self): | |||
self.handlers = {} | |||
def load_config(self) -> dict: | |||
""" | |||
加载当前插件配置 | |||
:return: 插件配置字典 | |||
""" | |||
return pconf(self.name) | |||
def get_help_text(self, **kwargs): | |||
return "暂无帮助信息" |
@@ -9,7 +9,7 @@ import sys | |||
from common.log import logger | |||
from common.singleton import singleton | |||
from common.sorted_dict import SortedDict | |||
from config import conf | |||
from config import conf, write_plugin_config | |||
from .event import * | |||
@@ -62,6 +62,28 @@ class PluginManager: | |||
self.save_config() | |||
return pconf | |||
@staticmethod | |||
def _load_all_config(): | |||
""" | |||
背景: 目前插件配置存放于每个插件目录的config.json下,docker运行时不方便进行映射,故增加统一管理的入口,优先 | |||
加载 plugins/config.json,原插件目录下的config.json 不受影响 | |||
从 plugins/config.json 中加载所有插件的配置并写入 config.py 的全局配置中,供插件中使用 | |||
插件实例中通过 config.pconf(plugin_name) 即可获取该插件的配置 | |||
""" | |||
all_config_path = "./plugins/config.json" | |||
try: | |||
if os.path.exists(all_config_path): | |||
# read from all plugins config | |||
with open(all_config_path, "r", encoding="utf-8") as f: | |||
all_conf = json.load(f) | |||
logger.info(f"load all config from plugins/config.json: {all_conf}") | |||
# write to global config | |||
write_plugin_config(all_conf) | |||
except Exception as e: | |||
logger.error(e) | |||
def scan_plugins(self): | |||
logger.info("Scaning plugins ...") | |||
plugins_dir = "./plugins" | |||
@@ -88,7 +110,7 @@ class PluginManager: | |||
self.loaded[plugin_path] = importlib.import_module(import_path) | |||
self.current_plugin_path = None | |||
except Exception as e: | |||
logger.exception("Failed to import plugin %s: %s" % (plugin_name, e)) | |||
logger.warn("Failed to import plugin %s: %s" % (plugin_name, e)) | |||
continue | |||
pconf = self.pconf | |||
news = [self.plugins[name] for name in self.plugins] | |||
@@ -149,6 +171,8 @@ class PluginManager: | |||
def load_plugins(self): | |||
self.load_config() | |||
self.scan_plugins() | |||
# 加载全量插件配置 | |||
self._load_all_config() | |||
pconf = self.pconf | |||
logger.debug("plugins.json config={}".format(pconf)) | |||
for name, plugin in pconf["plugins"].items(): | |||
@@ -126,7 +126,7 @@ class Tool(Plugin): | |||
return tool_config | |||
else: | |||
with open(config_path, "r") as f: | |||
tool_config = json.load(f) | |||
tool_config = super().load_config() or json.load(f) | |||
return tool_config | |||
def _build_tool_kwargs(self, kwargs: dict): | |||