feat(chat): 优化消息打断逻辑,仅限触发用户

为了防止群聊中其他用户的消息意外中断正在进行的AI多重回复,引入了“触发用户”机制。

- 现在,只有发起该轮对话的用户发送的新消息才可能触发打断。
- 此外,表情包和Emoji等非文本消息将被忽略,不再触发打断,以提高交互的流畅性。
This commit is contained in:
tt-P607
2025-10-23 14:30:42 +08:00
parent a94bd57912
commit cce30f34f1
3 changed files with 25 additions and 7 deletions

View File

@@ -110,6 +110,11 @@ class ChatterManager:
self.stats["streams_processed"] += 1
try:
# 设置触发用户ID
last_message = context.get_last_message()
if last_message:
context.triggering_user_id = last_message.user_info.user_id
result = await self.instances[stream_id].execute(context)
# 检查执行结果是否真正成功
@@ -156,6 +161,7 @@ class ChatterManager:
finally:
# 无论成功还是失败,都要清理处理任务记录
self.remove_processing_task(stream_id)
context.triggering_user_id = None # 清除触发用户ID
def get_stats(self) -> dict[str, Any]:
"""获取管理器统计信息"""

View File

@@ -171,7 +171,7 @@ class MessageManager:
if not chat_stream:
logger.warning(f"MessageManager.add_message: 聊天流 {stream_id} 不存在")
return
await self._check_and_handle_interruption(chat_stream)
await self._check_and_handle_interruption(chat_stream, message)
await chat_stream.context_manager.add_message(message)
except Exception as e:
@@ -361,15 +361,26 @@ class MessageManager:
except Exception as e:
logger.error(f"清理不活跃聊天流时发生错误: {e}")
async def _check_and_handle_interruption(self, chat_stream: ChatStream | None = None):
async def _check_and_handle_interruption(self, chat_stream: ChatStream | None = None, message: DatabaseMessages | None = None):
"""检查并处理消息打断 - 支持多重回复任务取消"""
if not global_config.chat.interruption_enabled or not chat_stream:
if not global_config.chat.interruption_enabled or not chat_stream or not message:
return
# 🌟 修复:获取所有处理任务(包括多重回复)
# 检查是否为表情包消息
if message.is_picid or message.is_emoji:
logger.info(f"消息 {message.message_id} 是表情包或Emoji跳过打断检查")
return
# 修复:获取所有处理任务(包括多重回复)
all_processing_tasks = self.chatter_manager.get_all_processing_tasks(chat_stream.stream_id)
if all_processing_tasks:
# 检查触发用户ID
triggering_user_id = chat_stream.context_manager.context.triggering_user_id
if triggering_user_id and message.user_info.user_id != triggering_user_id:
logger.info(f"消息来自非触发用户 {message.user_info.user_id},实际触发用户为 {triggering_user_id},跳过打断检查")
return
# 计算打断概率 - 使用新的线性概率模型
interruption_probability = chat_stream.context_manager.context.calculate_interruption_probability(
global_config.chat.interruption_max_limit
@@ -386,7 +397,7 @@ class MessageManager:
if random.random() < interruption_probability:
logger.info(f"聊天流 {chat_stream.stream_id} 触发消息打断,打断概率: {interruption_probability:.2f},检测到 {len(all_processing_tasks)} 个任务")
# 🌟 修复:取消所有任务(包括多重回复)
# 修复:取消所有任务(包括多重回复)
cancelled_count = self.chatter_manager.cancel_all_stream_tasks(chat_stream.stream_id)
if cancelled_count > 0:
@@ -397,8 +408,8 @@ class MessageManager:
# 增加打断计数
await chat_stream.context_manager.context.increment_interruption_count()
# 🚀 新增:打断后立即重新进入聊天流程
# 🚀 新增:打断后延迟重新进入聊天流程,以合并短时间内的多条消息
# 新增:打断后立即重新进入聊天流程
# 新增:打断后延迟重新进入聊天流程,以合并短时间内的多条消息
asyncio.create_task(self._trigger_delayed_reprocess(chat_stream, delay=0.5))
# 检查是否已达到最大次数

View File

@@ -51,6 +51,7 @@ class StreamContext(BaseDataModel):
current_message: Optional["DatabaseMessages"] = None
priority_mode: str | None = None
priority_info: dict | None = None
triggering_user_id: str | None = None # 触发当前聊天流的用户ID
def add_action_to_message(self, message_id: str, action: str):
"""