From b2eec7d3b1206f811e30b7ef69867e6cdeab444d Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Tue, 30 Sep 2025 01:29:10 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E9=BA=A6?= =?UTF-8?q?=E9=BA=A6=E5=A5=BD=E5=A5=87=E5=92=8Cmessage=5Fapi=E7=9A=84?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/utils/chat_message_builder.py | 10 +++---- src/common/message_repository.py | 3 +- src/curiousity/questions.py | 20 +++++-------- src/memory_system/Memory_chest.py | 36 ++++++++++++++++++----- src/plugin_system/apis/message_api.py | 18 ++++++++---- src/plugins/built_in/MaiCurious/plugin.py | 16 +++++----- 6 files changed, 63 insertions(+), 40 deletions(-) diff --git a/src/chat/utils/chat_message_builder.py b/src/chat/utils/chat_message_builder.py index fbaa9bd5..89c84001 100644 --- a/src/chat/utils/chat_message_builder.py +++ b/src/chat/utils/chat_message_builder.py @@ -124,6 +124,7 @@ def get_raw_msg_by_timestamp_with_chat( # 只有当 limit 为 0 时才应用外部 sort sort_order = [("time", 1)] if limit == 0 else None # 直接将 limit_mode 传递给 find_messages + # print(f"get_raw_msg_by_timestamp_with_chat: {chat_id}, {timestamp_start}, {timestamp_end}, {limit}, {limit_mode}, {filter_bot}, {filter_command}") return find_messages( message_filter=filter_query, sort=sort_order, @@ -681,10 +682,9 @@ def build_readable_messages( filtered_messages = [] for msg in messages: # 获取消息内容 - content = msg.display_message or msg.processed_plain_text or "" - + content = msg.processed_plain_text # 移除表情包 - emoji_pattern = r"\[表情包:[^\]]+\]" + emoji_pattern = r"\[表情包:[^\]]+\]" content = re.sub(emoji_pattern, "", content) # 如果移除表情包后内容不为空,则保留消息 @@ -699,10 +699,8 @@ def build_readable_messages( # 创建 MessageAndActionModel 但移除表情包 model = MessageAndActionModel.from_DatabaseMessages(msg) # 移除表情包 - if model.display_message: - model.display_message = re.sub(r"\[表情包:[^\]]+\]", "", model.display_message) if model.processed_plain_text: - model.processed_plain_text = re.sub(r"\[表情包:[^\]]+\]", "", model.processed_plain_text) + model.processed_plain_text = re.sub(r"\[表情包:[^\]]+\]", "", model.processed_plain_text) copy_messages.append(model) else: copy_messages.append(MessageAndActionModel.from_DatabaseMessages(msg)) diff --git a/src/common/message_repository.py b/src/common/message_repository.py index ab2eda32..fb9120ac 100644 --- a/src/common/message_repository.py +++ b/src/common/message_repository.py @@ -81,7 +81,8 @@ def find_messages( query = query.where(Messages.user_id != global_config.bot.qq_account) if filter_command: - query = query.where(not Messages.is_command) + # 使用按位取反构造 Peewee 的 NOT 条件,避免直接与 False 比较 + query = query.where(~Messages.is_command) if limit > 0: if limit_mode == "earliest": diff --git a/src/curiousity/questions.py b/src/curiousity/questions.py index 1a06b57a..324761ad 100644 --- a/src/curiousity/questions.py +++ b/src/curiousity/questions.py @@ -1,6 +1,5 @@ import time import asyncio -from rich.traceback import install from src.common.logger import get_logger from src.common.database.database_model import MemoryConflict from src.chat.utils.chat_message_builder import ( @@ -12,10 +11,6 @@ from src.config.config import model_config, global_config logger = get_logger("conflict_tracker") -logger = get_logger("conflict_tracker") - -install(extra_lines=3) - class QuestionTracker: """ 用于跟踪一个问题在后续聊天中的解答情况 @@ -41,26 +36,25 @@ class QuestionTracker: """ prompt = ( "你是一个严谨的判定器。下面给出聊天记录以及一个问题。\n" - "任务:判断在这段聊天中,该问题是否已经得到明确解答。或从聊天内容中可以整理出答案\n" + "任务:判断在这段聊天中,该问题是否已经得到明确解答。\n" "如果已解答,请只输出:YES: <简短答案>\n" "如果没有,请只输出:NO\n\n" f"问题:{self.question}\n" "聊天记录如下:\n" f"{conversation_text}" ) - - if global_config.debug.show_prompt: logger.info(f"判定提示词: {prompt}") else: logger.debug("已发送判定提示词") - result_text, _ = await self.llm_request.generate_response_async(prompt, temperature=0.2) + result_text, _ = await self.llm_request.generate_response_async(prompt, temperature=0.5) + + logger.info(f"判定结果: {prompt}\n{result_text}") + if not result_text: return False, "" - - logger.info(f"判定提示词: {prompt},问题: {self.question},result: {result_text}") text = result_text.strip() if text.upper().startswith("YES:"): @@ -123,7 +117,7 @@ class ConflictTracker: max_duration = 30 * 60 # 30 分钟 max_messages = 100 # 最多 100 条消息 poll_interval = 2.0 # 秒 - + logger.info(f"开始跟踪问题: {original_question}") while tracker.active: now_ts = time.time() # 终止条件:时长达到上限 @@ -136,7 +130,7 @@ class ConflictTracker: chat_id=tracker.chat_id, timestamp_start=tracker.last_read_time, timestamp_end=now_ts, - limit=0, + limit=30, limit_mode="latest", filter_bot=False, filter_command=True, diff --git a/src/memory_system/Memory_chest.py b/src/memory_system/Memory_chest.py index bfdabbe0..95532608 100644 --- a/src/memory_system/Memory_chest.py +++ b/src/memory_system/Memory_chest.py @@ -98,6 +98,31 @@ class MemoryChest: if chat_id and chat_id in self.running_content_list: current_running_content = self.running_content_list[chat_id]["content"] + # 随机从格式示例列表中选取若干行用于提示 + format_candidates = [ + "[概念] 是 [概念的含义(简短描述,不超过十个字)]", + "[概念] 不是 [对概念的负面含义(简短描述,不超过十个字)]", + "[概念1] 与 [概念2] 是 [概念1和概念2的关联(简短描述,不超过二十个字)]", + "[概念1] 包含 [概念2] 和 [概念3]", + "[概念1] 属于 [概念2]", + "[概念1] 的例子是 [例子1] 和 [例子2]", + "[概念] 的特征是 [特征1]、[特征2]", + "[概念1] 导致 [概念2]", + "[概念1] 需要 [条件1] 和 [条件2]", + "[概念1] 的用途是 [用途1] 和 [用途2]", + "[概念1] 与 [概念2] 的区别是 [区别点]", + "[概念] 的别名是 [别名]", + "[概念1] 包括但不限于 [概念2]、[概念3]", + "[概念] 的反义是 [反义概念]", + "[概念] 的组成有 [部分1]、[部分2]", + "[概念] 出现于 [时间或场景]", + "[概念] 的方法有 [方法1]、[方法2]", + ] + + selected_count = random.randint(5, len(format_candidates)) + selected_lines = random.sample(format_candidates, selected_count) + format_section = "\n".join(selected_lines) + "\n......(不要包含中括号)" + prompt = f""" 以下是你的记忆内容和新的聊天记录,请你将他们整合和修改: 记忆内容: @@ -117,13 +142,8 @@ class MemoryChest: 3.如果有图片,请只关注图片和文本结合的知识和概念性内容 4.记忆为一段纯文本,逻辑清晰,指出概念的含义,并说明关系 -记忆内容的格式,你必须仿照下面的格式,但不一定全部使用: -[概念] 是 [概念的含义(简短描述,不超过十个字)] -[概念] 不是 [对概念的负面含义(简短描述,不超过十个字)] -[概念1] 与 [概念2] 是 [概念1和概念2的关联(简短描述,不超过二十个字)] -[概念1] 包含 [概念2] 和 [概念3] -[概念1] 属于 [概念2] -......(不要包含中括号) + 记忆内容的格式,你必须仿照下面的格式,但不一定全部使用: +{format_section} 请仿照上述格式输出,每个知识点一句话。输出成一段平文本 现在请你输出,不要输出其他内容,注意一定要直白,白话,口语化不要浮夸,修辞。: @@ -136,7 +156,7 @@ class MemoryChest: running_content, (reasoning_content, model_name, tool_calls) = await self.LLMRequest_build.generate_response_async(prompt) - print(f"记忆仓库构建运行内容: {running_content}") + print(f"prompt: {prompt}\n记忆仓库构建运行内容: {running_content}") # 如果有chat_id,更新对应的running_content if chat_id and running_content: diff --git a/src/plugin_system/apis/message_api.py b/src/plugin_system/apis/message_api.py index f4ba0b71..7b3069ae 100644 --- a/src/plugin_system/apis/message_api.py +++ b/src/plugin_system/apis/message_api.py @@ -98,11 +98,19 @@ def get_messages_by_time_in_chat( raise ValueError("chat_id 不能为空") if not isinstance(chat_id, str): raise ValueError("chat_id 必须是字符串类型") - if filter_mai: - return filter_mai_messages( - get_raw_msg_by_timestamp_with_chat(chat_id, start_time, end_time, limit, limit_mode, filter_command) - ) - return get_raw_msg_by_timestamp_with_chat(chat_id, start_time, end_time, limit, limit_mode, filter_command) + # if filter_mai: + # return filter_mai_messages( + # get_raw_msg_by_timestamp_with_chat(chat_id, start_time, end_time, limit, limit_mode, filter_command) + # ) + return get_raw_msg_by_timestamp_with_chat( + chat_id=chat_id, + timestamp_start=start_time, + timestamp_end=end_time, + limit=limit, + limit_mode=limit_mode, + filter_bot=filter_mai, + filter_command=filter_command + ) def get_messages_by_time_in_chat_inclusive( diff --git a/src/plugins/built_in/MaiCurious/plugin.py b/src/plugins/built_in/MaiCurious/plugin.py index f93b6c83..7b902c0c 100644 --- a/src/plugins/built_in/MaiCurious/plugin.py +++ b/src/plugins/built_in/MaiCurious/plugin.py @@ -18,7 +18,7 @@ from src.plugin_system.apis import frequency_api from src.plugin_system.apis import generator_api from src.curiousity.questions import global_conflict_tracker -logger = get_logger("relation_actions") +logger = get_logger("question_actions") @@ -26,16 +26,16 @@ class CuriousAction(BaseAction): """频率调节动作 - 调整聊天发言频率""" activation_type = ActionActivationType.LLM_JUDGE - parallel_action = False + parallel_action = True # 动作基本信息 - action_name = "question" + action_name = "make_question" - action_description = "对现有的存在疑问的信息生成一个问题" + action_description = "提出一个问题,当有人反驳你的观点,或其他人之间有观点冲突时使用" # 动作参数定义 action_parameters = { - "question": "存在疑问的信息,提出一个问题", + "question": "对存在疑问的信息提出一个问题,描述全面,使用陈述句", } # 动作使用场景 @@ -46,6 +46,8 @@ class CuriousAction(BaseAction): f"当聊天记录中的信息存在逻辑上的矛盾时使用", f"当有人反对或否定你提出的信息时使用", f"或当你对现有的信息存在疑问时使用", + f"有人认为你的观点是错误的,请选择question动作", + f"有人与你观点不一致,请选择question动作", ] # 关联类型 @@ -59,10 +61,10 @@ class CuriousAction(BaseAction): # 存储问题到冲突追踪器 if question: await global_conflict_tracker.record_conflict(conflict_content=question, start_following=True,chat_id=self.chat_id) - logger.info(f"已存储问题到冲突追踪器: {len(question)} 字符") + logger.info(f"已存储问题到冲突追踪器: {question}") await self.store_action_info( action_build_into_prompt=True, - action_prompt_display=f"你产生了一个问题,原因:{question},尝试向其他人提问或回忆吧", + action_prompt_display=f"你产生了一个问题:{question},尝试向其他人提问或回忆吧", action_done=True, ) return True, "问题已记录"