mirror of https://github.com/Mai-with-u/MaiBot.git
Implement chat type-aware processing for private and group chats
parent
918aa57b01
commit
6fce7f8dcd
|
|
@ -383,8 +383,21 @@ class HeartFChatting:
|
|||
task_to_name_map = {}
|
||||
processor_time_costs = {} # 新增: 记录每个处理器耗时
|
||||
|
||||
# 获取聊天类型
|
||||
chat_stream = await asyncio.to_thread(chat_manager.get_stream, self.stream_id)
|
||||
is_group_chat = chat_stream.group_info is not None
|
||||
|
||||
# 根据聊天类型选择处理器
|
||||
selected_processors = []
|
||||
for processor in self.processors:
|
||||
processor_name = processor.__class__.log_prefix
|
||||
# 私聊时跳过某些处理器
|
||||
if not is_group_chat and processor_name in ["MindProcessor", "ToolProcessor"]:
|
||||
continue
|
||||
selected_processors.append(processor)
|
||||
|
||||
for processor in selected_processors:
|
||||
processor_name = processor.__class__.log_prefix
|
||||
|
||||
async def run_with_timeout(proc=processor):
|
||||
return await asyncio.wait_for(
|
||||
|
|
@ -465,9 +478,14 @@ class HeartFChatting:
|
|||
|
||||
self.all_observations = observations
|
||||
|
||||
# 获取聊天类型
|
||||
chat_stream = await asyncio.to_thread(chat_manager.get_stream, self.stream_id)
|
||||
is_group_chat = chat_stream.group_info is not None
|
||||
|
||||
with Timer("调整动作", cycle_timers):
|
||||
# 处理特殊的观察
|
||||
await self.action_modifier.modify_actions(observations=observations)
|
||||
if is_group_chat: # 只在群聊中调整动作
|
||||
await self.action_modifier.modify_actions(observations=observations)
|
||||
await self.action_observation.observe()
|
||||
observations.append(self.action_observation)
|
||||
|
||||
|
|
@ -497,59 +515,41 @@ class HeartFChatting:
|
|||
}
|
||||
|
||||
with Timer("规划器", cycle_timers):
|
||||
plan_result = await self.action_planner.plan(all_plan_info, running_memorys)
|
||||
# 私聊时使用简单规划
|
||||
if not is_group_chat:
|
||||
plan_result = await self.action_planner.plan_simple(all_plan_info, running_memorys)
|
||||
else:
|
||||
plan_result = await self.action_planner.plan(all_plan_info, running_memorys)
|
||||
|
||||
loop_plan_info = {
|
||||
"action_result": plan_result.get("action_result", {}),
|
||||
"current_mind": plan_result.get("current_mind", ""),
|
||||
"observed_messages": plan_result.get("observed_messages", ""),
|
||||
}
|
||||
loop_plan_info = {
|
||||
"action_result": plan_result,
|
||||
}
|
||||
|
||||
with Timer("执行动作", cycle_timers):
|
||||
action_type, action_data, reasoning = (
|
||||
plan_result.get("action_result", {}).get("action_type", "error"),
|
||||
plan_result.get("action_result", {}).get("action_data", {}),
|
||||
plan_result.get("action_result", {}).get("reasoning", "未提供理由"),
|
||||
action_taken, action_command, action_reason = await self._handle_action(
|
||||
action=plan_result["action_type"],
|
||||
reasoning=plan_result["reasoning"],
|
||||
action_data=plan_result["action_data"],
|
||||
cycle_timers=cycle_timers,
|
||||
thinking_id=thinking_id,
|
||||
)
|
||||
|
||||
if action_type == "reply":
|
||||
action_str = "回复"
|
||||
elif action_type == "no_reply":
|
||||
action_str = "不回复"
|
||||
else:
|
||||
action_str = action_type
|
||||
loop_action_info = {
|
||||
"action_taken": action_taken,
|
||||
"command": action_command,
|
||||
"reason": action_reason,
|
||||
}
|
||||
|
||||
logger.debug(f"{self.log_prefix} 麦麦想要:'{action_str}', 原因'{reasoning}'")
|
||||
|
||||
success, reply_text, command = await self._handle_action(
|
||||
action_type, reasoning, action_data, cycle_timers, thinking_id
|
||||
)
|
||||
|
||||
loop_action_info = {
|
||||
"action_taken": success,
|
||||
"reply_text": reply_text,
|
||||
"command": command,
|
||||
"taken_time": time.time(),
|
||||
}
|
||||
|
||||
loop_info = {
|
||||
return {
|
||||
"loop_observation_info": loop_observation_info,
|
||||
"loop_processor_info": loop_processor_info,
|
||||
"loop_plan_info": loop_plan_info,
|
||||
"loop_action_info": loop_action_info,
|
||||
}
|
||||
|
||||
return loop_info
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"{self.log_prefix} FOCUS聊天处理失败: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
return {
|
||||
"loop_observation_info": {},
|
||||
"loop_processor_info": {},
|
||||
"loop_plan_info": {},
|
||||
"loop_action_info": {"action_taken": False, "reply_text": "", "command": ""},
|
||||
}
|
||||
logger.error(f"{self.log_prefix} 循环处理出错: {e}")
|
||||
traceback.print_exc()
|
||||
raise
|
||||
|
||||
async def _handle_action(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
|
|||
from src.individuality.individuality import individuality
|
||||
from src.chat.focus_chat.planners.action_manager import ActionManager
|
||||
from json_repair import repair_json
|
||||
from src.chat.focus_chat.info.chat_info import ChattingInfo
|
||||
from src.chat.focus_chat.info.workingmemory_info import WorkingMemoryInfo
|
||||
|
||||
logger = get_logger("planner")
|
||||
|
||||
|
|
@ -85,6 +87,61 @@ class ActionPlanner:
|
|||
|
||||
self.action_manager = action_manager
|
||||
|
||||
async def plan_simple(self, all_plan_info: List[InfoBase], running_memorys: List[Dict[str, Any]]) -> Dict[str, Any]:
|
||||
"""
|
||||
为私聊提供的简单规划方法。
|
||||
主要关注ChattingInfo和WorkingMemory,不考虑复杂的心智状态和工具使用。
|
||||
|
||||
Args:
|
||||
all_plan_info: 所有处理器提供的信息
|
||||
running_memorys: 当前激活的记忆
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 包含action_type, action_data和reasoning的字典
|
||||
"""
|
||||
# 提取聊天信息
|
||||
chatting_info = None
|
||||
working_memory_info = None
|
||||
for info in all_plan_info:
|
||||
if isinstance(info, ChattingInfo):
|
||||
chatting_info = info
|
||||
elif isinstance(info, WorkingMemoryInfo):
|
||||
working_memory_info = info
|
||||
|
||||
if not chatting_info:
|
||||
return {
|
||||
"action_type": "no_reply",
|
||||
"action_data": {},
|
||||
"reasoning": "没有检测到新的聊天信息",
|
||||
}
|
||||
|
||||
# 检查是否有新消息需要回复
|
||||
if not chatting_info.new_messages:
|
||||
return {
|
||||
"action_type": "no_reply",
|
||||
"action_data": {},
|
||||
"reasoning": "没有新消息需要回复",
|
||||
}
|
||||
|
||||
# 获取最新消息
|
||||
latest_message = chatting_info.new_messages[-1]
|
||||
|
||||
# 检查工作记忆中是否有相关上下文
|
||||
context = ""
|
||||
if working_memory_info and working_memory_info.related_memory:
|
||||
context = working_memory_info.related_memory
|
||||
|
||||
# 构建回复动作
|
||||
return {
|
||||
"action_type": "reply",
|
||||
"action_data": {
|
||||
"message": latest_message,
|
||||
"context": context,
|
||||
"style": "direct", # 私聊使用直接回复风格
|
||||
},
|
||||
"reasoning": "收到新的私聊消息,直接回复",
|
||||
}
|
||||
|
||||
async def plan(self, all_plan_info: List[InfoBase], running_memorys: List[Dict[str, Any]]) -> Dict[str, Any]:
|
||||
"""
|
||||
规划器 (Planner): 使用LLM根据上下文决定做出什么动作。
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ class SubHeartflowManager:
|
|||
"""
|
||||
接收来自 HeartFChatting 的请求,将特定子心流的状态转换为 NORMAL。
|
||||
通常在连续多次 "no_reply" 后被调用。
|
||||
对于私聊和群聊,都转换为 NORMAL。
|
||||
对于群聊转换为 NORMAL,对于私聊转换为 ABSENT。
|
||||
|
||||
Args:
|
||||
subflow_id: 需要转换状态的子心流 ID。
|
||||
|
|
@ -234,8 +234,9 @@ class SubHeartflowManager:
|
|||
current_state = subflow.chat_state.chat_status
|
||||
|
||||
if current_state == ChatState.FOCUSED:
|
||||
target_state = ChatState.NORMAL
|
||||
log_reason = "转为NORMAL"
|
||||
# 根据聊天类型决定目标状态
|
||||
target_state = ChatState.NORMAL if subflow.is_group_chat else ChatState.ABSENT
|
||||
log_reason = "转为NORMAL" if subflow.is_group_chat else "转为ABSENT(私聊)"
|
||||
|
||||
logger.info(
|
||||
f"[状态转换请求] 接收到请求,将 {stream_name} (当前: {current_state.value}) 尝试转换为 {target_state.value} ({log_reason})"
|
||||
|
|
|
|||
Loading…
Reference in New Issue