修正粉丝日报信息区重复与热点区空白问题
1. 移除今日重点信息中的重复摘要列表,只保留卡片展示\n2. 为粉丝日报模板补充新旧载荷结构兼容逻辑,支持从llm_compact、peak_buckets、repeated_messages等字段自动兜底\n3. 热点窗口与共识梗区域增加空数据说明块,避免页面出现整块空白
This commit is contained in:
@@ -474,6 +474,95 @@ def _render_fans_metric_cards(metrics: List[Dict[str, str]]) -> str:
|
||||
return "".join(blocks)
|
||||
|
||||
|
||||
def _get_compact_scene_material(payload: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
兼容两种来源的粉丝日报载荷:
|
||||
1. 新版 prompt 材料已经预先组装好的 compact_scene_material;
|
||||
2. 正式渲染链路里仍然保留在 llm_compact 下的压缩材料。
|
||||
这样模板层可以向后兼容,不会因为字段尚未完全迁移就出现空版块。
|
||||
"""
|
||||
compact = payload.get("compact_scene_material", {}) or {}
|
||||
if compact:
|
||||
return compact
|
||||
return payload.get("llm_compact", {}) or {}
|
||||
|
||||
|
||||
def _get_topic_evidence_clusters(payload: Dict[str, Any]) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
兼容“已展开主题簇”和“仍放在 llm_compact.semantic_fact_hints.topic_clusters”两种结构。
|
||||
"""
|
||||
clusters = payload.get("topic_evidence_clusters", []) or []
|
||||
if clusters:
|
||||
return clusters
|
||||
compact = _get_compact_scene_material(payload)
|
||||
fact_hints = compact.get("semantic_fact_hints", {}) or {}
|
||||
normalized = []
|
||||
for item in (fact_hints.get("topic_clusters", []) or [])[:6]:
|
||||
normalized.append({
|
||||
"label": str(item.get("label") or "").strip(),
|
||||
"count": int(item.get("match_count", item.get("count", 0)) or 0),
|
||||
"user_count": int(item.get("user_count", 0) or 0),
|
||||
"time_range": (
|
||||
f"{str(item.get('first_hm') or '').strip()}-{str(item.get('last_hm') or '').strip()}"
|
||||
).strip("-"),
|
||||
"keywords": item.get("keywords", []) or [],
|
||||
"samples": item.get("samples", []) or [],
|
||||
})
|
||||
return normalized
|
||||
|
||||
|
||||
def _get_hero_mentions(payload: Dict[str, Any]) -> List[Dict[str, Any]]:
|
||||
compact = _get_compact_scene_material(payload)
|
||||
return (
|
||||
compact.get("semantic_fact_hints", {})
|
||||
.get("hero_mentions", [])
|
||||
or []
|
||||
)
|
||||
|
||||
|
||||
def _build_local_stats(payload: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
兼容新旧载荷的本地统计字段。
|
||||
如果没有 top-level local_stats,就从 peak_buckets / repeated_messages / burst_terms / content_cues 临时拼一份,
|
||||
保证“热点窗口与共识梗”始终有内容可用。
|
||||
"""
|
||||
local_stats = payload.get("local_stats", {}) or {}
|
||||
if local_stats:
|
||||
return local_stats
|
||||
|
||||
compact = _get_compact_scene_material(payload)
|
||||
content_cues = compact.get("content_cues", []) or []
|
||||
return {
|
||||
"message_count": int((payload.get("report_meta", {}) or {}).get("message_count", 0) or 0),
|
||||
"unique_user_count": int((payload.get("report_meta", {}) or {}).get("unique_user_count", 0) or 0),
|
||||
"top_emotion_bursts": [
|
||||
{
|
||||
"text": str(item.get("text") or "").strip(),
|
||||
"count": int(item.get("count", 0) or 0),
|
||||
}
|
||||
for item in content_cues
|
||||
if str(item.get("kind") or "").strip() == "emotion" and str(item.get("text") or "").strip()
|
||||
][:8],
|
||||
"top_repeated_messages": [
|
||||
{
|
||||
"text": str(item.get("text") or "").strip(),
|
||||
"count": int(item.get("count", 0) or 0),
|
||||
"user_count": int(item.get("user_count", 0) or 0),
|
||||
}
|
||||
for item in (payload.get("repeated_messages", []) or [])[:8]
|
||||
if str(item.get("text") or "").strip()
|
||||
],
|
||||
"peak_windows": [
|
||||
{
|
||||
"start_time": str(item.get("start_time") or "").strip(),
|
||||
"message_count": int(item.get("message_count", 0) or 0),
|
||||
"user_count": int(item.get("user_count", 0) or 0),
|
||||
}
|
||||
for item in (payload.get("peak_buckets", []) or [])[:6]
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def _build_fans_effective_info_lines(payload: Dict[str, Any], limit: int = 6) -> List[str]:
|
||||
"""
|
||||
为粉丝日报补一层“有效信息速览”。
|
||||
@@ -490,7 +579,7 @@ def _build_fans_effective_info_lines(payload: Dict[str, Any], limit: int = 6) ->
|
||||
seen.add(value)
|
||||
lines.append(value)
|
||||
|
||||
for item in (payload.get("topic_evidence_clusters", []) or [])[:6]:
|
||||
for item in _get_topic_evidence_clusters(payload)[:6]:
|
||||
label = str(item.get("label") or "").strip()
|
||||
count = int(item.get("count", 0) or 0)
|
||||
time_range = str(item.get("time_range") or "").strip()
|
||||
@@ -506,13 +595,13 @@ def _build_fans_effective_info_lines(payload: Dict[str, Any], limit: int = 6) ->
|
||||
if len(lines) >= limit:
|
||||
return lines[:limit]
|
||||
|
||||
hero_mentions = payload.get("compact_scene_material", {}).get("semantic_fact_hints", {}).get("hero_mentions", []) or []
|
||||
hero_mentions = _get_hero_mentions(payload)
|
||||
if hero_mentions:
|
||||
hero_names = [str(item.get("hero") or "").strip() for item in hero_mentions[:4] if str(item.get("hero") or "").strip()]
|
||||
if hero_names:
|
||||
push(f"英雄讨论主要集中在 {'、'.join(hero_names)}。")
|
||||
|
||||
hot_windows = payload.get("local_stats", {}).get("peak_windows", []) or []
|
||||
hot_windows = _build_local_stats(payload).get("peak_windows", []) or []
|
||||
if hot_windows:
|
||||
top_window = hot_windows[0]
|
||||
push(
|
||||
@@ -537,7 +626,7 @@ def _build_local_topic_focus_lines(payload: Dict[str, Any], limit: int = 4) -> L
|
||||
seen.add(value)
|
||||
lines.append(value)
|
||||
|
||||
for item in (payload.get("topic_evidence_clusters", []) or [])[:4]:
|
||||
for item in _get_topic_evidence_clusters(payload)[:4]:
|
||||
label = str(item.get("label") or "").strip()
|
||||
keywords = [str(keyword).strip() for keyword in (item.get("keywords", []) or [])[:5] if str(keyword).strip()]
|
||||
count = int(item.get("count", 0) or 0)
|
||||
@@ -555,12 +644,7 @@ def _build_local_hero_focus_lines(payload: Dict[str, Any], limit: int = 4) -> Li
|
||||
为“英雄与对局焦点”准备本地兜底。
|
||||
这部分直接复用英雄提及聚类,优先强调出现频次和代表发言,方便粉丝快速看懂今天在聊什么英雄。
|
||||
"""
|
||||
hero_mentions = (
|
||||
payload.get("compact_scene_material", {})
|
||||
.get("semantic_fact_hints", {})
|
||||
.get("hero_mentions", [])
|
||||
or []
|
||||
)
|
||||
hero_mentions = _get_hero_mentions(payload)
|
||||
lines: List[str] = []
|
||||
seen = set()
|
||||
|
||||
@@ -687,11 +771,20 @@ def _render_hot_window_cards(hot_windows: List[Dict[str, Any]]) -> str:
|
||||
f'<div class="fans-hot-window-meta">{message_count} 条弹幕 / {user_count} 人参与</div>'
|
||||
'</div>'
|
||||
)
|
||||
# 页面层兜底:
|
||||
# 如果热窗没有任何卡片,也返回一个说明块,避免整个区域看起来像渲染坏了。
|
||||
if not blocks:
|
||||
blocks.append(
|
||||
'<div class="fans-hot-window-card">'
|
||||
'<div class="fans-hot-window-time">--:--</div>'
|
||||
'<div class="fans-hot-window-meta">当前载荷里没有可展示的热点窗口数据</div>'
|
||||
'</div>'
|
||||
)
|
||||
return "".join(blocks)
|
||||
|
||||
|
||||
def _render_repeat_digest(payload: Dict[str, Any]) -> str:
|
||||
local_stats = payload.get("local_stats", {}) or {}
|
||||
local_stats = _build_local_stats(payload)
|
||||
repeated_messages = local_stats.get("top_repeated_messages", []) or []
|
||||
emotion_bursts = local_stats.get("top_emotion_bursts", []) or []
|
||||
blocks = []
|
||||
@@ -715,6 +808,13 @@ def _render_repeat_digest(payload: Dict[str, Any]) -> str:
|
||||
f'<span class="repeat-chip-count">{count} 次</span>'
|
||||
'</div>'
|
||||
)
|
||||
if not blocks:
|
||||
blocks.append(
|
||||
'<div class="repeat-chip">'
|
||||
'<span class="repeat-chip-text">暂无共识梗数据</span>'
|
||||
'<span class="repeat-chip-count">0 次</span>'
|
||||
'</div>'
|
||||
)
|
||||
return "".join(blocks)
|
||||
|
||||
|
||||
@@ -1054,14 +1154,9 @@ def render_fans_daily_report_html(
|
||||
lead_text = str(sections.get("lead") or "").strip()
|
||||
if not lead_text:
|
||||
lead_text = "今天这场直播的弹幕主打一个集体上头,观众一边盯着画面,一边忙着把梗越刷越离谱。"
|
||||
topic_clusters = payload.get("topic_evidence_clusters", []) or []
|
||||
hero_mentions = (
|
||||
payload.get("compact_scene_material", {})
|
||||
.get("semantic_fact_hints", {})
|
||||
.get("hero_mentions", [])
|
||||
or []
|
||||
)
|
||||
local_stats = payload.get("local_stats", {}) or {}
|
||||
topic_clusters = _get_topic_evidence_clusters(payload)
|
||||
hero_mentions = _get_hero_mentions(payload)
|
||||
local_stats = _build_local_stats(payload)
|
||||
|
||||
renderer = HtmlTemplateRenderer()
|
||||
return renderer.render(
|
||||
@@ -1072,7 +1167,6 @@ def render_fans_daily_report_html(
|
||||
"lead_text": lead_text,
|
||||
# 粉丝版不再只做“乐子文案展示”,而是补进本地提纯后的有效信息区。
|
||||
"fans_metrics_html": Markup(_render_fans_metric_cards(_build_fans_fun_metrics(payload))),
|
||||
"effective_summary_html": Markup(_render_list(effective_info_lines, item_class="section-summary-list")),
|
||||
"effective_info_html": Markup(_render_fans_info_cards(effective_info_lines)),
|
||||
"topic_focus_html": Markup(_render_list(topic_focus_lines, item_class="section-summary-list")),
|
||||
"topic_clusters_html": Markup(_render_topic_clusters(topic_clusters)),
|
||||
|
||||
@@ -398,7 +398,6 @@
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title"><span class="icon"></span><span>今日重点信息</span></div>
|
||||
{{ effective_summary_html }}
|
||||
<div class="info-grid">{{ effective_info_html }}</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user