From 118f82b1e363faee1e9e7b1268a7f5871ebfc943 Mon Sep 17 00:00:00 2001 From: minecraft1024a Date: Sun, 5 Oct 2025 18:25:06 +0800 Subject: [PATCH 1/5] =?UTF-8?q?refactor(proactive=5Fthinker):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=B8=BB=E5=8A=A8=E6=80=9D=E8=80=83=E7=9A=84=E5=86=B7?= =?UTF-8?q?=E5=8D=B4=E5=88=A4=E6=96=AD=E5=92=8C=E4=B8=8A=E4=B8=8B=E6=96=87?= =?UTF-8?q?=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 主动思考插件的冷却时间判断逻辑已从依赖 `stream.last_active_time` 切换为获取最新的消息时间。这使得冷却判断更加准确,避免了因流未及时更新而导致的不准确。 同时,优化了上下文获取逻辑: - 获取最近聊天记录时,增加了12小时的时间限制。 - 获取历史主动决策记录时,改为获取过去24小时内的动作记录,以提供更相关的上下文。 --- .../proactive_thinker/proacive_thinker_event.py | 10 +++++++--- .../proactive_thinker_executor.py | 15 +++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/plugins/built_in/proactive_thinker/proacive_thinker_event.py b/src/plugins/built_in/proactive_thinker/proacive_thinker_event.py index 1899361c4..f7e1fb2d7 100644 --- a/src/plugins/built_in/proactive_thinker/proacive_thinker_event.py +++ b/src/plugins/built_in/proactive_thinker/proacive_thinker_event.py @@ -11,7 +11,7 @@ from src.common.logger import get_logger from src.config.config import global_config from src.manager.async_task_manager import AsyncTask, async_task_manager from src.plugin_system import BaseEventHandler, EventType -from src.plugin_system.apis import chat_api, person_api +from src.plugin_system.apis import chat_api, message_api, person_api from src.plugin_system.base.base_event import HandlerResult from .proactive_thinker_executor import ProactiveThinkerExecutor @@ -160,7 +160,9 @@ class ProactiveThinkingTask(AsyncTask): continue # 检查冷却时间 - time_since_last_active = time.time() - stream.last_active_time + recent_messages = await message_api.get_recent_messages(chat_id=stream.stream_id, limit=1,limit_mode="latest") + last_message_time = recent_messages[0]["time"] if recent_messages else stream.create_time + time_since_last_active = time.time() - last_message_time if time_since_last_active > next_interval: logger.info( f"【日常唤醒-私聊】聊天流 {stream.stream_id} 已冷却 {time_since_last_active:.2f} 秒,触发主动对话。" @@ -184,7 +186,9 @@ class ProactiveThinkingTask(AsyncTask): # 检查群聊是否在白名单内 if not enabled_groups or f"qq:{stream.group_info.group_id}" in enabled_groups: # 检查冷却时间 - time_since_last_active = time.time() - stream.last_active_time + recent_messages = await message_api.get_recent_messages(chat_id=stream.stream_id, limit=1) + last_message_time = recent_messages[0]["time"] if recent_messages else stream.create_time + time_since_last_active = time.time() - last_message_time if time_since_last_active > next_interval: logger.info( f"【日常唤醒-群聊】聊天流 {stream.stream_id} 已冷却 {time_since_last_active:.2f} 秒,触发主动对话。" diff --git a/src/plugins/built_in/proactive_thinker/proactive_thinker_executor.py b/src/plugins/built_in/proactive_thinker/proactive_thinker_executor.py index e651ecfd5..692b6e106 100644 --- a/src/plugins/built_in/proactive_thinker/proactive_thinker_executor.py +++ b/src/plugins/built_in/proactive_thinker/proactive_thinker_executor.py @@ -1,8 +1,10 @@ +import time from datetime import datetime from typing import Any import orjson +from src.chat.utils.chat_message_builder import get_actions_by_timestamp_with_chat from src.common.logger import get_logger from src.config.config import global_config, model_config from src.mood.mood_manager import mood_manager @@ -140,17 +142,18 @@ class ProactiveThinkerExecutor: else "今天没有日程安排。" ) - recent_messages = await message_api.get_recent_messages(stream.stream_id) + recent_messages = await message_api.get_recent_messages(stream.stream_id,limit=50,limit_mode="latest",hours=12) recent_chat_history = ( await message_api.build_readable_messages_to_str(recent_messages) if recent_messages else "无" ) - action_history_list = await database_api.db_query( - database_api.MODEL_MAPPING["ActionRecords"], - filters={"chat_id": stream_id, "action_name": "proactive_decision"}, - limit=3, - order_by=["-time"], + action_history_list = await get_actions_by_timestamp_with_chat( + chat_id=stream.stream_id, + timestamp_start=time.time() - 3600 * 24, #过去24小时 + timestamp_end=time.time(), + limit=7, ) + action_history_context = ( "\n".join([f"- {a['action_data']}" for a in action_history_list if isinstance(a, dict)]) if isinstance(action_history_list, list) From 3e37b7cef57b9694997dd025198752fcf71ab93f Mon Sep 17 00:00:00 2001 From: Windpicker-owo <3431391539@qq.com> Date: Sun, 5 Oct 2025 18:30:16 +0800 Subject: [PATCH 2/5] =?UTF-8?q?refactor(chat):=20=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E5=BC=82=E6=AD=A5=E8=B0=83=E7=94=A8=E6=A8=A1=E5=BC=8F=E5=B9=B6?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BE=AA=E7=8E=AF=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 chat_manager.get_stream() 调用改为异步 - 将 replyer_manager.get_replyer() 方法改为异步 - 在 generator_api 中使用动态导入避免循环依赖 - 在 action_manager 中添加待处理动作队列清理 - 更新所有相关调用点以支持异步模式 --- src/chat/memory_system/memory_system.py | 2 +- src/chat/planner_actions/action_manager.py | 1 + src/chat/replyer/replyer_manager.py | 4 ++-- src/chat/utils/prompt.py | 2 +- src/plugin_system/apis/generator_api.py | 21 +++++++++++-------- .../affinity_flow_chatter/plan_executor.py | 2 +- 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/chat/memory_system/memory_system.py b/src/chat/memory_system/memory_system.py index e1494a83e..e2fd710e8 100644 --- a/src/chat/memory_system/memory_system.py +++ b/src/chat/memory_system/memory_system.py @@ -1111,7 +1111,7 @@ class MemorySystem: from src.chat.message_receive.chat_stream import get_chat_manager chat_manager = get_chat_manager() - chat_stream = chat_manager.get_stream(stream_id) + chat_stream = await chat_manager.get_stream(stream_id) if chat_stream and hasattr(chat_stream, "context_manager"): history_limit = self._determine_history_limit(context) messages = chat_stream.context_manager.get_messages(limit=history_limit, include_unread=True) diff --git a/src/chat/planner_actions/action_manager.py b/src/chat/planner_actions/action_manager.py index 054acce63..13eebb548 100644 --- a/src/chat/planner_actions/action_manager.py +++ b/src/chat/planner_actions/action_manager.py @@ -615,6 +615,7 @@ class ChatterActionManager: """禁用批量存储模式""" self._batch_storage_enabled = False self._current_chat_id = None + self._pending_actions = [] # 清空队列 logger.debug("已禁用批量存储模式") def add_action_to_batch(self, action_name: str, action_data: dict, thinking_id: str = "", diff --git a/src/chat/replyer/replyer_manager.py b/src/chat/replyer/replyer_manager.py index 55a422c1b..4f3f4f428 100644 --- a/src/chat/replyer/replyer_manager.py +++ b/src/chat/replyer/replyer_manager.py @@ -9,7 +9,7 @@ class ReplyerManager: def __init__(self): self._repliers: dict[str, DefaultReplyer] = {} - def get_replyer( + async def get_replyer( self, chat_stream: ChatStream | None = None, chat_id: str | None = None, @@ -37,7 +37,7 @@ class ReplyerManager: target_stream = chat_stream if not target_stream: if chat_manager := get_chat_manager(): - target_stream = chat_manager.get_stream(stream_id) + target_stream = await chat_manager.get_stream(stream_id) if not target_stream: logger.warning(f"[ReplyerManager] 未找到 stream_id='{stream_id}' 的聊天流,无法创建回复器。") diff --git a/src/chat/utils/prompt.py b/src/chat/utils/prompt.py index dddbd7692..9f24d6e29 100644 --- a/src/chat/utils/prompt.py +++ b/src/chat/utils/prompt.py @@ -490,7 +490,7 @@ class Prompt: from src.plugin_system.apis.generator_api import get_replyer # 创建临时生成器实例来使用其方法 - temp_generator = get_replyer(None, chat_id, request_type="prompt_building") + temp_generator = await get_replyer(None, chat_id, request_type="prompt_building") return await temp_generator.build_s4u_chat_history_prompts( message_list_before_now, target_user_id, sender, chat_id ) diff --git a/src/plugin_system/apis/generator_api.py b/src/plugin_system/apis/generator_api.py index 21bc6fdde..05f388c2a 100644 --- a/src/plugin_system/apis/generator_api.py +++ b/src/plugin_system/apis/generator_api.py @@ -9,17 +9,18 @@ """ import traceback -from typing import Any +from typing import TYPE_CHECKING, Any from rich.traceback import install from src.chat.message_receive.chat_stream import ChatStream -from src.chat.replyer.default_generator import DefaultReplyer -from src.chat.replyer.replyer_manager import replyer_manager from src.chat.utils.utils import process_llm_response from src.common.logger import get_logger from src.plugin_system.base.component_types import ActionInfo +if TYPE_CHECKING: + from src.chat.replyer.default_generator import DefaultReplyer + install(extra_lines=3) # 日志记录器 @@ -31,11 +32,11 @@ logger = get_logger("generator_api") # ============================================================================= -def get_replyer( +async def get_replyer( chat_stream: ChatStream | None = None, chat_id: str | None = None, request_type: str = "replyer", -) -> DefaultReplyer | None: +) -> Any | None: """获取回复器对象 优先使用chat_stream,如果没有则使用chat_id直接查找。 @@ -56,7 +57,9 @@ def get_replyer( raise ValueError("chat_stream 和 chat_id 不可均为空") try: logger.debug(f"[GeneratorAPI] 正在获取回复器,chat_id: {chat_id}, chat_stream: {'有' if chat_stream else '无'}") - return replyer_manager.get_replyer( + # 动态导入避免循环依赖 + from src.chat.replyer.replyer_manager import replyer_manager + return await replyer_manager.get_replyer( chat_stream=chat_stream, chat_id=chat_id, request_type=request_type, @@ -110,7 +113,7 @@ async def generate_reply( """ try: # 获取回复器 - replyer = get_replyer(chat_stream, chat_id, request_type=request_type) + replyer = await get_replyer(chat_stream, chat_id, request_type=request_type) if not replyer: logger.error("[GeneratorAPI] 无法获取回复器") return False, [], None @@ -199,7 +202,7 @@ async def rewrite_reply( """ try: # 获取回复器 - replyer = get_replyer(chat_stream, chat_id, request_type=request_type) + replyer = await get_replyer(chat_stream, chat_id, request_type=request_type) if not replyer: logger.error("[GeneratorAPI] 无法获取回复器") return False, [], None @@ -285,7 +288,7 @@ async def generate_response_custom( Returns: Optional[str]: 生成的回复内容 """ - replyer = get_replyer(chat_stream, chat_id, request_type=request_type) + replyer = await get_replyer(chat_stream, chat_id, request_type=request_type) if not replyer: logger.error("[GeneratorAPI] 无法获取回复器") return None diff --git a/src/plugins/built_in/affinity_flow_chatter/plan_executor.py b/src/plugins/built_in/affinity_flow_chatter/plan_executor.py index 10d44b1a8..91ea6ccc7 100644 --- a/src/plugins/built_in/affinity_flow_chatter/plan_executor.py +++ b/src/plugins/built_in/affinity_flow_chatter/plan_executor.py @@ -441,7 +441,7 @@ class ChatterPlanExecutor: # 通过 chat_id 获取真实的 chat_stream 对象 from src.plugin_system.apis.chat_api import get_chat_manager chat_manager = get_chat_manager() - chat_stream = chat_manager.get_stream(plan.chat_id) + chat_stream = await chat_manager.get_stream(plan.chat_id) if chat_stream: # 调用 action_manager 的批量存储 From 1ce933c93b3fbcf27b3d62a84f509fa8cbb4d63a Mon Sep 17 00:00:00 2001 From: minecraft1024a Date: Sun, 5 Oct 2025 18:53:01 +0800 Subject: [PATCH 3/5] =?UTF-8?q?refactor(proactive=5Fthinker):=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E5=B7=A5=E5=85=B7=E5=87=BD=E6=95=B0=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E5=8F=AF=E8=AF=BB=E7=9A=84=E5=8A=A8=E4=BD=9C=E5=8E=86=E5=8F=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 `proactive_thinker_executor` 中手动拼接动作历史字符串的逻辑,替换为调用 `chat_message_builder` 中新增的 `build_readable_actions` 工具函数。 这提高了代码的可读性和可维护性,将格式化逻辑集中到一处。 --- .../proactive_thinker/proactive_thinker_executor.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/plugins/built_in/proactive_thinker/proactive_thinker_executor.py b/src/plugins/built_in/proactive_thinker/proactive_thinker_executor.py index 692b6e106..d9fb6d2a2 100644 --- a/src/plugins/built_in/proactive_thinker/proactive_thinker_executor.py +++ b/src/plugins/built_in/proactive_thinker/proactive_thinker_executor.py @@ -4,7 +4,7 @@ from typing import Any import orjson -from src.chat.utils.chat_message_builder import get_actions_by_timestamp_with_chat +from src.chat.utils.chat_message_builder import build_readable_actions, get_actions_by_timestamp_with_chat from src.common.logger import get_logger from src.config.config import global_config, model_config from src.mood.mood_manager import mood_manager @@ -154,11 +154,7 @@ class ProactiveThinkerExecutor: limit=7, ) - action_history_context = ( - "\n".join([f"- {a['action_data']}" for a in action_history_list if isinstance(a, dict)]) - if isinstance(action_history_list, list) - else "无" - ) + action_history_context = build_readable_actions(actions=action_history_list) # 2. 构建基础上下文 mood_state = "暂时没有" From 9fee56984860dd715697ec288c9562d07897dc2b Mon Sep 17 00:00:00 2001 From: tt-P607 <68868379+tt-P607@users.noreply.github.com> Date: Sun, 5 Oct 2025 18:57:08 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E6=98=AF=E8=B0=81=E8=BF=9E=E7=BB=AD?= =?UTF-8?q?=E5=86=99=E4=BA=86=E4=B8=A4=E9=81=8D=20async=20def=20get=5Frepl?= =?UTF-8?q?yer(=EF=BC=8C=E6=88=91=E4=B8=8D=E8=AF=B4=F0=9F=A4=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugin_system/apis/generator_api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugin_system/apis/generator_api.py b/src/plugin_system/apis/generator_api.py index 458ab1572..803a2d739 100644 --- a/src/plugin_system/apis/generator_api.py +++ b/src/plugin_system/apis/generator_api.py @@ -32,7 +32,6 @@ logger = get_logger("generator_api") # ============================================================================= -async def get_replyer( async def get_replyer( chat_stream: ChatStream | None = None, chat_id: str | None = None, From 43524f92c7a71d82c4eb44e542d980d34df0ab3b Mon Sep 17 00:00:00 2001 From: Windpicker-owo <3431391539@qq.com> Date: Sun, 5 Oct 2025 19:20:21 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix(replyer=5Fmanager):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20get=5Freplyer=20=E6=96=B9=E6=B3=95=E7=9A=84?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/replyer/replyer_manager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/chat/replyer/replyer_manager.py b/src/chat/replyer/replyer_manager.py index e1aef6a4f..4f3f4f428 100644 --- a/src/chat/replyer/replyer_manager.py +++ b/src/chat/replyer/replyer_manager.py @@ -9,7 +9,6 @@ class ReplyerManager: def __init__(self): self._repliers: dict[str, DefaultReplyer] = {} - async def get_replyer( async def get_replyer( self, chat_stream: ChatStream | None = None,