mirror of https://github.com/Mai-with-u/MaiBot.git
parent
f7e8050fd7
commit
712505f6ca
|
|
@ -1,6 +1,6 @@
|
|||
import random
|
||||
import time
|
||||
from typing import Optional
|
||||
from typing import Optional, List
|
||||
from loguru import logger
|
||||
|
||||
from ...common.database import Database
|
||||
|
|
@ -18,25 +18,140 @@ class PromptBuilder:
|
|||
self.activate_messages = ''
|
||||
self.db = Database.get_instance()
|
||||
|
||||
|
||||
|
||||
async def _build_prompt(self,
|
||||
message_txt: str,
|
||||
sender_name: str = "某人",
|
||||
relationship_value: float = 0.0,
|
||||
stream_id: Optional[int] = None) -> tuple[str, str]:
|
||||
message_txt: str,
|
||||
sender_name: str = "某人",
|
||||
relationship_value: float = 0.0,
|
||||
stream_id: Optional[int] = None) -> tuple[str, str]:
|
||||
"""构建prompt
|
||||
|
||||
Args:
|
||||
message_txt: 消息文本
|
||||
sender_name: 发送者昵称
|
||||
relationship_value: 关系值
|
||||
group_id: 群组ID
|
||||
stream_id: 消息上下文ID
|
||||
|
||||
Returns:
|
||||
str: 构建好的prompt
|
||||
"""
|
||||
# 先禁用关系
|
||||
|
||||
# 开始构建prompt
|
||||
role_core = await self._build_role_core_prompt(message_txt, sender_name, relationship_value, stream_id)
|
||||
chat_context = await self._build_chat_context_prompt(message_txt, sender_name, relationship_value, stream_id)
|
||||
constraints = await self._build_constraints_prompt(message_txt, sender_name, relationship_value, stream_id)
|
||||
|
||||
# 合并prompt
|
||||
prompt = '\n\n'.join((
|
||||
'# 角色核心设定\n* ' + '\n* '.join(role_core),
|
||||
'# 对话背景\n* ' + '\n* '.join(chat_context),
|
||||
'# 要求\n* ' + '\n* '.join(constraints),
|
||||
'# 目标: 发言或回复用户'
|
||||
))
|
||||
|
||||
'''读空气prompt处理 [未启用]'''
|
||||
# activate_prompt_chec
|
||||
# extra_check_info = f"请注意把握k = f"以上是群里正在进行的聊天,昵称为 '{sender_name}' 的用户说的:{message_txt}。引起了你的注意,你和他{relation_prompt},你想要{relation_prompt_2},但是这不一定是合适的时机,请你决定是否要回应这条消息。"
|
||||
# #
|
||||
# # prompt_personality_check = ''群里的聊天内容的基础上,综合群内的氛围,例如,和{global_config.BOT_NICKNAME}相关的话题要积极回复,如果是at自己的消息一定要回复,如果自己正在和别人聊天一定要回复,其他话题如果合适搭话也可以回复,如果认为应该回复请输出yes,否则输出no,请注意是决定是否需要回复,而不是编写回复内容,除了yes和no不要输出任何回复内容。"
|
||||
# if personality_choice < probability_1: # 第一种人格
|
||||
# prompt_personality_check = f'''你的网名叫{global_config.BOT_NICKNAME},{personality[0]}, 你正在浏览qq群,{promt_info_prompt} {activate_prompt_check} {extra_check_info}'''
|
||||
# elif personality_choice < probability_1 + probability_2: # 第二种人格
|
||||
# prompt_personality_check = f'''你的网名叫{global_config.BOT_NICKNAME},{personality[1]}, 你正在浏览qq群,{promt_info_prompt} {activate_prompt_check} {extra_check_info}'''
|
||||
# else: # 第三种人格
|
||||
# prompt_personality_check = f'''你的网名叫{global_config.BOT_NICKNAME},{personality[2]}, 你正在浏览qq群,{promt_info_prompt} {activate_prompt_check} {extra_check_info}'''
|
||||
# prompt_check_if_response = f"{prompt_info}\n{prompt_date}\n{chat_talking_prompt}\n{prompt_personality_check}"
|
||||
prompt_check_if_response = ''
|
||||
|
||||
return prompt, prompt_check_if_response
|
||||
|
||||
async def _build_role_core_prompt(self,
|
||||
message_txt: str,
|
||||
sender_name: str = "某人",
|
||||
relationship_value: float = 0.0,
|
||||
stream_id: Optional[int] = None) -> List[str]:
|
||||
role_core_prompt = []
|
||||
|
||||
# 人格选择
|
||||
personality = random.choices(global_config.PROMPT_PERSONALITY, global_config.PERSONALITY_PROBS)[0]
|
||||
role_core_prompt.append(personality)
|
||||
|
||||
role_core_prompt.append(f'你的网名叫{global_config.BOT_NICKNAME}')
|
||||
if len(global_config.BOT_ALIAS_NAMES) > 0:
|
||||
role_core_prompt.append(f'别人也叫你:{"/".join(global_config.BOT_ALIAS_NAMES)}')
|
||||
|
||||
# 心情
|
||||
role_core_prompt.append(MoodManager.get_instance().get_prompt())
|
||||
|
||||
# 日程构建
|
||||
current_date = time.strftime("%Y-%m-%d", time.localtime())
|
||||
current_time = time.strftime("%H:%M:%S", time.localtime())
|
||||
bot_schedule_now_time, bot_schedule_now_activity = bot_schedule.get_current_task()
|
||||
schedule_str = '\n'.join([f"\t- {time} {activity}"
|
||||
for time, activity in bot_schedule.today_schedule.items()])
|
||||
role_core_prompt.append(f'今天是{current_date},现在是{current_time},你今天的日程是:\n{schedule_str}')
|
||||
role_core_prompt.append(f'你现在正在{bot_schedule_now_activity}')
|
||||
|
||||
# 知识构建 [未启用]
|
||||
start_time = time.time()
|
||||
knowledge_prompt = ''
|
||||
promt_info_prompt = ''
|
||||
knowledge_prompt = await self.get_prompt_info(message_txt, threshold=0.5)
|
||||
if knowledge_prompt:
|
||||
knowledge_prompt = f'''你有以下这些[知识]:{knowledge_prompt}请你记住上面的[
|
||||
知识],之后可能会用到-'''
|
||||
end_time = time.time()
|
||||
logger.debug(f"知识检索耗时: {(end_time - start_time):.3f}秒")
|
||||
|
||||
# 中文高手(新加的好玩功能)
|
||||
prompt_ger = ''
|
||||
if random.random() < 0.04:
|
||||
prompt_ger += '你喜欢用倒装句'
|
||||
if random.random() < 0.02:
|
||||
prompt_ger += '你喜欢用反问句'
|
||||
if random.random() < 0.01:
|
||||
prompt_ger += '你喜欢用文言文'
|
||||
if len(prompt_ger) > 0:
|
||||
role_core_prompt.append(prompt_ger)
|
||||
|
||||
return role_core_prompt
|
||||
|
||||
async def _build_chat_context_prompt(self,
|
||||
message_txt: str,
|
||||
sender_name: str = "某人",
|
||||
relationship_value: float = 0.0,
|
||||
stream_id: Optional[int] = None) -> List[str]:
|
||||
chat_context_prompt = []
|
||||
|
||||
# 获取聊天上下文
|
||||
chat_in_group = True
|
||||
chat_talking_prompt = ''
|
||||
if stream_id:
|
||||
chat_context: List[str] = get_recent_group_detailed_plain_text(self.db, stream_id,
|
||||
limit=global_config.MAX_CONTEXT_SIZE,
|
||||
combine=False)
|
||||
chat_stream = chat_manager.get_stream(stream_id)
|
||||
if chat_stream.group_info:
|
||||
chat_talking_prompt = "以下是群里正在聊的内容:\n\t- "
|
||||
else:
|
||||
chat_in_group = False
|
||||
chat_talking_prompt = f"以下是你正在和{sender_name}私聊的内容:\n"
|
||||
# print(f"\033[1;34m[调试]\033[0m 已从数据库获取群 {stream_id} 的消息记录:{chat_talking_prompt}")
|
||||
chat_talking_prompt += "\n\t- ".join(chat_context)
|
||||
chat_context_prompt.append(chat_talking_prompt)
|
||||
|
||||
# [未启用]
|
||||
if chat_in_group:
|
||||
prompt_in_group = f"你正在浏览{chat_stream.platform}群"
|
||||
else:
|
||||
prompt_in_group = f"你正在{chat_stream.platform}上和{sender_name}私聊"
|
||||
|
||||
# 使用新的记忆获取方法
|
||||
memory_prompt = await self._build_memory_prompt(message_txt)
|
||||
if len(memory_prompt) > 0:
|
||||
chat_context_prompt.append(memory_prompt)
|
||||
|
||||
|
||||
# 关系 [未启用]
|
||||
if 0 > 30:
|
||||
relation_prompt = "关系特别特别好,你很喜欢喜欢他"
|
||||
relation_prompt_2 = "热情发言或者回复"
|
||||
|
|
@ -47,47 +162,17 @@ class PromptBuilder:
|
|||
relation_prompt = "关系一般"
|
||||
relation_prompt_2 = "发言或者回复"
|
||||
|
||||
# 开始构建prompt
|
||||
# 激活prompt构建
|
||||
activate_prompt = ''
|
||||
if chat_in_group:
|
||||
activate_prompt = f"现在昵称为 '{sender_name}' 的用户说的:{message_txt}。引起了你的注意,你和ta{relation_prompt},你想要{relation_prompt_2}。"
|
||||
else:
|
||||
activate_prompt = f"现在昵称为 '{sender_name}' 的用户说的:{message_txt}。引起了你的注意,你和ta{relation_prompt},你想要{relation_prompt_2}。"
|
||||
chat_context_prompt.append(activate_prompt)
|
||||
|
||||
# 心情
|
||||
mood_manager = MoodManager.get_instance()
|
||||
mood_prompt = mood_manager.get_prompt()
|
||||
return chat_context_prompt
|
||||
|
||||
# 日程构建
|
||||
current_date = time.strftime("%Y-%m-%d", time.localtime())
|
||||
current_time = time.strftime("%H:%M:%S", time.localtime())
|
||||
bot_schedule_now_time, bot_schedule_now_activity = bot_schedule.get_current_task()
|
||||
prompt_date = f'''今天是{current_date},现在是{current_time},你今天的日程是:\n{bot_schedule.today_schedule}\n你现在正在{bot_schedule_now_activity}\n'''
|
||||
|
||||
# 知识构建
|
||||
start_time = time.time()
|
||||
|
||||
prompt_info = ''
|
||||
promt_info_prompt = ''
|
||||
prompt_info = await self.get_prompt_info(message_txt, threshold=0.5)
|
||||
if prompt_info:
|
||||
prompt_info = f'''你有以下这些[知识]:{prompt_info}请你记住上面的[
|
||||
知识],之后可能会用到-'''
|
||||
|
||||
end_time = time.time()
|
||||
logger.debug(f"知识检索耗时: {(end_time - start_time):.3f}秒")
|
||||
|
||||
# 获取聊天上下文
|
||||
chat_in_group=True
|
||||
chat_talking_prompt = ''
|
||||
if stream_id:
|
||||
chat_talking_prompt = get_recent_group_detailed_plain_text(self.db, stream_id, limit=global_config.MAX_CONTEXT_SIZE,combine = True)
|
||||
chat_stream=chat_manager.get_stream(stream_id)
|
||||
if chat_stream.group_info:
|
||||
chat_talking_prompt = f"以下是群里正在聊天的内容:\n{chat_talking_prompt}"
|
||||
else:
|
||||
chat_in_group=False
|
||||
chat_talking_prompt = f"以下是你正在和{sender_name}私聊的内容:\n{chat_talking_prompt}"
|
||||
# print(f"\033[1;34m[调试]\033[0m 已从数据库获取群 {group_id} 的消息记录:{chat_talking_prompt}")
|
||||
|
||||
|
||||
|
||||
# 使用新的记忆获取方法
|
||||
async def _build_memory_prompt(self, message_txt: str) -> str:
|
||||
memory_prompt = ''
|
||||
start_time = time.time()
|
||||
|
||||
|
|
@ -103,9 +188,9 @@ class PromptBuilder:
|
|||
# 格式化记忆内容
|
||||
memory_items = []
|
||||
for memory in relevant_memories:
|
||||
memory_items.append(f"关于「{memory['topic']}」的记忆:{memory['content']}")
|
||||
memory_items.append(f"\t- 关于「{memory['topic']}」的记忆:{memory['content']}")
|
||||
|
||||
memory_prompt = "看到这些聊天,你想起来:\n" + "\n".join(memory_items) + "\n"
|
||||
memory_prompt = "看到这些聊天,你想起来:\n" + "\n".join(memory_items)
|
||||
|
||||
# 打印调试信息
|
||||
logger.debug("[记忆检索]找到以下相关记忆:")
|
||||
|
|
@ -115,15 +200,38 @@ class PromptBuilder:
|
|||
end_time = time.time()
|
||||
logger.info(f"回忆耗时: {(end_time - start_time):.3f}秒")
|
||||
|
||||
# 激活prompt构建
|
||||
activate_prompt = ''
|
||||
if chat_in_group:
|
||||
activate_prompt = f"以上是群里正在进行的聊天,{memory_prompt} 现在昵称为 '{sender_name}' 的用户说的:{message_txt}。引起了你的注意,你和ta{relation_prompt},{mood_prompt},你想要{relation_prompt_2}。"
|
||||
else:
|
||||
activate_prompt = f"以上是你正在和{sender_name}私聊的内容,{memory_prompt} 现在昵称为 '{sender_name}' 的用户说的:{message_txt}。引起了你的注意,你和ta{relation_prompt},{mood_prompt},你想要{relation_prompt_2}。"
|
||||
return memory_prompt
|
||||
|
||||
# 关键词检测与反应
|
||||
# 获取当前规则中(实际命中的关键词-反应)
|
||||
async def _build_constraints_prompt(self,
|
||||
message_txt: str,
|
||||
sender_name: str = "某人",
|
||||
relationship_value: float = 0.0,
|
||||
stream_id: Optional[int] = None) -> List[str]:
|
||||
constraints_prompt = []
|
||||
|
||||
keyword_prompt = self._build_keywords_reaction_prompt(message_txt)
|
||||
if len(keyword_prompt) > 0:
|
||||
constraints_prompt.append(keyword_prompt)
|
||||
|
||||
# 额外信息要求
|
||||
constraints_prompt.append('请给出日常且口语化的回复,平淡一些,尽量简短一些,尤其注意在没明确提到时不要过多提及自身的背景.')
|
||||
constraints_prompt.append('不要直接回复别人发的表情包.')
|
||||
constraints_prompt.append('请注意把握群里的聊天内容,不要刻意突出自身学科背景,不要回复的太有条理,可以有个性.')
|
||||
constraints_prompt.append('只输出回复内容,不要输出其他任何内容,包括前后缀、冒号、引号、括号、表情等.')
|
||||
constraints_prompt.append('请表现你自己的见解和观点,不要一昧迎合,可以表现个性,尽量简短一些.')
|
||||
|
||||
return constraints_prompt
|
||||
|
||||
def _build_keywords_reaction_prompt(self, message_txt: str) -> str:
|
||||
"""关键词检测与反应
|
||||
|
||||
Returns: 没命中返回空字符串;命中时返回prompt格式如下:
|
||||
群聊的发言命中了预设规则,你需要按照要求的反应回复:
|
||||
- 命中关键字: 'test', '测试'; 回复要求: '回答测试成功'
|
||||
- 命中关键字: '人机'; 回复要求: '否定这一事实,攻击或反问他。注意,只有认为你是机器人才回复,否则不要否认'
|
||||
"""
|
||||
|
||||
# 获取当前规则 (实际命中的关键词-反应)
|
||||
triggered_keyword_prompt_arr = []
|
||||
lower_msg_text = message_txt.lower()
|
||||
for rule in global_config.keywords_reaction_rules:
|
||||
|
|
@ -135,73 +243,14 @@ class PromptBuilder:
|
|||
logger.info(f"检测到关键词:{matched_kws},触发反应:{reaction}")
|
||||
triggered_keyword_prompt_arr.append((matched_kws, reaction))
|
||||
|
||||
"""
|
||||
群聊的发言有命中预设规则,你需要按照要求的反应回复:
|
||||
- 命中关键字: 'test', 'hello'; 回复要求: '回答测试成功'
|
||||
- 命中关键字: '人机'; 回复要求: '否定这一事实,攻击或反问他。注意,只有认为你是机器人才回复,否则不要否认'
|
||||
"""
|
||||
keywords_reaction_prompt = ''
|
||||
if len(triggered_keyword_prompt_arr) > 0:
|
||||
keywords_reaction_prompt = '群聊的发言有命中,你需要按照预设的反应回复:\n' \
|
||||
+ "\n".join(f'- 命中关键字: {", ".join(map(repr, matched_kws))}; 回复要求: {reaction!r}' for matched_kws, reaction in triggered_keyword_prompt_arr)
|
||||
keywords_reaction_prompt = '群聊的发言命中了预设规则,你需要按照要求的反应回复:\n' \
|
||||
+ "\n".join(
|
||||
f'\t - 命中关键字: {", ".join(map(repr, matched_kws))}; 回复要求: {reaction!r}' for
|
||||
matched_kws, reaction in triggered_keyword_prompt_arr)
|
||||
|
||||
# 人格选择
|
||||
personality = random.choices(global_config.PROMPT_PERSONALITY, global_config.PERSONALITY_PROBS)[0]
|
||||
|
||||
prompt_personality = f'{activate_prompt}你的网名叫{global_config.BOT_NICKNAME},你还有很多别名:{"/".join(global_config.BOT_ALIAS_NAMES)},'
|
||||
personality_choice = random.random()
|
||||
if chat_in_group:
|
||||
prompt_in_group=f"你正在浏览{chat_stream.platform}群"
|
||||
else:
|
||||
prompt_in_group=f"你正在{chat_stream.platform}上和{sender_name}私聊"
|
||||
if personality_choice < probability_1: # 第一种人格
|
||||
prompt_personality += f'''{personality}, 你正在浏览qq群,{promt_info_prompt},
|
||||
现在请你给出日常且口语化的回复,平淡一些,尽量简短一些。{keywords_reaction_prompt}
|
||||
请注意把握群里的聊天内容,不要刻意突出自身学科背景,不要回复的太有条理,可以有个性。'''
|
||||
elif personality_choice < probability_1 + probability_2: # 第二种人格
|
||||
prompt_personality += f'''{personality}, 你正在浏览qq群,{promt_info_prompt},
|
||||
现在请你给出日常且口语化的回复,请表现你自己的见解,不要一昧迎合,尽量简短一些。{keywords_reaction_prompt}
|
||||
请你表达自己的见解和观点。可以有个性。'''
|
||||
else: # 第三种人格
|
||||
prompt_personality += f'''{personality}, 你正在浏览qq群,{promt_info_prompt},
|
||||
现在请你给出日常且口语化的回复,请表现你自己的见解,不要一昧迎合,尽量简短一些。{keywords_reaction_prompt}
|
||||
请你表达自己的见解和观点。可以有个性。'''
|
||||
|
||||
# 中文高手(新加的好玩功能)
|
||||
prompt_ger = ''
|
||||
if random.random() < 0.04:
|
||||
prompt_ger += '你喜欢用倒装句'
|
||||
if random.random() < 0.02:
|
||||
prompt_ger += '你喜欢用反问句'
|
||||
if random.random() < 0.01:
|
||||
prompt_ger += '你喜欢用文言文'
|
||||
|
||||
# 额外信息要求
|
||||
extra_info = '''但是记得回复平淡一些,简短一些,尤其注意在没明确提到时不要过多提及自身的背景, 不要直接回复别人发的表情包,记住不要输出多余内容(包括前后缀,冒号和引号,括号,表情等),只需要输出回复内容就好,不要输出其他任何内容'''
|
||||
|
||||
# 合并prompt
|
||||
prompt = ""
|
||||
prompt += f"{prompt_info}\n"
|
||||
prompt += f"{prompt_date}\n"
|
||||
prompt += f"{chat_talking_prompt}\n"
|
||||
prompt += f"{prompt_personality}\n"
|
||||
prompt += f"{prompt_ger}\n"
|
||||
prompt += f"{extra_info}\n"
|
||||
|
||||
'''读空气prompt处理'''
|
||||
activate_prompt_check = f"以上是群里正在进行的聊天,昵称为 '{sender_name}' 的用户说的:{message_txt}。引起了你的注意,你和他{relation_prompt},你想要{relation_prompt_2},但是这不一定是合适的时机,请你决定是否要回应这条消息。"
|
||||
prompt_personality_check = ''
|
||||
extra_check_info = f"请注意把握群里的聊天内容的基础上,综合群内的氛围,例如,和{global_config.BOT_NICKNAME}相关的话题要积极回复,如果是at自己的消息一定要回复,如果自己正在和别人聊天一定要回复,其他话题如果合适搭话也可以回复,如果认为应该回复请输出yes,否则输出no,请注意是决定是否需要回复,而不是编写回复内容,除了yes和no不要输出任何回复内容。"
|
||||
if personality_choice < probability_1: # 第一种人格
|
||||
prompt_personality_check = f'''你的网名叫{global_config.BOT_NICKNAME},{personality[0]}, 你正在浏览qq群,{promt_info_prompt} {activate_prompt_check} {extra_check_info}'''
|
||||
elif personality_choice < probability_1 + probability_2: # 第二种人格
|
||||
prompt_personality_check = f'''你的网名叫{global_config.BOT_NICKNAME},{personality[1]}, 你正在浏览qq群,{promt_info_prompt} {activate_prompt_check} {extra_check_info}'''
|
||||
else: # 第三种人格
|
||||
prompt_personality_check = f'''你的网名叫{global_config.BOT_NICKNAME},{personality[2]}, 你正在浏览qq群,{promt_info_prompt} {activate_prompt_check} {extra_check_info}'''
|
||||
|
||||
prompt_check_if_response = f"{prompt_info}\n{prompt_date}\n{chat_talking_prompt}\n{prompt_personality_check}"
|
||||
|
||||
return prompt, prompt_check_if_response
|
||||
return keywords_reaction_prompt
|
||||
|
||||
def _build_initiative_prompt_select(self, group_id, probability_1=0.8, probability_2=0.1):
|
||||
current_date = time.strftime("%Y-%m-%d", time.localtime())
|
||||
|
|
|
|||
Loading…
Reference in New Issue