fix: 修复了导致增量分析报告发送失败的几个核心问题:

修复报告分发器初始化错误:
在 AutoScheduler 中,初始化 ReportDispatcher 时漏传了 report_generator,导致在尝试生成报告(图片或文本)时出现 'NoneType' object has no attribute 'generate_image_report' 错误。
已更新 AutoScheduler 的构造函数并正确传递 report_generator。
修复 LLM 分析器在增量模式下的数据结构错误:UserTitleAnalyzer 报错:在增量模式下,用户活动数据被简化存储,导致 UserTitleAnalyzer 找不到 'hours' 键(Error: 'hours')。
补全数据维度:更新了 AnalysisApplicationService 的增量数据转换逻辑,保留了完整的每小时活跃分布 (hours) 和回复数 (reply_count)。
统一字段名:增量模式下使用了 nickname 字段以匹配分析器的预期(之前被错误转为了 name)。
增强容错性:优化了 UserTitleAnalyzer 的逻辑,现在它能安全地处理 hours 缺失或旧版本数据 schema,不再会因为找不到键而崩溃。
修复增量数据合并逻辑:
更新了 IncrementalMergeService,现在它能正确合并多个批次中的每小时发言统计和回复数统计,确保最终生成的报告数据准确。
This commit is contained in:
SXP-Simon
2026-02-11 12:54:02 +08:00
parent e292558965
commit ced38e6a9e
5 changed files with 81 additions and 57 deletions
@@ -250,9 +250,7 @@ class AnalysisApplicationService:
if last_analyzed_ts > 0:
unified_messages = [
msg
for msg in unified_messages
if msg.timestamp > last_analyzed_ts
msg for msg in unified_messages if msg.timestamp > last_analyzed_ts
]
# 5. 检查最小消息阈值
@@ -282,7 +280,7 @@ class AnalysisApplicationService:
# 7. LLM 增量分析(仅话题 + 金句)
topics_per_batch = self.config_manager.get_incremental_topics_per_batch()
quotes_per_batch = self.config_manager.get_incremental_quotes_per_batch()
# 获取功能开关状态
topic_enabled = self.config_manager.get_topic_analysis_enabled()
golden_quote_enabled = self.config_manager.get_golden_quote_analysis_enabled()
@@ -295,15 +293,17 @@ class AnalysisApplicationService:
f"{platform_id}:GroupMessage:{group_id}" if platform_id else group_id
)
topics, golden_quotes, token_usage = (
await self.llm_analyzer.analyze_incremental_concurrent(
legacy_messages,
umo=unified_msg_origin,
topics_per_batch=topics_per_batch,
quotes_per_batch=quotes_per_batch,
topic_enabled=topic_enabled,
golden_quote_enabled=golden_quote_enabled,
)
(
topics,
golden_quotes,
token_usage,
) = await self.llm_analyzer.analyze_incremental_concurrent(
legacy_messages,
umo=unified_msg_origin,
topics_per_batch=topics_per_batch,
quotes_per_batch=quotes_per_batch,
topic_enabled=topic_enabled,
golden_quote_enabled=golden_quote_enabled,
)
# 8. 构建 IncrementalBatch
@@ -441,9 +441,7 @@ class AnalysisApplicationService:
# 3. 检查批次有效性
if not batches:
logger.warning(
f"{group_id} 滑动窗口内无增量分析数据,无法生成最终报告"
)
logger.warning(f"{group_id} 滑动窗口内无增量分析数据,无法生成最终报告")
return {"success": False, "reason": "no_incremental_data"}
# 4. 合并批次为 IncrementalState
@@ -466,19 +464,18 @@ class AnalysisApplicationService:
top_users = state.get_user_activity_ranking(max_user_titles)
unified_msg_origin = (
f"{platform_id}:GroupMessage:{group_id}"
if platform_id
else group_id
f"{platform_id}:GroupMessage:{group_id}" if platform_id else group_id
)
try:
user_titles_result, title_token_usage = (
await self.llm_analyzer.analyze_user_titles(
messages=[], # 增量模式下不传原始消息
user_analysis=state.user_activities,
umo=unified_msg_origin,
top_users=top_users,
)
(
user_titles_result,
title_token_usage,
) = await self.llm_analyzer.analyze_user_titles(
messages=[], # 增量模式下不传原始消息
user_analysis=state.user_activities,
umo=unified_msg_origin,
top_users=top_users,
)
user_titles = user_titles_result
@@ -579,11 +576,14 @@ class AnalysisApplicationService:
result: dict[str, dict] = {}
for user_id, stats in user_activity.items():
result[user_id] = {
"name": stats.get("nickname", user_id),
"nickname": stats.get("nickname", user_id),
"message_count": stats.get("message_count", 0),
"char_count": stats.get("char_count", 0),
"emoji_count": stats.get("emoji_count", 0),
"active_hours": list(stats.get("hours", {}).keys()),
"reply_count": stats.get("reply_count", 0),
"hours": dict(
stats.get("hours", {})
), # 这里的 hours 是 defaultdict(int),转为 dict
"last_message_time": user_last_time.get(user_id, 0),
}