From 825cfb44f5ef5fd8d980f59e7eecbbd245ee0b4b Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Fri, 11 Jul 2025 01:22:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:s4u=E6=A8=A1=E5=BC=8F=E7=8E=B0=E5=9C=A8?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E6=93=8D=E6=8E=A7=E8=A1=A8=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../body_emotion_action_manager.py | 244 ++++++++++++ src/mais4u/mais4u_chat/s4u_mood_manager.py | 365 ++++++++++++++++++ src/mais4u/mais4u_chat/s4u_msg_processor.py | 55 +++ src/mais4u/mais4u_chat/s4u_prompt.py | 5 - 4 files changed, 664 insertions(+), 5 deletions(-) create mode 100644 src/mais4u/mais4u_chat/body_emotion_action_manager.py create mode 100644 src/mais4u/mais4u_chat/s4u_mood_manager.py diff --git a/src/mais4u/mais4u_chat/body_emotion_action_manager.py b/src/mais4u/mais4u_chat/body_emotion_action_manager.py new file mode 100644 index 000000000..d7d196a20 --- /dev/null +++ b/src/mais4u/mais4u_chat/body_emotion_action_manager.py @@ -0,0 +1,244 @@ +import json +import math +import random +import time + +from src.chat.message_receive.message import MessageRecv +from src.llm_models.utils_model import LLMRequest +from src.common.logger import get_logger +from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_by_timestamp_with_chat_inclusive +from src.config.config import global_config +from src.chat.utils.prompt_builder import Prompt, global_prompt_manager +from src.manager.async_task_manager import AsyncTask, async_task_manager +from json_repair import repair_json + +logger = get_logger("action") + + +def init_prompt(): + Prompt( + """ +{chat_talking_prompt} +以上是群里正在进行的聊天记录 + +{indentify_block} +你现在的动作状态是: +- 手部:{hand_action} +- 上半身:{upper_body_action} +- 头部:{head_action} + +现在,因为你发送了消息,或者群里其他人发送了消息,引起了你的注意,你对其进行了阅读和思考,请你更新你的动作状态。 +请只按照以下json格式输出,描述你新的动作状态,每个动作一到三个中文词,确保每个字段都存在: +{{ + "hand_action": "...", + "upper_body_action": "...", + "head_action": "..." +}} +""", + "change_action_prompt", + ) + Prompt( + """ +{chat_talking_prompt} +以上是群里最近的聊天记录 + +{indentify_block} +你之前的动作状态是: +- 手部:{hand_action} +- 上半身:{upper_body_action} +- 头部:{head_action} + +距离你上次关注群里消息已经过去了一段时间,你冷静了下来,你的动作会趋于平缓或静止,请你输出你现在新的动作状态,用中文。 +请只按照以下json格式输出,描述你新的动作状态,每个动作一到三个词,确保每个字段都存在: +{{ + "hand_action": "...", + "upper_body_action": "...", + "head_action": "..." +}} +""", + "regress_action_prompt", + ) + + +class ChatAction: + def __init__(self, chat_id: str): + self.chat_id: str = chat_id + self.hand_action: str = "双手放在桌面" + self.upper_body_action: str = "坐着" + self.head_action: str = "注视摄像机" + + self.regression_count: int = 0 + + self.action_model = LLMRequest( + model=global_config.model.emotion, + temperature=0.7, + request_type="action", + ) + + self.last_change_time = 0 + + async def update_action_by_message(self, message: MessageRecv): + self.regression_count = 0 + + message_time = message.message_info.time + message_list_before_now = get_raw_msg_by_timestamp_with_chat_inclusive( + chat_id=self.chat_id, + timestamp_start=self.last_change_time, + timestamp_end=message_time, + limit=15, + limit_mode="last", + ) + chat_talking_prompt = build_readable_messages( + message_list_before_now, + replace_bot_name=True, + merge_messages=False, + timestamp_mode="normal_no_YMD", + read_mark=0.0, + truncate=True, + show_actions=True, + ) + + bot_name = global_config.bot.nickname + if global_config.bot.alias_names: + bot_nickname = f",也有人叫你{','.join(global_config.bot.alias_names)}" + else: + bot_nickname = "" + + prompt_personality = global_config.personality.personality_core + indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}:" + + prompt = await global_prompt_manager.format_prompt( + "change_action_prompt", + chat_talking_prompt=chat_talking_prompt, + indentify_block=indentify_block, + hand_action=self.hand_action, + upper_body_action=self.upper_body_action, + head_action=self.head_action, + ) + + logger.info(f"prompt: {prompt}") + response, (reasoning_content, model_name) = await self.action_model.generate_response_async(prompt=prompt) + logger.info(f"response: {response}") + logger.info(f"reasoning_content: {reasoning_content}") + + action_data = json.loads(repair_json(response)) + + if action_data: + self.hand_action = action_data.get("hand_action", self.hand_action) + self.upper_body_action = action_data.get("upper_body_action", self.upper_body_action) + self.head_action = action_data.get("head_action", self.head_action) + + self.last_change_time = message_time + + async def regress_action(self): + message_time = time.time() + message_list_before_now = get_raw_msg_by_timestamp_with_chat_inclusive( + chat_id=self.chat_id, + timestamp_start=self.last_change_time, + timestamp_end=message_time, + limit=15, + limit_mode="last", + ) + chat_talking_prompt = build_readable_messages( + message_list_before_now, + replace_bot_name=True, + merge_messages=False, + timestamp_mode="normal_no_YMD", + read_mark=0.0, + truncate=True, + show_actions=True, + ) + + bot_name = global_config.bot.nickname + if global_config.bot.alias_names: + bot_nickname = f",也有人叫你{','.join(global_config.bot.alias_names)}" + else: + bot_nickname = "" + + prompt_personality = global_config.personality.personality_core + indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}:" + + prompt = await global_prompt_manager.format_prompt( + "regress_action_prompt", + chat_talking_prompt=chat_talking_prompt, + indentify_block=indentify_block, + hand_action=self.hand_action, + upper_body_action=self.upper_body_action, + head_action=self.head_action, + ) + + logger.info(f"prompt: {prompt}") + response, (reasoning_content, model_name) = await self.action_model.generate_response_async(prompt=prompt) + logger.info(f"response: {response}") + logger.info(f"reasoning_content: {reasoning_content}") + + action_data = json.loads(repair_json(response)) + if action_data: + self.hand_action = action_data.get("hand_action", self.hand_action) + self.upper_body_action = action_data.get("upper_body_action", self.upper_body_action) + self.head_action = action_data.get("head_action", self.head_action) + + self.regression_count += 1 + + +class ActionRegressionTask(AsyncTask): + def __init__(self, action_manager: "ActionManager"): + super().__init__(task_name="ActionRegressionTask", run_interval=30) + self.action_manager = action_manager + + async def run(self): + logger.debug("Running action regression task...") + now = time.time() + for action_state in self.action_manager.action_state_list: + if action_state.last_change_time == 0: + continue + + if now - action_state.last_change_time > 180: + if action_state.regression_count >= 3: + continue + + logger.info(f"chat {action_state.chat_id} 开始动作回归, 这是第 {action_state.regression_count + 1} 次") + await action_state.regress_action() + + +class ActionManager: + def __init__(self): + self.action_state_list: list[ChatAction] = [] + """当前动作状态""" + self.task_started: bool = False + + async def start(self): + """启动动作回归后台任务""" + if self.task_started: + return + + logger.info("启动动作回归任务...") + task = ActionRegressionTask(self) + await async_task_manager.add_task(task) + self.task_started = True + logger.info("动作回归任务已启动") + + def get_action_state_by_chat_id(self, chat_id: str) -> ChatAction: + for action_state in self.action_state_list: + if action_state.chat_id == chat_id: + return action_state + + new_action_state = ChatAction(chat_id) + self.action_state_list.append(new_action_state) + return new_action_state + + def reset_action_state_by_chat_id(self, chat_id: str): + for action_state in self.action_state_list: + if action_state.chat_id == chat_id: + action_state.hand_action = "双手放在桌面" + action_state.upper_body_action = "坐着" + action_state.head_action = "注视摄像机" + action_state.regression_count = 0 + return + self.action_state_list.append(ChatAction(chat_id)) + + +init_prompt() + +action_manager = ActionManager() +"""全局动作管理器""" diff --git a/src/mais4u/mais4u_chat/s4u_mood_manager.py b/src/mais4u/mais4u_chat/s4u_mood_manager.py new file mode 100644 index 000000000..57e15831c --- /dev/null +++ b/src/mais4u/mais4u_chat/s4u_mood_manager.py @@ -0,0 +1,365 @@ +import asyncio +import json +import math +import random +import time + +from src.chat.message_receive.message import MessageRecv +from src.llm_models.utils_model import LLMRequest +from src.common.logger import get_logger +from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_by_timestamp_with_chat_inclusive +from src.config.config import global_config +from src.chat.utils.prompt_builder import Prompt, global_prompt_manager +from src.manager.async_task_manager import AsyncTask, async_task_manager +from src.plugin_system.apis import send_api + +logger = get_logger("mood") + + +async def send_joy_action(chat_id: str): + action_content = {"action": "Joy_eye", "data": 1.0} + await send_api.custom_to_stream(message_type="face_emotion", content=action_content, stream_id=chat_id) + logger.info(f"[{chat_id}] 已发送 Joy 动作: {action_content}") + + await asyncio.sleep(5.0) + + end_action_content = {"action": "Joy_eye", "data": 0.0} + await send_api.custom_to_stream(message_type="face_emotion", content=end_action_content, stream_id=chat_id) + logger.info(f"[{chat_id}] 已发送 Joy 结束动作: {end_action_content}") + + +def init_prompt(): + Prompt( + """ +{chat_talking_prompt} +以上是直播间里正在进行的对话 + +{indentify_block} +你刚刚的情绪状态是:{mood_state} + +现在,发送了消息,引起了你的注意,你对其进行了阅读和思考,请你输出一句话描述你新的情绪状态,不要输出任何其他内容 +请只输出情绪状态,不要输出其他内容: +""", + "change_mood_prompt", + ) + Prompt( + """ +{chat_talking_prompt} +以上是直播间里最近的对话 + +{indentify_block} +你之前的情绪状态是:{mood_state} + +距离你上次关注直播间消息已经过去了一段时间,你冷静了下来,请你输出一句话描述你现在的情绪状态 +请只输出情绪状态,不要输出其他内容: +""", + "regress_mood_prompt", + ) + Prompt( + """ +{chat_talking_prompt} +以上是直播间里正在进行的对话 + +{indentify_block} +你刚刚的情绪状态是:{mood_state} +具体来说,从1-10分,你的情绪状态是: +喜(Joy): {joy} +怒(Anger): {anger} +哀(Sorrow): {sorrow} +乐(Pleasure): {pleasure} +惧(Fear): {fear} + +现在,发送了消息,引起了你的注意,你对其进行了阅读和思考。请基于对话内容,评估你新的情绪状态。 +请以JSON格式输出你新的情绪状态,包含“喜怒哀乐惧”五个维度,每个维度的取值范围为1-10。 +键值请使用英文: "joy", "anger", "sorrow", "pleasure", "fear". +例如: {{"joy": 5, "anger": 1, "sorrow": 1, "pleasure": 5, "fear": 1}} +不要输出任何其他内容,只输出JSON。 +""", + "change_mood_numerical_prompt", + ) + Prompt( + """ +{chat_talking_prompt} +以上是直播间里最近的对话 + +{indentify_block} +你之前的情绪状态是:{mood_state} +具体来说,从1-10分,你的情绪状态是: +喜(Joy): {joy} +怒(Anger): {anger} +哀(Sorrow): {sorrow} +乐(Pleasure): {pleasure} +惧(Fear): {fear} + +距离你上次关注直播间消息已经过去了一段时间,你冷静了下来。请基于此,评估你现在的情绪状态。 +请以JSON格式输出你新的情绪状态,包含“喜怒哀乐惧”五个维度,每个维度的取值范围为1-10。 +键值请使用英文: "joy", "anger", "sorrow", "pleasure", "fear". +例如: {{"joy": 5, "anger": 1, "sorrow": 1, "pleasure": 5, "fear": 1}} +不要输出任何其他内容,只输出JSON。 +""", + "regress_mood_numerical_prompt", + ) + + +class ChatMood: + def __init__(self, chat_id: str): + self.chat_id: str = chat_id + self.mood_state: str = "感觉很平静" + self.mood_values: dict[str, int] = {"joy": 5, "anger": 1, "sorrow": 1, "pleasure": 5, "fear": 1} + + self.regression_count: int = 0 + + self.mood_model = LLMRequest( + model=global_config.model.emotion, + temperature=0.7, + request_type="mood_text", + ) + self.mood_model_numerical = LLMRequest( + model=global_config.model.emotion, + temperature=0.4, + request_type="mood_numerical", + ) + + self.last_change_time = 0 + + def _parse_numerical_mood(self, response: str) -> dict[str, int] | None: + try: + # The LLM might output markdown with json inside + if "```json" in response: + response = response.split("```json")[1].split("```")[0] + elif "```" in response: + response = response.split("```")[1].split("```")[0] + + data = json.loads(response) + + # Validate + required_keys = {"joy", "anger", "sorrow", "pleasure", "fear"} + if not required_keys.issubset(data.keys()): + logger.warning(f"Numerical mood response missing keys: {response}") + return None + + for key in required_keys: + value = data[key] + if not isinstance(value, int) or not (1 <= value <= 10): + logger.warning(f"Numerical mood response invalid value for {key}: {value} in {response}") + return None + + return {key: data[key] for key in required_keys} + + except json.JSONDecodeError: + logger.warning(f"Failed to parse numerical mood JSON: {response}") + return None + except Exception as e: + logger.error(f"Error parsing numerical mood: {e}, response: {response}") + return None + + async def update_mood_by_message(self, message: MessageRecv): + self.regression_count = 0 + + message_time = message.message_info.time + message_list_before_now = get_raw_msg_by_timestamp_with_chat_inclusive( + chat_id=self.chat_id, + timestamp_start=self.last_change_time, + timestamp_end=message_time, + limit=15, + limit_mode="last", + ) + chat_talking_prompt = build_readable_messages( + message_list_before_now, + replace_bot_name=True, + merge_messages=False, + timestamp_mode="normal_no_YMD", + read_mark=0.0, + truncate=True, + show_actions=True, + ) + + bot_name = global_config.bot.nickname + if global_config.bot.alias_names: + bot_nickname = f",也有人叫你{','.join(global_config.bot.alias_names)}" + else: + bot_nickname = "" + + prompt_personality = global_config.personality.personality_core + indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}:" + + async def _update_text_mood(): + prompt = await global_prompt_manager.format_prompt( + "change_mood_prompt", + chat_talking_prompt=chat_talking_prompt, + indentify_block=indentify_block, + mood_state=self.mood_state, + ) + logger.debug(f"text mood prompt: {prompt}") + response, (reasoning_content, model_name) = await self.mood_model.generate_response_async(prompt=prompt) + logger.info(f"text mood response: {response}") + logger.debug(f"text mood reasoning_content: {reasoning_content}") + return response + + async def _update_numerical_mood(): + prompt = await global_prompt_manager.format_prompt( + "change_mood_numerical_prompt", + chat_talking_prompt=chat_talking_prompt, + indentify_block=indentify_block, + mood_state=self.mood_state, + joy=self.mood_values["joy"], + anger=self.mood_values["anger"], + sorrow=self.mood_values["sorrow"], + pleasure=self.mood_values["pleasure"], + fear=self.mood_values["fear"], + ) + logger.info(f"numerical mood prompt: {prompt}") + response, (reasoning_content, model_name) = await self.mood_model_numerical.generate_response_async( + prompt=prompt + ) + logger.info(f"numerical mood response: {response}") + logger.debug(f"numerical mood reasoning_content: {reasoning_content}") + return self._parse_numerical_mood(response) + + results = await asyncio.gather(_update_text_mood(), _update_numerical_mood()) + text_mood_response, numerical_mood_response = results + + if text_mood_response: + self.mood_state = text_mood_response + + if numerical_mood_response: + self.mood_values = numerical_mood_response + if self.mood_values.get("joy", 0) > 5: + asyncio.create_task(send_joy_action(self.chat_id)) + + self.last_change_time = message_time + + async def regress_mood(self): + message_time = time.time() + message_list_before_now = get_raw_msg_by_timestamp_with_chat_inclusive( + chat_id=self.chat_id, + timestamp_start=self.last_change_time, + timestamp_end=message_time, + limit=15, + limit_mode="last", + ) + chat_talking_prompt = build_readable_messages( + message_list_before_now, + replace_bot_name=True, + merge_messages=False, + timestamp_mode="normal_no_YMD", + read_mark=0.0, + truncate=True, + show_actions=True, + ) + + bot_name = global_config.bot.nickname + if global_config.bot.alias_names: + bot_nickname = f",也有人叫你{','.join(global_config.bot.alias_names)}" + else: + bot_nickname = "" + + prompt_personality = global_config.personality.personality_core + indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}:" + + async def _regress_text_mood(): + prompt = await global_prompt_manager.format_prompt( + "regress_mood_prompt", + chat_talking_prompt=chat_talking_prompt, + indentify_block=indentify_block, + mood_state=self.mood_state, + ) + logger.debug(f"text regress prompt: {prompt}") + response, (reasoning_content, model_name) = await self.mood_model.generate_response_async(prompt=prompt) + logger.info(f"text regress response: {response}") + logger.debug(f"text regress reasoning_content: {reasoning_content}") + return response + + async def _regress_numerical_mood(): + prompt = await global_prompt_manager.format_prompt( + "regress_mood_numerical_prompt", + chat_talking_prompt=chat_talking_prompt, + indentify_block=indentify_block, + mood_state=self.mood_state, + joy=self.mood_values["joy"], + anger=self.mood_values["anger"], + sorrow=self.mood_values["sorrow"], + pleasure=self.mood_values["pleasure"], + fear=self.mood_values["fear"], + ) + logger.debug(f"numerical regress prompt: {prompt}") + response, (reasoning_content, model_name) = await self.mood_model_numerical.generate_response_async( + prompt=prompt + ) + logger.info(f"numerical regress response: {response}") + logger.debug(f"numerical regress reasoning_content: {reasoning_content}") + return self._parse_numerical_mood(response) + + results = await asyncio.gather(_regress_text_mood(), _regress_numerical_mood()) + text_mood_response, numerical_mood_response = results + + if text_mood_response: + self.mood_state = text_mood_response + + if numerical_mood_response: + self.mood_values = numerical_mood_response + if self.mood_values.get("joy", 0) > 5: + asyncio.create_task(send_joy_action(self.chat_id)) + + self.regression_count += 1 + + +class MoodRegressionTask(AsyncTask): + def __init__(self, mood_manager: "MoodManager"): + super().__init__(task_name="MoodRegressionTask", run_interval=30) + self.mood_manager = mood_manager + + async def run(self): + logger.debug("Running mood regression task...") + now = time.time() + for mood in self.mood_manager.mood_list: + if mood.last_change_time == 0: + continue + + if now - mood.last_change_time > 180: + if mood.regression_count >= 3: + continue + + logger.info(f"chat {mood.chat_id} 开始情绪回归, 这是第 {mood.regression_count + 1} 次") + await mood.regress_mood() + + +class MoodManager: + def __init__(self): + self.mood_list: list[ChatMood] = [] + """当前情绪状态""" + self.task_started: bool = False + + async def start(self): + """启动情绪回归后台任务""" + if self.task_started: + return + + logger.info("启动情绪回归任务...") + task = MoodRegressionTask(self) + await async_task_manager.add_task(task) + self.task_started = True + logger.info("情绪回归任务已启动") + + def get_mood_by_chat_id(self, chat_id: str) -> ChatMood: + for mood in self.mood_list: + if mood.chat_id == chat_id: + return mood + + new_mood = ChatMood(chat_id) + self.mood_list.append(new_mood) + return new_mood + + def reset_mood_by_chat_id(self, chat_id: str): + for mood in self.mood_list: + if mood.chat_id == chat_id: + mood.mood_state = "感觉很平静" + mood.regression_count = 0 + return + self.mood_list.append(ChatMood(chat_id)) + + +init_prompt() + +mood_manager = MoodManager() +"""全局情绪管理器""" diff --git a/src/mais4u/mais4u_chat/s4u_msg_processor.py b/src/mais4u/mais4u_chat/s4u_msg_processor.py index ecdefe109..220f49a7e 100644 --- a/src/mais4u/mais4u_chat/s4u_msg_processor.py +++ b/src/mais4u/mais4u_chat/s4u_msg_processor.py @@ -1,7 +1,18 @@ +import asyncio +import math +from typing import Tuple + +from src.chat.memory_system.Hippocampus import hippocampus_manager from src.chat.message_receive.message import MessageRecv from src.chat.message_receive.storage import MessageStorage from src.chat.message_receive.chat_stream import get_chat_manager +from src.chat.utils.timer_calculator import Timer +from src.chat.utils.utils import is_mentioned_bot_in_message from src.common.logger import get_logger +from src.config.config import global_config +from src.mais4u.mais4u_chat.body_emotion_action_manager import action_manager +from src.mais4u.mais4u_chat.s4u_mood_manager import mood_manager + from .s4u_chat import get_s4u_chat_manager @@ -10,6 +21,42 @@ from .s4u_chat import get_s4u_chat_manager logger = get_logger("chat") +async def _calculate_interest(message: MessageRecv) -> Tuple[float, bool]: + """计算消息的兴趣度 + + Args: + message: 待处理的消息对象 + + Returns: + Tuple[float, bool]: (兴趣度, 是否被提及) + """ + is_mentioned, _ = is_mentioned_bot_in_message(message) + interested_rate = 0.0 + + if global_config.memory.enable_memory: + with Timer("记忆激活"): + interested_rate = await hippocampus_manager.get_activate_from_text( + message.processed_plain_text, + fast_retrieval=True, + ) + logger.debug(f"记忆激活率: {interested_rate:.2f}") + + text_len = len(message.processed_plain_text) + # 根据文本长度调整兴趣度,长度越大兴趣度越高,但增长率递减,最低0.01,最高0.05 + # 采用对数函数实现递减增长 + + base_interest = 0.01 + (0.05 - 0.01) * (math.log10(text_len + 1) / math.log10(1000 + 1)) + base_interest = min(max(base_interest, 0.01), 0.05) + + interested_rate += base_interest + + if is_mentioned: + interest_increase_on_mention = 1 + interested_rate += interest_increase_on_mention + + return interested_rate, is_mentioned + + class S4UMessageProcessor: """心流处理器,负责处理接收到的消息并计算兴趣度""" @@ -53,5 +100,13 @@ class S4UMessageProcessor: else: await s4u_chat.add_message(message) + interested_rate, _ = await _calculate_interest(message) + + chat_mood = mood_manager.get_mood_by_chat_id(chat.stream_id) + asyncio.create_task(chat_mood.update_mood_by_message(message)) + chat_action = action_manager.get_action_state_by_chat_id(chat.stream_id) + asyncio.create_task(chat_action.update_action_by_message(message)) + # asyncio.create_task(chat_action.update_facial_expression_by_message(message, interested_rate)) + # 7. 日志记录 logger.info(f"[S4U]{userinfo.user_nickname}:{message.processed_plain_text}") diff --git a/src/mais4u/mais4u_chat/s4u_prompt.py b/src/mais4u/mais4u_chat/s4u_prompt.py index 24dba6029..13c142e8d 100644 --- a/src/mais4u/mais4u_chat/s4u_prompt.py +++ b/src/mais4u/mais4u_chat/s4u_prompt.py @@ -17,11 +17,6 @@ logger = get_logger("prompt") def init_prompt(): - Prompt("你正在qq群里聊天,下面是群里在聊的内容:", "chat_target_group1") - Prompt("你正在和{sender_name}聊天,这是你们之前聊的内容:", "chat_target_private1") - Prompt("在群里聊天", "chat_target_group2") - Prompt("和{sender_name}私聊", "chat_target_private2") - Prompt("\n你有以下这些**知识**:\n{prompt_info}\n请你**记住上面的知识**,之后可能会用到。\n", "knowledge_prompt") Prompt("\n关于你们的关系,你需要知道:\n{relation_info}\n", "relation_prompt") Prompt("你回想起了一些事情:\n{memory_info}\n", "memory_prompt")