feat:优化了了auto模式切换逻辑
This commit is contained in:
@@ -42,14 +42,13 @@ def init_prompt():
|
|||||||
请你阅读聊天记录,查看是否需要调取某个人的信息,这个人可以是出现在聊天记录中的,也可以是记录中提到的人。
|
请你阅读聊天记录,查看是否需要调取某个人的信息,这个人可以是出现在聊天记录中的,也可以是记录中提到的人。
|
||||||
你不同程度上认识群聊里的人,以及他们谈论到的人,你可以根据聊天记录,回忆起有关他们的信息,帮助你参与聊天
|
你不同程度上认识群聊里的人,以及他们谈论到的人,你可以根据聊天记录,回忆起有关他们的信息,帮助你参与聊天
|
||||||
1.你需要提供用户名,以及你想要提取的信息名称类型来进行调取
|
1.你需要提供用户名,以及你想要提取的信息名称类型来进行调取
|
||||||
2.你也可以完全不输出任何信息
|
2.请注意,提取的信息类型一定要和用户有关,不要提取无关的信息
|
||||||
3.阅读调取记录,如果已经回忆过某个人的信息,请不要重复调取,除非你忘记了
|
3.阅读调取记录,如果已经回忆过某个人的信息,请不要重复调取,除非你忘记了
|
||||||
|
|
||||||
请以json格式输出,例如:
|
请以json格式输出,例如:
|
||||||
|
|
||||||
{{
|
{{
|
||||||
"用户A": "昵称",
|
"用户A": "昵称",
|
||||||
"用户A": "性别",
|
|
||||||
"用户B": "对你的态度",
|
"用户B": "对你的态度",
|
||||||
"用户C": "你和ta最近做的事",
|
"用户C": "你和ta最近做的事",
|
||||||
"用户D": "你对ta的印象",
|
"用户D": "你对ta的印象",
|
||||||
@@ -230,10 +229,10 @@ class RelationshipProcessor(BaseProcessor):
|
|||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logger.debug(f"{self.log_prefix} 人物信息prompt: \n{prompt}\n")
|
# logger.debug(f"{self.log_prefix} 人物信息prompt: \n{prompt}\n")
|
||||||
content, _ = await self.llm_model.generate_response_async(prompt=prompt)
|
content, _ = await self.llm_model.generate_response_async(prompt=prompt)
|
||||||
if content:
|
if content:
|
||||||
print(f"content: {content}")
|
# print(f"content: {content}")
|
||||||
content_json = json.loads(repair_json(content))
|
content_json = json.loads(repair_json(content))
|
||||||
|
|
||||||
# 收集即时提取任务
|
# 收集即时提取任务
|
||||||
|
|||||||
@@ -110,8 +110,8 @@ class WorkingMemoryProcessor(BaseProcessor):
|
|||||||
try:
|
try:
|
||||||
content, _ = await self.llm_model.generate_response_async(prompt=prompt)
|
content, _ = await self.llm_model.generate_response_async(prompt=prompt)
|
||||||
|
|
||||||
print(f"prompt: {prompt}---------------------------------")
|
# print(f"prompt: {prompt}---------------------------------")
|
||||||
print(f"content: {content}---------------------------------")
|
# print(f"content: {content}---------------------------------")
|
||||||
|
|
||||||
if not content:
|
if not content:
|
||||||
logger.warning(f"{self.log_prefix} LLM返回空结果,处理工作记忆失败。")
|
logger.warning(f"{self.log_prefix} LLM返回空结果,处理工作记忆失败。")
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ class ActionManager:
|
|||||||
self._using_actions = self._default_actions.copy()
|
self._using_actions = self._default_actions.copy()
|
||||||
|
|
||||||
# 添加系统核心动作
|
# 添加系统核心动作
|
||||||
self._add_system_core_actions()
|
# self._add_system_core_actions()
|
||||||
|
|
||||||
def _load_plugin_actions(self) -> None:
|
def _load_plugin_actions(self) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -377,8 +377,8 @@ class ActionManager:
|
|||||||
if action_mode == "all" or action_mode == mode:
|
if action_mode == "all" or action_mode == mode:
|
||||||
filtered_actions[action_name] = action_info
|
filtered_actions[action_name] = action_info
|
||||||
logger.debug(f"动作 {action_name} 在模式 {mode} 下可用 (mode_enable: {action_mode})")
|
logger.debug(f"动作 {action_name} 在模式 {mode} 下可用 (mode_enable: {action_mode})")
|
||||||
else:
|
# else:
|
||||||
logger.debug(f"动作 {action_name} 在模式 {mode} 下不可用 (mode_enable: {action_mode})")
|
# logger.debug(f"动作 {action_name} 在模式 {mode} 下不可用 (mode_enable: {action_mode})")
|
||||||
|
|
||||||
logger.debug(f"模式 {mode} 下可用动作: {list(filtered_actions.keys())}")
|
logger.debug(f"模式 {mode} 下可用动作: {list(filtered_actions.keys())}")
|
||||||
return filtered_actions
|
return filtered_actions
|
||||||
@@ -475,19 +475,19 @@ class ActionManager:
|
|||||||
"""恢复默认动作集到使用集"""
|
"""恢复默认动作集到使用集"""
|
||||||
self._using_actions = self._default_actions.copy()
|
self._using_actions = self._default_actions.copy()
|
||||||
# 添加系统核心动作(即使enable_plugin为False的系统动作)
|
# 添加系统核心动作(即使enable_plugin为False的系统动作)
|
||||||
self._add_system_core_actions()
|
# self._add_system_core_actions()
|
||||||
|
|
||||||
def _add_system_core_actions(self) -> None:
|
# def _add_system_core_actions(self) -> None:
|
||||||
"""
|
# """
|
||||||
添加系统核心动作到使用集
|
# 添加系统核心动作到使用集
|
||||||
系统核心动作是那些enable_plugin为False但是系统必需的动作
|
# 系统核心动作是那些enable_plugin为False但是系统必需的动作
|
||||||
"""
|
# """
|
||||||
system_core_actions = ["exit_focus_chat"] # 可以根据需要扩展
|
# system_core_actions = ["exit_focus_chat"] # 可以根据需要扩展
|
||||||
|
|
||||||
for action_name in system_core_actions:
|
# for action_name in system_core_actions:
|
||||||
if action_name in self._registered_actions and action_name not in self._using_actions:
|
# if action_name in self._registered_actions and action_name not in self._using_actions:
|
||||||
self._using_actions[action_name] = self._registered_actions[action_name]
|
# self._using_actions[action_name] = self._registered_actions[action_name]
|
||||||
logger.debug(f"添加系统核心动作到使用集: {action_name}")
|
# logger.debug(f"添加系统核心动作到使用集: {action_name}")
|
||||||
|
|
||||||
def add_system_action_if_needed(self, action_name: str) -> bool:
|
def add_system_action_if_needed(self, action_name: str) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -136,6 +136,13 @@ class ActionModifier:
|
|||||||
if chat_content is not None:
|
if chat_content is not None:
|
||||||
logger.debug(f"{self.log_prefix}开始激活类型判定阶段")
|
logger.debug(f"{self.log_prefix}开始激活类型判定阶段")
|
||||||
|
|
||||||
|
# 保存exit_focus_chat动作(如果存在)
|
||||||
|
exit_focus_action = None
|
||||||
|
if "exit_focus_chat" in self.action_manager.get_using_actions():
|
||||||
|
exit_focus_action = self.action_manager.get_using_actions()["exit_focus_chat"]
|
||||||
|
self.action_manager.remove_action_from_using("exit_focus_chat")
|
||||||
|
logger.debug(f"{self.log_prefix}临时移除exit_focus_chat动作以进行激活类型判定")
|
||||||
|
|
||||||
# 获取当前使用的动作集(经过第一阶段处理,且适用于FOCUS模式)
|
# 获取当前使用的动作集(经过第一阶段处理,且适用于FOCUS模式)
|
||||||
current_using_actions = self.action_manager.get_using_actions()
|
current_using_actions = self.action_manager.get_using_actions()
|
||||||
all_registered_actions = self.action_manager.get_registered_actions()
|
all_registered_actions = self.action_manager.get_registered_actions()
|
||||||
@@ -185,6 +192,11 @@ class ActionModifier:
|
|||||||
reason = removal_reasons.get(action_name, "未知原因")
|
reason = removal_reasons.get(action_name, "未知原因")
|
||||||
logger.info(f"{self.log_prefix}移除动作: {action_name},原因: {reason}")
|
logger.info(f"{self.log_prefix}移除动作: {action_name},原因: {reason}")
|
||||||
|
|
||||||
|
# 恢复exit_focus_chat动作(如果之前存在)
|
||||||
|
if exit_focus_action:
|
||||||
|
self.action_manager.add_action_to_using("exit_focus_chat")
|
||||||
|
logger.debug(f"{self.log_prefix}恢复exit_focus_chat动作")
|
||||||
|
|
||||||
logger.info(f"{self.log_prefix}激活类型判定完成,最终可用动作: {list(final_activated_actions.keys())}")
|
logger.info(f"{self.log_prefix}激活类型判定完成,最终可用动作: {list(final_activated_actions.keys())}")
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
|
|||||||
@@ -55,14 +55,6 @@ class SubHeartflow:
|
|||||||
self.heart_fc_instance: Optional[HeartFChatting] = None # 该sub_heartflow的HeartFChatting实例
|
self.heart_fc_instance: Optional[HeartFChatting] = None # 该sub_heartflow的HeartFChatting实例
|
||||||
self.normal_chat_instance: Optional[NormalChat] = None # 该sub_heartflow的NormalChat实例
|
self.normal_chat_instance: Optional[NormalChat] = None # 该sub_heartflow的NormalChat实例
|
||||||
|
|
||||||
# 观察,目前只有聊天观察,可以载入多个
|
|
||||||
# 负责对处理过的消息进行观察
|
|
||||||
# self.observations: List[ChattingObservation] = [] # 观察列表
|
|
||||||
# self.running_knowledges = [] # 运行中的知识,待完善
|
|
||||||
|
|
||||||
# 日志前缀 - Moved determination to initialize
|
|
||||||
self.log_prefix = str(subheartflow_id) # Initial default prefix
|
|
||||||
|
|
||||||
async def initialize(self):
|
async def initialize(self):
|
||||||
"""异步初始化方法,创建兴趣流并确定聊天类型"""
|
"""异步初始化方法,创建兴趣流并确定聊天类型"""
|
||||||
|
|
||||||
@@ -83,7 +75,7 @@ class SubHeartflow:
|
|||||||
切出 CHAT 状态时使用
|
切出 CHAT 状态时使用
|
||||||
"""
|
"""
|
||||||
if self.normal_chat_instance:
|
if self.normal_chat_instance:
|
||||||
logger.info(f"{self.log_prefix} 离开CHAT模式,结束 随便水群")
|
logger.info(f"{self.log_prefix} 离开normal模式")
|
||||||
try:
|
try:
|
||||||
await self.normal_chat_instance.stop_chat() # 调用 stop_chat
|
await self.normal_chat_instance.stop_chat() # 调用 stop_chat
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -223,7 +215,7 @@ class SubHeartflow:
|
|||||||
log_prefix = f"[{self.log_prefix}]"
|
log_prefix = f"[{self.log_prefix}]"
|
||||||
|
|
||||||
if new_state == ChatState.NORMAL:
|
if new_state == ChatState.NORMAL:
|
||||||
logger.debug(f"{log_prefix} 准备进入或保持 普通聊天 状态")
|
logger.debug(f"{log_prefix} 准备进入 normal聊天 状态")
|
||||||
if await self._start_normal_chat():
|
if await self._start_normal_chat():
|
||||||
logger.debug(f"{log_prefix} 成功进入或保持 NormalChat 状态。")
|
logger.debug(f"{log_prefix} 成功进入或保持 NormalChat 状态。")
|
||||||
state_changed = True
|
state_changed = True
|
||||||
@@ -233,7 +225,7 @@ class SubHeartflow:
|
|||||||
return
|
return
|
||||||
|
|
||||||
elif new_state == ChatState.FOCUSED:
|
elif new_state == ChatState.FOCUSED:
|
||||||
logger.debug(f"{log_prefix} 准备进入或保持 专注聊天 状态")
|
logger.debug(f"{log_prefix} 准备进入 focus聊天 状态")
|
||||||
if await self._start_heart_fc_chat():
|
if await self._start_heart_fc_chat():
|
||||||
logger.debug(f"{log_prefix} 成功进入或保持 HeartFChatting 状态。")
|
logger.debug(f"{log_prefix} 成功进入或保持 HeartFChatting 状态。")
|
||||||
state_changed = True
|
state_changed = True
|
||||||
|
|||||||
@@ -154,54 +154,61 @@ class NormalChat:
|
|||||||
通常由start_monitoring_interest()启动
|
通常由start_monitoring_interest()启动
|
||||||
"""
|
"""
|
||||||
while True:
|
while True:
|
||||||
async with global_prompt_manager.async_message_scope(self.chat_stream.context.get_template_name()):
|
try:
|
||||||
await asyncio.sleep(0.5) # 每秒检查一次
|
async with global_prompt_manager.async_message_scope(self.chat_stream.context.get_template_name()):
|
||||||
# 检查任务是否已被取消
|
await asyncio.sleep(0.5) # 每秒检查一次
|
||||||
if self._chat_task is None or self._chat_task.cancelled():
|
# 检查任务是否已被取消
|
||||||
logger.info(f"[{self.stream_name}] 兴趣监控任务被取消或置空,退出")
|
if self._chat_task is None or self._chat_task.cancelled():
|
||||||
break
|
logger.info(f"[{self.stream_name}] 兴趣监控任务被取消或置空,退出")
|
||||||
|
break
|
||||||
|
|
||||||
items_to_process = list(self.interest_dict.items())
|
items_to_process = list(self.interest_dict.items())
|
||||||
if not items_to_process:
|
if not items_to_process:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 并行处理兴趣消息
|
# 并行处理兴趣消息
|
||||||
async def process_single_message(msg_id, message, interest_value, is_mentioned):
|
async def process_single_message(msg_id, message, interest_value, is_mentioned):
|
||||||
"""处理单个兴趣消息"""
|
"""处理单个兴趣消息"""
|
||||||
try:
|
try:
|
||||||
# 处理消息
|
# 处理消息
|
||||||
if time.time() - self.start_time > 300:
|
if time.time() - self.start_time > 300:
|
||||||
self.adjust_reply_frequency(duration=300 / 60)
|
self.adjust_reply_frequency(duration=300 / 60)
|
||||||
else:
|
else:
|
||||||
self.adjust_reply_frequency(duration=(time.time() - self.start_time) / 60)
|
self.adjust_reply_frequency(duration=(time.time() - self.start_time) / 60)
|
||||||
|
|
||||||
await self.normal_response(
|
await self.normal_response(
|
||||||
message=message,
|
message=message,
|
||||||
is_mentioned=is_mentioned,
|
is_mentioned=is_mentioned,
|
||||||
interested_rate=interest_value * self.willing_amplifier,
|
interested_rate=interest_value * self.willing_amplifier,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[{self.stream_name}] 处理兴趣消息{msg_id}时出错: {e}\n{traceback.format_exc()}")
|
logger.error(f"[{self.stream_name}] 处理兴趣消息{msg_id}时出错: {e}\n{traceback.format_exc()}")
|
||||||
finally:
|
finally:
|
||||||
self.interest_dict.pop(msg_id, None)
|
self.interest_dict.pop(msg_id, None)
|
||||||
|
|
||||||
# 创建并行任务列表
|
# 创建并行任务列表
|
||||||
tasks = []
|
tasks = []
|
||||||
for msg_id, (message, interest_value, is_mentioned) in items_to_process:
|
for msg_id, (message, interest_value, is_mentioned) in items_to_process:
|
||||||
task = process_single_message(msg_id, message, interest_value, is_mentioned)
|
task = process_single_message(msg_id, message, interest_value, is_mentioned)
|
||||||
tasks.append(task)
|
tasks.append(task)
|
||||||
|
|
||||||
# 并行执行所有任务,限制并发数量避免资源过度消耗
|
# 并行执行所有任务,限制并发数量避免资源过度消耗
|
||||||
if tasks:
|
if tasks:
|
||||||
# 使用信号量控制并发数,最多同时处理5个消息
|
# 使用信号量控制并发数,最多同时处理5个消息
|
||||||
semaphore = asyncio.Semaphore(5)
|
semaphore = asyncio.Semaphore(5)
|
||||||
|
|
||||||
async def limited_process(task):
|
async def limited_process(task):
|
||||||
async with semaphore:
|
async with semaphore:
|
||||||
await task
|
await task
|
||||||
|
|
||||||
limited_tasks = [limited_process(task) for task in tasks]
|
limited_tasks = [limited_process(task) for task in tasks]
|
||||||
await asyncio.gather(*limited_tasks, return_exceptions=True)
|
await asyncio.gather(*limited_tasks, return_exceptions=True)
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
logger.info(f"[{self.stream_name}] 兴趣监控任务被取消")
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[{self.stream_name}] 兴趣监控任务出错: {e}\n{traceback.format_exc()}")
|
||||||
|
await asyncio.sleep(1) # 出错后等待一秒再继续
|
||||||
|
|
||||||
# 改为实例方法, 移除 chat 参数
|
# 改为实例方法, 移除 chat 参数
|
||||||
async def normal_response(self, message: MessageRecv, is_mentioned: bool, interested_rate: float) -> None:
|
async def normal_response(self, message: MessageRecv, is_mentioned: bool, interested_rate: float) -> None:
|
||||||
@@ -259,7 +266,7 @@ class NormalChat:
|
|||||||
await self.action_modifier.modify_actions_for_normal_chat(
|
await self.action_modifier.modify_actions_for_normal_chat(
|
||||||
self.chat_stream, self.recent_replies, message.processed_plain_text
|
self.chat_stream, self.recent_replies, message.processed_plain_text
|
||||||
)
|
)
|
||||||
available_actions = self.action_manager.get_using_actions()
|
available_actions = self.action_manager.get_using_actions_for_mode("normal")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"[{self.stream_name}] 获取available_actions失败: {e}")
|
logger.warning(f"[{self.stream_name}] 获取available_actions失败: {e}")
|
||||||
available_actions = None
|
available_actions = None
|
||||||
@@ -428,12 +435,6 @@ class NormalChat:
|
|||||||
else:
|
else:
|
||||||
logger.warning(f"[{self.stream_name}] 没有设置切换到focus聊天模式的回调函数,无法执行切换")
|
logger.warning(f"[{self.stream_name}] 没有设置切换到focus聊天模式的回调函数,无法执行切换")
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
await self._check_switch_to_focus()
|
|
||||||
pass
|
|
||||||
|
|
||||||
# with Timer("关系更新", timing_results):
|
|
||||||
# await self._update_relationship(message, response_set)
|
|
||||||
|
|
||||||
# 回复后处理
|
# 回复后处理
|
||||||
await willing_manager.after_generate_reply_handle(message.message_info.message_id)
|
await willing_manager.after_generate_reply_handle(message.message_info.message_id)
|
||||||
@@ -494,7 +495,10 @@ class NormalChat:
|
|||||||
logger.debug(f"[{self.stream_name}] 尝试取消normal聊天任务。")
|
logger.debug(f"[{self.stream_name}] 尝试取消normal聊天任务。")
|
||||||
task.cancel()
|
task.cancel()
|
||||||
try:
|
try:
|
||||||
await task # 等待任务响应取消
|
# 添加超时机制,最多等待2秒
|
||||||
|
await asyncio.wait_for(task, timeout=2.0)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
logger.warning(f"[{self.stream_name}] 等待任务取消超时,强制结束")
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
logger.info(f"[{self.stream_name}] 结束一般聊天模式。")
|
logger.info(f"[{self.stream_name}] 结束一般聊天模式。")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -539,29 +543,6 @@ class NormalChat:
|
|||||||
# 返回最近的limit条记录,按时间倒序排列
|
# 返回最近的limit条记录,按时间倒序排列
|
||||||
return sorted(self.recent_replies[-limit:], key=lambda x: x["time"], reverse=True)
|
return sorted(self.recent_replies[-limit:], key=lambda x: x["time"], reverse=True)
|
||||||
|
|
||||||
async def _check_switch_to_focus(self) -> None:
|
|
||||||
"""检查是否满足切换到focus模式的条件"""
|
|
||||||
if not self.on_switch_to_focus_callback:
|
|
||||||
return # 如果没有设置回调函数,直接返回
|
|
||||||
current_time = time.time()
|
|
||||||
|
|
||||||
time_threshold = 120 / global_config.chat.auto_focus_threshold
|
|
||||||
reply_threshold = 6 * global_config.chat.auto_focus_threshold
|
|
||||||
|
|
||||||
one_minute_ago = current_time - time_threshold
|
|
||||||
|
|
||||||
# 统计1分钟内的回复数量
|
|
||||||
recent_reply_count = sum(1 for reply in self.recent_replies if reply["time"] > one_minute_ago)
|
|
||||||
if recent_reply_count > reply_threshold:
|
|
||||||
logger.info(
|
|
||||||
f"[{self.stream_name}] 检测到1分钟内回复数量({recent_reply_count})大于{reply_threshold},触发切换到focus模式"
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
# 调用回调函数通知上层切换到focus模式
|
|
||||||
await self.on_switch_to_focus_callback()
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"[{self.stream_name}] 触发切换到focus模式时出错: {e}\n{traceback.format_exc()}")
|
|
||||||
|
|
||||||
def adjust_reply_frequency(self, duration: int = 10):
|
def adjust_reply_frequency(self, duration: int = 10):
|
||||||
"""
|
"""
|
||||||
调整回复频率
|
调整回复频率
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ from src.chat.utils.chat_message_builder import build_readable_messages, get_raw
|
|||||||
from src.config.config import global_config
|
from src.config.config import global_config
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
|
from src.chat.message_receive.message_sender import message_manager
|
||||||
|
from src.chat.message_receive.message import MessageThinking
|
||||||
|
|
||||||
logger = get_logger("normal_chat_action_modifier")
|
logger = get_logger("normal_chat_action_modifier")
|
||||||
|
|
||||||
@@ -42,6 +44,7 @@ class NormalChatActionModifier:
|
|||||||
Args:
|
Args:
|
||||||
chat_stream: 聊天流对象
|
chat_stream: 聊天流对象
|
||||||
recent_replies: 最近的回复记录
|
recent_replies: 最近的回复记录
|
||||||
|
message_content: 当前消息内容
|
||||||
**kwargs: 其他参数
|
**kwargs: 其他参数
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -104,7 +107,7 @@ class NormalChatActionModifier:
|
|||||||
# print(f"current_actions: {current_actions}")
|
# print(f"current_actions: {current_actions}")
|
||||||
# print(f"chat_content: {chat_content}")
|
# print(f"chat_content: {chat_content}")
|
||||||
final_activated_actions = await self._apply_normal_activation_filtering(
|
final_activated_actions = await self._apply_normal_activation_filtering(
|
||||||
current_actions, chat_content, message_content
|
current_actions, chat_content, message_content, recent_replies
|
||||||
)
|
)
|
||||||
# print(f"final_activated_actions: {final_activated_actions}")
|
# print(f"final_activated_actions: {final_activated_actions}")
|
||||||
|
|
||||||
@@ -157,6 +160,7 @@ class NormalChatActionModifier:
|
|||||||
actions_with_info: Dict[str, Any],
|
actions_with_info: Dict[str, Any],
|
||||||
chat_content: str = "",
|
chat_content: str = "",
|
||||||
message_content: str = "",
|
message_content: str = "",
|
||||||
|
recent_replies: List[dict] = None,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
应用Normal模式的激活类型过滤逻辑
|
应用Normal模式的激活类型过滤逻辑
|
||||||
@@ -166,22 +170,37 @@ class NormalChatActionModifier:
|
|||||||
2. RANDOM类型保持概率激活
|
2. RANDOM类型保持概率激活
|
||||||
3. KEYWORD类型保持关键词匹配
|
3. KEYWORD类型保持关键词匹配
|
||||||
4. ALWAYS类型直接激活
|
4. ALWAYS类型直接激活
|
||||||
|
5. change_to_focus_chat 特殊处理:根据回复频率判断
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
actions_with_info: 带完整信息的动作字典
|
actions_with_info: 带完整信息的动作字典
|
||||||
chat_content: 聊天内容
|
chat_content: 聊天内容
|
||||||
|
message_content: 当前消息内容
|
||||||
|
recent_replies: 最近的回复记录列表
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict[str, Any]: 过滤后激活的actions字典
|
Dict[str, Any]: 过滤后激活的actions字典
|
||||||
"""
|
"""
|
||||||
activated_actions = {}
|
activated_actions = {}
|
||||||
|
|
||||||
|
# 特殊处理 change_to_focus_chat 动作
|
||||||
|
if "change_to_focus_chat" in actions_with_info:
|
||||||
|
# 检查是否满足切换到focus模式的条件
|
||||||
|
if await self._check_should_switch_to_focus(recent_replies):
|
||||||
|
activated_actions["change_to_focus_chat"] = actions_with_info["change_to_focus_chat"]
|
||||||
|
logger.debug(f"{self.log_prefix} 特殊激活 change_to_focus_chat 动作,原因: 满足切换到focus模式条件")
|
||||||
|
return activated_actions
|
||||||
|
|
||||||
# 分类处理不同激活类型的actions
|
# 分类处理不同激活类型的actions
|
||||||
always_actions = {}
|
always_actions = {}
|
||||||
random_actions = {}
|
random_actions = {}
|
||||||
keyword_actions = {}
|
keyword_actions = {}
|
||||||
|
|
||||||
for action_name, action_info in actions_with_info.items():
|
for action_name, action_info in actions_with_info.items():
|
||||||
|
# 跳过已特殊处理的 change_to_focus_chat
|
||||||
|
if action_name == "change_to_focus_chat":
|
||||||
|
continue
|
||||||
|
|
||||||
# 使用normal_activation_type
|
# 使用normal_activation_type
|
||||||
activation_type = action_info.get("normal_activation_type", "always")
|
activation_type = action_info.get("normal_activation_type", "always")
|
||||||
|
|
||||||
@@ -220,8 +239,6 @@ class NormalChatActionModifier:
|
|||||||
else:
|
else:
|
||||||
keywords = action_info.get("activation_keywords", [])
|
keywords = action_info.get("activation_keywords", [])
|
||||||
logger.debug(f"{self.log_prefix}未激活动作: {action_name},原因: KEYWORD类型未匹配关键词({keywords})")
|
logger.debug(f"{self.log_prefix}未激活动作: {action_name},原因: KEYWORD类型未匹配关键词({keywords})")
|
||||||
# print(f"keywords: {keywords}")
|
|
||||||
# print(f"chat_content: {chat_content}")
|
|
||||||
|
|
||||||
logger.debug(f"{self.log_prefix}Normal模式激活类型过滤完成: {list(activated_actions.keys())}")
|
logger.debug(f"{self.log_prefix}Normal模式激活类型过滤完成: {list(activated_actions.keys())}")
|
||||||
return activated_actions
|
return activated_actions
|
||||||
@@ -276,6 +293,46 @@ class NormalChatActionModifier:
|
|||||||
logger.debug(f"{self.log_prefix}动作 {action_name} 未匹配到任何关键词: {activation_keywords}")
|
logger.debug(f"{self.log_prefix}动作 {action_name} 未匹配到任何关键词: {activation_keywords}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
async def _check_should_switch_to_focus(self, recent_replies: List[dict]) -> bool:
|
||||||
|
"""
|
||||||
|
检查是否满足切换到focus模式的条件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
recent_replies: 最近的回复记录列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否应该切换到focus模式
|
||||||
|
"""
|
||||||
|
# 检查思考消息堆积情况
|
||||||
|
container = await message_manager.get_container(self.stream_id)
|
||||||
|
if container:
|
||||||
|
thinking_count = sum(1 for msg in container.messages if isinstance(msg, MessageThinking))
|
||||||
|
print(f"thinking_count: {thinking_count}")
|
||||||
|
if thinking_count >= 4 / global_config.chat.auto_focus_threshold: # 如果堆积超过3条思考消息
|
||||||
|
logger.debug(f"{self.log_prefix} 检测到思考消息堆积({thinking_count}条),切换到focus模式")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not recent_replies:
|
||||||
|
return False
|
||||||
|
|
||||||
|
current_time = time.time()
|
||||||
|
time_threshold = 120 / global_config.chat.auto_focus_threshold
|
||||||
|
reply_threshold = 6 * global_config.chat.auto_focus_threshold
|
||||||
|
|
||||||
|
one_minute_ago = current_time - time_threshold
|
||||||
|
|
||||||
|
# 统计1分钟内的回复数量
|
||||||
|
recent_reply_count = sum(1 for reply in recent_replies if reply["time"] > one_minute_ago)
|
||||||
|
|
||||||
|
print(f"recent_reply_count: {recent_reply_count}")
|
||||||
|
print(f"reply_threshold: {reply_threshold}")
|
||||||
|
|
||||||
|
should_switch = recent_reply_count > reply_threshold
|
||||||
|
if should_switch:
|
||||||
|
logger.debug(f"{self.log_prefix} 检测到1分钟内回复数量({recent_reply_count})大于{reply_threshold},满足切换到focus模式条件")
|
||||||
|
|
||||||
|
return should_switch
|
||||||
|
|
||||||
def get_available_actions_count(self) -> int:
|
def get_available_actions_count(self) -> int:
|
||||||
"""获取当前可用动作数量(排除默认的no_action)"""
|
"""获取当前可用动作数量(排除默认的no_action)"""
|
||||||
current_actions = self.action_manager.get_using_actions_for_mode("normal")
|
current_actions = self.action_manager.get_using_actions_for_mode("normal")
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ def init_prompt():
|
|||||||
|
|
||||||
重要说明:
|
重要说明:
|
||||||
- "no_action" 表示只进行普通聊天回复,不执行任何额外动作
|
- "no_action" 表示只进行普通聊天回复,不执行任何额外动作
|
||||||
- "change_to_focus_chat" 表示当聊天变得热烈、自己回复条数很多或需要深入交流时,正常回复消息并切换到focus_chat模式进行更深入的对话
|
|
||||||
- 其他action表示在普通回复的基础上,执行相应的额外动作
|
- 其他action表示在普通回复的基础上,执行相应的额外动作
|
||||||
|
|
||||||
你必须从上面列出的可用action中选择一个,并说明原因。
|
你必须从上面列出的可用action中选择一个,并说明原因。
|
||||||
@@ -159,7 +158,7 @@ class NormalChatPlanner:
|
|||||||
try:
|
try:
|
||||||
content, (reasoning_content, model_name) = await self.planner_llm.generate_response_async(prompt)
|
content, (reasoning_content, model_name) = await self.planner_llm.generate_response_async(prompt)
|
||||||
|
|
||||||
# logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}")
|
logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}")
|
||||||
logger.info(f"{self.log_prefix}规划器原始响应: {content}")
|
logger.info(f"{self.log_prefix}规划器原始响应: {content}")
|
||||||
logger.info(f"{self.log_prefix}规划器推理: {reasoning_content}")
|
logger.info(f"{self.log_prefix}规划器推理: {reasoning_content}")
|
||||||
logger.info(f"{self.log_prefix}规划器模型: {model_name}")
|
logger.info(f"{self.log_prefix}规划器模型: {model_name}")
|
||||||
@@ -177,7 +176,7 @@ class NormalChatPlanner:
|
|||||||
action_data = {k: v for k, v in action_result.items() if k not in ["action", "reasoning"]}
|
action_data = {k: v for k, v in action_result.items() if k not in ["action", "reasoning"]}
|
||||||
|
|
||||||
# 验证动作是否在可用动作列表中,或者是特殊动作
|
# 验证动作是否在可用动作列表中,或者是特殊动作
|
||||||
if action not in current_available_actions and action != "change_to_focus_chat":
|
if action not in current_available_actions:
|
||||||
logger.warning(f"{self.log_prefix}规划器选择了不可用的动作: {action}, 回退到no_action")
|
logger.warning(f"{self.log_prefix}规划器选择了不可用的动作: {action}, 回退到no_action")
|
||||||
action = "no_action"
|
action = "no_action"
|
||||||
reasoning = f"选择的动作{action}不在可用列表中,回退到no_action"
|
reasoning = f"选择的动作{action}不在可用列表中,回退到no_action"
|
||||||
@@ -257,21 +256,6 @@ class NormalChatPlanner:
|
|||||||
# 构建动作选项文本
|
# 构建动作选项文本
|
||||||
action_options_text = ""
|
action_options_text = ""
|
||||||
|
|
||||||
# 添加特殊的change_to_focus_chat动作
|
|
||||||
action_options_text += "动作:change_to_focus_chat\n"
|
|
||||||
action_options_text += "该动作的描述:当聊天变得热烈、自己回复条数很多或需要深入交流时使用,正常回复消息并切换到focus_chat模式\n"
|
|
||||||
|
|
||||||
action_options_text += "使用该动作的场景:\n"
|
|
||||||
action_options_text += "- 聊天上下文中自己的回复条数较多(超过3-4条)\n"
|
|
||||||
action_options_text += "- 对话进行得非常热烈活跃\n"
|
|
||||||
action_options_text += "- 用户表现出深入交流的意图\n"
|
|
||||||
action_options_text += "- 话题需要更专注和深入的讨论\n\n"
|
|
||||||
|
|
||||||
action_options_text += "输出要求:\n"
|
|
||||||
action_options_text += "{{"
|
|
||||||
action_options_text += ' "action": "change_to_focus_chat"'
|
|
||||||
action_options_text += "}}\n\n"
|
|
||||||
|
|
||||||
for action_name, action_info in current_available_actions.items():
|
for action_name, action_info in current_available_actions.items():
|
||||||
action_description = action_info.get("description", "")
|
action_description = action_info.get("description", "")
|
||||||
action_parameters = action_info.get("parameters", {})
|
action_parameters = action_info.get("parameters", {})
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ class PromptBuilder:
|
|||||||
|
|
||||||
# 构建action描述 (如果启用planner)
|
# 构建action描述 (如果启用planner)
|
||||||
action_descriptions = ""
|
action_descriptions = ""
|
||||||
logger.debug(f"Enable planner {enable_planner}, available actions: {available_actions}")
|
# logger.debug(f"Enable planner {enable_planner}, available actions: {available_actions}")
|
||||||
if enable_planner and available_actions:
|
if enable_planner and available_actions:
|
||||||
action_descriptions = "你有以下的动作能力,但执行这些动作不由你决定,由另外一个模型同步决定,因此你只需要知道有如下能力即可:\n"
|
action_descriptions = "你有以下的动作能力,但执行这些动作不由你决定,由另外一个模型同步决定,因此你只需要知道有如下能力即可:\n"
|
||||||
for action_name, action_info in available_actions.items():
|
for action_name, action_info in available_actions.items():
|
||||||
|
|||||||
@@ -250,11 +250,38 @@ class EmojiAction(BaseAction):
|
|||||||
return reply_text
|
return reply_text
|
||||||
|
|
||||||
|
|
||||||
|
class ChangeToFocusChatAction(BaseAction):
|
||||||
|
"""切换到专注聊天动作 - 从普通模式切换到专注模式"""
|
||||||
|
|
||||||
|
focus_activation_type = ActionActivationType.NEVER
|
||||||
|
normal_activation_type = ActionActivationType.NEVER
|
||||||
|
mode_enable = ChatMode.NORMAL
|
||||||
|
parallel_action = False
|
||||||
|
|
||||||
|
# 动作参数定义
|
||||||
|
action_parameters = {}
|
||||||
|
|
||||||
|
# 动作使用场景
|
||||||
|
action_require = [
|
||||||
|
"你想要进入专注聊天模式",
|
||||||
|
"聊天上下文中自己的回复条数较多(超过3-4条)",
|
||||||
|
"对话进行得非常热烈活跃",
|
||||||
|
"用户表现出深入交流的意图",
|
||||||
|
"话题需要更专注和深入的讨论"
|
||||||
|
]
|
||||||
|
|
||||||
|
async def execute(self) -> Tuple[bool, str]:
|
||||||
|
"""执行切换到专注聊天动作"""
|
||||||
|
logger.info(f"{self.log_prefix} 决定切换到专注聊天: {self.reasoning}")
|
||||||
|
# 这里只做决策标记,具体切换逻辑由上层管理器处理
|
||||||
|
return True, "决定切换到专注聊天模式"
|
||||||
|
|
||||||
|
|
||||||
class ExitFocusChatAction(BaseAction):
|
class ExitFocusChatAction(BaseAction):
|
||||||
"""退出专注聊天动作 - 从专注模式切换到普通模式"""
|
"""退出专注聊天动作 - 从专注模式切换到普通模式"""
|
||||||
|
|
||||||
# 激活设置
|
# 激活设置
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
focus_activation_type = ActionActivationType.NEVER
|
||||||
normal_activation_type = ActionActivationType.NEVER
|
normal_activation_type = ActionActivationType.NEVER
|
||||||
mode_enable = ChatMode.FOCUS
|
mode_enable = ChatMode.FOCUS
|
||||||
parallel_action = False
|
parallel_action = False
|
||||||
@@ -354,6 +381,13 @@ class CoreActionsPlugin(BasePlugin):
|
|||||||
),
|
),
|
||||||
ExitFocusChatAction,
|
ExitFocusChatAction,
|
||||||
),
|
),
|
||||||
|
# 切换到专注聊天动作
|
||||||
|
(
|
||||||
|
ChangeToFocusChatAction.get_action_info(
|
||||||
|
name="change_to_focus_chat", description="切换到专注聊天,从普通模式切换到专注模式"
|
||||||
|
),
|
||||||
|
ChangeToFocusChatAction,
|
||||||
|
),
|
||||||
# 示例Command - Ping命令
|
# 示例Command - Ping命令
|
||||||
(PingCommand.get_command_info(name="ping", description="测试机器人响应,拦截后续处理"), PingCommand),
|
(PingCommand.get_command_info(name="ping", description="测试机器人响应,拦截后续处理"), PingCommand),
|
||||||
# 示例Command - Log命令
|
# 示例Command - Log命令
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ description = "展示新插件系统完整功能的示例插件"
|
|||||||
|
|
||||||
# 组件启用控制
|
# 组件启用控制
|
||||||
[components]
|
[components]
|
||||||
enable_greeting = true
|
enable_greeting = false
|
||||||
enable_help = true
|
enable_help = false
|
||||||
enable_send = true
|
enable_send = false
|
||||||
enable_echo = true
|
enable_echo = false
|
||||||
enable_info = true
|
enable_info = false
|
||||||
|
|
||||||
# 智能问候配置
|
# 智能问候配置
|
||||||
[greeting]
|
[greeting]
|
||||||
|
|||||||
Reference in New Issue
Block a user