mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-27 07:54:19 +00:00
初步追加通过json导入messages数组的方式进行情景预设
This commit is contained in:
Binary file not shown.
+63
-14
@@ -4,6 +4,7 @@
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
import json
|
||||
@@ -20,6 +21,8 @@ import pkg.plugin.models as plugin_models
|
||||
sessions = {}
|
||||
|
||||
|
||||
|
||||
|
||||
class SessionOfflineStatus:
|
||||
ON_GOING = 'on_going'
|
||||
EXPLICITLY_CLOSED = 'explicitly_closed'
|
||||
@@ -128,25 +131,56 @@ class Session:
|
||||
logging.debug('{},lock release successfully,{}'.format(self.name, self.response_lock))
|
||||
|
||||
# 从配置文件获取会话预设信息
|
||||
def get_default_prompt(self, use_default: str = None):
|
||||
config = pkg.utils.context.get_config()
|
||||
# get_only: 仅返回初始prompt, 不更改该session的bot_name和bot_filter
|
||||
def get_default_prompt(self, use_default: str = None, get_only = False):
|
||||
|
||||
config = pkg.utils.context.get_config()
|
||||
import pkg.openai.dprompt as dprompt
|
||||
|
||||
if use_default is None:
|
||||
current_default_prompt = dprompt.get_prompt(dprompt.get_current())
|
||||
use_default = dprompt.get_current()
|
||||
|
||||
current_default_prompt = \
|
||||
[
|
||||
{
|
||||
'role': 'user',
|
||||
'content': '如果我之后想获取帮助,请你说“输入!help获取帮助”'
|
||||
}, {
|
||||
'role': 'assistant',
|
||||
'content': 'ok'
|
||||
}
|
||||
]
|
||||
|
||||
# 根据设置进行prompt预设模式
|
||||
|
||||
if config.preset_mode == "full_scenario":
|
||||
|
||||
##
|
||||
dir = os.path.join(os.getcwd(), config.full_prompt_dir)
|
||||
json_file = os.path.join(dir, use_default) + '.json'
|
||||
|
||||
logging.info("try to load json: {}".format(json_file))
|
||||
|
||||
try:
|
||||
with open(json_file, 'r', encoding ='utf-8') as f:
|
||||
json_content = json.load(f)
|
||||
current_default_prompt = json_content['prompt']
|
||||
|
||||
if not get_only:
|
||||
self.bot_name = json_content['name'] # 读取机器人名字,用于响应信息
|
||||
self.bot_filter = json_content['filter'] # 过滤掉不符合人格的警告
|
||||
logging.debug("first bot filter: {}".format(self.bot_filter))
|
||||
|
||||
except FileNotFoundError:
|
||||
logging.info("couldn't find file {}".format(json_file))
|
||||
|
||||
# logging.info("json: {}".format(current_default_prompt))
|
||||
##
|
||||
|
||||
else:
|
||||
current_default_prompt = dprompt.get_prompt(use_default)
|
||||
|
||||
return [
|
||||
{
|
||||
'role': 'user',
|
||||
'content': current_default_prompt
|
||||
}, {
|
||||
'role': 'assistant',
|
||||
'content': 'ok'
|
||||
}
|
||||
]
|
||||
return current_default_prompt
|
||||
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
@@ -155,6 +189,8 @@ class Session:
|
||||
self.schedule()
|
||||
|
||||
self.response_lock = threading.Lock()
|
||||
self.bot_name = 'ai'
|
||||
self.bot_filter = None
|
||||
self.prompt = self.get_default_prompt()
|
||||
|
||||
# 设定检查session最后一次对话是否超过过期时间的计时器
|
||||
@@ -199,7 +235,7 @@ class Session:
|
||||
self.last_interact_timestamp = int(time.time())
|
||||
|
||||
# 触发插件事件
|
||||
if self.prompt == self.get_default_prompt():
|
||||
if self.prompt == self.get_default_prompt(get_only=True):
|
||||
args = {
|
||||
'session_name': self.name,
|
||||
'session': self,
|
||||
@@ -228,10 +264,23 @@ class Session:
|
||||
del (res_ans_spt[0])
|
||||
res_ans = '\n\n'.join(res_ans_spt)
|
||||
|
||||
#检测是否包含ai人格否定
|
||||
logging.debug('bot_filter: {}'.format(self.bot_filter))
|
||||
if config.filter_ai_warning and self.bot_filter:
|
||||
import re
|
||||
match = re.search(self.bot_filter['reg'], res_ans)
|
||||
logging.debug(self.bot_filter)
|
||||
logging.debug(res_ans)
|
||||
if match:
|
||||
logging.debug('回复:{}, 检测到人格否定,替换中。。'.format(res_ans))
|
||||
res_ans = self.bot_filter['replace']
|
||||
logging.debug('替换为: {}'.format(res_ans))
|
||||
|
||||
# 将此次对话的双方内容加入到prompt中
|
||||
self.prompt.append({'role': 'user', 'content': text})
|
||||
self.prompt.append({'role': 'assistant', 'content': res_ans})
|
||||
|
||||
|
||||
if self.just_switched_to_exist_session:
|
||||
self.just_switched_to_exist_session = False
|
||||
self.set_ongoing()
|
||||
@@ -280,7 +329,7 @@ class Session:
|
||||
|
||||
# 持久化session
|
||||
def persistence(self):
|
||||
if self.prompt == self.get_default_prompt():
|
||||
if self.prompt == self.get_default_prompt(get_only=True):
|
||||
return
|
||||
|
||||
db_inst = pkg.utils.context.get_database_manager()
|
||||
|
||||
+2
-9
@@ -7,8 +7,6 @@ import logging
|
||||
|
||||
class ReplyFilter:
|
||||
sensitive_words = []
|
||||
mask = "*"
|
||||
mask_word = ""
|
||||
|
||||
# 默认值( 兼容性考虑 )
|
||||
baidu_check = False
|
||||
@@ -16,10 +14,8 @@ class ReplyFilter:
|
||||
baidu_secret_key = ""
|
||||
inappropriate_message_tips = "[百度云]请珍惜机器人,当前返回内容不合规"
|
||||
|
||||
def __init__(self, sensitive_words: list, mask: str = "*", mask_word: str = ""):
|
||||
def __init__(self, sensitive_words: list):
|
||||
self.sensitive_words = sensitive_words
|
||||
self.mask = mask
|
||||
self.mask_word = mask_word
|
||||
import config
|
||||
if hasattr(config, 'baidu_check') and hasattr(config, 'baidu_api_key') and hasattr(config, 'baidu_secret_key'):
|
||||
self.baidu_check = config.baidu_check
|
||||
@@ -40,10 +36,7 @@ class ReplyFilter:
|
||||
match = re.findall(word, message)
|
||||
if len(match) > 0:
|
||||
for i in range(len(match)):
|
||||
if self.mask_word == "":
|
||||
message = message.replace(match[i], self.mask * len(match[i]))
|
||||
else:
|
||||
message = message.replace(match[i], self.mask_word)
|
||||
message = message.replace(match[i], "*" * len(match[i]))
|
||||
|
||||
# 百度云审核
|
||||
if self.baidu_check:
|
||||
|
||||
+30
-51
@@ -2,7 +2,6 @@ import asyncio
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
import mirai.models.bus
|
||||
from mirai import At, GroupMessage, MessageEvent, Mirai, StrangerMessage, WebSocketAdapter, HTTPAdapter, \
|
||||
@@ -22,11 +21,26 @@ import pkg.plugin.host as plugin_host
|
||||
import pkg.plugin.models as plugin_models
|
||||
|
||||
|
||||
# 并行运行
|
||||
def go(func, args=()):
|
||||
thread = threading.Thread(target=func, args=args, daemon=True)
|
||||
thread.start()
|
||||
|
||||
|
||||
# 检查消息是否符合泛响应匹配机制
|
||||
def check_response_rule(text: str):
|
||||
def check_response_rule(text: str, event):
|
||||
config = pkg.utils.context.get_config()
|
||||
if not hasattr(config, 'response_rules'):
|
||||
return False, ''
|
||||
|
||||
|
||||
bot_name = pkg.openai.session.get_session('group_{}'.format(event.group.id)).bot_name
|
||||
logging.debug(bot_name)
|
||||
# 检查情景json自带的名字
|
||||
if bot_name:
|
||||
import re
|
||||
if re.search(bot_name, text):
|
||||
return True, text
|
||||
|
||||
rules = config.response_rules
|
||||
# 检查前缀匹配
|
||||
@@ -42,33 +56,14 @@ def check_response_rule(text: str):
|
||||
match = re.match(rule, text)
|
||||
if match:
|
||||
return True, text
|
||||
|
||||
|
||||
return False, ""
|
||||
|
||||
|
||||
def response_at():
|
||||
config = pkg.utils.context.get_config()
|
||||
if 'at' not in config.response_rules:
|
||||
return True
|
||||
|
||||
return config.response_rules['at']
|
||||
|
||||
|
||||
def random_responding():
|
||||
config = pkg.utils.context.get_config()
|
||||
if 'random_rate' in config.response_rules:
|
||||
import random
|
||||
return random.random() < config.response_rules['random_rate']
|
||||
return False
|
||||
|
||||
|
||||
# 控制QQ消息输入输出的类
|
||||
class QQBotManager:
|
||||
retry = 3
|
||||
|
||||
#线程池控制
|
||||
pool = None
|
||||
|
||||
bot: Mirai = None
|
||||
|
||||
reply_filter = None
|
||||
@@ -78,14 +73,11 @@ class QQBotManager:
|
||||
ban_person = []
|
||||
ban_group = []
|
||||
|
||||
def __init__(self, mirai_http_api_config: dict, timeout: int = 60, retry: int = 3, pool_num: int = 10, first_time_init=True):
|
||||
def __init__(self, mirai_http_api_config: dict, timeout: int = 60, retry: int = 3, first_time_init=True):
|
||||
|
||||
self.timeout = timeout
|
||||
self.retry = retry
|
||||
|
||||
self.pool_num = pool_num
|
||||
self.pool = ThreadPoolExecutor(max_workers=self.pool_num)
|
||||
logging.debug("Registered thread pool Size:{}".format(pool_num))
|
||||
|
||||
# 加载禁用列表
|
||||
if os.path.exists("banlist.py"):
|
||||
import banlist
|
||||
@@ -99,12 +91,7 @@ class QQBotManager:
|
||||
and config.sensitive_word_filter is not None \
|
||||
and config.sensitive_word_filter:
|
||||
with open("sensitive.json", "r", encoding="utf-8") as f:
|
||||
sensitive_json = json.load(f)
|
||||
self.reply_filter = pkg.qqbot.filter.ReplyFilter(
|
||||
sensitive_words=sensitive_json['words'],
|
||||
mask=sensitive_json['mask'] if 'mask' in sensitive_json else '*',
|
||||
mask_word=sensitive_json['mask_word'] if 'mask_word' in sensitive_json else ''
|
||||
)
|
||||
self.reply_filter = pkg.qqbot.filter.ReplyFilter(json.load(f)['words'])
|
||||
else:
|
||||
self.reply_filter = pkg.qqbot.filter.ReplyFilter([])
|
||||
|
||||
@@ -138,7 +125,7 @@ class QQBotManager:
|
||||
|
||||
self.on_person_message(event)
|
||||
|
||||
self.go(friend_message_handler, event)
|
||||
go(friend_message_handler, (event,))
|
||||
|
||||
@self.bot.on(StrangerMessage)
|
||||
async def on_stranger_message(event: StrangerMessage):
|
||||
@@ -158,7 +145,7 @@ class QQBotManager:
|
||||
|
||||
self.on_person_message(event)
|
||||
|
||||
self.go(stranger_message_handler, event)
|
||||
go(stranger_message_handler, (event,))
|
||||
|
||||
@self.bot.on(GroupMessage)
|
||||
async def on_group_message(event: GroupMessage):
|
||||
@@ -178,7 +165,7 @@ class QQBotManager:
|
||||
|
||||
self.on_group_message(event)
|
||||
|
||||
self.go(group_message_handler, event)
|
||||
go(group_message_handler, (event,))
|
||||
|
||||
def unsubscribe_all():
|
||||
"""取消所有订阅
|
||||
@@ -195,9 +182,6 @@ class QQBotManager:
|
||||
|
||||
self.unsubscribe_all = unsubscribe_all
|
||||
|
||||
def go(self, func, *args, **kwargs):
|
||||
self.pool.submit(func, *args, **kwargs)
|
||||
|
||||
def first_time_init(self, mirai_http_api_config: dict):
|
||||
"""热重载后不再运行此函数"""
|
||||
|
||||
@@ -313,19 +297,14 @@ class QQBotManager:
|
||||
|
||||
if Image in event.message_chain:
|
||||
pass
|
||||
else:
|
||||
if At(self.bot.qq) in event.message_chain and response_at():
|
||||
# 直接调用
|
||||
reply = process()
|
||||
else:
|
||||
check, result = check_response_rule(str(event.message_chain).strip())
|
||||
elif At(self.bot.qq) not in event.message_chain:
|
||||
check, result = check_response_rule(str(event.message_chain).strip(), event)
|
||||
|
||||
if check:
|
||||
reply = process(result.strip())
|
||||
# 检查是否随机响应
|
||||
elif random_responding():
|
||||
logging.info("随机响应group_{}消息".format(event.group.id))
|
||||
reply = process()
|
||||
if check:
|
||||
reply = process(result.strip())
|
||||
else:
|
||||
# 直接调用
|
||||
reply = process()
|
||||
|
||||
if reply:
|
||||
return self.send(event, reply)
|
||||
|
||||
File diff suppressed because one or more lines are too long
+6
-19
@@ -54,7 +54,7 @@ def get_current_tag() -> str:
|
||||
return current_tag
|
||||
|
||||
|
||||
def update_all(cli: bool = False) -> bool:
|
||||
def update_all() -> bool:
|
||||
"""检查更新并下载源码"""
|
||||
current_tag = get_current_tag()
|
||||
|
||||
@@ -69,19 +69,12 @@ def update_all(cli: bool = False) -> bool:
|
||||
|
||||
if latest_rls == {}:
|
||||
latest_rls = rls
|
||||
if not cli:
|
||||
logging.info("更新日志: {}".format(rls_notes))
|
||||
else:
|
||||
print("更新日志: {}".format(rls_notes))
|
||||
|
||||
logging.info("更新日志: {}".format(rls_notes))
|
||||
if latest_rls == {}: # 没有新版本
|
||||
return False
|
||||
|
||||
# 下载最新版本的zip到temp目录
|
||||
if not cli:
|
||||
logging.info("开始下载最新版本: {}".format(latest_rls['zipball_url']))
|
||||
else:
|
||||
print("开始下载最新版本: {}".format(latest_rls['zipball_url']))
|
||||
logging.info("开始下载最新版本: {}".format(latest_rls['zipball_url']))
|
||||
zip_url = latest_rls['zipball_url']
|
||||
zip_resp = requests.get(url=zip_url)
|
||||
zip_data = zip_resp.content
|
||||
@@ -94,10 +87,7 @@ def update_all(cli: bool = False) -> bool:
|
||||
with open("temp/updater/{}.zip".format(latest_rls['tag_name']), "wb") as f:
|
||||
f.write(zip_data)
|
||||
|
||||
if not cli:
|
||||
logging.info("下载最新版本完成: {}".format("temp/updater/{}.zip".format(latest_rls['tag_name'])))
|
||||
else:
|
||||
print("下载最新版本完成: {}".format("temp/updater/{}.zip".format(latest_rls['tag_name'])))
|
||||
logging.info("下载最新版本完成: {}".format("temp/updater/{}.zip".format(latest_rls['tag_name'])))
|
||||
|
||||
# 解压zip到temp/updater/<tag_name>/
|
||||
import zipfile
|
||||
@@ -134,11 +124,8 @@ def update_all(cli: bool = False) -> bool:
|
||||
f.write(current_tag)
|
||||
|
||||
# 通知管理员
|
||||
if not cli:
|
||||
import pkg.utils.context
|
||||
pkg.utils.context.get_qqbot_manager().notify_admin("已更新到最新版本: {}\n更新日志:\n{}\n新功能通常可以在config-template.py中看到,完整的更新日志请前往 https://github.com/RockChinQ/QChatGPT/releases 查看".format(current_tag, "\n".join(rls_notes)))
|
||||
else:
|
||||
print("已更新到最新版本: {}\n更新日志:\n{}\n新功能通常可以在config-template.py中看到,完整的更新日志请前往 https://github.com/RockChinQ/QChatGPT/releases 查看".format(current_tag, "\n".join(rls_notes)))
|
||||
import pkg.utils.context
|
||||
pkg.utils.context.get_qqbot_manager().notify_admin("已更新到最新版本: {}\n更新日志:\n{}\n新功能通常可以在config-template.py中看到,完整的更新日志请前往 https://github.com/RockChinQ/QChatGPT/releases 查看".format(current_tag, "\n".join(rls_notes)))
|
||||
return True
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user