diff --git a/bot.py b/bot.py index 5b12b0389..c9568ecba 100644 --- a/bot.py +++ b/bot.py @@ -7,12 +7,16 @@ from pathlib import Path import time import platform from dotenv import load_dotenv -from src.common.logger import get_module_logger +from src.common.logger import get_module_logger, LogConfig, CONFIRM_STYLE_CONFIG from src.common.crash_logger import install_crash_handler from src.main import MainSystem logger = get_module_logger("main_bot") - +confirm_logger_config = LogConfig( + console_format=CONFIRM_STYLE_CONFIG["console_format"], + file_format=CONFIRM_STYLE_CONFIG["file_format"], +) +confirm_logger = get_module_logger("main_bot", config=confirm_logger_config) # 获取没有加载env时的环境变量 env_mask = {key: os.getenv(key) for key in os.environ} @@ -166,8 +170,8 @@ def check_eula(): # 如果EULA或隐私条款有更新,提示用户重新确认 if eula_updated or privacy_updated: - print("EULA或隐私条款内容已更新,请在阅读后重新确认,继续运行视为同意更新后的以上两款协议") - print( + confirm_logger.critical("EULA或隐私条款内容已更新,请在阅读后重新确认,继续运行视为同意更新后的以上两款协议") + confirm_logger.critical( f'输入"同意"或"confirmed"或设置环境变量"EULA_AGREE={eula_new_hash}"和"PRIVACY_AGREE={privacy_new_hash}"继续运行' ) while True: @@ -176,14 +180,14 @@ def check_eula(): # print("确认成功,继续运行") # print(f"确认成功,继续运行{eula_updated} {privacy_updated}") if eula_updated: - print(f"更新EULA确认文件{eula_new_hash}") + logger.info(f"更新EULA确认文件{eula_new_hash}") eula_confirm_file.write_text(eula_new_hash, encoding="utf-8") if privacy_updated: - print(f"更新隐私条款确认文件{privacy_new_hash}") + logger.info(f"更新隐私条款确认文件{privacy_new_hash}") privacy_confirm_file.write_text(privacy_new_hash, encoding="utf-8") break else: - print('请输入"同意"或"confirmed"以继续运行') + confirm_logger.critical('请输入"同意"或"confirmed"以继续运行') return elif eula_confirmed and privacy_confirmed: return diff --git a/src/common/logger.py b/src/common/logger.py index 9e118622d..cded9467c 100644 --- a/src/common/logger.py +++ b/src/common/logger.py @@ -290,6 +290,12 @@ WILLING_STYLE_CONFIG = { }, } +CONFIRM_STYLE_CONFIG = { + "console_format": ( + "{message}" + ), # noqa: E501 + "file_format": ("{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | EULA与PRIVACY确认 | {message}"), +} # 根据SIMPLE_OUTPUT选择配置 MEMORY_STYLE_CONFIG = MEMORY_STYLE_CONFIG["simple"] if SIMPLE_OUTPUT else MEMORY_STYLE_CONFIG["advanced"] diff --git a/src/heart_flow/heartflow.py b/src/heart_flow/heartflow.py index f5b394f2e..3ea51917c 100644 --- a/src/heart_flow/heartflow.py +++ b/src/heart_flow/heartflow.py @@ -9,6 +9,7 @@ from src.common.logger import get_module_logger, LogConfig, HEARTFLOW_STYLE_CONF from src.individuality.individuality import Individuality import time import random +from typing import Dict, Any heartflow_config = LogConfig( # 使用海马体专用样式 @@ -39,7 +40,7 @@ class Heartflow: model=global_config.llm_heartflow, temperature=0.6, max_tokens=1000, request_type="heart_flow" ) - self._subheartflows = {} + self._subheartflows: Dict[Any, SubHeartflow] = {} self.active_subheartflows_nums = 0 async def _cleanup_inactive_subheartflows(self): diff --git a/src/plugins/chat/auto_speak.py b/src/plugins/chat/auto_speak.py index 62a5a20a5..ac76a2714 100644 --- a/src/plugins/chat/auto_speak.py +++ b/src/plugins/chat/auto_speak.py @@ -142,7 +142,11 @@ class AutoSpeakManager: message_manager.add_message(thinking_message) # 生成自主发言内容 - response, raw_content = await self.gpt.generate_response(message) + try: + response, raw_content = await self.gpt.generate_response(message) + except Exception as e: + logger.error(f"生成自主发言内容时发生错误: {e}") + return False if response: message_set = MessageSet(None, think_id) # 不需要chat_stream diff --git a/src/plugins/chat_module/reasoning_chat/reasoning_chat.py b/src/plugins/chat_module/reasoning_chat/reasoning_chat.py index b9e94e4fe..c097427de 100644 --- a/src/plugins/chat_module/reasoning_chat/reasoning_chat.py +++ b/src/plugins/chat_module/reasoning_chat/reasoning_chat.py @@ -59,11 +59,7 @@ class ReasoningChat: return thinking_id - async def _send_response_messages(self, - message, - chat, - response_set:List[str], - thinking_id) -> MessageSending: + async def _send_response_messages(self, message, chat, response_set: List[str], thinking_id) -> MessageSending: """发送回复消息""" container = message_manager.get_container(chat.stream_id) thinking_message = None @@ -240,19 +236,23 @@ class ReasoningChat: thinking_id = await self._create_thinking_message(message, chat, userinfo, messageinfo) timer2 = time.time() timing_results["创建思考消息"] = timer2 - timer1 - + logger.debug(f"创建捕捉器,thinking_id:{thinking_id}") - + info_catcher = info_catcher_manager.get_info_catcher(thinking_id) info_catcher.catch_decide_to_response(message) # 生成回复 timer1 = time.time() - response_set = await self.gpt.generate_response(message,thinking_id) - timer2 = time.time() - timing_results["生成回复"] = timer2 - timer1 - - info_catcher.catch_after_generate_response(timing_results["生成回复"]) + try: + response_set = await self.gpt.generate_response(message, thinking_id) + timer2 = time.time() + timing_results["生成回复"] = timer2 - timer1 + + info_catcher.catch_after_generate_response(timing_results["生成回复"]) + except Exception as e: + logger.error(f"回复生成出现错误:str{e}") + response_set = None if not response_set: logger.info("为什么生成回复失败?") @@ -263,10 +263,9 @@ class ReasoningChat: first_bot_msg = await self._send_response_messages(message, chat, response_set, thinking_id) timer2 = time.time() timing_results["发送消息"] = timer2 - timer1 - - info_catcher.catch_after_response(timing_results["发送消息"],response_set,first_bot_msg) - - + + info_catcher.catch_after_response(timing_results["发送消息"], response_set, first_bot_msg) + info_catcher.done_catch() # 处理表情包 diff --git a/src/plugins/memory_system/Hippocampus.py b/src/plugins/memory_system/Hippocampus.py index 516e211a1..0a738b312 100644 --- a/src/plugins/memory_system/Hippocampus.py +++ b/src/plugins/memory_system/Hippocampus.py @@ -934,9 +934,437 @@ class EntorhinalCortex: logger.success(f"[数据库] 同步了 {len(memory_nodes)} 个节点和 {len(memory_edges)} 条边") +# 海马体 +class Hippocampus: + def __init__(self): + self.memory_graph = Memory_graph() + self.llm_topic_judge = None + self.llm_summary_by_topic = None + self.entorhinal_cortex = None + self.parahippocampal_gyrus = None + self.config = None + + def initialize(self, global_config): + self.config = MemoryConfig.from_global_config(global_config) + # 初始化子组件 + self.entorhinal_cortex = EntorhinalCortex(self) + self.parahippocampal_gyrus = ParahippocampalGyrus(self) + # 从数据库加载记忆图 + self.entorhinal_cortex.sync_memory_from_db() + self.llm_topic_judge = LLM_request(self.config.llm_topic_judge, request_type="memory") + self.llm_summary_by_topic = LLM_request(self.config.llm_summary_by_topic, request_type="memory") + + def get_all_node_names(self) -> list: + """获取记忆图中所有节点的名字列表""" + return list(self.memory_graph.G.nodes()) + + def calculate_node_hash(self, concept, memory_items) -> int: + """计算节点的特征值""" + if not isinstance(memory_items, list): + memory_items = [memory_items] if memory_items else [] + sorted_items = sorted(memory_items) + content = f"{concept}:{'|'.join(sorted_items)}" + return hash(content) + + def calculate_edge_hash(self, source, target) -> int: + """计算边的特征值""" + nodes = sorted([source, target]) + return hash(f"{nodes[0]}:{nodes[1]}") + + def find_topic_llm(self, text, topic_num): + prompt = ( + f"这是一段文字:{text}。请你从这段话中总结出最多{topic_num}个关键的概念,可以是名词,动词,或者特定人物,帮我列出来," + f"将主题用逗号隔开,并加上<>,例如<主题1>,<主题2>......尽可能精简。只需要列举最多{topic_num}个话题就好,不要有序号,不要告诉我其他内容。" + f"如果确定找不出主题或者没有明显主题,返回。" + ) + return prompt + + def topic_what(self, text, topic, time_info): + prompt = ( + f'这是一段文字,{time_info}:{text}。我想让你基于这段文字来概括"{topic}"这个概念,帮我总结成一句自然的话,' + f"可以包含时间和人物,以及具体的观点。只输出这句话就好" + ) + return prompt + + def calculate_topic_num(self, text, compress_rate): + """计算文本的话题数量""" + information_content = calculate_information_content(text) + topic_by_length = text.count("\n") * compress_rate + topic_by_information_content = max(1, min(5, int((information_content - 3) * 2))) + topic_num = int((topic_by_length + topic_by_information_content) / 2) + logger.debug( + f"topic_by_length: {topic_by_length}, topic_by_information_content: {topic_by_information_content}, " + f"topic_num: {topic_num}" + ) + return topic_num + + def get_memory_from_keyword(self, keyword: str, max_depth: int = 2) -> list: + """从关键词获取相关记忆。 + + Args: + keyword (str): 关键词 + max_depth (int, optional): 记忆检索深度,默认为2。1表示只获取直接相关的记忆,2表示获取间接相关的记忆。 + + Returns: + list: 记忆列表,每个元素是一个元组 (topic, memory_items, similarity) + - topic: str, 记忆主题 + - memory_items: list, 该主题下的记忆项列表 + - similarity: float, 与关键词的相似度 + """ + if not keyword: + return [] + + # 获取所有节点 + all_nodes = list(self.memory_graph.G.nodes()) + memories = [] + + # 计算关键词的词集合 + keyword_words = set(jieba.cut(keyword)) + + # 遍历所有节点,计算相似度 + for node in all_nodes: + node_words = set(jieba.cut(node)) + all_words = keyword_words | node_words + v1 = [1 if word in keyword_words else 0 for word in all_words] + v2 = [1 if word in node_words else 0 for word in all_words] + similarity = cosine_similarity(v1, v2) + + # 如果相似度超过阈值,获取该节点的记忆 + if similarity >= 0.3: # 可以调整这个阈值 + node_data = self.memory_graph.G.nodes[node] + memory_items = node_data.get("memory_items", []) + if not isinstance(memory_items, list): + memory_items = [memory_items] if memory_items else [] + + memories.append((node, memory_items, similarity)) + + # 按相似度降序排序 + memories.sort(key=lambda x: x[2], reverse=True) + return memories + + async def get_memory_from_text( + self, + text: str, + max_memory_num: int = 3, + max_memory_length: int = 2, + max_depth: int = 3, + fast_retrieval: bool = False, + ) -> list: + """从文本中提取关键词并获取相关记忆。 + + Args: + text (str): 输入文本 + num (int, optional): 需要返回的记忆数量。默认为5。 + max_depth (int, optional): 记忆检索深度。默认为2。 + fast_retrieval (bool, optional): 是否使用快速检索。默认为False。 + 如果为True,使用jieba分词和TF-IDF提取关键词,速度更快但可能不够准确。 + 如果为False,使用LLM提取关键词,速度较慢但更准确。 + + Returns: + list: 记忆列表,每个元素是一个元组 (topic, memory_items, similarity) + - topic: str, 记忆主题 + - memory_items: list, 该主题下的记忆项列表 + - similarity: float, 与文本的相似度 + """ + if not text: + return [] + + if fast_retrieval: + # 使用jieba分词提取关键词 + words = jieba.cut(text) + # 过滤掉停用词和单字词 + keywords = [word for word in words if len(word) > 1] + # 去重 + keywords = list(set(keywords)) + # 限制关键词数量 + keywords = keywords[:5] + else: + # 使用LLM提取关键词 + topic_num = min(5, max(1, int(len(text) * 0.1))) # 根据文本长度动态调整关键词数量 + # logger.info(f"提取关键词数量: {topic_num}") + topics_response = await self.llm_topic_judge.generate_response(self.find_topic_llm(text, topic_num)) + + # 提取关键词 + keywords = re.findall(r"<([^>]+)>", topics_response[0]) + if not keywords: + keywords = [] + else: + keywords = [ + keyword.strip() + for keyword in ",".join(keywords).replace(",", ",").replace("、", ",").replace(" ", ",").split(",") + if keyword.strip() + ] + + # logger.info(f"提取的关键词: {', '.join(keywords)}") + + # 过滤掉不存在于记忆图中的关键词 + valid_keywords = [keyword for keyword in keywords if keyword in self.memory_graph.G] + if not valid_keywords: + logger.info("没有找到有效的关键词节点") + return [] + + logger.info(f"有效的关键词: {', '.join(valid_keywords)}") + + # 从每个关键词获取记忆 + all_memories = [] + activate_map = {} # 存储每个词的累计激活值 + + # 对每个关键词进行扩散式检索 + for keyword in valid_keywords: + logger.debug(f"开始以关键词 '{keyword}' 为中心进行扩散检索 (最大深度: {max_depth}):") + # 初始化激活值 + activation_values = {keyword: 1.0} + # 记录已访问的节点 + visited_nodes = {keyword} + # 待处理的节点队列,每个元素是(节点, 激活值, 当前深度) + nodes_to_process = [(keyword, 1.0, 0)] + + while nodes_to_process: + current_node, current_activation, current_depth = nodes_to_process.pop(0) + + # 如果激活值小于0或超过最大深度,停止扩散 + if current_activation <= 0 or current_depth >= max_depth: + continue + + # 获取当前节点的所有邻居 + neighbors = list(self.memory_graph.G.neighbors(current_node)) + + for neighbor in neighbors: + if neighbor in visited_nodes: + continue + + # 获取连接强度 + edge_data = self.memory_graph.G[current_node][neighbor] + strength = edge_data.get("strength", 1) + + # 计算新的激活值 + new_activation = current_activation - (1 / strength) + + if new_activation > 0: + activation_values[neighbor] = new_activation + visited_nodes.add(neighbor) + nodes_to_process.append((neighbor, new_activation, current_depth + 1)) + logger.debug( + f"节点 '{neighbor}' 被激活,激活值: {new_activation:.2f} (通过 '{current_node}' 连接,强度: {strength}, 深度: {current_depth + 1})" + ) # noqa: E501 + + # 更新激活映射 + for node, activation_value in activation_values.items(): + if activation_value > 0: + if node in activate_map: + activate_map[node] += activation_value + else: + activate_map[node] = activation_value + + # 输出激活映射 + # logger.info("激活映射统计:") + # for node, total_activation in sorted(activate_map.items(), key=lambda x: x[1], reverse=True): + # logger.info(f"节点 '{node}': 累计激活值 = {total_activation:.2f}") + + # 基于激活值平方的独立概率选择 + remember_map = {} + # logger.info("基于激活值平方的归一化选择:") + + # 计算所有激活值的平方和 + total_squared_activation = sum(activation**2 for activation in activate_map.values()) + if total_squared_activation > 0: + # 计算归一化的激活值 + normalized_activations = { + node: (activation**2) / total_squared_activation for node, activation in activate_map.items() + } + + # 按归一化激活值排序并选择前max_memory_num个 + sorted_nodes = sorted(normalized_activations.items(), key=lambda x: x[1], reverse=True)[:max_memory_num] + + # 将选中的节点添加到remember_map + for node, normalized_activation in sorted_nodes: + remember_map[node] = activate_map[node] # 使用原始激活值 + logger.debug( + f"节点 '{node}' (归一化激活值: {normalized_activation:.2f}, 激活值: {activate_map[node]:.2f})" + ) + else: + logger.info("没有有效的激活值") + + # 从选中的节点中提取记忆 + all_memories = [] + # logger.info("开始从选中的节点中提取记忆:") + for node, activation in remember_map.items(): + logger.debug(f"处理节点 '{node}' (激活值: {activation:.2f}):") + node_data = self.memory_graph.G.nodes[node] + memory_items = node_data.get("memory_items", []) + if not isinstance(memory_items, list): + memory_items = [memory_items] if memory_items else [] + + if memory_items: + logger.debug(f"节点包含 {len(memory_items)} 条记忆") + # 计算每条记忆与输入文本的相似度 + memory_similarities = [] + for memory in memory_items: + # 计算与输入文本的相似度 + memory_words = set(jieba.cut(memory)) + text_words = set(jieba.cut(text)) + all_words = memory_words | text_words + v1 = [1 if word in memory_words else 0 for word in all_words] + v2 = [1 if word in text_words else 0 for word in all_words] + similarity = cosine_similarity(v1, v2) + memory_similarities.append((memory, similarity)) + + # 按相似度排序 + memory_similarities.sort(key=lambda x: x[1], reverse=True) + # 获取最匹配的记忆 + top_memories = memory_similarities[:max_memory_length] + + # 添加到结果中 + for memory, similarity in top_memories: + all_memories.append((node, [memory], similarity)) + # logger.info(f"选中记忆: {memory} (相似度: {similarity:.2f})") + else: + logger.info("节点没有记忆") + + # 去重(基于记忆内容) + logger.debug("开始记忆去重:") + seen_memories = set() + unique_memories = [] + for topic, memory_items, activation_value in all_memories: + memory = memory_items[0] # 因为每个topic只有一条记忆 + if memory not in seen_memories: + seen_memories.add(memory) + unique_memories.append((topic, memory_items, activation_value)) + logger.debug(f"保留记忆: {memory} (来自节点: {topic}, 激活值: {activation_value:.2f})") + else: + logger.debug(f"跳过重复记忆: {memory} (来自节点: {topic})") + + # 转换为(关键词, 记忆)格式 + result = [] + for topic, memory_items, _ in unique_memories: + memory = memory_items[0] # 因为每个topic只有一条记忆 + result.append((topic, memory)) + logger.info(f"选中记忆: {memory} (来自节点: {topic})") + + return result + + async def get_activate_from_text(self, text: str, max_depth: int = 3, fast_retrieval: bool = False) -> float: + """从文本中提取关键词并获取相关记忆。 + + Args: + text (str): 输入文本 + num (int, optional): 需要返回的记忆数量。默认为5。 + max_depth (int, optional): 记忆检索深度。默认为2。 + fast_retrieval (bool, optional): 是否使用快速检索。默认为False。 + 如果为True,使用jieba分词和TF-IDF提取关键词,速度更快但可能不够准确。 + 如果为False,使用LLM提取关键词,速度较慢但更准确。 + + Returns: + float: 激活节点数与总节点数的比值 + """ + if not text: + return 0 + + if fast_retrieval: + # 使用jieba分词提取关键词 + words = jieba.cut(text) + # 过滤掉停用词和单字词 + keywords = [word for word in words if len(word) > 1] + # 去重 + keywords = list(set(keywords)) + # 限制关键词数量 + keywords = keywords[:5] + else: + # 使用LLM提取关键词 + topic_num = min(5, max(1, int(len(text) * 0.1))) # 根据文本长度动态调整关键词数量 + # logger.info(f"提取关键词数量: {topic_num}") + topics_response = await self.llm_topic_judge.generate_response(self.find_topic_llm(text, topic_num)) + + # 提取关键词 + keywords = re.findall(r"<([^>]+)>", topics_response[0]) + if not keywords: + keywords = [] + else: + keywords = [ + keyword.strip() + for keyword in ",".join(keywords).replace(",", ",").replace("、", ",").replace(" ", ",").split(",") + if keyword.strip() + ] + + # logger.info(f"提取的关键词: {', '.join(keywords)}") + + # 过滤掉不存在于记忆图中的关键词 + valid_keywords = [keyword for keyword in keywords if keyword in self.memory_graph.G] + if not valid_keywords: + logger.info("没有找到有效的关键词节点") + return 0 + + logger.info(f"有效的关键词: {', '.join(valid_keywords)}") + + # 从每个关键词获取记忆 + activate_map = {} # 存储每个词的累计激活值 + + # 对每个关键词进行扩散式检索 + for keyword in valid_keywords: + logger.debug(f"开始以关键词 '{keyword}' 为中心进行扩散检索 (最大深度: {max_depth}):") + # 初始化激活值 + activation_values = {keyword: 1.0} + # 记录已访问的节点 + visited_nodes = {keyword} + # 待处理的节点队列,每个元素是(节点, 激活值, 当前深度) + nodes_to_process = [(keyword, 1.0, 0)] + + while nodes_to_process: + current_node, current_activation, current_depth = nodes_to_process.pop(0) + + # 如果激活值小于0或超过最大深度,停止扩散 + if current_activation <= 0 or current_depth >= max_depth: + continue + + # 获取当前节点的所有邻居 + neighbors = list(self.memory_graph.G.neighbors(current_node)) + + for neighbor in neighbors: + if neighbor in visited_nodes: + continue + + # 获取连接强度 + edge_data = self.memory_graph.G[current_node][neighbor] + strength = edge_data.get("strength", 1) + + # 计算新的激活值 + new_activation = current_activation - (1 / strength) + + if new_activation > 0: + activation_values[neighbor] = new_activation + visited_nodes.add(neighbor) + nodes_to_process.append((neighbor, new_activation, current_depth + 1)) + # logger.debug( + # f"节点 '{neighbor}' 被激活,激活值: {new_activation:.2f} (通过 '{current_node}' 连接,强度: {strength}, 深度: {current_depth + 1})") # noqa: E501 + + # 更新激活映射 + for node, activation_value in activation_values.items(): + if activation_value > 0: + if node in activate_map: + activate_map[node] += activation_value + else: + activate_map[node] = activation_value + + # 输出激活映射 + # logger.info("激活映射统计:") + # for node, total_activation in sorted(activate_map.items(), key=lambda x: x[1], reverse=True): + # logger.info(f"节点 '{node}': 累计激活值 = {total_activation:.2f}") + + # 计算激活节点数与总节点数的比值 + total_activation = sum(activate_map.values()) + logger.info(f"总激活值: {total_activation:.2f}") + total_nodes = len(self.memory_graph.G.nodes()) + # activated_nodes = len(activate_map) + activation_ratio = total_activation / total_nodes if total_nodes > 0 else 0 + activation_ratio = activation_ratio * 60 + logger.info(f"总激活值: {total_activation:.2f}, 总节点数: {total_nodes}, 激活: {activation_ratio}") + + return activation_ratio + + # 负责整合,遗忘,合并记忆 class ParahippocampalGyrus: - def __init__(self, hippocampus): + def __init__(self, hippocampus: Hippocampus): self.hippocampus = hippocampus self.memory_graph = hippocampus.memory_graph self.config = hippocampus.config @@ -1025,8 +1453,12 @@ class ParahippocampalGyrus: tasks = [] for topic in filtered_topics: topic_what_prompt = self.hippocampus.topic_what(input_text, topic, time_info) - task = self.hippocampus.llm_summary_by_topic.generate_response_async(topic_what_prompt) - tasks.append((topic.strip(), task)) + try: + task = self.hippocampus.llm_summary_by_topic.generate_response_async(topic_what_prompt) + tasks.append((topic.strip(), task)) + except Exception as e: + logger.error(f"生成话题 '{topic}' 的摘要时发生错误: {e}") + continue # 等待所有任务完成 compressed_memory = set() @@ -1075,7 +1507,11 @@ class ParahippocampalGyrus: logger.debug(f"进度: [{bar}] {progress:.1f}% ({i}/{len(memory_samples)})") compress_rate = self.config.memory_compress_rate - compressed_memory, similar_topics_dict = await self.memory_compress(messages, compress_rate) + try: + compressed_memory, similar_topics_dict = await self.memory_compress(messages, compress_rate) + except Exception as e: + logger.error(f"压缩记忆时发生错误: {e}") + continue logger.debug(f"压缩后记忆数量: {compressed_memory},似曾相识的话题: {similar_topics_dict}") current_time = datetime.datetime.now().timestamp() @@ -1247,7 +1683,6 @@ class ParahippocampalGyrus: logger.info(f"[遗忘] 总耗时: {end_time - start_time:.2f}秒") - class HippocampusManager: _instance = None _hippocampus = None @@ -1318,12 +1753,13 @@ class HippocampusManager: if not self._initialized: raise RuntimeError("HippocampusManager 尚未初始化,请先调用 initialize 方法") try: - response = await self._hippocampus.get_memory_from_text(text, max_memory_num, max_memory_length, max_depth, fast_retrieval) + response = await self._hippocampus.get_memory_from_text( + text, max_memory_num, max_memory_length, max_depth, fast_retrieval + ) except Exception as e: logger.error(f"文本激活记忆失败: {e}") response = [] return response - async def get_activate_from_text(self, text: str, max_depth: int = 3, fast_retrieval: bool = False) -> float: """从文本中获取激活值的公共接口""" diff --git a/src/plugins/storage/storage.py b/src/plugins/storage/storage.py index c35f55be5..d07b02719 100644 --- a/src/plugins/storage/storage.py +++ b/src/plugins/storage/storage.py @@ -1,3 +1,4 @@ +import re from typing import Union from ...common.database import db @@ -7,19 +8,34 @@ from src.common.logger import get_module_logger logger = get_module_logger("message_storage") - class MessageStorage: async def store_message(self, message: Union[MessageSending, MessageRecv], chat_stream: ChatStream) -> None: """存储消息到数据库""" try: + # 莫越权 救世啊 + pattern = r".*?|.*?|.*?" + + processed_plain_text = message.processed_plain_text + if processed_plain_text: + filtered_processed_plain_text = re.sub(pattern, "", processed_plain_text, flags=re.DOTALL) + else: + filtered_processed_plain_text = "" + + detailed_plain_text = message.detailed_plain_text + if detailed_plain_text: + filtered_detailed_plain_text = re.sub(pattern, "", detailed_plain_text, flags=re.DOTALL) + else: + filtered_detailed_plain_text = "" + message_data = { "message_id": message.message_info.message_id, "time": message.message_info.time, "chat_id": chat_stream.stream_id, "chat_info": chat_stream.to_dict(), "user_info": message.message_info.user_info.to_dict(), - "processed_plain_text": message.processed_plain_text, - "detailed_plain_text": message.detailed_plain_text, + # 使用过滤后的文本 + "processed_plain_text": filtered_processed_plain_text, + "detailed_plain_text": filtered_detailed_plain_text, "memorized_times": message.memorized_times, } db.messages.insert_one(message_data)