feat:为normal_chat提供选项,有效控制回复频率

This commit is contained in:
SengokuCola
2025-05-28 20:41:46 +08:00
parent a2eb4a163b
commit bc489861d3
12 changed files with 138 additions and 284 deletions

View File

@@ -1,12 +1,9 @@
import asyncio
import statistics # 导入 statistics 模块
import time
import traceback
from random import random
from typing import List, Optional # 导入 Optional
from maim_message import UserInfo, Seg
from src.common.logger_manager import get_logger
from src.chat.heart_flow.utils_chat import get_chat_type_and_target_info
from src.manager.mood_manager import mood_manager
@@ -21,6 +18,7 @@ from src.chat.message_receive.message_sender import message_manager
from src.chat.utils.utils_image import image_path_to_base64
from src.chat.emoji_system.emoji_manager import emoji_manager
from src.chat.normal_chat.willing.willing_manager import willing_manager
from src.chat.normal_chat.normal_chat_utils import get_recent_message_stats
from src.config.config import global_config
logger = get_logger("normal_chat")
@@ -39,6 +37,8 @@ class NormalChat:
self.is_group_chat: bool = False
self.chat_target_info: Optional[dict] = None
self.willing_amplifier = 1
# Other sync initializations
self.gpt = NormalChatGenerator()
@@ -209,10 +209,12 @@ class NormalChat:
for msg_id, (message, interest_value, is_mentioned) in items_to_process:
try:
# 处理消息
self.adjust_reply_frequency()
await self.normal_response(
message=message,
is_mentioned=is_mentioned,
interested_rate=interest_value,
interested_rate=interest_value * self.willing_amplifier,
rewind_response=False,
)
except Exception as e:
@@ -228,26 +230,18 @@ class NormalChat:
if self._disabled:
logger.info(f"[{self.stream_name}] 已停用,忽略 normal_response。")
return
# 检查收到的消息是否属于当前实例处理的 chat stream
if message.chat_stream.stream_id != self.stream_id:
logger.error(
f"[{self.stream_name}] normal_response 收到不匹配的消息 (来自 {message.chat_stream.stream_id}),预期 {self.stream_id}。已忽略。"
)
return
timing_results = {}
reply_probability = 1.0 if is_mentioned else 0.0 # 如果被提及基础概率为1否则需要意愿判断
# 意愿管理器设置当前message信息
willing_manager.setup(message, self.chat_stream, is_mentioned, interested_rate)
# 获取回复概率
is_willing = False
# is_willing = False
# 仅在未被提及或基础概率不为1时查询意愿概率
if reply_probability < 1: # 简化逻辑,如果未提及 (reply_probability 为 0),则获取意愿概率
is_willing = True
# is_willing = True
reply_probability = await willing_manager.get_reply_probability(message.message_info.message_id)
if message.message_info.additional_config:
@@ -257,13 +251,13 @@ class NormalChat:
# 打印消息信息
mes_name = self.chat_stream.group_info.group_name if self.chat_stream.group_info else "私聊"
current_time = time.strftime("%H:%M:%S", time.localtime(message.message_info.time))
# current_time = time.strftime("%H:%M:%S", time.localtime(message.message_info.time))
# 使用 self.stream_id
willing_log = f"[回复意愿:{await willing_manager.get_willing(self.stream_id):.2f}]" if is_willing else ""
# willing_log = f"[激活值:{await willing_manager.get_willing(self.stream_id):.2f}]" if is_willing else ""
logger.info(
f"[{current_time}][{mes_name}]"
f"[{mes_name}]"
f"{message.message_info.user_info.user_nickname}:" # 使用 self.chat_stream
f"{message.processed_plain_text}{willing_log}[概率:{reply_probability * 100:.1f}%]"
f"{message.processed_plain_text}[回复概率:{reply_probability * 100:.1f}%]"
)
do_reply = False
response_set = None # 初始化 response_set
@@ -346,16 +340,13 @@ class NormalChat:
# 检查是否需要切换到focus模式
await self._check_switch_to_focus()
else:
logger.warning(f"[{self.stream_name}] 思考消息 {thinking_id} 在发送前丢失,无法记录 info_catcher")
info_catcher.done_catch()
# 处理表情包 (不再需要传入 chat)
with Timer("处理表情包", timing_results):
await self._handle_emoji(message, response_set[0])
# 更新关系情绪 (不再需要传入 chat)
with Timer("关系更新", timing_results):
await self._update_relationship(message, response_set)
@@ -479,9 +470,6 @@ class NormalChat:
# 统计1分钟内的回复数量
recent_reply_count = sum(1 for reply in self.recent_replies if reply["time"] > one_minute_ago)
# print(111111111111111333333333333333333333333331111111111111111111111111111111111)
# print(recent_reply_count)
# 如果1分钟内回复数量大于8触发切换到focus模式
if recent_reply_count > reply_threshold:
logger.info(
f"[{self.stream_name}] 检测到1分钟内回复数量({recent_reply_count})大于{reply_threshold}触发切换到focus模式"
@@ -491,3 +479,29 @@ class NormalChat:
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):
"""
调整回复频率
"""
# 获取最近30分钟内的消息统计
print(f"willing_amplifier: {self.willing_amplifier}")
stats = get_recent_message_stats(minutes=duration, chat_id=self.stream_id)
bot_reply_count = stats["bot_reply_count"]
print(f"[{self.stream_name}] 最近{duration}分钟内回复数量: {bot_reply_count}")
total_message_count = stats["total_message_count"]
print(f"[{self.stream_name}] 最近{duration}分钟内消息总数: {total_message_count}")
# 计算回复频率
_reply_frequency = bot_reply_count / total_message_count
# 如果回复频率低于0.5,增加回复概率
if bot_reply_count/duration < global_config.normal_chat.talk_frequency:
# differ = global_config.normal_chat.talk_frequency - reply_frequency
logger.info(f"[{self.stream_name}] 回复频率低于{global_config.normal_chat.talk_frequency},增加回复概率")
self.willing_amplifier += 0.1
else:
logger.info(f"[{self.stream_name}] 回复频率高于{global_config.normal_chat.talk_frequency},减少回复概率")
self.willing_amplifier -= 0.1

View File

@@ -0,0 +1,33 @@
import time
from src.config.config import global_config
from src.common.message_repository import count_messages
def get_recent_message_stats(minutes: int = 30, chat_id: str = None) -> dict:
"""
Args:
minutes (int): 检索的分钟数默认30分钟
chat_id (str, optional): 指定的chat_id仅统计该chat下的消息。为None时统计全部。
Returns:
dict: {"bot_reply_count": int, "total_message_count": int}
"""
now = time.time()
start_time = now - minutes * 60
bot_id = global_config.bot.qq_account
filter_base = {"time": {"$gte": start_time}}
if chat_id is not None:
filter_base["chat_id"] = chat_id
# 总消息数
total_message_count = count_messages(filter_base)
# bot自身回复数
bot_filter = filter_base.copy()
bot_filter["user_id"] = bot_id
bot_reply_count = count_messages(bot_filter)
return {
"bot_reply_count": bot_reply_count,
"total_message_count": total_message_count
}