主动思考定时任务优化,目前有个问题at动作会认为当建环境环是群聊,我多次尝试解决不了……唉
This commit is contained in:
@@ -11,3 +11,4 @@ class ProactiveTriggerEvent:
|
|||||||
source: str # 触发源的标识,例如 "silence_monitor", "insomnia_manager"
|
source: str # 触发源的标识,例如 "silence_monitor", "insomnia_manager"
|
||||||
reason: str # 触发的具体原因,例如 "聊天已沉默10分钟", "深夜emo"
|
reason: str # 触发的具体原因,例如 "聊天已沉默10分钟", "深夜emo"
|
||||||
metadata: Optional[Dict[str, Any]] = field(default_factory=dict) # 可选的元数据,用于传递额外信息
|
metadata: Optional[Dict[str, Any]] = field(default_factory=dict) # 可选的元数据,用于传递额外信息
|
||||||
|
related_message_id: Optional[str] = None # 关联的消息ID,用于加载上下文
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import orjson
|
import orjson
|
||||||
|
import re
|
||||||
from typing import TYPE_CHECKING, Dict, Any
|
from typing import TYPE_CHECKING, Dict, Any
|
||||||
|
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
@@ -15,7 +16,8 @@ from src.plugin_system.base.component_types import ComponentType
|
|||||||
from src.config.config import global_config
|
from src.config.config import global_config
|
||||||
from src.chat.utils.chat_message_builder import get_raw_msg_before_timestamp_with_chat, build_readable_messages_with_id
|
from src.chat.utils.chat_message_builder import get_raw_msg_before_timestamp_with_chat, build_readable_messages_with_id
|
||||||
from src.mood.mood_manager import mood_manager
|
from src.mood.mood_manager import mood_manager
|
||||||
from src.common.database.sqlalchemy_database_api import store_action_info
|
from src.common.database.sqlalchemy_database_api import store_action_info, db_get
|
||||||
|
from src.common.database.sqlalchemy_models import Messages
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..cycle_processor import CycleProcessor
|
from ..cycle_processor import CycleProcessor
|
||||||
@@ -118,57 +120,128 @@ class ProactiveThinker:
|
|||||||
trigger_event (ProactiveTriggerEvent): 触发事件。
|
trigger_event (ProactiveTriggerEvent): 触发事件。
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 调用规划器的 PROACTIVE 模式,让其决定下一步的行动
|
# 如果是提醒事件,跳过规划器,直接构建默认动作
|
||||||
|
if trigger_event.source == "reminder_system":
|
||||||
|
# 1. 获取原始消息上下文
|
||||||
|
action_message = {}
|
||||||
|
if trigger_event.related_message_id:
|
||||||
|
# 直接将从数据库获取的完整消息记录作为 action_message
|
||||||
|
action_message = await db_get(
|
||||||
|
Messages, {"message_id": trigger_event.related_message_id}, single_result=True
|
||||||
|
) or {}
|
||||||
|
|
||||||
|
# 2. 智能确定@对象
|
||||||
|
reason_text = trigger_event.reason.replace("定时提醒:", "").strip()
|
||||||
|
user_name_match = re.search(r"艾特一下(\S+)", reason_text)
|
||||||
|
|
||||||
|
if user_name_match:
|
||||||
|
user_name = user_name_match.group(1)
|
||||||
|
at_message = reason_text.replace(f"艾特一下{user_name}", "").strip()
|
||||||
|
elif action_message.get("user_nickname"):
|
||||||
|
user_name = action_message.get("user_nickname")
|
||||||
|
at_message = reason_text
|
||||||
|
else:
|
||||||
|
user_name = "我"
|
||||||
|
at_message = reason_text
|
||||||
|
|
||||||
|
# 3. 构建动作
|
||||||
|
action_result = {
|
||||||
|
"action_type": "at_user",
|
||||||
|
"reasoning": "执行定时提醒",
|
||||||
|
"action_data": {
|
||||||
|
"user_name": user_name,
|
||||||
|
"at_message": at_message or "时间到啦!"
|
||||||
|
},
|
||||||
|
"action_message": action_message
|
||||||
|
}
|
||||||
|
|
||||||
|
# 4. 执行或回退
|
||||||
|
try:
|
||||||
|
success, _, _ = await self.cycle_processor._handle_action(
|
||||||
|
action=action_result["action_type"],
|
||||||
|
reasoning=action_result["reasoning"],
|
||||||
|
action_data=action_result["action_data"],
|
||||||
|
cycle_timers={},
|
||||||
|
thinking_id="",
|
||||||
|
action_message=action_result["action_message"]
|
||||||
|
)
|
||||||
|
if not success:
|
||||||
|
raise Exception("at_user action failed")
|
||||||
|
except Exception:
|
||||||
|
logger.warning(f"{self.context.log_prefix} at_user动作执行失败,回退到proactive_reply")
|
||||||
|
fallback_action = {
|
||||||
|
"action_type": "proactive_reply",
|
||||||
|
"action_data": {"topic": trigger_event.reason},
|
||||||
|
"action_message": action_message
|
||||||
|
}
|
||||||
|
await self._generate_proactive_content_and_send(fallback_action, trigger_event)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# 对于其他来源的主动思考,正常调用规划器
|
||||||
actions, _ = await self.cycle_processor.action_planner.plan(mode=ChatMode.PROACTIVE)
|
actions, _ = await self.cycle_processor.action_planner.plan(mode=ChatMode.PROACTIVE)
|
||||||
|
|
||||||
# 通常只关心规划出的第一个动作
|
|
||||||
action_result = actions[0] if actions else {}
|
action_result = actions[0] if actions else {}
|
||||||
|
|
||||||
action_type = action_result.get("action_type")
|
action_type = action_result.get("action_type")
|
||||||
|
|
||||||
if action_type == "proactive_reply":
|
if action_type == "proactive_reply":
|
||||||
await self._generate_proactive_content_and_send(action_result)
|
await self._generate_proactive_content_and_send(action_result, trigger_event)
|
||||||
elif action_type != "do_nothing":
|
elif action_type not in ["do_nothing", "no_action"]:
|
||||||
logger.warning(f"{self.context.log_prefix} 主动思考返回了未知的动作类型: {action_type}")
|
await self.cycle_processor._handle_action(
|
||||||
|
action=action_result["action_type"],
|
||||||
|
reasoning=action_result.get("reasoning", ""),
|
||||||
|
action_data=action_result.get("action_data", {}),
|
||||||
|
cycle_timers={},
|
||||||
|
thinking_id="",
|
||||||
|
action_message=action_result.get("action_message")
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# 如果规划结果是“什么都不做”,则记录日志
|
|
||||||
logger.info(f"{self.context.log_prefix} 主动思考决策: 保持沉默")
|
logger.info(f"{self.context.log_prefix} 主动思考决策: 保持沉默")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{self.context.log_prefix} 主动思考执行异常: {e}")
|
logger.error(f"{self.context.log_prefix} 主动思考执行异常: {e}")
|
||||||
logger.error(traceback.format_exc())
|
logger.error(traceback.format_exc())
|
||||||
|
|
||||||
async def _generate_proactive_content_and_send(self, action_result: Dict[str, Any]):
|
async def _get_reminder_context(self, message_id: str) -> str:
|
||||||
|
"""获取提醒消息的上下文"""
|
||||||
|
try:
|
||||||
|
# 只获取那一条消息
|
||||||
|
message_record = await db_get(Messages, {"message_id": message_id}, single_result=True)
|
||||||
|
if message_record:
|
||||||
|
# 使用 build_readable_messages_with_id 来格式化单条消息
|
||||||
|
chat_context_block, _ = build_readable_messages_with_id(messages=[message_record])
|
||||||
|
return chat_context_block
|
||||||
|
return "无法加载相关的聊天记录。"
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{self.context.log_prefix} 获取提醒上下文失败: {e}")
|
||||||
|
return "无法加载相关的聊天记录。"
|
||||||
|
|
||||||
|
async def _generate_proactive_content_and_send(self, action_result: Dict[str, Any], trigger_event: ProactiveTriggerEvent):
|
||||||
"""
|
"""
|
||||||
获取实时信息,构建最终的生成提示词,并生成和发送主动回复。
|
获取实时信息,构建最终的生成提示词,并生成和发送主动回复。
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
action_result (Dict[str, Any]): 规划器返回的动作结果。
|
action_result (Dict[str, Any]): 规划器返回的动作结果。
|
||||||
|
trigger_event (ProactiveTriggerEvent): 触发事件。
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
topic = action_result.get("action_data", {}).get("topic", "随便聊聊")
|
topic = action_result.get("action_data", {}).get("topic", "随便聊聊")
|
||||||
logger.info(f"{self.context.log_prefix} 主动思考确定主题: '{topic}'")
|
logger.info(f"{self.context.log_prefix} 主动思考确定主题: '{topic}'")
|
||||||
|
|
||||||
# 1. 获取日程信息
|
|
||||||
schedule_block = "你今天没有日程安排。"
|
schedule_block = "你今天没有日程安排。"
|
||||||
if global_config.planning_system.schedule_enable:
|
if global_config.planning_system.schedule_enable:
|
||||||
if current_activity := schedule_manager.get_current_activity():
|
if current_activity := schedule_manager.get_current_activity():
|
||||||
schedule_block = f"你当前正在:{current_activity}。"
|
schedule_block = f"你当前正在:{current_activity}。"
|
||||||
|
|
||||||
# 2. 网络搜索
|
|
||||||
news_block = "暂时没有获取到最新资讯。"
|
news_block = "暂时没有获取到最新资讯。"
|
||||||
|
if trigger_event.source != "reminder_system":
|
||||||
try:
|
try:
|
||||||
web_search_tool = tool_api.get_tool_instance("web_search")
|
web_search_tool = tool_api.get_tool_instance("web_search")
|
||||||
if web_search_tool:
|
if web_search_tool:
|
||||||
# 检查工具的execute方法签名,使用正确的参数名
|
|
||||||
try:
|
try:
|
||||||
search_result_dict = await web_search_tool.execute(search_query=topic, max_results=10)
|
search_result_dict = await web_search_tool.execute(search_query=topic, max_results=10)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# 如果search_query不工作,尝试其他可能的参数名
|
|
||||||
try:
|
try:
|
||||||
search_result_dict = await web_search_tool.execute(keyword=topic, max_results=10)
|
search_result_dict = await web_search_tool.execute(keyword=topic, max_results=10)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# 跳过网络搜索,避免影响主动思考
|
|
||||||
logger.warning(f"{self.context.log_prefix} 网络搜索工具参数不匹配,跳过搜索")
|
logger.warning(f"{self.context.log_prefix} 网络搜索工具参数不匹配,跳过搜索")
|
||||||
news_block = "跳过网络搜索。"
|
news_block = "跳过网络搜索。"
|
||||||
search_result_dict = None
|
search_result_dict = None
|
||||||
@@ -182,7 +255,9 @@ class ProactiveThinker:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{self.context.log_prefix} 主动思考时网络搜索失败: {e}")
|
logger.error(f"{self.context.log_prefix} 主动思考时网络搜索失败: {e}")
|
||||||
|
|
||||||
# 3. 获取最新的聊天上下文
|
if trigger_event.source == "reminder_system" and trigger_event.related_message_id:
|
||||||
|
chat_context_block = await self._get_reminder_context(trigger_event.related_message_id)
|
||||||
|
else:
|
||||||
message_list = get_raw_msg_before_timestamp_with_chat(
|
message_list = get_raw_msg_before_timestamp_with_chat(
|
||||||
chat_id=self.context.stream_id,
|
chat_id=self.context.stream_id,
|
||||||
timestamp=time.time(),
|
timestamp=time.time(),
|
||||||
@@ -190,13 +265,11 @@ class ProactiveThinker:
|
|||||||
)
|
)
|
||||||
chat_context_block, _ = build_readable_messages_with_id(messages=message_list)
|
chat_context_block, _ = build_readable_messages_with_id(messages=message_list)
|
||||||
|
|
||||||
# 4. 使用决策模型进行二次确认(节省珍贵的回复模型调用)
|
|
||||||
from src.llm_models.utils_model import LLMRequest
|
from src.llm_models.utils_model import LLMRequest
|
||||||
from src.config.config import model_config
|
from src.config.config import model_config
|
||||||
|
|
||||||
bot_name = global_config.bot.nickname
|
bot_name = global_config.bot.nickname
|
||||||
|
|
||||||
# 构建二次确认提示词
|
|
||||||
confirmation_prompt = f"""# 主动回复二次确认
|
confirmation_prompt = f"""# 主动回复二次确认
|
||||||
|
|
||||||
## 基本信息
|
## 基本信息
|
||||||
@@ -219,7 +292,6 @@ class ProactiveThinker:
|
|||||||
|
|
||||||
请严格按照上述格式输出,不要添加任何解释。"""
|
请严格按照上述格式输出,不要添加任何解释。"""
|
||||||
|
|
||||||
# 使用决策模型进行二次确认
|
|
||||||
planner_llm = LLMRequest(
|
planner_llm = LLMRequest(
|
||||||
model_set=model_config.model_task_config.planner,
|
model_set=model_config.model_task_config.planner,
|
||||||
request_type="planner"
|
request_type="planner"
|
||||||
@@ -227,12 +299,10 @@ class ProactiveThinker:
|
|||||||
|
|
||||||
confirmation_result, _ = await planner_llm.generate_response_async(prompt=confirmation_prompt)
|
confirmation_result, _ = await planner_llm.generate_response_async(prompt=confirmation_prompt)
|
||||||
|
|
||||||
# 检查二次确认结果
|
|
||||||
if not confirmation_result or "SKIP_PROACTIVE_REPLY" in confirmation_result:
|
if not confirmation_result or "SKIP_PROACTIVE_REPLY" in confirmation_result:
|
||||||
logger.info(f"{self.context.log_prefix} 决策模型二次确认决定跳过主动回复")
|
logger.info(f"{self.context.log_prefix} 决策模型二次确认决定跳过主动回复")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 5. 只有通过二次确认才调用珍贵的回复模型
|
|
||||||
bot_name = global_config.bot.nickname
|
bot_name = global_config.bot.nickname
|
||||||
personality = global_config.personality
|
personality = global_config.personality
|
||||||
identity_block = (
|
identity_block = (
|
||||||
|
|||||||
@@ -199,7 +199,8 @@ class HeartFCMessageReceiver:
|
|||||||
"chat_id": chat.stream_id,
|
"chat_id": chat.stream_id,
|
||||||
"content": reminder_event.content,
|
"content": reminder_event.content,
|
||||||
"confidence": reminder_event.confidence,
|
"confidence": reminder_event.confidence,
|
||||||
"created_at": datetime.now().isoformat()
|
"created_at": datetime.now().isoformat(),
|
||||||
|
"original_message_id": message.message_info.message_id
|
||||||
}
|
}
|
||||||
|
|
||||||
success = await event_scheduler.schedule_event(
|
success = await event_scheduler.schedule_event(
|
||||||
|
|||||||
@@ -484,6 +484,7 @@ class ActionPlanner:
|
|||||||
mode: ChatMode = ChatMode.FOCUS,
|
mode: ChatMode = ChatMode.FOCUS,
|
||||||
loop_start_time: float = 0.0,
|
loop_start_time: float = 0.0,
|
||||||
available_actions: Optional[Dict[str, ActionInfo]] = None,
|
available_actions: Optional[Dict[str, ActionInfo]] = None,
|
||||||
|
pseudo_message: Optional[str] = None,
|
||||||
) -> Tuple[List[Dict[str, Any]], Optional[Dict[str, Any]]]:
|
) -> Tuple[List[Dict[str, Any]], Optional[Dict[str, Any]]]:
|
||||||
"""
|
"""
|
||||||
[注释] "大脑"规划器。
|
[注释] "大脑"规划器。
|
||||||
@@ -513,6 +514,8 @@ class ActionPlanner:
|
|||||||
truncate=False,
|
truncate=False,
|
||||||
show_actions=False,
|
show_actions=False,
|
||||||
)
|
)
|
||||||
|
if pseudo_message:
|
||||||
|
chat_content_block_short += f"\n[m99] 刚刚, 用户: {pseudo_message}"
|
||||||
self.last_obs_time_mark = time.time()
|
self.last_obs_time_mark = time.time()
|
||||||
|
|
||||||
is_group_chat, chat_target_info, current_available_actions = self.get_necessary_info()
|
is_group_chat, chat_target_info, current_available_actions = self.get_necessary_info()
|
||||||
@@ -522,8 +525,8 @@ class ActionPlanner:
|
|||||||
# --- 2. 启动小脑并行思考 ---
|
# --- 2. 启动小脑并行思考 ---
|
||||||
all_sub_planner_results: List[Dict[str, Any]] = []
|
all_sub_planner_results: List[Dict[str, Any]] = []
|
||||||
|
|
||||||
# PROACTIVE模式下禁用小脑,避免与大脑的主动思考决策冲突
|
# PROACTIVE模式下,只有在有伪消息(来自提醒)时才激活小脑
|
||||||
if mode != ChatMode.PROACTIVE:
|
if mode != ChatMode.PROACTIVE or pseudo_message:
|
||||||
try:
|
try:
|
||||||
sub_planner_actions: Dict[str, ActionInfo] = {}
|
sub_planner_actions: Dict[str, ActionInfo] = {}
|
||||||
for action_name, action_info in available_actions.items():
|
for action_name, action_info in available_actions.items():
|
||||||
@@ -607,6 +610,11 @@ class ActionPlanner:
|
|||||||
action, reasoning = "no_reply", f"大脑处理错误: {e}"
|
action, reasoning = "no_reply", f"大脑处理错误: {e}"
|
||||||
|
|
||||||
# --- 4. 整合大脑和小脑的决策 ---
|
# --- 4. 整合大脑和小脑的决策 ---
|
||||||
|
# 特殊规则:如果是提醒任务,且大脑决定do_nothing,则忽略大脑,采用小脑的决策
|
||||||
|
if mode == ChatMode.PROACTIVE and pseudo_message and action == "do_nothing":
|
||||||
|
logger.info(f"{self.log_prefix}提醒任务触发,大脑决策为do_nothing,忽略大脑并采用小脑决策")
|
||||||
|
final_actions = all_sub_planner_results
|
||||||
|
else:
|
||||||
# 如果是私聊且开启了强制回复,则将no_reply强制改为reply
|
# 如果是私聊且开启了强制回复,则将no_reply强制改为reply
|
||||||
if not is_group_chat and global_config.chat.force_reply_private and action == "no_reply":
|
if not is_group_chat and global_config.chat.force_reply_private and action == "no_reply":
|
||||||
action = "reply"
|
action = "reply"
|
||||||
|
|||||||
Reference in New Issue
Block a user