import time import asyncio import random from random import random as random_float from typing import Dict from ..config.config import global_config from .message import MessageSending, MessageThinking, MessageSet, MessageRecv from ..message.message_base import UserInfo, Seg from .message_sender import message_manager from ..moods.moods import MoodManager from ..chat_module.reasoning_chat.reasoning_generator import ResponseGenerator from src.common.logger import get_module_logger from src.heart_flow.heartflow import heartflow from ...common.database import db logger = get_module_logger("auto_speak") class AutoSpeakManager: def __init__(self): self._last_auto_speak_time: Dict[str, float] = {} # 记录每个聊天流上次自主发言的时间 self.mood_manager = MoodManager.get_instance() self.gpt = ResponseGenerator() # 添加gpt实例 self._started = False self._check_task = None self.db = db async def get_chat_info(self, chat_id: str) -> dict: """从数据库获取聊天流信息""" chat_info = await self.db.chat_streams.find_one({"stream_id": chat_id}) return chat_info async def start_auto_speak_check(self): """启动自动发言检查任务""" if not self._started: self._check_task = asyncio.create_task(self._periodic_check()) self._started = True logger.success("自动发言检查任务已启动") async def _periodic_check(self): """定期检查是否需要自主发言""" while True and global_config.enable_think_flow: # 获取所有活跃的子心流 active_subheartflows = [] for chat_id, subheartflow in heartflow._subheartflows.items(): if ( subheartflow.is_active and subheartflow.current_state.willing > 0 ): # 只考虑活跃且意愿值大于0.5的子心流 active_subheartflows.append((chat_id, subheartflow)) logger.debug( f"发现活跃子心流 - 聊天ID: {chat_id}, 意愿值: {subheartflow.current_state.willing:.2f}" ) if not active_subheartflows: logger.debug("当前没有活跃的子心流") await asyncio.sleep(20) # 添加异步等待 continue # 随机选择一个活跃的子心流 chat_id, subheartflow = random.choice(active_subheartflows) logger.info(f"随机选择子心流 - 聊天ID: {chat_id}, 意愿值: {subheartflow.current_state.willing:.2f}") # 检查是否应该自主发言 if await self.check_auto_speak(subheartflow): logger.info(f"准备自主发言 - 聊天ID: {chat_id}") # 生成自主发言 bot_user_info = UserInfo( user_id=global_config.BOT_QQ, user_nickname=global_config.BOT_NICKNAME, platform="qq", # 默认使用qq平台 ) # 创建一个空的MessageRecv对象作为上下文 message = MessageRecv( { "message_info": { "user_info": {"user_id": chat_id, "user_nickname": "", "platform": "qq"}, "group_info": None, "platform": "qq", "time": time.time(), }, "processed_plain_text": "", "raw_message": "", "is_emoji": False, } ) await self.generate_auto_speak( subheartflow, message, bot_user_info, message.message_info["user_info"], message.message_info ) else: logger.debug(f"不满足自主发言条件 - 聊天ID: {chat_id}") # 每分钟检查一次 await asyncio.sleep(20) # await asyncio.sleep(5) # 发生错误时等待5秒再继续 async def check_auto_speak(self, subheartflow) -> bool: """检查是否应该自主发言""" if not subheartflow: return False current_time = time.time() chat_id = subheartflow.observe_chat_id # 获取上次自主发言时间 if chat_id not in self._last_auto_speak_time: self._last_auto_speak_time[chat_id] = 0 last_speak_time = self._last_auto_speak_time.get(chat_id, 0) # 如果距离上次自主发言不到5分钟,不发言 if current_time - last_speak_time < 30: logger.debug( f"距离上次发言时间太短 - 聊天ID: {chat_id}, 剩余时间: {30 - (current_time - last_speak_time):.1f}秒" ) return False # 获取当前意愿值 current_willing = subheartflow.current_state.willing if current_willing > 0.1 and random_float() < 0.5: self._last_auto_speak_time[chat_id] = current_time logger.info(f"满足自主发言条件 - 聊天ID: {chat_id}, 意愿值: {current_willing:.2f}") return True logger.debug(f"不满足自主发言条件 - 聊天ID: {chat_id}, 意愿值: {current_willing:.2f}") return False async def generate_auto_speak(self, subheartflow, message, bot_user_info: UserInfo, userinfo, messageinfo): """生成自主发言内容""" thinking_time_point = round(time.time(), 2) think_id = "mt" + str(thinking_time_point) thinking_message = MessageThinking( message_id=think_id, chat_stream=None, # 不需要chat_stream bot_user_info=bot_user_info, reply=message, thinking_start_time=thinking_time_point, ) message_manager.add_message(thinking_message) # 生成自主发言内容 try: response, raw_content = await self.gpt.generate_response(message) except Exception as e: logger.error(f"生成自主发言内容时发生错误: {e}") return False if response: message_set = MessageSet(None, think_id) # 不需要chat_stream mark_head = False for msg in response: message_segment = Seg(type="text", data=msg) bot_message = MessageSending( message_id=think_id, chat_stream=None, # 不需要chat_stream bot_user_info=bot_user_info, sender_info=userinfo, message_segment=message_segment, reply=message, is_head=not mark_head, is_emoji=False, thinking_start_time=thinking_time_point, ) if not mark_head: mark_head = True message_set.add_message(bot_message) message_manager.add_message(message_set) # 更新情绪和关系 stance, emotion = await self.gpt._get_emotion_tags(raw_content, message.processed_plain_text) self.mood_manager.update_mood_from_emotion(emotion, global_config.mood_intensity_factor) return True return False # 创建全局AutoSpeakManager实例 auto_speak_manager = AutoSpeakManager()