🤖 自动格式化代码 [skip ci]
This commit is contained in:
@@ -454,7 +454,7 @@ async def build_anonymous_messages(messages: List[Dict[str, Any]]) -> str:
|
||||
def reply_replacer(match):
|
||||
# aaa = match.group(1)
|
||||
bbb = match.group(2)
|
||||
anon_reply = get_anon_name(platform, bbb) #noqa
|
||||
anon_reply = get_anon_name(platform, bbb) # noqa
|
||||
return f"回复 {anon_reply}"
|
||||
|
||||
content = re.sub(reply_pattern, reply_replacer, content, count=1)
|
||||
@@ -465,7 +465,7 @@ async def build_anonymous_messages(messages: List[Dict[str, Any]]) -> str:
|
||||
def at_replacer(match):
|
||||
# aaa = match.group(1)
|
||||
bbb = match.group(2)
|
||||
anon_at = get_anon_name(platform, bbb) #noqa
|
||||
anon_at = get_anon_name(platform, bbb) # noqa
|
||||
return f"@{anon_at}"
|
||||
|
||||
content = re.sub(at_pattern, at_replacer, content)
|
||||
|
||||
@@ -103,11 +103,11 @@ class InfoCatcher:
|
||||
|
||||
print(f"查询参数: time_start={time_start}, time_end={time_end}, chat_id={chat_id}")
|
||||
|
||||
messages_between_query = Messages.select().where(
|
||||
(Messages.chat_id == chat_id) &
|
||||
(Messages.time > time_start) &
|
||||
(Messages.time < time_end)
|
||||
).order_by(Messages.time.desc())
|
||||
messages_between_query = (
|
||||
Messages.select()
|
||||
.where((Messages.chat_id == chat_id) & (Messages.time > time_start) & (Messages.time < time_end))
|
||||
.order_by(Messages.time.desc())
|
||||
)
|
||||
|
||||
result = list(messages_between_query)
|
||||
print(f"查询结果数量: {len(result)}")
|
||||
@@ -124,10 +124,12 @@ class InfoCatcher:
|
||||
message_id_val = message.message_info.message_id
|
||||
chat_id_val = message.chat_stream.stream_id
|
||||
|
||||
messages_before_query = Messages.select().where(
|
||||
(Messages.chat_id == chat_id_val) &
|
||||
(Messages.message_id < message_id_val)
|
||||
).order_by(Messages.time.desc()).limit(self.context_length * 3)
|
||||
messages_before_query = (
|
||||
Messages.select()
|
||||
.where((Messages.chat_id == chat_id_val) & (Messages.message_id < message_id_val))
|
||||
.order_by(Messages.time.desc())
|
||||
.limit(self.context_length * 3)
|
||||
)
|
||||
|
||||
return list(messages_before_query)
|
||||
|
||||
@@ -137,7 +139,7 @@ class InfoCatcher:
|
||||
processed_msg_item = msg_item
|
||||
if not isinstance(msg_item, dict):
|
||||
processed_msg_item = self.message_to_dict(msg_item)
|
||||
|
||||
|
||||
if not processed_msg_item:
|
||||
continue
|
||||
|
||||
@@ -163,15 +165,15 @@ class InfoCatcher:
|
||||
"user_nickname": msg_obj.user_nickname,
|
||||
"processed_plain_text": msg_obj.processed_plain_text,
|
||||
}
|
||||
|
||||
if hasattr(msg_obj, 'message_info') and hasattr(msg_obj.message_info, 'user_info'):
|
||||
|
||||
if hasattr(msg_obj, "message_info") and hasattr(msg_obj.message_info, "user_info"):
|
||||
return {
|
||||
"time": msg_obj.message_info.time,
|
||||
"user_id": msg_obj.message_info.user_info.user_id,
|
||||
"user_nickname": msg_obj.message_info.user_info.user_nickname,
|
||||
"processed_plain_text": msg_obj.processed_plain_text,
|
||||
}
|
||||
|
||||
|
||||
print(f"Warning: message_to_dict received an unhandled type: {type(msg_obj)}")
|
||||
return {}
|
||||
|
||||
@@ -198,7 +200,7 @@ class InfoCatcher:
|
||||
chat_history_in_thinking_json=json.dumps(chat_history_in_thinking_list),
|
||||
chat_history_after_response_json=json.dumps(chat_history_after_response_list),
|
||||
heartflow_data_json=json.dumps(self.heartflow_data),
|
||||
reasoning_data_json=json.dumps(self.reasoning_data)
|
||||
reasoning_data_json=json.dumps(self.reasoning_data),
|
||||
)
|
||||
log_entry.save()
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ from typing import Any, Dict, Tuple, List
|
||||
from src.common.logger import get_module_logger
|
||||
from src.manager.async_task_manager import AsyncTask
|
||||
|
||||
from ...common.database.database import db # This db is the Peewee database instance
|
||||
from ...common.database.database_model import OnlineTime, LLMUsage, Messages # Import the Peewee model
|
||||
from ...common.database.database import db # This db is the Peewee database instance
|
||||
from ...common.database.database_model import OnlineTime, LLMUsage, Messages # Import the Peewee model
|
||||
from src.manager.local_store_manager import local_storage
|
||||
|
||||
logger = get_module_logger("maibot_statistic")
|
||||
@@ -48,8 +48,8 @@ class OnlineTimeRecordTask(AsyncTask):
|
||||
@staticmethod
|
||||
def _init_database():
|
||||
"""初始化数据库"""
|
||||
with db.atomic(): # Use atomic operations for schema changes
|
||||
OnlineTime.create_table(safe=True) # Creates table if it doesn't exist, Peewee handles indexes from model
|
||||
with db.atomic(): # Use atomic operations for schema changes
|
||||
OnlineTime.create_table(safe=True) # Creates table if it doesn't exist, Peewee handles indexes from model
|
||||
|
||||
async def run(self):
|
||||
try:
|
||||
@@ -62,14 +62,17 @@ class OnlineTimeRecordTask(AsyncTask):
|
||||
updated_rows = query.execute()
|
||||
if updated_rows == 0:
|
||||
# Record might have been deleted or ID is stale, try to find/create
|
||||
self.record_id = None # Reset record_id to trigger find/create logic below
|
||||
|
||||
if not self.record_id: # Check again if record_id was reset or initially None
|
||||
self.record_id = None # Reset record_id to trigger find/create logic below
|
||||
|
||||
if not self.record_id: # Check again if record_id was reset or initially None
|
||||
# 如果没有记录,检查一分钟以内是否已有记录
|
||||
# Look for a record whose end_timestamp is recent enough to be considered ongoing
|
||||
recent_record = OnlineTime.select().where(
|
||||
OnlineTime.end_timestamp >= (current_time - timedelta(minutes=1))
|
||||
).order_by(OnlineTime.end_timestamp.desc()).first()
|
||||
recent_record = (
|
||||
OnlineTime.select()
|
||||
.where(OnlineTime.end_timestamp >= (current_time - timedelta(minutes=1)))
|
||||
.order_by(OnlineTime.end_timestamp.desc())
|
||||
.first()
|
||||
)
|
||||
|
||||
if recent_record:
|
||||
# 如果有记录,则更新结束时间
|
||||
@@ -87,7 +90,6 @@ class OnlineTimeRecordTask(AsyncTask):
|
||||
logger.error(f"在线时间记录失败,错误信息:{e}")
|
||||
|
||||
|
||||
|
||||
def _format_online_time(online_seconds: int) -> str:
|
||||
"""
|
||||
格式化在线时间
|
||||
@@ -197,7 +199,7 @@ class StatisticOutputTask(AsyncTask):
|
||||
"""
|
||||
if not collect_period:
|
||||
return {}
|
||||
|
||||
|
||||
# 排序-按照时间段开始时间降序排列(最晚的时间段在前)
|
||||
collect_period.sort(key=lambda x: x[1], reverse=True)
|
||||
|
||||
@@ -228,14 +230,14 @@ class StatisticOutputTask(AsyncTask):
|
||||
# Assuming LLMUsage.timestamp is a DateTimeField
|
||||
query_start_time = collect_period[-1][1]
|
||||
for record in LLMUsage.select().where(LLMUsage.timestamp >= query_start_time):
|
||||
record_timestamp = record.timestamp # This is already a datetime object
|
||||
record_timestamp = record.timestamp # This is already a datetime object
|
||||
for idx, (_, period_start) in enumerate(collect_period):
|
||||
if record_timestamp >= period_start:
|
||||
for period_key, _ in collect_period[idx:]:
|
||||
stats[period_key][TOTAL_REQ_CNT] += 1
|
||||
|
||||
request_type = record.request_type or "unknown"
|
||||
user_id = record.user_id or "unknown" # user_id is TextField, already string
|
||||
user_id = record.user_id or "unknown" # user_id is TextField, already string
|
||||
model_name = record.model_name or "unknown"
|
||||
|
||||
stats[period_key][REQ_CNT_BY_TYPE][request_type] += 1
|
||||
@@ -275,7 +277,7 @@ class StatisticOutputTask(AsyncTask):
|
||||
"""
|
||||
if not collect_period:
|
||||
return {}
|
||||
|
||||
|
||||
collect_period.sort(key=lambda x: x[1], reverse=True)
|
||||
|
||||
stats = {
|
||||
@@ -300,7 +302,7 @@ class StatisticOutputTask(AsyncTask):
|
||||
for period_key, current_period_start_time in collect_period[idx:]:
|
||||
# Determine the portion of the record that falls within this specific statistical period
|
||||
overlap_start = max(record_start_timestamp, current_period_start_time)
|
||||
overlap_end = effective_end_time # Already capped by 'now' and record's own end
|
||||
overlap_end = effective_end_time # Already capped by 'now' and record's own end
|
||||
|
||||
if overlap_end > overlap_start:
|
||||
stats[period_key][ONLINE_TIME] += (overlap_end - overlap_start).total_seconds()
|
||||
@@ -315,7 +317,7 @@ class StatisticOutputTask(AsyncTask):
|
||||
"""
|
||||
if not collect_period:
|
||||
return {}
|
||||
|
||||
|
||||
collect_period.sort(key=lambda x: x[1], reverse=True)
|
||||
|
||||
stats = {
|
||||
@@ -326,9 +328,9 @@ class StatisticOutputTask(AsyncTask):
|
||||
for period_key, _ in collect_period
|
||||
}
|
||||
|
||||
query_start_timestamp = collect_period[-1][1].timestamp() # Messages.time is a DoubleField (timestamp)
|
||||
query_start_timestamp = collect_period[-1][1].timestamp() # Messages.time is a DoubleField (timestamp)
|
||||
for message in Messages.select().where(Messages.time >= query_start_timestamp):
|
||||
message_time_ts = message.time # This is a float timestamp
|
||||
message_time_ts = message.time # This is a float timestamp
|
||||
|
||||
chat_id = None
|
||||
chat_name = None
|
||||
@@ -337,16 +339,18 @@ class StatisticOutputTask(AsyncTask):
|
||||
if message.chat_info_group_id:
|
||||
chat_id = f"g{message.chat_info_group_id}"
|
||||
chat_name = message.chat_info_group_name or f"群{message.chat_info_group_id}"
|
||||
elif message.user_id: # Fallback to sender's info for chat_id if not a group_info based chat
|
||||
# This uses the message SENDER's ID as per original logic's fallback
|
||||
chat_id = f"u{message.user_id}" # SENDER's user_id
|
||||
chat_name = message.user_nickname # SENDER's nickname
|
||||
elif message.user_id: # Fallback to sender's info for chat_id if not a group_info based chat
|
||||
# This uses the message SENDER's ID as per original logic's fallback
|
||||
chat_id = f"u{message.user_id}" # SENDER's user_id
|
||||
chat_name = message.user_nickname # SENDER's nickname
|
||||
else:
|
||||
# If neither group_id nor sender_id is available for chat identification
|
||||
logger.warning(f"Message (PK: {message.id if hasattr(message, 'id') else 'N/A'}) lacks group_id and user_id for chat stats.")
|
||||
logger.warning(
|
||||
f"Message (PK: {message.id if hasattr(message, 'id') else 'N/A'}) lacks group_id and user_id for chat stats."
|
||||
)
|
||||
continue
|
||||
|
||||
if not chat_id: # Should not happen if above logic is correct
|
||||
|
||||
if not chat_id: # Should not happen if above logic is correct
|
||||
continue
|
||||
|
||||
# Update name_mapping
|
||||
|
||||
@@ -35,13 +35,13 @@ class ImageManager:
|
||||
if not self._initialized:
|
||||
self._ensure_image_dir()
|
||||
self._llm = LLMRequest(model=global_config.vlm, temperature=0.4, max_tokens=300, request_type="image")
|
||||
|
||||
|
||||
try:
|
||||
db.connect(reuse_if_open=True)
|
||||
db.create_tables([Images, ImageDescriptions], safe=True)
|
||||
except Exception as e:
|
||||
logger.error(f"数据库连接或表创建失败: {e}")
|
||||
|
||||
|
||||
self._initialized = True
|
||||
|
||||
def _ensure_image_dir(self):
|
||||
@@ -61,8 +61,7 @@ class ImageManager:
|
||||
"""
|
||||
try:
|
||||
record = ImageDescriptions.get_or_none(
|
||||
(ImageDescriptions.hash == image_hash) &
|
||||
(ImageDescriptions.type == description_type)
|
||||
(ImageDescriptions.hash == image_hash) & (ImageDescriptions.type == description_type)
|
||||
)
|
||||
return record.description if record else None
|
||||
except Exception as e:
|
||||
@@ -80,14 +79,9 @@ class ImageManager:
|
||||
"""
|
||||
try:
|
||||
current_timestamp = time.time()
|
||||
defaults = {
|
||||
'description': description,
|
||||
'timestamp': current_timestamp
|
||||
}
|
||||
defaults = {"description": description, "timestamp": current_timestamp}
|
||||
desc_obj, created = ImageDescriptions.get_or_create(
|
||||
hash=image_hash,
|
||||
type=description_type,
|
||||
defaults=defaults
|
||||
hash=image_hash, type=description_type, defaults=defaults
|
||||
)
|
||||
if not created: # 如果记录已存在,则更新
|
||||
desc_obj.description = description
|
||||
@@ -120,7 +114,7 @@ class ImageManager:
|
||||
else:
|
||||
prompt = "这是一个表情包,请用使用几个词描述一下表情包所表达的情感和内容,简短一些"
|
||||
description, _ = await self._llm.generate_response_for_image(prompt, image_base64, image_format)
|
||||
|
||||
|
||||
if description is None:
|
||||
logger.warning("AI未能生成表情包描述")
|
||||
return "[表情包(描述生成失败)]"
|
||||
@@ -191,7 +185,7 @@ class ImageManager:
|
||||
"请用中文描述这张图片的内容。如果有文字,请把文字都描述出来。并尝试猜测这个图片的含义。最多100个字。"
|
||||
)
|
||||
description, _ = await self._llm.generate_response_for_image(prompt, image_base64, image_format)
|
||||
|
||||
|
||||
if description is None:
|
||||
logger.warning("AI未能生成图片描述")
|
||||
return "[图片(描述生成失败)]"
|
||||
|
||||
Reference in New Issue
Block a user