diff --git a/src/chat/express/expression_learner.py b/src/chat/express/expression_learner.py index e02ff7311..4afcfe7dd 100644 --- a/src/chat/express/expression_learner.py +++ b/src/chat/express/expression_learner.py @@ -2,6 +2,7 @@ import time import random import json import os +from datetime import datetime from typing import List, Dict, Optional, Any, Tuple @@ -21,6 +22,16 @@ DECAY_MIN = 0.01 # 最小衰减值 logger = get_logger("expressor") +def format_create_date(timestamp: float) -> str: + """ + 将时间戳格式化为可读的日期字符串 + """ + try: + return datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S") + except (ValueError, OSError): + return "未知时间" + + def init_prompt() -> None: learn_style_prompt = """ {chat_str} @@ -77,6 +88,7 @@ class ExpressionLearner: ) self.llm_model = None self._auto_migrate_json_to_db() + self._migrate_old_data_create_date() def _auto_migrate_json_to_db(self): """ @@ -127,6 +139,7 @@ class ExpressionLearner: last_active_time=last_active_time, chat_id=chat_id, type=type_str, + create_date=last_active_time, # 迁移时使用last_active_time作为创建时间 ) logger.info(f"已迁移 {expr_file} 到数据库") except Exception as e: @@ -139,6 +152,27 @@ class ExpressionLearner: except Exception as e: logger.error(f"写入done.done标记文件失败: {e}") + def _migrate_old_data_create_date(self): + """ + 为没有create_date的老数据设置创建日期 + 使用last_active_time作为create_date的默认值 + """ + try: + # 查找所有create_date为空的表达方式 + old_expressions = Expression.select().where(Expression.create_date.is_null()) + updated_count = 0 + + for expr in old_expressions: + # 使用last_active_time作为create_date + expr.create_date = expr.last_active_time + expr.save() + updated_count += 1 + + if updated_count > 0: + logger.info(f"已为 {updated_count} 个老的表达方式设置创建日期") + except Exception as e: + logger.error(f"迁移老数据创建日期失败: {e}") + def get_expression_by_chat_id(self, chat_id: str) -> Tuple[List[Dict[str, float]], List[Dict[str, float]]]: """ 获取指定chat_id的style和grammar表达方式 @@ -150,6 +184,8 @@ class ExpressionLearner: # 直接从数据库查询 style_query = Expression.select().where((Expression.chat_id == chat_id) & (Expression.type == "style")) for expr in style_query: + # 确保create_date存在,如果不存在则使用last_active_time + create_date = expr.create_date if expr.create_date is not None else expr.last_active_time learnt_style_expressions.append( { "situation": expr.situation, @@ -158,10 +194,13 @@ class ExpressionLearner: "last_active_time": expr.last_active_time, "source_id": chat_id, "type": "style", + "create_date": create_date, } ) grammar_query = Expression.select().where((Expression.chat_id == chat_id) & (Expression.type == "grammar")) for expr in grammar_query: + # 确保create_date存在,如果不存在则使用last_active_time + create_date = expr.create_date if expr.create_date is not None else expr.last_active_time learnt_grammar_expressions.append( { "situation": expr.situation, @@ -170,10 +209,40 @@ class ExpressionLearner: "last_active_time": expr.last_active_time, "source_id": chat_id, "type": "grammar", + "create_date": create_date, } ) return learnt_style_expressions, learnt_grammar_expressions + def get_expression_create_info(self, chat_id: str, limit: int = 10) -> List[Dict[str, Any]]: + """ + 获取指定chat_id的表达方式创建信息,按创建日期排序 + """ + try: + expressions = (Expression.select() + .where(Expression.chat_id == chat_id) + .order_by(Expression.create_date.desc()) + .limit(limit)) + + result = [] + for expr in expressions: + create_date = expr.create_date if expr.create_date is not None else expr.last_active_time + result.append({ + "situation": expr.situation, + "style": expr.style, + "type": expr.type, + "count": expr.count, + "create_date": create_date, + "create_date_formatted": format_create_date(create_date), + "last_active_time": expr.last_active_time, + "last_active_formatted": format_create_date(expr.last_active_time), + }) + + return result + except Exception as e: + logger.error(f"获取表达方式创建信息失败: {e}") + return [] + def is_similar(self, s1: str, s2: str) -> bool: """ 判断两个字符串是否相似(只考虑长度大于5且有80%以上重合,不考虑子串) @@ -350,6 +419,7 @@ class ExpressionLearner: last_active_time=current_time, chat_id=chat_id, type=type, + create_date=current_time, # 手动设置创建日期 ) # 限制最大数量 exprs = list( diff --git a/src/chat/express/expression_selector.py b/src/chat/express/expression_selector.py index 4ebad5a0e..d83d3a472 100644 --- a/src/chat/express/expression_selector.py +++ b/src/chat/express/expression_selector.py @@ -132,7 +132,8 @@ class ExpressionSelector: "count": expr.count, "last_active_time": expr.last_active_time, "source_id": cid, - "type": "style" + "type": "style", + "create_date": expr.create_date if expr.create_date is not None else expr.last_active_time, } for expr in style_query ]) grammar_exprs.extend([ @@ -142,7 +143,8 @@ class ExpressionSelector: "count": expr.count, "last_active_time": expr.last_active_time, "source_id": cid, - "type": "grammar" + "type": "grammar", + "create_date": expr.create_date if expr.create_date is not None else expr.last_active_time, } for expr in grammar_query ]) style_num = int(total_num * style_percentage) diff --git a/src/chat/utils/statistic.py b/src/chat/utils/statistic.py index 82d24ea23..7a6f499aa 100644 --- a/src/chat/utils/statistic.py +++ b/src/chat/utils/statistic.py @@ -630,9 +630,7 @@ class StatisticOutputTask(AsyncTask): logger.warning(f"获取聊天显示名称失败: {e}") return chat_id - def _generate_versions_tab(self, stat: dict) -> str: - """版本对比功能占位符,防止报错""" - return '

版本对比

暂未实现版本对比功能。

' + # 移除_generate_versions_tab方法 def _generate_html_report(self, stat: dict[str, Any], now: datetime): """ @@ -642,6 +640,7 @@ class StatisticOutputTask(AsyncTask): :return: HTML格式的统计报告 """ + # 移除版本对比内容相关tab和内容 tab_list = [ f'' for period in self.stat_period @@ -771,10 +770,7 @@ class StatisticOutputTask(AsyncTask): _format_stat_data(stat["all_time"], "all_time", datetime.fromtimestamp(local_storage["deploy_time"])) # type: ignore ) - # 添加版本对比内容 - versions_tab = self._generate_versions_tab(stat) - tab_content_list.append(versions_tab) - + # 不再添加版本对比内容 # 添加图表内容 chart_data = self._generate_chart_data(stat) tab_content_list.append(self._generate_chart_tab(chart_data)) diff --git a/src/common/database/database_model.py b/src/common/database/database_model.py index 645b0a5d6..23d27dc86 100644 --- a/src/common/database/database_model.py +++ b/src/common/database/database_model.py @@ -2,6 +2,7 @@ from peewee import Model, DoubleField, IntegerField, BooleanField, TextField, Fl from .database import db import datetime from src.common.logger import get_logger +import time logger = get_logger("database_model") # 请在此处定义您的数据库实例。 @@ -306,6 +307,7 @@ class Expression(BaseModel): last_active_time = FloatField() chat_id = TextField(index=True) type = TextField() + create_date = FloatField(null=True) # 创建日期,允许为空以兼容老数据 class Meta: table_name = "expression" @@ -449,9 +451,12 @@ def initialize_database(): alter_sql = f"ALTER TABLE {table_name} ADD COLUMN {field_name} {sql_type}" alter_sql += " NULL" if field_obj.null else " NOT NULL" if hasattr(field_obj, "default") and field_obj.default is not None: - # 正确处理不同类型的默认值 + # 正确处理不同类型的默认值,跳过lambda函数 default_value = field_obj.default - if isinstance(default_value, str): + if callable(default_value): + # 跳过lambda函数或其他可调用对象,这些无法在SQL中表示 + pass + elif isinstance(default_value, str): alter_sql += f" DEFAULT '{default_value}'" elif isinstance(default_value, bool): alter_sql += f" DEFAULT {int(default_value)}" diff --git a/template/bot_config_template.toml b/template/bot_config_template.toml index fb4802efb..0d11f3dea 100644 --- a/template/bot_config_template.toml +++ b/template/bot_config_template.toml @@ -1,5 +1,5 @@ [inner] -version = "4.4.5" +version = "4.4.6" #----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读---- #如果你想要修改配置文件,请在修改后将version的值进行变更 @@ -151,7 +151,7 @@ mood_decay_rate = 0.95 # 情绪衰减率 mood_intensity_factor = 1.0 # 情绪强度因子 [lpmm_knowledge] # lpmm知识库配置 -enable = true # 是否启用lpmm知识库 +enable = false # 是否启用lpmm知识库 rag_synonym_search_top_k = 10 # 同义词搜索TopK rag_synonym_threshold = 0.8 # 同义词阈值(相似度高于此阈值的词语会被认为是同义词) info_extraction_workers = 3 # 实体提取同时执行线程数,非Pro模型不要设置超过5