feat:启用频率控制,优化模式切换
This commit is contained in:
@@ -100,6 +100,7 @@ class HeartFChatting:
|
||||
# 循环控制内部状态
|
||||
self.running: bool = False
|
||||
self._loop_task: Optional[asyncio.Task] = None # 主循环任务
|
||||
self._energy_task: Optional[asyncio.Task] = None
|
||||
|
||||
# 添加循环信息管理相关的属性
|
||||
self.history_loop: List[CycleDetail] = []
|
||||
@@ -139,6 +140,9 @@ class HeartFChatting:
|
||||
# 标记为活动状态,防止重复启动
|
||||
self.running = True
|
||||
|
||||
self._energy_task = asyncio.create_task(self._energy_loop())
|
||||
self._energy_task.add_done_callback(self._handle_energy_completion)
|
||||
|
||||
self._loop_task = asyncio.create_task(self._main_chat_loop())
|
||||
self._loop_task.add_done_callback(self._handle_loop_completion)
|
||||
logger.info(f"{self.log_prefix} HeartFChatting 启动完成")
|
||||
@@ -173,6 +177,22 @@ class HeartFChatting:
|
||||
self.history_loop.append(self._current_cycle_detail)
|
||||
self._current_cycle_detail.timers = cycle_timers
|
||||
self._current_cycle_detail.end_time = time.time()
|
||||
|
||||
|
||||
def _handle_energy_completion(self, task: asyncio.Task):
|
||||
if exception := task.exception():
|
||||
logger.error(f"{self.log_prefix} HeartFChatting: 能量循环异常: {exception}")
|
||||
logger.error(traceback.format_exc())
|
||||
else:
|
||||
logger.info(f"{self.log_prefix} HeartFChatting: 能量循环完成")
|
||||
|
||||
async def _energy_loop(self):
|
||||
while self.running:
|
||||
await asyncio.sleep(1)
|
||||
if self.loop_mode == ChatMode.NORMAL:
|
||||
self.energy_value -= 1
|
||||
if self.energy_value <= 0:
|
||||
self.energy_value = 0
|
||||
|
||||
def print_cycle_info(self, cycle_timers):
|
||||
# 记录循环信息和计时器结果
|
||||
@@ -190,12 +210,16 @@ class HeartFChatting:
|
||||
|
||||
async def _loopbody(self):
|
||||
if self.loop_mode == ChatMode.FOCUS:
|
||||
self.energy_value -= 5 * global_config.chat.focus_value
|
||||
if await self._observe():
|
||||
self.energy_value -= 1 * global_config.chat.focus_value
|
||||
else:
|
||||
self.energy_value -= 3 * global_config.chat.focus_value
|
||||
if self.energy_value <= 0:
|
||||
self.energy_value = 0
|
||||
self.loop_mode = ChatMode.NORMAL
|
||||
return True
|
||||
|
||||
return await self._observe()
|
||||
return False
|
||||
elif self.loop_mode == ChatMode.NORMAL:
|
||||
new_messages_data = get_raw_msg_by_timestamp_with_chat(
|
||||
chat_id=self.stream_id,
|
||||
@@ -206,17 +230,24 @@ class HeartFChatting:
|
||||
filter_bot=True,
|
||||
)
|
||||
|
||||
if len(new_messages_data) > 4 * global_config.chat.focus_value:
|
||||
if len(new_messages_data) > 3 * global_config.chat.focus_value:
|
||||
self.loop_mode = ChatMode.FOCUS
|
||||
self.energy_value = 10 + (new_messages_data / 3) * 10
|
||||
return True
|
||||
|
||||
if self.energy_value >= 30 * global_config.chat.focus_value:
|
||||
self.loop_mode = ChatMode.FOCUS
|
||||
self.energy_value = 100
|
||||
return True
|
||||
|
||||
if new_messages_data:
|
||||
earliest_messages_data = new_messages_data[0]
|
||||
self.last_read_time = earliest_messages_data.get("time")
|
||||
|
||||
await self.normal_response(earliest_messages_data)
|
||||
return True
|
||||
if_think = await self.normal_response(earliest_messages_data)
|
||||
if if_think:
|
||||
self.energy_value *= 1.1
|
||||
logger.info(f"{self.log_prefix} 麦麦进行了思考,能量值增加1,当前能量值:{self.energy_value}")
|
||||
return False
|
||||
|
||||
await asyncio.sleep(1)
|
||||
|
||||
@@ -234,6 +265,7 @@ class HeartFChatting:
|
||||
async def _observe(self, message_data: Optional[Dict[str, Any]] = None):
|
||||
if not message_data:
|
||||
message_data = {}
|
||||
action_type = "no_action"
|
||||
# 创建新的循环信息
|
||||
cycle_timers, thinking_id = self.start_cycle()
|
||||
|
||||
@@ -322,6 +354,8 @@ class HeartFChatting:
|
||||
success, reply_text, command = await self._handle_action(
|
||||
action_type, reasoning, action_data, cycle_timers, thinking_id, action_message
|
||||
)
|
||||
|
||||
|
||||
|
||||
loop_info = {
|
||||
"loop_plan_info": {
|
||||
@@ -346,6 +380,9 @@ class HeartFChatting:
|
||||
if self.loop_mode == ChatMode.NORMAL:
|
||||
await self.willing_manager.after_generate_reply_handle(message_data.get("message_id", ""))
|
||||
|
||||
if action_type != "no_reply" and action_type != "no_action":
|
||||
return True
|
||||
|
||||
return True
|
||||
|
||||
async def _main_chat_loop(self):
|
||||
@@ -432,110 +469,6 @@ class HeartFChatting:
|
||||
traceback.print_exc()
|
||||
return False, "", ""
|
||||
|
||||
# async def shutdown(self):
|
||||
# """优雅关闭HeartFChatting实例,取消活动循环任务"""
|
||||
# logger.info(f"{self.log_prefix} 正在关闭HeartFChatting...")
|
||||
# self.running = False # <-- 在开始关闭时设置标志位
|
||||
|
||||
# # 记录最终的消息统计
|
||||
# if self._message_count > 0:
|
||||
# logger.info(f"{self.log_prefix} 本次focus会话共发送了 {self._message_count} 条消息")
|
||||
# if self._fatigue_triggered:
|
||||
# logger.info(f"{self.log_prefix} 因疲惫而退出focus模式")
|
||||
|
||||
# # 取消循环任务
|
||||
# if self._loop_task and not self._loop_task.done():
|
||||
# logger.info(f"{self.log_prefix} 正在取消HeartFChatting循环任务")
|
||||
# self._loop_task.cancel()
|
||||
# try:
|
||||
# await asyncio.wait_for(self._loop_task, timeout=1.0)
|
||||
# logger.info(f"{self.log_prefix} HeartFChatting循环任务已取消")
|
||||
# except (asyncio.CancelledError, asyncio.TimeoutError):
|
||||
# pass
|
||||
# except Exception as e:
|
||||
# logger.error(f"{self.log_prefix} 取消循环任务出错: {e}")
|
||||
# else:
|
||||
# logger.info(f"{self.log_prefix} 没有活动的HeartFChatting循环任务")
|
||||
|
||||
# # 清理状态
|
||||
# self.running = False
|
||||
# self._loop_task = None
|
||||
|
||||
# # 重置消息计数器,为下次启动做准备
|
||||
# self.reset_message_count()
|
||||
|
||||
# logger.info(f"{self.log_prefix} HeartFChatting关闭完成")
|
||||
|
||||
def adjust_reply_frequency(self):
|
||||
"""
|
||||
根据预设规则动态调整回复意愿(willing_amplifier)。
|
||||
- 评估周期:10分钟
|
||||
- 目标频率:由 global_config.chat.talk_frequency 定义(例如 1条/分钟)
|
||||
- 调整逻辑:
|
||||
- 0条回复 -> 5.0x 意愿
|
||||
- 达到目标回复数 -> 1.0x 意愿(基准)
|
||||
- 达到目标2倍回复数 -> 0.2x 意愿
|
||||
- 中间值线性变化
|
||||
- 增益抑制:如果最近5分钟回复过快,则不增加意愿。
|
||||
"""
|
||||
# --- 1. 定义参数 ---
|
||||
evaluation_minutes = 10.0
|
||||
target_replies_per_min = global_config.chat.get_current_talk_frequency(
|
||||
self.stream_id
|
||||
) # 目标频率:e.g. 1条/分钟
|
||||
target_replies_in_window = target_replies_per_min * evaluation_minutes # 10分钟内的目标回复数
|
||||
|
||||
if target_replies_in_window <= 0:
|
||||
logger.debug(f"[{self.log_prefix}] 目标回复频率为0或负数,不调整意愿放大器。")
|
||||
return
|
||||
|
||||
# --- 2. 获取近期统计数据 ---
|
||||
stats_10_min = get_recent_message_stats(minutes=evaluation_minutes, chat_id=self.stream_id)
|
||||
bot_reply_count_10_min = stats_10_min["bot_reply_count"]
|
||||
|
||||
# --- 3. 计算新的意愿放大器 (willing_amplifier) ---
|
||||
# 基于回复数在 [0, target*2] 区间内进行分段线性映射
|
||||
if bot_reply_count_10_min <= target_replies_in_window:
|
||||
# 在 [0, 目标数] 区间,意愿从 5.0 线性下降到 1.0
|
||||
new_amplifier = 5.0 + (bot_reply_count_10_min - 0) * (1.0 - 5.0) / (target_replies_in_window - 0)
|
||||
elif bot_reply_count_10_min <= target_replies_in_window * 2:
|
||||
# 在 [目标数, 目标数*2] 区间,意愿从 1.0 线性下降到 0.2
|
||||
over_target_cap = target_replies_in_window * 2
|
||||
new_amplifier = 1.0 + (bot_reply_count_10_min - target_replies_in_window) * (0.2 - 1.0) / (
|
||||
over_target_cap - target_replies_in_window
|
||||
)
|
||||
else:
|
||||
# 超过目标数2倍,直接设为最小值
|
||||
new_amplifier = 0.2
|
||||
|
||||
# --- 4. 检查是否需要抑制增益 ---
|
||||
# "如果邻近5分钟内,回复数量 > 频率/2,就不再进行增益"
|
||||
suppress_gain = False
|
||||
if new_amplifier > self.willing_amplifier: # 仅在计算结果为增益时检查
|
||||
suppression_minutes = 5.0
|
||||
# 5分钟内目标回复数的一半
|
||||
suppression_threshold = (target_replies_per_min / 2) * suppression_minutes # e.g., (1/2)*5 = 2.5
|
||||
stats_5_min = get_recent_message_stats(minutes=suppression_minutes, chat_id=self.stream_id)
|
||||
bot_reply_count_5_min = stats_5_min["bot_reply_count"]
|
||||
|
||||
if bot_reply_count_5_min > suppression_threshold:
|
||||
suppress_gain = True
|
||||
|
||||
# --- 5. 更新意愿放大器 ---
|
||||
if suppress_gain:
|
||||
logger.debug(
|
||||
f"[{self.log_prefix}] 回复增益被抑制。最近5分钟内回复数 ({bot_reply_count_5_min}) "
|
||||
f"> 阈值 ({suppression_threshold:.1f})。意愿放大器保持在 {self.willing_amplifier:.2f}"
|
||||
)
|
||||
# 不做任何改动
|
||||
else:
|
||||
# 限制最终值在 [0.2, 5.0] 范围内
|
||||
self.willing_amplifier = max(0.2, min(5.0, new_amplifier))
|
||||
logger.debug(
|
||||
f"[{self.log_prefix}] 调整回复意愿。10分钟内回复: {bot_reply_count_10_min} (目标: {target_replies_in_window:.0f}) -> "
|
||||
f"意愿放大器更新为: {self.willing_amplifier:.2f}"
|
||||
)
|
||||
|
||||
async def normal_response(self, message_data: dict) -> None:
|
||||
"""
|
||||
处理接收到的消息。
|
||||
@@ -575,12 +508,18 @@ class HeartFChatting:
|
||||
f"{message_data.get('user_nickname')}:"
|
||||
f"{message_data.get('processed_plain_text')}[兴趣:{interested_rate:.2f}][回复概率:{reply_probability * 100:.1f}%]"
|
||||
)
|
||||
|
||||
talk_frequency = global_config.chat.get_current_talk_frequency(self.stream_id)
|
||||
reply_probability = talk_frequency * reply_probability
|
||||
|
||||
if random.random() < reply_probability:
|
||||
await self.willing_manager.before_generate_reply_handle(message_data.get("message_id", ""))
|
||||
await self._observe(message_data=message_data)
|
||||
return True
|
||||
|
||||
|
||||
# 意愿管理器:注销当前message信息 (无论是否回复,只要处理过就删除)
|
||||
return False
|
||||
self.willing_manager.delete(message_data.get("message_id", ""))
|
||||
|
||||
async def _generate_response(
|
||||
|
||||
Reference in New Issue
Block a user