迁移:69a855d(feat:保存关键词到message数据库)

This commit is contained in:
Windpicker-owo
2025-09-01 15:24:43 +08:00
parent 276c08224e
commit 6cf59deef3
8 changed files with 51 additions and 59 deletions

View File

@@ -159,18 +159,11 @@ class CycleProcessor:
self.context.last_action = action_type self.context.last_action = action_type
# 处理no_reply相关的逻辑 # 处理no_reply相关的逻辑
if action_type != "no_reply" and action_type != "no_action": if action_type != "no_reply":
# 导入NoReplyAction并重置计数器
from src.plugins.built_in.core_actions.no_reply import NoReplyAction
NoReplyAction.reset_consecutive_count()
self.context.no_reply_consecutive = 0 self.context.no_reply_consecutive = 0
logger.info(f"{self.context.log_prefix} 执行了{action_type}动作重置no_reply计数器") if hasattr(self.context, 'chat_instance') and self.context.chat_instance:
elif action_type == "no_action": self.context.chat_instance.recent_interest_records.clear()
# 当执行回复动作时也重置no_reply计数 logger.info(f"{self.context.log_prefix} 执行了{action_type}动作重置no_reply计数器和兴趣度记录")
from src.plugins.built_in.core_actions.no_reply import NoReplyAction
NoReplyAction.reset_consecutive_count()
self.context.no_reply_consecutive = 0
logger.info(f"{self.context.log_prefix} 执行了回复动作重置no_reply计数器")
if action_type == "no_reply": if action_type == "no_reply":
self.context.no_reply_consecutive += 1 self.context.no_reply_consecutive += 1

View File

@@ -3,6 +3,7 @@ import time
import traceback import traceback
import random import random
from typing import Optional, List, Dict, Any, Tuple from typing import Optional, List, Dict, Any, Tuple
from collections import deque
from src.common.logger import get_logger from src.common.logger import get_logger
from src.config.config import global_config from src.config.config import global_config
@@ -56,6 +57,9 @@ class HeartFChatting:
self._loop_task: Optional[asyncio.Task] = None self._loop_task: Optional[asyncio.Task] = None
# 记录最近3次的兴趣度
self.recent_interest_records: deque = deque(maxlen=3)
self._initialize_chat_mode() self._initialize_chat_mode()
logger.info(f"{self.context.log_prefix} HeartFChatting 初始化完成") logger.info(f"{self.context.log_prefix} HeartFChatting 初始化完成")
@@ -242,14 +246,11 @@ class HeartFChatting:
logger.info(f"{self.context.log_prefix} 从睡眠中被唤醒,将处理积压的消息。") logger.info(f"{self.context.log_prefix} 从睡眠中被唤醒,将处理积压的消息。")
# 根据聊天模式处理新消息 # 根据聊天模式处理新消息
if self.context.loop_mode == ChatMode.FOCUS: # 统一使用 _should_process_messages 判断是否应该处理
# 如果上一个动作是no_reply则执行no_reply逻辑 if not self._should_process_messages(recent_messages if has_new_messages else None):
if self.context.last_action == "no_reply":
if not await self._execute_no_reply(recent_messages):
self.context.energy_value -= 0.3 / global_config.chat.focus_value
logger.info(f"{self.context.log_prefix} 能量值减少,当前能量值:{self.context.energy_value:.1f}")
return has_new_messages return has_new_messages
if self.context.loop_mode == ChatMode.FOCUS:
# 处理新消息 # 处理新消息
for message in recent_messages: for message in recent_messages:
await self.cycle_processor.observe(message) await self.cycle_processor.observe(message)
@@ -399,8 +400,7 @@ class HeartFChatting:
self.context.focus_energy = 1 self.context.focus_energy = 1
else: else:
# 计算最近三次记录的兴趣度总和 # 计算最近三次记录的兴趣度总和
from src.plugins.built_in.core_actions.no_reply import NoReplyAction total_recent_interest = sum(self.recent_interest_records)
total_recent_interest = sum(NoReplyAction._recent_interest_records)
# 获取当前聊天频率和意愿系数 # 获取当前聊天频率和意愿系数
talk_frequency = global_config.chat.get_current_talk_frequency(self.context.stream_id) talk_frequency = global_config.chat.get_current_talk_frequency(self.context.stream_id)
@@ -418,6 +418,22 @@ class HeartFChatting:
logger.info(f"{self.context.log_prefix} 兴趣度充足") logger.info(f"{self.context.log_prefix} 兴趣度充足")
self.context.focus_energy = 1 self.context.focus_energy = 1
def _should_process_messages(self, messages: List[Dict[str, Any]] = None) -> bool:
"""
统一判断是否应该处理消息的函数
根据当前循环模式和消息内容决定是否继续处理
"""
from src.chat.utils.utils_image import is_image_message
if self.context.loop_mode == ChatMode.FOCUS:
if self.context.last_action == "no_reply":
if messages:
return self._execute_no_reply(messages)
return False
return True
return True
async def _execute_no_reply(self, new_message: List[Dict[str, Any]]) -> bool: async def _execute_no_reply(self, new_message: List[Dict[str, Any]]) -> bool:
"""执行breaking形式的no_reply原有逻辑""" """执行breaking形式的no_reply原有逻辑"""
new_message_count = len(new_message) new_message_count = len(new_message)
@@ -427,14 +443,13 @@ class HeartFChatting:
if new_message_count >= modified_exit_count_threshold: if new_message_count >= modified_exit_count_threshold:
# 记录兴趣度到列表 # 记录兴趣度到列表
from src.plugins.built_in.core_actions.no_reply import NoReplyAction
total_interest = 0.0 total_interest = 0.0
for msg_dict in new_message: for msg_dict in new_message:
interest_value = msg_dict.get("interest_value", 0.0) interest_value = msg_dict.get("interest_value", 0.0)
if msg_dict.get("processed_plain_text", ""): if msg_dict.get("processed_plain_text", ""):
total_interest += interest_value total_interest += interest_value
NoReplyAction._recent_interest_records.append(total_interest) self.recent_interest_records.append(total_interest)
logger.info( logger.info(
f"{self.context.log_prefix} 累计消息数量达到{new_message_count}条(>{modified_exit_count_threshold}),结束等待" f"{self.context.log_prefix} 累计消息数量达到{new_message_count}条(>{modified_exit_count_threshold}),结束等待"
@@ -458,11 +473,10 @@ class HeartFChatting:
if accumulated_interest >= 3 / talk_frequency: if accumulated_interest >= 3 / talk_frequency:
# 记录兴趣度到列表 # 记录兴趣度到列表
from src.plugins.built_in.core_actions.no_reply import NoReplyAction self.recent_interest_records.append(accumulated_interest)
NoReplyAction._recent_interest_records.append(accumulated_interest)
logger.info( logger.info(
f"{self.context.log_prefix} 累计兴趣值达到{accumulated_interest:.2f}(>{5 / talk_frequency}),结束等待" f"{self.context.log_prefix} 累计兴趣值达到{accumulated_interest:.2f}(>{3 / talk_frequency}),结束等待"
) )
return True return True

View File

@@ -37,7 +37,7 @@ async def _calculate_interest(message: MessageRecv) -> Tuple[float, bool, list[s
with Timer("记忆激活"): with Timer("记忆激活"):
interested_rate, keywords = await hippocampus_manager.get_activate_from_text( interested_rate, keywords = await hippocampus_manager.get_activate_from_text(
message.processed_plain_text, message.processed_plain_text,
max_depth=5, max_depth=4,
fast_retrieval=False, fast_retrieval=False,
) )
message.key_words = keywords message.key_words = keywords

View File

@@ -121,6 +121,9 @@ class MessageRecv(Message):
self.priority_info = None self.priority_info = None
self.interest_value: float = 0.0 self.interest_value: float = 0.0
self.key_words = []
self.key_words_lite = []
def update_chat_stream(self, chat_stream: "ChatStream"): def update_chat_stream(self, chat_stream: "ChatStream"):
self.chat_stream = chat_stream self.chat_stream = chat_stream

View File

@@ -19,7 +19,7 @@ class MessageStorage:
def _serialize_keywords(keywords) -> str: def _serialize_keywords(keywords) -> str:
"""将关键词列表序列化为JSON字符串""" """将关键词列表序列化为JSON字符串"""
if isinstance(keywords, list): if isinstance(keywords, list):
return json.dumps(keywords, ensure_ascii=False) return orjson.dumps(keywords).decode("utf-8")
return "[]" return "[]"
@staticmethod @staticmethod
@@ -28,8 +28,8 @@ class MessageStorage:
if not keywords_str: if not keywords_str:
return [] return []
try: try:
return json.loads(keywords_str) return orjson.loads(keywords_str)
except (json.JSONDecodeError, TypeError): except (orjson.JSONDecodeError, TypeError):
return [] return []
@staticmethod @staticmethod
@@ -64,7 +64,6 @@ class MessageStorage:
is_command = False is_command = False
key_words = "" key_words = ""
key_words_lite = "" key_words_lite = ""
selected_expressions = message.selected_expressions
else: else:
filtered_display_message = "" filtered_display_message = ""
interest_value = message.interest_value interest_value = message.interest_value
@@ -79,7 +78,6 @@ class MessageStorage:
# 序列化关键词列表为JSON字符串 # 序列化关键词列表为JSON字符串
key_words = MessageStorage._serialize_keywords(message.key_words) key_words = MessageStorage._serialize_keywords(message.key_words)
key_words_lite = MessageStorage._serialize_keywords(message.key_words_lite) key_words_lite = MessageStorage._serialize_keywords(message.key_words_lite)
selected_expressions = ""
chat_info_dict = chat_stream.to_dict() chat_info_dict = chat_stream.to_dict()
user_info_dict = message.message_info.user_info.to_dict() # type: ignore user_info_dict = message.message_info.user_info.to_dict() # type: ignore
@@ -130,7 +128,6 @@ class MessageStorage:
is_command=is_command, is_command=is_command,
key_words=key_words, key_words=key_words,
key_words_lite=key_words_lite, key_words_lite=key_words_lite,
selected_expressions=selected_expressions,
) )
with get_db_session() as session: with get_db_session() as session:
session.add(new_message) session.add(new_message)

View File

@@ -128,6 +128,8 @@ class Messages(Base):
chat_id = Column(get_string_field(64), nullable=False, index=True) chat_id = Column(get_string_field(64), nullable=False, index=True)
reply_to = Column(Text, nullable=True) reply_to = Column(Text, nullable=True)
interest_value = Column(Float, nullable=True) interest_value = Column(Float, nullable=True)
key_words = Column(Text, nullable=True)
key_words_lite = Column(Text, nullable=True)
is_mentioned = Column(Boolean, nullable=True) is_mentioned = Column(Boolean, nullable=True)
# 从 chat_info 扁平化而来的字段 # 从 chat_info 扁平化而来的字段

View File

@@ -114,11 +114,7 @@ class ChatConfig(ValidatedConfigBase):
# 检查全局时段配置(第一个元素为空字符串的配置) # 检查全局时段配置(第一个元素为空字符串的配置)
global_frequency = self._get_global_frequency() global_frequency = self._get_global_frequency()
if global_frequency is not None: return self.talk_frequency if global_frequency is None else global_frequency
return global_frequency
# 如果都没有匹配,返回默认值
return self.talk_frequency
def _get_time_based_frequency(self, time_freq_list: list[str]) -> Optional[float]: def _get_time_based_frequency(self, time_freq_list: list[str]) -> Optional[float]:
""" """

View File

@@ -1,5 +1,4 @@
from typing import Tuple, List from typing import Tuple
from collections import deque
# 导入新插件系统 # 导入新插件系统
from src.plugin_system import BaseAction, ActionActivationType, ChatMode from src.plugin_system import BaseAction, ActionActivationType, ChatMode
@@ -23,11 +22,10 @@ class NoReplyAction(BaseAction):
action_name = "no_reply" action_name = "no_reply"
action_description = "暂时不回复消息" action_description = "暂时不回复消息"
# 最近三次no_reply的新消息兴趣度记录
_recent_interest_records: deque = deque(maxlen=3)
# 动作参数定义 # 动作参数定义
action_parameters = {} action_parameters = {
"reason": "不回复的原因",
}
# 动作使用场景 # 动作使用场景
action_require = [""] action_require = [""]
@@ -60,14 +58,3 @@ class NoReplyAction(BaseAction):
action_done=True, action_done=True,
) )
return False, f"不回复动作执行失败: {e}" return False, f"不回复动作执行失败: {e}"
@classmethod
def reset_consecutive_count(cls):
"""重置连续计数器和兴趣度记录"""
cls._recent_interest_records.clear()
logger.debug("NoReplyAction连续计数器和兴趣度记录已重置")
@classmethod
def get_recent_interest_records(cls) -> List[float]:
"""获取最近的兴趣度记录"""
return list(cls._recent_interest_records)