Merge branch 'dev' of https://github.com/MaiM-with-u/MaiBot into dev
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
|
||||
from src.plugin_system.apis import send_api
|
||||
|
||||
|
||||
async def send_loading(chat_id: str, content: str):
|
||||
await send_api.custom_to_stream(
|
||||
message_type="loading",
|
||||
@@ -9,7 +10,8 @@ async def send_loading(chat_id: str, content: str):
|
||||
storage_message=False,
|
||||
show_log=True,
|
||||
)
|
||||
|
||||
|
||||
|
||||
async def send_unloading(chat_id: str):
|
||||
await send_api.custom_to_stream(
|
||||
message_type="loading",
|
||||
@@ -18,4 +20,3 @@ async def send_unloading(chat_id: str):
|
||||
storage_message=False,
|
||||
show_log=True,
|
||||
)
|
||||
|
||||
@@ -125,7 +125,7 @@ class ChatMood:
|
||||
)
|
||||
|
||||
self.last_change_time = 0
|
||||
|
||||
|
||||
# 发送初始情绪状态到ws端
|
||||
asyncio.create_task(self.send_emotion_update(self.mood_values))
|
||||
|
||||
@@ -231,10 +231,10 @@ class ChatMood:
|
||||
if numerical_mood_response:
|
||||
_old_mood_values = self.mood_values.copy()
|
||||
self.mood_values = numerical_mood_response
|
||||
|
||||
|
||||
# 发送情绪更新到ws端
|
||||
await self.send_emotion_update(self.mood_values)
|
||||
|
||||
|
||||
logger.info(f"[{self.chat_id}] 情绪变化: {_old_mood_values} -> {self.mood_values}")
|
||||
|
||||
self.last_change_time = message_time
|
||||
@@ -308,10 +308,10 @@ class ChatMood:
|
||||
if numerical_mood_response:
|
||||
_old_mood_values = self.mood_values.copy()
|
||||
self.mood_values = numerical_mood_response
|
||||
|
||||
|
||||
# 发送情绪更新到ws端
|
||||
await self.send_emotion_update(self.mood_values)
|
||||
|
||||
|
||||
logger.info(f"[{self.chat_id}] 情绪回归: {_old_mood_values} -> {self.mood_values}")
|
||||
|
||||
self.regression_count += 1
|
||||
@@ -322,9 +322,9 @@ class ChatMood:
|
||||
"joy": mood_values.get("joy", 5),
|
||||
"anger": mood_values.get("anger", 1),
|
||||
"sorrow": mood_values.get("sorrow", 1),
|
||||
"fear": mood_values.get("fear", 1)
|
||||
"fear": mood_values.get("fear", 1),
|
||||
}
|
||||
|
||||
|
||||
await send_api.custom_to_stream(
|
||||
message_type="emotion",
|
||||
content=emotion_data,
|
||||
@@ -332,7 +332,7 @@ class ChatMood:
|
||||
storage_message=False,
|
||||
show_log=True,
|
||||
)
|
||||
|
||||
|
||||
logger.info(f"[{self.chat_id}] 发送情绪更新: {emotion_data}")
|
||||
|
||||
|
||||
@@ -345,27 +345,27 @@ class MoodRegressionTask(AsyncTask):
|
||||
async def run(self):
|
||||
self.run_count += 1
|
||||
logger.info(f"[回归任务] 第{self.run_count}次检查,当前管理{len(self.mood_manager.mood_list)}个聊天的情绪状态")
|
||||
|
||||
|
||||
now = time.time()
|
||||
regression_executed = 0
|
||||
|
||||
|
||||
for mood in self.mood_manager.mood_list:
|
||||
chat_info = f"chat {mood.chat_id}"
|
||||
|
||||
|
||||
if mood.last_change_time == 0:
|
||||
logger.debug(f"[回归任务] {chat_info} 尚未有情绪变化,跳过回归")
|
||||
continue
|
||||
|
||||
time_since_last_change = now - mood.last_change_time
|
||||
|
||||
|
||||
# 检查是否有极端情绪需要快速回归
|
||||
high_emotions = {k: v for k, v in mood.mood_values.items() if v >= 8}
|
||||
has_extreme_emotion = len(high_emotions) > 0
|
||||
|
||||
|
||||
# 回归条件:1. 正常时间间隔(120s) 或 2. 有极端情绪且距上次变化>=30s
|
||||
should_regress = False
|
||||
regress_reason = ""
|
||||
|
||||
|
||||
if time_since_last_change > 120:
|
||||
should_regress = True
|
||||
regress_reason = f"常规回归(距上次变化{int(time_since_last_change)}秒)"
|
||||
@@ -373,24 +373,28 @@ class MoodRegressionTask(AsyncTask):
|
||||
should_regress = True
|
||||
high_emotion_str = ", ".join([f"{k}={v}" for k, v in high_emotions.items()])
|
||||
regress_reason = f"极端情绪快速回归({high_emotion_str}, 距上次变化{int(time_since_last_change)}秒)"
|
||||
|
||||
|
||||
if should_regress:
|
||||
if mood.regression_count >= 3:
|
||||
logger.debug(f"[回归任务] {chat_info} 已达到最大回归次数(3次),停止回归")
|
||||
continue
|
||||
|
||||
logger.info(f"[回归任务] {chat_info} 开始情绪回归 ({regress_reason},第{mood.regression_count + 1}次回归)")
|
||||
logger.info(
|
||||
f"[回归任务] {chat_info} 开始情绪回归 ({regress_reason},第{mood.regression_count + 1}次回归)"
|
||||
)
|
||||
await mood.regress_mood()
|
||||
regression_executed += 1
|
||||
else:
|
||||
if has_extreme_emotion:
|
||||
remaining_time = 5 - time_since_last_change
|
||||
high_emotion_str = ", ".join([f"{k}={v}" for k, v in high_emotions.items()])
|
||||
logger.debug(f"[回归任务] {chat_info} 存在极端情绪({high_emotion_str}),距离快速回归还需等待{int(remaining_time)}秒")
|
||||
logger.debug(
|
||||
f"[回归任务] {chat_info} 存在极端情绪({high_emotion_str}),距离快速回归还需等待{int(remaining_time)}秒"
|
||||
)
|
||||
else:
|
||||
remaining_time = 120 - time_since_last_change
|
||||
logger.debug(f"[回归任务] {chat_info} 距离回归还需等待{int(remaining_time)}秒")
|
||||
|
||||
|
||||
if regression_executed > 0:
|
||||
logger.info(f"[回归任务] 本次执行了{regression_executed}个聊天的情绪回归")
|
||||
else:
|
||||
@@ -409,11 +413,11 @@ class MoodManager:
|
||||
return
|
||||
|
||||
logger.info("启动情绪管理任务...")
|
||||
|
||||
|
||||
# 启动情绪回归任务
|
||||
regression_task = MoodRegressionTask(self)
|
||||
await async_task_manager.add_task(regression_task)
|
||||
|
||||
|
||||
self.task_started = True
|
||||
logger.info("情绪管理任务已启动(情绪回归)")
|
||||
|
||||
@@ -435,7 +439,7 @@ class MoodManager:
|
||||
# 发送重置后的情绪状态到ws端
|
||||
asyncio.create_task(mood.send_emotion_update(mood.mood_values))
|
||||
return
|
||||
|
||||
|
||||
# 如果没有找到现有的mood,创建新的
|
||||
new_mood = ChatMood(chat_id)
|
||||
self.mood_list.append(new_mood)
|
||||
|
||||
@@ -107,7 +107,6 @@ class S4UStreamGenerator:
|
||||
model_name: str,
|
||||
**kwargs,
|
||||
) -> AsyncGenerator[str, None]:
|
||||
|
||||
buffer = ""
|
||||
delimiters = ",。!?,.!?\n\r" # For final trimming
|
||||
punctuation_buffer = ""
|
||||
|
||||
@@ -43,23 +43,24 @@ logger = get_logger("watching")
|
||||
|
||||
class WatchingState(Enum):
|
||||
"""视线状态枚举"""
|
||||
|
||||
WANDERING = "wandering" # 随意看
|
||||
DANMU = "danmu" # 看弹幕
|
||||
LENS = "lens" # 看镜头
|
||||
DANMU = "danmu" # 看弹幕
|
||||
LENS = "lens" # 看镜头
|
||||
|
||||
|
||||
class ChatWatching:
|
||||
def __init__(self, chat_id: str):
|
||||
self.chat_id: str = chat_id
|
||||
self.current_state: WatchingState = WatchingState.LENS # 默认看镜头
|
||||
self.last_sent_state: Optional[WatchingState] = None # 上次发送的状态
|
||||
self.state_needs_update: bool = True # 是否需要更新状态
|
||||
|
||||
self.last_sent_state: Optional[WatchingState] = None # 上次发送的状态
|
||||
self.state_needs_update: bool = True # 是否需要更新状态
|
||||
|
||||
# 状态切换相关
|
||||
self.is_replying: bool = False # 是否正在生成回复
|
||||
self.reply_finished_time: Optional[float] = None # 回复完成时间
|
||||
self.danmu_viewing_duration: float = 1.0 # 看弹幕持续时间(秒)
|
||||
|
||||
self.is_replying: bool = False # 是否正在生成回复
|
||||
self.reply_finished_time: Optional[float] = None # 回复完成时间
|
||||
self.danmu_viewing_duration: float = 1.0 # 看弹幕持续时间(秒)
|
||||
|
||||
logger.info(f"[{self.chat_id}] 视线管理器初始化,默认状态: {self.current_state.value}")
|
||||
|
||||
async def _change_state(self, new_state: WatchingState, reason: str = ""):
|
||||
@@ -69,7 +70,7 @@ class ChatWatching:
|
||||
self.current_state = new_state
|
||||
self.state_needs_update = True
|
||||
logger.info(f"[{self.chat_id}] 视线状态切换: {old_state.value} → {new_state.value} ({reason})")
|
||||
|
||||
|
||||
# 立即发送视线状态更新
|
||||
await self._send_watching_update()
|
||||
else:
|
||||
@@ -86,7 +87,7 @@ class ChatWatching:
|
||||
"""开始生成回复时调用"""
|
||||
self.is_replying = True
|
||||
self.reply_finished_time = None
|
||||
|
||||
|
||||
if look_at_lens:
|
||||
await self._change_state(WatchingState.LENS, "开始生成回复-看镜头")
|
||||
else:
|
||||
@@ -96,35 +97,29 @@ class ChatWatching:
|
||||
"""生成回复完毕时调用"""
|
||||
self.is_replying = False
|
||||
self.reply_finished_time = time.time()
|
||||
|
||||
|
||||
# 先看弹幕1秒
|
||||
await self._change_state(WatchingState.DANMU, "回复完毕-看弹幕")
|
||||
logger.info(f"[{self.chat_id}] 回复完毕,将看弹幕{self.danmu_viewing_duration}秒后转为看镜头")
|
||||
|
||||
|
||||
# 设置定时器,1秒后自动切换到看镜头
|
||||
asyncio.create_task(self._auto_switch_to_lens())
|
||||
|
||||
async def _auto_switch_to_lens(self):
|
||||
"""自动切换到看镜头(延迟执行)"""
|
||||
await asyncio.sleep(self.danmu_viewing_duration)
|
||||
|
||||
|
||||
# 检查是否仍需要切换(可能状态已经被其他事件改变)
|
||||
if (self.reply_finished_time is not None and
|
||||
self.current_state == WatchingState.DANMU and
|
||||
not self.is_replying):
|
||||
|
||||
if self.reply_finished_time is not None and self.current_state == WatchingState.DANMU and not self.is_replying:
|
||||
await self._change_state(WatchingState.LENS, "看弹幕时间结束")
|
||||
self.reply_finished_time = None # 重置完成时间
|
||||
|
||||
async def _send_watching_update(self):
|
||||
"""立即发送视线状态更新"""
|
||||
await send_api.custom_to_stream(
|
||||
message_type="watching",
|
||||
content=self.current_state.value,
|
||||
stream_id=self.chat_id,
|
||||
storage_message=False
|
||||
message_type="watching", content=self.current_state.value, stream_id=self.chat_id, storage_message=False
|
||||
)
|
||||
|
||||
|
||||
logger.info(f"[{self.chat_id}] 发送视线状态更新: {self.current_state.value}")
|
||||
self.last_sent_state = self.current_state
|
||||
self.state_needs_update = False
|
||||
@@ -139,11 +134,10 @@ class ChatWatching:
|
||||
"current_state": self.current_state.value,
|
||||
"is_replying": self.is_replying,
|
||||
"reply_finished_time": self.reply_finished_time,
|
||||
"state_needs_update": self.state_needs_update
|
||||
"state_needs_update": self.state_needs_update,
|
||||
}
|
||||
|
||||
|
||||
|
||||
class WatchingManager:
|
||||
def __init__(self):
|
||||
self.watching_list: list[ChatWatching] = []
|
||||
@@ -156,7 +150,7 @@ class WatchingManager:
|
||||
return
|
||||
|
||||
logger.info("启动视线管理系统...")
|
||||
|
||||
|
||||
self.task_started = True
|
||||
logger.info("视线管理系统已启动(状态变化时立即发送)")
|
||||
|
||||
@@ -169,10 +163,10 @@ class WatchingManager:
|
||||
new_watching = ChatWatching(chat_id)
|
||||
self.watching_list.append(new_watching)
|
||||
logger.info(f"为chat {chat_id}创建新的视线管理器")
|
||||
|
||||
|
||||
# 发送初始状态
|
||||
asyncio.create_task(new_watching._send_watching_update())
|
||||
|
||||
|
||||
return new_watching
|
||||
|
||||
def reset_watching_by_chat_id(self, chat_id: str):
|
||||
@@ -185,27 +179,24 @@ class WatchingManager:
|
||||
watching.is_replying = False
|
||||
watching.reply_finished_time = None
|
||||
logger.info(f"[{chat_id}] 视线状态已重置为默认状态")
|
||||
|
||||
|
||||
# 发送重置后的状态
|
||||
asyncio.create_task(watching._send_watching_update())
|
||||
return
|
||||
|
||||
|
||||
# 如果没有找到现有的watching,创建新的
|
||||
new_watching = ChatWatching(chat_id)
|
||||
self.watching_list.append(new_watching)
|
||||
logger.info(f"为chat {chat_id}创建并重置视线管理器")
|
||||
|
||||
|
||||
# 发送初始状态
|
||||
asyncio.create_task(new_watching._send_watching_update())
|
||||
|
||||
def get_all_watching_info(self) -> dict:
|
||||
"""获取所有聊天的视线状态信息(用于调试)"""
|
||||
return {
|
||||
watching.chat_id: watching.get_state_info()
|
||||
for watching in self.watching_list
|
||||
}
|
||||
return {watching.chat_id: watching.get_state_info() for watching in self.watching_list}
|
||||
|
||||
|
||||
# 全局视线管理器实例
|
||||
watching_manager = WatchingManager()
|
||||
"""全局视线管理器"""
|
||||
"""全局视线管理器"""
|
||||
|
||||
Reference in New Issue
Block a user