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 = {}
|
task_to_name_map = {}
|
||||||
processor_time_costs = {} # 新增: 记录每个处理器耗时
|
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:
|
for processor in self.processors:
|
||||||
processor_name = processor.__class__.log_prefix
|
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):
|
async def run_with_timeout(proc=processor):
|
||||||
return await asyncio.wait_for(
|
return await asyncio.wait_for(
|
||||||
|
|
@ -465,9 +478,14 @@ class HeartFChatting:
|
||||||
|
|
||||||
self.all_observations = observations
|
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):
|
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()
|
await self.action_observation.observe()
|
||||||
observations.append(self.action_observation)
|
observations.append(self.action_observation)
|
||||||
|
|
||||||
|
|
@ -497,59 +515,41 @@ class HeartFChatting:
|
||||||
}
|
}
|
||||||
|
|
||||||
with Timer("规划器", cycle_timers):
|
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 = {
|
loop_plan_info = {
|
||||||
"action_result": plan_result.get("action_result", {}),
|
"action_result": plan_result,
|
||||||
"current_mind": plan_result.get("current_mind", ""),
|
}
|
||||||
"observed_messages": plan_result.get("observed_messages", ""),
|
|
||||||
}
|
|
||||||
|
|
||||||
with Timer("执行动作", cycle_timers):
|
with Timer("执行动作", cycle_timers):
|
||||||
action_type, action_data, reasoning = (
|
action_taken, action_command, action_reason = await self._handle_action(
|
||||||
plan_result.get("action_result", {}).get("action_type", "error"),
|
action=plan_result["action_type"],
|
||||||
plan_result.get("action_result", {}).get("action_data", {}),
|
reasoning=plan_result["reasoning"],
|
||||||
plan_result.get("action_result", {}).get("reasoning", "未提供理由"),
|
action_data=plan_result["action_data"],
|
||||||
|
cycle_timers=cycle_timers,
|
||||||
|
thinking_id=thinking_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
if action_type == "reply":
|
loop_action_info = {
|
||||||
action_str = "回复"
|
"action_taken": action_taken,
|
||||||
elif action_type == "no_reply":
|
"command": action_command,
|
||||||
action_str = "不回复"
|
"reason": action_reason,
|
||||||
else:
|
}
|
||||||
action_str = action_type
|
|
||||||
|
|
||||||
logger.debug(f"{self.log_prefix} 麦麦想要:'{action_str}', 原因'{reasoning}'")
|
return {
|
||||||
|
|
||||||
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 = {
|
|
||||||
"loop_observation_info": loop_observation_info,
|
"loop_observation_info": loop_observation_info,
|
||||||
"loop_processor_info": loop_processor_info,
|
"loop_processor_info": loop_processor_info,
|
||||||
"loop_plan_info": loop_plan_info,
|
"loop_plan_info": loop_plan_info,
|
||||||
"loop_action_info": loop_action_info,
|
"loop_action_info": loop_action_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
return loop_info
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{self.log_prefix} FOCUS聊天处理失败: {e}")
|
logger.error(f"{self.log_prefix} 循环处理出错: {e}")
|
||||||
logger.error(traceback.format_exc())
|
traceback.print_exc()
|
||||||
return {
|
raise
|
||||||
"loop_observation_info": {},
|
|
||||||
"loop_processor_info": {},
|
|
||||||
"loop_plan_info": {},
|
|
||||||
"loop_action_info": {"action_taken": False, "reply_text": "", "command": ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
async def _handle_action(
|
async def _handle_action(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
|
||||||
from src.individuality.individuality import individuality
|
from src.individuality.individuality import individuality
|
||||||
from src.chat.focus_chat.planners.action_manager import ActionManager
|
from src.chat.focus_chat.planners.action_manager import ActionManager
|
||||||
from json_repair import repair_json
|
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")
|
logger = get_logger("planner")
|
||||||
|
|
||||||
|
|
@ -85,6 +87,61 @@ class ActionPlanner:
|
||||||
|
|
||||||
self.action_manager = action_manager
|
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]:
|
async def plan(self, all_plan_info: List[InfoBase], running_memorys: List[Dict[str, Any]]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
规划器 (Planner): 使用LLM根据上下文决定做出什么动作。
|
规划器 (Planner): 使用LLM根据上下文决定做出什么动作。
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ class SubHeartflowManager:
|
||||||
"""
|
"""
|
||||||
接收来自 HeartFChatting 的请求,将特定子心流的状态转换为 NORMAL。
|
接收来自 HeartFChatting 的请求,将特定子心流的状态转换为 NORMAL。
|
||||||
通常在连续多次 "no_reply" 后被调用。
|
通常在连续多次 "no_reply" 后被调用。
|
||||||
对于私聊和群聊,都转换为 NORMAL。
|
对于群聊转换为 NORMAL,对于私聊转换为 ABSENT。
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
subflow_id: 需要转换状态的子心流 ID。
|
subflow_id: 需要转换状态的子心流 ID。
|
||||||
|
|
@ -234,8 +234,9 @@ class SubHeartflowManager:
|
||||||
current_state = subflow.chat_state.chat_status
|
current_state = subflow.chat_state.chat_status
|
||||||
|
|
||||||
if current_state == ChatState.FOCUSED:
|
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(
|
logger.info(
|
||||||
f"[状态转换请求] 接收到请求,将 {stream_name} (当前: {current_state.value}) 尝试转换为 {target_state.value} ({log_reason})"
|
f"[状态转换请求] 接收到请求,将 {stream_name} (当前: {current_state.value}) 尝试转换为 {target_state.value} ({log_reason})"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue