feat(config): 添加消息缓存系统配置和表达方式过期天数设置
feat(expression_learner): 实现清理过期表达方式功能 fix(context_manager): 根据配置检查消息缓存系统启用状态
This commit is contained in:
@@ -132,6 +132,56 @@ class ExpressionLearner:
|
|||||||
self.chat_name = stream_name or self.chat_id
|
self.chat_name = stream_name or self.chat_id
|
||||||
self._chat_name_initialized = True
|
self._chat_name_initialized = True
|
||||||
|
|
||||||
|
async def cleanup_expired_expressions(self, expiration_days: int | None = None) -> int:
|
||||||
|
"""
|
||||||
|
清理过期的表达方式
|
||||||
|
|
||||||
|
Args:
|
||||||
|
expiration_days: 过期天数,超过此天数未激活的表达方式将被删除(不指定则从配置读取)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 删除的表达方式数量
|
||||||
|
"""
|
||||||
|
# 从配置读取过期天数
|
||||||
|
if expiration_days is None:
|
||||||
|
expiration_days = global_config.expression.expiration_days
|
||||||
|
|
||||||
|
current_time = time.time()
|
||||||
|
expiration_threshold = current_time - (expiration_days * 24 * 3600)
|
||||||
|
|
||||||
|
try:
|
||||||
|
deleted_count = 0
|
||||||
|
async with get_db_session() as session:
|
||||||
|
# 查询过期的表达方式(只清理当前chat_id的)
|
||||||
|
query = await session.execute(
|
||||||
|
select(Expression).where(
|
||||||
|
(Expression.chat_id == self.chat_id)
|
||||||
|
& (Expression.last_active_time < expiration_threshold)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
expired_expressions = list(query.scalars())
|
||||||
|
|
||||||
|
if expired_expressions:
|
||||||
|
for expr in expired_expressions:
|
||||||
|
await session.delete(expr)
|
||||||
|
deleted_count += 1
|
||||||
|
|
||||||
|
await session.commit()
|
||||||
|
logger.info(f"清理了 {deleted_count} 个过期表达方式(超过 {expiration_days} 天未使用)")
|
||||||
|
|
||||||
|
# 清除缓存
|
||||||
|
from src.common.database.optimization.cache_manager import get_cache
|
||||||
|
from src.common.database.utils.decorators import generate_cache_key
|
||||||
|
cache = await get_cache()
|
||||||
|
await cache.delete(generate_cache_key("chat_expressions", self.chat_id))
|
||||||
|
else:
|
||||||
|
logger.debug(f"没有发现过期的表达方式(阈值:{expiration_days} 天)")
|
||||||
|
|
||||||
|
return deleted_count
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"清理过期表达方式失败: {e}")
|
||||||
|
return 0
|
||||||
|
|
||||||
def can_learn_for_chat(self) -> bool:
|
def can_learn_for_chat(self) -> bool:
|
||||||
"""
|
"""
|
||||||
检查指定聊天流是否允许学习表达
|
检查指定聊天流是否允许学习表达
|
||||||
@@ -214,6 +264,9 @@ class ExpressionLearner:
|
|||||||
try:
|
try:
|
||||||
logger.info(f"为聊天流 {self.chat_name} 触发表达学习")
|
logger.info(f"为聊天流 {self.chat_name} 触发表达学习")
|
||||||
|
|
||||||
|
# 🔥 改进3:在学习前清理过期的表达方式
|
||||||
|
await self.cleanup_expired_expressions()
|
||||||
|
|
||||||
# 学习语言风格
|
# 学习语言风格
|
||||||
learnt_style = await self.learn_and_store(type="style", num=25)
|
learnt_style = await self.learn_and_store(type="style", num=25)
|
||||||
|
|
||||||
@@ -397,9 +450,29 @@ class ExpressionLearner:
|
|||||||
for chat_id, expr_list in chat_dict.items():
|
for chat_id, expr_list in chat_dict.items():
|
||||||
async with get_db_session() as session:
|
async with get_db_session() as session:
|
||||||
for new_expr in expr_list:
|
for new_expr in expr_list:
|
||||||
# 查找是否已存在相似表达方式
|
# 🔥 改进1:检查是否存在相同情景或相同表达的数据
|
||||||
# 注意: get_all_by 不支持复杂条件,这里仍需使用 session
|
# 情况1:相同 chat_id + type + situation(相同情景,不同表达)
|
||||||
query = await session.execute(
|
query_same_situation = await session.execute(
|
||||||
|
select(Expression).where(
|
||||||
|
(Expression.chat_id == chat_id)
|
||||||
|
& (Expression.type == type)
|
||||||
|
& (Expression.situation == new_expr["situation"])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
same_situation_expr = query_same_situation.scalar()
|
||||||
|
|
||||||
|
# 情况2:相同 chat_id + type + style(相同表达,不同情景)
|
||||||
|
query_same_style = await session.execute(
|
||||||
|
select(Expression).where(
|
||||||
|
(Expression.chat_id == chat_id)
|
||||||
|
& (Expression.type == type)
|
||||||
|
& (Expression.style == new_expr["style"])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
same_style_expr = query_same_style.scalar()
|
||||||
|
|
||||||
|
# 情况3:完全相同(相同情景+相同表达)
|
||||||
|
query_exact_match = await session.execute(
|
||||||
select(Expression).where(
|
select(Expression).where(
|
||||||
(Expression.chat_id == chat_id)
|
(Expression.chat_id == chat_id)
|
||||||
& (Expression.type == type)
|
& (Expression.type == type)
|
||||||
@@ -407,16 +480,29 @@ class ExpressionLearner:
|
|||||||
& (Expression.style == new_expr["style"])
|
& (Expression.style == new_expr["style"])
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
existing_expr = query.scalar()
|
exact_match_expr = query_exact_match.scalar()
|
||||||
if existing_expr:
|
|
||||||
expr_obj = existing_expr
|
# 优先处理完全匹配的情况
|
||||||
# 50%概率替换内容
|
if exact_match_expr:
|
||||||
if random.random() < 0.5:
|
# 完全相同:增加count,更新时间
|
||||||
expr_obj.situation = new_expr["situation"]
|
expr_obj = exact_match_expr
|
||||||
expr_obj.style = new_expr["style"]
|
|
||||||
expr_obj.count = expr_obj.count + 1
|
expr_obj.count = expr_obj.count + 1
|
||||||
expr_obj.last_active_time = current_time
|
expr_obj.last_active_time = current_time
|
||||||
|
logger.debug(f"完全匹配:更新count {expr_obj.count}")
|
||||||
|
elif same_situation_expr:
|
||||||
|
# 相同情景,不同表达:覆盖旧的表达
|
||||||
|
logger.info(f"相同情景覆盖:'{same_situation_expr.situation}' 的表达从 '{same_situation_expr.style}' 更新为 '{new_expr['style']}'")
|
||||||
|
same_situation_expr.style = new_expr["style"]
|
||||||
|
same_situation_expr.count = same_situation_expr.count + 1
|
||||||
|
same_situation_expr.last_active_time = current_time
|
||||||
|
elif same_style_expr:
|
||||||
|
# 相同表达,不同情景:覆盖旧的情景
|
||||||
|
logger.info(f"相同表达覆盖:'{same_style_expr.style}' 的情景从 '{same_style_expr.situation}' 更新为 '{new_expr['situation']}'")
|
||||||
|
same_style_expr.situation = new_expr["situation"]
|
||||||
|
same_style_expr.count = same_style_expr.count + 1
|
||||||
|
same_style_expr.last_active_time = current_time
|
||||||
else:
|
else:
|
||||||
|
# 完全新的表达方式:创建新记录
|
||||||
new_expression = Expression(
|
new_expression = Expression(
|
||||||
situation=new_expr["situation"],
|
situation=new_expr["situation"],
|
||||||
style=new_expr["style"],
|
style=new_expr["style"],
|
||||||
@@ -427,6 +513,7 @@ class ExpressionLearner:
|
|||||||
create_date=current_time, # 手动设置创建日期
|
create_date=current_time, # 手动设置创建日期
|
||||||
)
|
)
|
||||||
session.add(new_expression)
|
session.add(new_expression)
|
||||||
|
logger.debug(f"新增表达方式:{new_expr['situation']} -> {new_expr['style']}")
|
||||||
|
|
||||||
# 限制最大数量 - 使用 get_all_by_sorted 获取排序结果
|
# 限制最大数量 - 使用 get_all_by_sorted 获取排序结果
|
||||||
exprs_result = await session.execute(
|
exprs_result = await session.execute(
|
||||||
|
|||||||
@@ -69,7 +69,11 @@ class SingleStreamContextManager:
|
|||||||
try:
|
try:
|
||||||
from .message_manager import message_manager as mm
|
from .message_manager import message_manager as mm
|
||||||
message_manager = mm
|
message_manager = mm
|
||||||
use_cache_system = message_manager.is_running
|
# 检查配置是否启用消息缓存系统
|
||||||
|
cache_enabled = global_config.chat.enable_message_cache
|
||||||
|
use_cache_system = message_manager.is_running and cache_enabled
|
||||||
|
if not cache_enabled:
|
||||||
|
logger.debug(f"消息缓存系统已在配置中禁用")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"MessageManager不可用,使用直接添加: {e}")
|
logger.debug(f"MessageManager不可用,使用直接添加: {e}")
|
||||||
use_cache_system = False
|
use_cache_system = False
|
||||||
|
|||||||
@@ -120,6 +120,10 @@ class ChatConfig(ValidatedConfigBase):
|
|||||||
timestamp_display_mode: Literal["normal", "normal_no_YMD", "relative"] = Field(
|
timestamp_display_mode: Literal["normal", "normal_no_YMD", "relative"] = Field(
|
||||||
default="normal_no_YMD", description="时间戳显示模式"
|
default="normal_no_YMD", description="时间戳显示模式"
|
||||||
)
|
)
|
||||||
|
# 消息缓存系统配置
|
||||||
|
enable_message_cache: bool = Field(
|
||||||
|
default=True, description="是否启用消息缓存系统(启用后,处理中收到的消息会被缓存,处理完成后统一刷新到未读列表)"
|
||||||
|
)
|
||||||
# 消息打断系统配置 - 线性概率模型
|
# 消息打断系统配置 - 线性概率模型
|
||||||
interruption_enabled: bool = Field(default=True, description="是否启用消息打断系统")
|
interruption_enabled: bool = Field(default=True, description="是否启用消息打断系统")
|
||||||
allow_reply_interruption: bool = Field(
|
allow_reply_interruption: bool = Field(
|
||||||
@@ -181,6 +185,10 @@ class ExpressionConfig(ValidatedConfigBase):
|
|||||||
default="classic",
|
default="classic",
|
||||||
description="表达方式选择模式: classic=经典LLM评估, exp_model=机器学习模型预测"
|
description="表达方式选择模式: classic=经典LLM评估, exp_model=机器学习模型预测"
|
||||||
)
|
)
|
||||||
|
expiration_days: int = Field(
|
||||||
|
default=90,
|
||||||
|
description="表达方式过期天数,超过此天数未激活的表达方式将被清理"
|
||||||
|
)
|
||||||
rules: list[ExpressionRule] = Field(default_factory=list, description="表达学习规则")
|
rules: list[ExpressionRule] = Field(default_factory=list, description="表达学习规则")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[inner]
|
[inner]
|
||||||
version = "7.5.7"
|
version = "7.5.8"
|
||||||
|
|
||||||
#----以下是给开发人员阅读的,如果你只是部署了MoFox-Bot,不需要阅读----
|
#----以下是给开发人员阅读的,如果你只是部署了MoFox-Bot,不需要阅读----
|
||||||
#如果你想要修改配置文件,请递增version的值
|
#如果你想要修改配置文件,请递增version的值
|
||||||
@@ -107,6 +107,9 @@ compress_identity = true # 是否压缩身份,压缩后会精简身份信息
|
|||||||
# - "exp_model": 表达模型模式,使用机器学习模型预测最合适的表达
|
# - "exp_model": 表达模型模式,使用机器学习模型预测最合适的表达
|
||||||
mode = "classic"
|
mode = "classic"
|
||||||
|
|
||||||
|
# expiration_days: 表达方式过期天数,超过此天数未激活的表达方式将被清理
|
||||||
|
expiration_days = 3
|
||||||
|
|
||||||
# rules是一个列表,每个元素都是一个学习规则
|
# rules是一个列表,每个元素都是一个学习规则
|
||||||
# chat_stream_id: 聊天流ID,格式为 "platform:id:type",例如 "qq:123456:private"。空字符串""表示全局配置
|
# chat_stream_id: 聊天流ID,格式为 "platform:id:type",例如 "qq:123456:private"。空字符串""表示全局配置
|
||||||
# use_expression: 是否使用学到的表达 (true/false)
|
# use_expression: 是否使用学到的表达 (true/false)
|
||||||
@@ -139,6 +142,9 @@ allow_reply_self = false # 是否允许回复自己说的话
|
|||||||
max_context_size = 25 # 上下文长度
|
max_context_size = 25 # 上下文长度
|
||||||
thinking_timeout = 40 # MoFox-Bot一次回复最长思考规划时间,超过这个时间的思考会放弃(往往是api反应太慢)
|
thinking_timeout = 40 # MoFox-Bot一次回复最长思考规划时间,超过这个时间的思考会放弃(往往是api反应太慢)
|
||||||
|
|
||||||
|
# 消息缓存系统配置
|
||||||
|
enable_message_cache = true # 是否启用消息缓存系统(启用后,处理中收到的消息会被缓存,处理完成后统一刷新到未读列表)
|
||||||
|
|
||||||
# 消息打断系统配置 - 反比例函数概率模型
|
# 消息打断系统配置 - 反比例函数概率模型
|
||||||
interruption_enabled = true # 是否启用消息打断系统
|
interruption_enabled = true # 是否启用消息打断系统
|
||||||
allow_reply_interruption = false # 是否允许在正在生成回复时打断(true=允许打断回复,false=回复期间不允许打断)
|
allow_reply_interruption = false # 是否允许在正在生成回复时打断(true=允许打断回复,false=回复期间不允许打断)
|
||||||
|
|||||||
Reference in New Issue
Block a user