feat(chat): 私聊专注模式下强制回复
在私聊的专注模式下,即使用户的发言没有触发任何功能,机器人也会进行回复,而不是选择“no_reply”。 此举旨在提升私聊场景下的用户体验,避免机器人因未匹配到关键词而沉默,让对话感觉更自然。
This commit is contained in:
committed by
Windpicker-owo
parent
f0b1e66477
commit
ebf811a85c
@@ -607,26 +607,32 @@ class HeartFChatting:
|
|||||||
available_actions=available_actions,
|
available_actions=available_actions,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
action_data["loop_start_time"] = loop_start_time
|
||||||
|
|
||||||
# 3. 并行执行所有动作
|
# 在私聊的专注模式下,如果规划动作为no_reply,则强制改为reply
|
||||||
async def execute_action(action_info,actions):
|
is_private_chat = self.chat_stream.group_info is None
|
||||||
"""执行单个动作的通用函数"""
|
if self.loop_mode == ChatMode.FOCUS and is_private_chat and action_type == "no_reply":
|
||||||
try:
|
action_type = "reply"
|
||||||
if action_info["action_type"] == "no_reply":
|
logger.info(f"{self.log_prefix} 私聊专注模式下强制回复")
|
||||||
# 直接处理no_reply逻辑,不再通过动作系统
|
|
||||||
reason = action_info.get("reasoning", "选择不回复")
|
if action_type == "reply":
|
||||||
logger.info(f"{self.log_prefix} 选择不回复,原因: {reason}")
|
logger.info(f"{self.log_prefix}{global_config.bot.nickname} 决定进行回复")
|
||||||
|
elif is_parallel:
|
||||||
# 存储no_reply信息到数据库
|
logger.info(f"{self.log_prefix}{global_config.bot.nickname} 决定进行回复, 同时执行{action_type}动作")
|
||||||
await database_api.store_action_info(
|
else:
|
||||||
chat_stream=self.chat_stream,
|
# 只有在gen_task存在时才进行相关操作
|
||||||
action_build_into_prompt=False,
|
if gen_task:
|
||||||
action_prompt_display=reason,
|
if not gen_task.done():
|
||||||
action_done=True,
|
gen_task.cancel()
|
||||||
thinking_id=thinking_id,
|
logger.debug(f"{self.log_prefix} 已取消预生成的回复任务")
|
||||||
action_data={"reason": reason},
|
logger.info(
|
||||||
action_name="no_reply",
|
f"{self.log_prefix}{global_config.bot.nickname} 原本想要回复,但选择执行{action_type},不发表回复"
|
||||||
|
)
|
||||||
|
elif generation_result := gen_task.result():
|
||||||
|
content = " ".join([item[1] for item in generation_result if item[0] == "text"])
|
||||||
|
logger.debug(f"{self.log_prefix} 预生成的回复任务已完成")
|
||||||
|
logger.info(
|
||||||
|
f"{self.log_prefix}{global_config.bot.nickname} 原本想要回复:{content},但选择执行{action_type},不发表回复"
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
81
src/plugins/built_in/core_actions/no_reply.py
Normal file
81
src/plugins/built_in/core_actions/no_reply.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
from typing import Tuple, List
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
|
# 导入新插件系统
|
||||||
|
from src.plugin_system import BaseAction, ActionActivationType, ChatMode
|
||||||
|
from src.plugin_system.base.component_types import ChatType
|
||||||
|
|
||||||
|
# 导入依赖的系统组件
|
||||||
|
from src.common.logger import get_logger
|
||||||
|
|
||||||
|
|
||||||
|
logger = get_logger("no_reply_action")
|
||||||
|
|
||||||
|
|
||||||
|
class NoReplyAction(BaseAction):
|
||||||
|
"""不回复动作,支持waiting和breaking两种形式."""
|
||||||
|
|
||||||
|
focus_activation_type = ActionActivationType.NEVER
|
||||||
|
normal_activation_type = ActionActivationType.NEVER
|
||||||
|
mode_enable = ChatMode.FOCUS
|
||||||
|
parallel_action = False
|
||||||
|
|
||||||
|
# 动作基本信息
|
||||||
|
action_name = "no_reply"
|
||||||
|
action_description = "暂时不回复消息"
|
||||||
|
|
||||||
|
# 最近三次no_reply的新消息兴趣度记录
|
||||||
|
_recent_interest_records: deque = deque(maxlen=3)
|
||||||
|
|
||||||
|
# 兴趣值退出阈值
|
||||||
|
_interest_exit_threshold = 3.0
|
||||||
|
# 消息数量退出阈值
|
||||||
|
_min_exit_message_count = 3
|
||||||
|
_max_exit_message_count = 6
|
||||||
|
|
||||||
|
# 动作参数定义
|
||||||
|
action_parameters = {}
|
||||||
|
|
||||||
|
# 动作使用场景
|
||||||
|
action_require = [""]
|
||||||
|
|
||||||
|
# 关联类型
|
||||||
|
associated_types = []
|
||||||
|
|
||||||
|
async def execute(self) -> Tuple[bool, str]:
|
||||||
|
"""执行不回复动作"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
reason = self.action_data.get("reason", "")
|
||||||
|
|
||||||
|
logger.info(f"{self.log_prefix} 选择不回复,原因: {reason}")
|
||||||
|
|
||||||
|
await self.store_action_info(
|
||||||
|
action_build_into_prompt=False,
|
||||||
|
action_prompt_display=reason,
|
||||||
|
action_done=True,
|
||||||
|
)
|
||||||
|
return True, reason
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{self.log_prefix} 不回复动作执行失败: {e}")
|
||||||
|
exit_reason = f"执行异常: {str(e)}"
|
||||||
|
full_prompt = f"no_reply执行异常: {exit_reason},你思考是否要进行回复"
|
||||||
|
await self.store_action_info(
|
||||||
|
action_build_into_prompt=True,
|
||||||
|
action_prompt_display=full_prompt,
|
||||||
|
action_done=True,
|
||||||
|
)
|
||||||
|
return False, f"不回复动作执行失败: {e}"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset_consecutive_count(cls):
|
||||||
|
"""重置连续计数器和兴趣度记录"""
|
||||||
|
cls._recent_interest_records.clear()
|
||||||
|
logger.debug("NoReplyAction连续计数器和兴趣度记录已重置")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_recent_interest_records(cls) -> List[float]:
|
||||||
|
"""获取最近的兴趣度记录"""
|
||||||
|
return list(cls._recent_interest_records)
|
||||||
|
|
||||||
Reference in New Issue
Block a user