feat(sleep): 引入多样化的失眠触发机制

重构了失眠系统,引入了两种新的失眠触发机制:
1.  **低睡眠压力失眠**:当睡后检查时睡眠压力低于设定阈值,将触发失眠。
2.  **随机失眠**:在睡眠压力正常的情况下,仍有一定概率随机触发失眠。

同时,移除了原有的 `post_sleep_insomnia` 特定情绪,并调整了相关配置项,使失眠原因的传递和处理更加灵活。
This commit is contained in:
minecraft1024a
2025-09-06 13:55:57 +08:00
parent 0b1d365fce
commit 614f8064ba
4 changed files with 14 additions and 16 deletions

View File

@@ -89,8 +89,6 @@ class ProactiveThinker:
new_mood = "深夜emo胡思乱想" new_mood = "深夜emo胡思乱想"
elif trigger_event.reason == "goodnight": elif trigger_event.reason == "goodnight":
new_mood = "有点困了,准备睡觉了" new_mood = "有点困了,准备睡觉了"
elif trigger_event.reason == "post_sleep_insomnia":
new_mood = "可恶,刚刚好像睡着了又醒了,现在睡不着了"
# 如果成功匹配到了新的情绪,则更新情绪状态 # 如果成功匹配到了新的情绪,则更新情绪状态
if new_mood: if new_mood:
@@ -117,7 +115,7 @@ class ProactiveThinker:
actions, target_message = await self.cycle_processor.action_planner.plan(mode=ChatMode.PROACTIVE) actions, target_message = await self.cycle_processor.action_planner.plan(mode=ChatMode.PROACTIVE)
# 通常只关心规划出的第一个动作 # 通常只关心规划出的第一个动作
action_result = actions if actions else {} action_result = actions[0] if actions else {}
# 检查规划出的动作是否是“什么都不做” # 检查规划出的动作是否是“什么都不做”
if action_result and action_result.get("action_type") != "do_nothing": if action_result and action_result.get("action_type") != "do_nothing":

View File

@@ -20,13 +20,13 @@ class NotificationSender:
logger.error(f"发送晚安通知失败: {e}") logger.error(f"发送晚安通知失败: {e}")
@staticmethod @staticmethod
async def send_insomnia_notification(context: HfcContext): async def send_insomnia_notification(context: HfcContext, reason: str):
"""发送失眠通知""" """发送失眠通知"""
try: try:
from ..proactive.events import ProactiveTriggerEvent from ..proactive.events import ProactiveTriggerEvent
from ..proactive.proactive_thinker import ProactiveThinker from ..proactive.proactive_thinker import ProactiveThinker
event = ProactiveTriggerEvent(source="sleep_manager", reason="post_sleep_insomnia") event = ProactiveTriggerEvent(source="sleep_manager", reason=reason)
proactive_thinker = ProactiveThinker(context, context.chat_instance.cycle_processor) proactive_thinker = ProactiveThinker(context, context.chat_instance.cycle_processor)
await proactive_thinker.think(event) await proactive_thinker.think(event)
except Exception as e: except Exception as e:

View File

@@ -148,19 +148,26 @@ class SleepManager:
if wakeup_manager: if wakeup_manager:
sleep_pressure = wakeup_manager.context.sleep_pressure sleep_pressure = wakeup_manager.context.sleep_pressure
pressure_threshold = global_config.sleep_system.flexible_sleep_pressure_threshold pressure_threshold = global_config.sleep_system.flexible_sleep_pressure_threshold
# 如果睡眠压力低于阈值,则触发失眠 # 检查是否触发失眠
insomnia_reason = None
if sleep_pressure < pressure_threshold: if sleep_pressure < pressure_threshold:
insomnia_reason = "low_pressure"
logger.info(f"睡眠压力 ({sleep_pressure:.1f}) 低于阈值 ({pressure_threshold}),触发睡后失眠。") logger.info(f"睡眠压力 ({sleep_pressure:.1f}) 低于阈值 ({pressure_threshold}),触发睡后失眠。")
elif random.random() < getattr(global_config.sleep_system, "random_insomnia_chance", 0.1):
insomnia_reason = "random"
logger.info("随机触发失眠。")
if insomnia_reason:
self._current_state = SleepState.INSOMNIA self._current_state = SleepState.INSOMNIA
# 设置失眠的持续时间 # 设置失眠的持续时间
duration_minutes_range = global_config.sleep_system.insomnia_duration_minutes duration_minutes_range = global_config.sleep_system.insomnia_duration_minutes
duration_minutes = random.randint(duration_minutes_range[0], duration_minutes_range[1]) duration_minutes = random.randint(*duration_minutes_range)
self._sleep_buffer_end_time = now + timedelta(minutes=duration_minutes) self._sleep_buffer_end_time = now + timedelta(minutes=duration_minutes)
# 发送失眠通知 # 发送失眠通知
asyncio.create_task(NotificationSender.send_insomnia_notification(wakeup_manager.context)) asyncio.create_task(NotificationSender.send_insomnia_notification(wakeup_manager.context, insomnia_reason))
logger.info(f"进入失眠状态,将持续 {duration_minutes} 分钟。") logger.info(f"进入失眠状态 (原因: {insomnia_reason}),将持续 {duration_minutes} 分钟。")
else: else:
# 睡眠压力正常,不触发失眠,清除检查时间点 # 睡眠压力正常,不触发失眠,清除检查时间点
logger.info(f"睡眠压力 ({sleep_pressure:.1f}) 正常,未触发睡后失眠。") logger.info(f"睡眠压力 ({sleep_pressure:.1f}) 正常,未触发睡后失眠。")

View File

@@ -222,11 +222,6 @@ willing_mode = "classical" # 回复意愿模式 —— 经典模式classical
[tool] [tool]
enable_tool = true # 是否在普通聊天中启用工具 enable_tool = true # 是否在普通聊天中启用工具
[tool.history]
enable_history = true # 是否启用工具调用历史记录
enable_prompt_history = true # 是否在提示词中加入工具历史记录
max_history = 5 # 每个会话最多保留的历史记录数
[mood] [mood]
enable_mood = true # 是否启用情绪系统 enable_mood = true # 是否启用情绪系统
mood_update_threshold = 1 # 情绪更新阈值,越高,更新越慢 mood_update_threshold = 1 # 情绪更新阈值,越高,更新越慢
@@ -443,8 +438,6 @@ enable_insomnia_system = false # 是否启用失眠系统
sleep_pressure_threshold = 30.0 sleep_pressure_threshold = 30.0
# 进入“深度睡眠”的睡眠压力阈值 # 进入“深度睡眠”的睡眠压力阈值
deep_sleep_threshold = 80.0 deep_sleep_threshold = 80.0
# 压力不足时的失眠基础概率 (0.0 to 1.0)
insomnia_chance_low_pressure = 0.6
# 压力正常时的失眠基础概率 (0.0 to 1.0) # 压力正常时的失眠基础概率 (0.0 to 1.0)
insomnia_chance_normal_pressure = 0.1 insomnia_chance_normal_pressure = 0.1
# 每次AI执行动作后增加的睡眠压力值 # 每次AI执行动作后增加的睡眠压力值