feat(proactive_thinking): 重构主动思考为由Planner直接决策
重构了主动思考的触发和决策流程。原有的通过生成特定prompt来启动思考循环的方式被移除,改为直接调用Planner的`PROACTIVE`模式。 - **Planner增强**: - 新增`PROACTIVE`聊天模式,用于处理主动思考场景。 - 为`PROACTIVE`模式设计了专用的prompt模板,整合了长期记忆、当前状态等信息。 - 引入`do_nothing`动作,允许Planner在分析后决定保持沉默。 - 增加从海马体(长期记忆)获取上下文的功能,为决策提供更丰富的背景。 - **ProactiveThinker简化**: - 移除了原有的prompt生成和调用`observe`的逻辑。 - 现在直接调用`action_planner.plan(mode=ChatMode.PROACTIVE)`来获取决策。 - 根据Planner返回的动作(如`do_nothing`或具体行动),决定是保持沉默还是执行计划。 - **CycleProcessor & Tracker调整**: - `CycleProcessor`新增`execute_plan`方法,用于执行一个已经由Planner预先制定好的计划。 - `CycleTracker`能够区分并标记由主动思考发起的循环(例如,cycle_id为 "1.p"),以便于追踪和分析。
This commit is contained in:
@@ -130,6 +130,34 @@ class CycleProcessor:
|
||||
|
||||
return True
|
||||
|
||||
async def execute_plan(self, action_result: Dict[str, Any], target_message: Optional[Dict[str, Any]]):
|
||||
"""
|
||||
执行一个已经制定好的计划
|
||||
"""
|
||||
action_type = action_result.get("action_type", "error")
|
||||
|
||||
# 这里我们需要为执行计划创建一个新的循环追踪
|
||||
cycle_timers, thinking_id = self.cycle_tracker.start_cycle(is_proactive=True)
|
||||
loop_start_time = time.time()
|
||||
|
||||
if action_type == "reply":
|
||||
# 主动思考不应该直接触发简单回复,但为了逻辑完整性,我们假设它会调用response_handler
|
||||
# 注意:这里的 available_actions 和 plan_result 是缺失的,需要根据实际情况处理
|
||||
await self._handle_reply_action(target_message, {}, None, loop_start_time, cycle_timers, thinking_id, {"action_result": action_result})
|
||||
else:
|
||||
await self._handle_other_actions(
|
||||
action_type,
|
||||
action_result.get("reasoning", ""),
|
||||
action_result.get("action_data", {}),
|
||||
action_result.get("is_parallel", False),
|
||||
None,
|
||||
target_message,
|
||||
cycle_timers,
|
||||
thinking_id,
|
||||
{"action_result": action_result},
|
||||
loop_start_time
|
||||
)
|
||||
|
||||
async def _handle_reply_action(self, message_data, available_actions, gen_task, loop_start_time, cycle_timers, thinking_id, plan_result):
|
||||
"""
|
||||
处理回复类型的动作
|
||||
|
||||
@@ -21,10 +21,13 @@ class CycleTracker:
|
||||
"""
|
||||
self.context = context
|
||||
|
||||
def start_cycle(self) -> Tuple[Dict[str, float], str]:
|
||||
def start_cycle(self, is_proactive: bool = False) -> Tuple[Dict[str, float], str]:
|
||||
"""
|
||||
开始新的思考循环
|
||||
|
||||
Args:
|
||||
is_proactive: 标记这个循环是否由主动思考发起
|
||||
|
||||
Returns:
|
||||
tuple: (循环计时器字典, 思考ID字符串)
|
||||
|
||||
@@ -34,8 +37,11 @@ class CycleTracker:
|
||||
- 生成唯一的思考ID
|
||||
- 初始化循环计时器
|
||||
"""
|
||||
self.context.cycle_counter += 1
|
||||
self.context.current_cycle_detail = CycleDetail(self.context.cycle_counter)
|
||||
if not is_proactive:
|
||||
self.context.cycle_counter += 1
|
||||
|
||||
cycle_id = self.context.cycle_counter if not is_proactive else f"{self.context.cycle_counter}.p"
|
||||
self.context.current_cycle_detail = CycleDetail(cycle_id)
|
||||
self.context.current_cycle_detail.thinking_id = f"tid{str(round(time.time(), 2))}"
|
||||
cycle_timers = {}
|
||||
return cycle_timers, self.context.current_cycle_detail.thinking_id
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import time
|
||||
from typing import Optional, Dict, Any
|
||||
from typing import Optional, Dict, Any, Union
|
||||
|
||||
from src.config.config import global_config
|
||||
from src.common.logger import get_logger
|
||||
@@ -23,7 +23,7 @@ class CycleDetail:
|
||||
- 提供序列化和转换功能
|
||||
"""
|
||||
|
||||
def __init__(self, cycle_id: int):
|
||||
def __init__(self, cycle_id: Union[int, str]):
|
||||
"""
|
||||
初始化循环详情记录
|
||||
|
||||
|
||||
@@ -245,58 +245,23 @@ class ProactiveThinker:
|
||||
|
||||
Args:
|
||||
silence_duration: 沉默持续时间(秒)
|
||||
|
||||
功能说明:
|
||||
- 格式化沉默时间并记录触发日志
|
||||
- 获取适当的思考提示模板
|
||||
- 创建主动思考类型的消息数据
|
||||
- 调用循环处理器执行思考和可能的回复
|
||||
- 处理执行过程中的异常
|
||||
"""
|
||||
formatted_time = self._format_duration(silence_duration)
|
||||
logger.info(f"{self.context.log_prefix} 触发主动思考,已沉默{formatted_time}")
|
||||
|
||||
try:
|
||||
proactive_prompt = self._get_proactive_prompt(formatted_time)
|
||||
# 直接调用 planner 的 PROACTIVE 模式
|
||||
action_result_tuple, target_message = await self.cycle_processor.action_planner.plan(mode=ChatMode.PROACTIVE)
|
||||
action_result = action_result_tuple.get("action_result")
|
||||
|
||||
thinking_message = {
|
||||
"processed_plain_text": proactive_prompt,
|
||||
"user_id": "system_proactive_thinking",
|
||||
"user_platform": "system",
|
||||
"timestamp": time.time(),
|
||||
"message_type": "proactive_thinking",
|
||||
"user_nickname": "系统主动思考",
|
||||
"chat_info_platform": "system",
|
||||
"message_id": f"proactive_{int(time.time())}",
|
||||
}
|
||||
|
||||
logger.info(f"{self.context.log_prefix} 开始主动思考...")
|
||||
await self.cycle_processor.observe(message_data=thinking_message)
|
||||
logger.info(f"{self.context.log_prefix} 主动思考完成")
|
||||
# 如果决策不是 do_nothing,则执行
|
||||
if action_result and action_result.get("action_type") != "do_nothing":
|
||||
logger.info(f"{self.context.log_prefix} 主动思考决策: {action_result.get('action_type')}, 原因: {action_result.get('reasoning')}")
|
||||
# 将决策结果交给 cycle_processor 的后续流程处理
|
||||
await self.cycle_processor.execute_plan(action_result, target_message)
|
||||
else:
|
||||
logger.info(f"{self.context.log_prefix} 主动思考决策: 保持沉默")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"{self.context.log_prefix} 主动思考执行异常: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
def _get_proactive_prompt(self, formatted_time: str) -> str:
|
||||
"""
|
||||
获取主动思考的提示模板
|
||||
|
||||
Args:
|
||||
formatted_time: 格式化后的沉默时间字符串
|
||||
|
||||
Returns:
|
||||
str: 填充了时间信息的提示模板
|
||||
|
||||
功能说明:
|
||||
- 优先使用自定义的提示模板(如果配置了)
|
||||
- 根据聊天类型(群聊/私聊)选择默认模板
|
||||
- 将格式化的时间信息填入模板
|
||||
- 返回完整的主动思考提示文本
|
||||
"""
|
||||
if hasattr(global_config.chat, 'proactive_thinking_prompt_template') and global_config.chat.proactive_thinking_prompt_template.strip():
|
||||
return global_config.chat.proactive_thinking_prompt_template.format(time=formatted_time)
|
||||
|
||||
chat_type = "group" if self.context.chat_stream and self.context.chat_stream.group_info else "private"
|
||||
prompt_template = self.proactive_thinking_prompts.get(chat_type, self.proactive_thinking_prompts["group"])
|
||||
return prompt_template.format(time=formatted_time)
|
||||
Reference in New Issue
Block a user