33 KiB
33 KiB
新闻智能分析系统开发计划 v2.0
基于大模型的时政/军事/科技新闻聚类、评价与整合系统
迭代说明:参考 AI Daily 项目实践,融合细粒度聚类与工程化部署经验
一、项目概述
1.1 项目目标
构建一个自动化新闻分析系统,实现:
- 细粒度聚类:保留多角度报道,避免简单去重丢失热点
- 动态热点识别:基于当日新闻分布统计特征自适应判定热点
- 双层整合:摘要级速览(全量)+ 洞察级深度分析(Top 10)
- 混合处理:实时热点感知 + 每日批量汇总生成早报
- 跨日关联:追踪同一事件的多日发展脉络
1.2 核心约束
| 维度 | 约束 |
|---|---|
| 数据规模 | 200-500篇/日 |
| 数据源 | RSS Feed(公众号订阅源) |
| 输出格式 | Web页面 / Markdown / 即时推送 |
| 成本预算 | 混合模型调度,日成本约1.3-1.6元 |
| 处理时效 | 批处理15-20分钟完成 |
| 部署方式 | 支持systemd服务化部署 |
1.3 双循环架构(参考AI Daily优化)
┌─────────────────────────────────────────────────────────────────┐
│ Fetch 循环(实时) │
│ 每30分钟运行一次 │
│ RSS抓取 → 转为Markdown → LLM评分 → 重要性判断 → 即时推送? │
│ ↓ ↓ │
│ 存入数据库(fetch-yyyy-mm-dd.json) 飞书/Discord│
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ Push 循环(定时) │
│ 每日定时运行(如早8点) │
│ 读取碎片化信息 → 细粒度聚类 → 多角度关联 → 综合评分 │
│ → 摘要级整合(全量) → 洞察级整合(Top10) → 生成日报 → 推送 │
└─────────────────────────────────────────────────────────────────┘
二、与AI Daily的对比分析
2.1 相似性
| 维度 | AI Daily | 本系统 | 相似度 |
|---|---|---|---|
| 数据源 | RSS订阅源 | RSS订阅源(公众号) | ⭐⭐⭐⭐⭐ |
| 核心流程 | RSS→LLM评分→推送/汇总 | RSS→聚类→评分→整合→推送/汇总 | ⭐⭐⭐⭐ |
| 双循环架构 | Fetch循环+Push循环 | 实时检测+批处理 | ⭐⭐⭐⭐⭐ |
| 即时推送 | 飞书/Discord webhook | 飞书/企微/邮件 | ⭐⭐⭐⭐ |
| 定时汇总 | 每日定时推送 | 每日早报生成 | ⭐⭐⭐⭐⭐ |
| 成本预算 | 每天6毛钱 | 每天1.3-1.6元 | ⭐⭐⭐⭐ |
2.2 本系统的差异化优势
| 特性 | AI Daily | 本系统 | 价值 |
|---|---|---|---|
| 热点识别 | 单篇文章评分 | 双层筛选:硬约束+动态阈值融合 | 质量控制+热点发现协同 |
| 去重策略 | 简单去重 | 细粒度聚类+多角度保留 | 不丢失多角度报道 |
| 内容整合 | 单篇摘要 | 双层整合(摘要+洞察) | 深度分析Top热点 |
| 领域聚焦 | AI领域 | 时政/军事/科技 | 专业领域实体识别 |
| 角度分类 | 无 | 6种报道角度分类 | 支持多角度整合 |
| 跨日关联 | 无 | 事件时间线追踪+Sentinel标记 | 追踪事件发展脉络 |
2.3 AI Daily 参考资源
- 项目介绍(热点追踪系统):https://yeekal.com/ai/ai-daily-news-tracker/
- 项目介绍(进化实录):https://yeekal.com/ai/ai-daily-news-update/
- GitHub 代码库:https://github.com/YeeKal/ai-daily
2.4 从AI Daily借鉴的核心设计
- 双循环架构:Fetch循环(实时)+ Push循环(定时)
- systemd服务化:使用systemd timer替代Python内部定时,提升稳定性
- 文件存储规范:fetch/notify/push三种文件类型,明确保留策略
- 评分硬约束:非目标领域上限、KOL转述上限,有效控制信息质量
- Prompt防退化:禁止套话、要求从素材出发,避免LLM输出风格趋同
- 双视角洞察:metadata(事实压缩)+ 正文(趋势判断)解耦
- Sentinel分段标记:单文件多板块精确管理,支持跨日关联
三、开发阶段规划
阶段一:基础架构搭建(Week 1-2)
目标:建立数据流和存储基础,确保稳定采集
| 序号 | 任务 | 描述 | 输出 | 依赖 |
|---|---|---|---|---|
| 1.1 | RSS采集模块 | 解析公众号RSS Feed,提取标题、正文、来源、发布时间 | 原始文章数据库 | - |
| 1.2 | 数据标准化 | 统一文章格式,清洗HTML标签,提取纯文本 | 标准化文章表 | 1.1 |
| 1.3 | 文件存储层 | JSON文件存储(fetch-yyyy-mm-dd.json) | 存储规范 | 1.2 |
| 1.4 | 数据库设计 | SQLite设计文章表、实体表、聚类表 | 数据库Schema | 1.2 |
| 1.5 | 基础监控 | 采集成功率、文章数量统计 | 监控面板 | 1.1 |
| 1.6 | 日志系统 | 有效日志记录,便于问题定位 | 日志模块 | 1.1 |
数据字段规范:
{
"title": "内容标题",
"link": "原始链接",
"published": "发布时间",
"source": "来源(公众号名称)",
"content": "Markdown格式的正文内容",
"tags": "LLM识别的标签",
"score": "LLM评分(0-100)",
"summary": "LLM生成的中文摘要",
"fetched_at": "抓取时间",
"entities": ["提取的实体列表"],
"reporting_angle": "报道角度"
}
验收标准:
- 稳定采集50+ RSS源
- 数据入库成功率 > 95%
- 基础监控可查看当日采集概况
- 日志系统可定位问题
阶段二:Fetch循环与双层评分系统(Week 3-4)
目标:实现实时采集、双层评分(硬约束+动态阈值融合)、即时推送
| 序号 | 任务 | 描述 | 输出 | 依赖 |
|---|---|---|---|---|
| 2.1 | Fetch循环引擎 | 每30分钟循环一次,抓取RSS→Markdown→评分 | fetch引擎 | 1.6 |
| 2.2 | 第一层:单篇评分Prompt | 单篇文章重要性评分(0-100),含硬约束 | prompts/article_score.txt |
2.1 |
| 2.3 | 硬约束过滤器 | 非时政军事上限、KOL转述上限、时效衰减 | 硬约束模块 | 2.2 |
| 2.4 | 即时推送判断 | 单篇≥90分触发即时推送候选 | 推送判断模块 | 2.3 |
| 2.5 | 飞书Webhook推送 | 飞书群机器人推送 | 飞书推送适配器 | 2.4 |
| 2.6 | systemd服务化 | 使用systemd timer管理服务 | systemd配置 | 2.1 |
双层评分架构设计
第一层:单篇文章评分(硬约束) 第二层:实体簇热度(动态阈值)
├── 输入:单篇RSS文章 ├── 输入:同一实体的多篇报道(已硬约束评分)
├── 处理:LLM评分 + 硬约束修正 ├── 处理:统计特征 + 动态阈值计算
└── 输出:0-100分(已约束) └── 输出:热点判定
├── ≤79:非目标领域,过滤 ├── 低于阈值:普通关注
├── 80-89:一般关注,进入聚类 └── 高于阈值:热点,优先整合
└── 90+:高优先级,即时推送候选
第一层:评分硬约束设计
Prompt核心约束:
## 评分规则(硬性约束)
1. **非时政/军事/科技主题上限 79 分**
- 如果内容不属于目标领域(如纯娱乐八卦、生活琐事),最高只能给 79 分
2. **KOL 转述上限 89 分**
- 如果只是 KOL/大V 对已有信息的转述/评论,而非原创信息,最高只能给 89 分
3. **时效性衰减**
- 发布超过24小时:分数×0.9
- 发布超过48小时:分数×0.8
4. **90+ 分必须同时满足**:
- 重大事件/突破性进展/政策发布
- 一手信息源(官方发布、权威媒体首发)
- 对目标领域有实质性影响
5. **标签禁止空泛**
- 禁止:["军事", "新闻", "热点"]
- 要求:["歼-35A", "舰载战斗机", "隐身性能", "海军航空兵"]
代码实现:
def apply_score_constraints(entry: dict, raw_score: int) -> tuple[int, list[str]]:
"""
应用评分硬约束
返回:修正后的分数,应用的约束标签列表
"""
constraints_applied = []
# 约束1:非目标领域上限79
if not is_target_domain(entry['content']):
raw_score = min(raw_score, 79)
constraints_applied.append("非目标领域")
# 约束2:KOL转述上限89
if is_kol_repost(entry):
raw_score = min(raw_score, 89)
constraints_applied.append("KOL转述")
# 约束3:时效性衰减
hours_old = get_hours_since_published(entry)
if hours_old > 24:
decay_factor = 0.9 ** (hours_old // 24)
raw_score = int(raw_score * decay_factor)
constraints_applied.append(f"时效衰减({hours_old}h)")
return raw_score, constraints_applied
第一层输出分级:
| 分数段 | 处理策略 | 说明 |
|---|---|---|
| ≤79 | 过滤,不入库 | 非目标领域内容 |
| 80-89 | 入库,进入聚类 | 一般关注,参与动态阈值计算 |
| 90+ | 入库,即时推送候选 | 高优先级,同时触发即时推送判断 |
验收标准:
- Fetch循环每30分钟稳定运行
- 硬约束生效(非目标领域≤79,KOL转述≤89,时效衰减)
- 90+文章触发即时推送候选
- systemd服务可一键启动/停止
阶段三:实体提取与细粒度聚类(Week 5-6)
目标:实现细粒度聚类,区分同一实体的不同报道角度
| 序号 | 任务 | 描述 | 输出 | 依赖 |
|---|---|---|---|---|
| 3.1 | 实体提取Prompt | 设计并优化实体提取提示词 | prompts/extract_entities.txt |
2.6 |
| 3.2 | 角度分类Prompt | 设计报道角度分类提示词 | prompts/classify_angle.txt |
2.6 |
| 3.3 | 批量实体提取 | 实现50篇/批并发调用,小模型处理 | 实体提取服务 | 3.1 |
| 3.4 | 角度分类服务 | 批量角度分类,与实体提取并行 | 角度分类服务 | 3.2 |
| 3.5 | 实体归一化 | 大模型消歧,合并别名 | 实体归一化服务 | 3.3 |
| 3.6 | 聚类算法 | 基于实体+角度的细粒度聚类 | 聚类引擎 | 3.4, 3.5 |
| 3.7 | 记忆系统 | 避免同一信息反复推送 | 去重模块 | 3.6 |
验收标准:
- 实体提取准确率 > 85%
- 角度分类准确率 > 80%
- 聚类后实体簇数量合理(200篇→30-50个簇)
- 同一信息不重复推送
阶段四:热度评价与动态阈值(Week 7-8)
目标:实现第二层筛选——基于硬约束后分数的动态热点识别
| 序号 | 任务 | 描述 | 输出 | 依赖 |
|---|---|---|---|---|
| 4.1 | 实体簇热度计算 | 融合硬约束分数的多维度热度计算 | 热度指标服务 | 3.6 |
| 4.2 | 第二层:动态阈值算法 | 基于硬约束后分数分布的自适应阈值 | 阈值计算模块 | 4.1 |
| 4.3 | 热点识别引擎 | 硬约束过滤 + 动态阈值筛选的双层判定 | 热点识别服务 | 4.2 |
| 4.4 | 热点精评Prompt | 大模型深度评分(Top 30热点簇) | prompts/precise_heat.txt |
4.3 |
第二层:动态阈值设计(融合硬约束分数)
实体簇热度计算:
class Cluster:
def __init__(self, entity_name: str):
self.entity_name = entity_name
self.articles = [] # 已硬约束评分的文章列表
self.hot_score = 0 # 综合热度分
def calculate_hot_score(self) -> int:
"""
计算实体簇热度,融合硬约束后的单篇分数
"""
if not self.articles:
return 0
# 基础分数:最高分文章的分数(已硬约束)
max_score = max(a['score'] for a in self.articles)
# 传播热度:报道数量 × log(来源多样性)
report_count = len(self.articles)
source_diversity = len(set(a['source'] for a in self.articles))
propagation_heat = report_count * math.log(source_diversity + 1)
# 角度覆盖度:不同报道角度数 / 6
angles = set(a.get('reporting_angle', 'unknown') for a in self.articles)
angle_coverage = len(angles) / 6
# 高优先级文章加成(90+文章额外加权)
high_priority_count = sum(1 for a in self.articles if a['score'] >= 90)
priority_bonus = high_priority_count * 5 # 每篇90+加5分
# 综合计算
self.hot_score = min(100, int(
max_score * 0.4 + # 单篇最高分权重40%
min(propagation_heat * 3, 30) + # 传播热度权重30%
angle_coverage * 20 + # 角度覆盖权重20%
priority_bonus # 高优先级加成10%
))
return self.hot_score
动态阈值算法(融合版):
def calculate_hotspot_threshold(clusters: list[Cluster], date: str) -> float:
"""
基于硬约束后分数分布计算动态阈值
同时考虑统计特征和高优先级文章数量
"""
# 获取当日所有簇的热度分数(已融合硬约束)
scores = [c.hot_score for c in clusters]
if len(scores) < 5:
return 75 # 数据不足时使用保底阈值
# 统计特征
mean_score = mean(scores)
std_score = std(scores)
median_score = median(scores)
# 方法1:统计阈值(均值+1.5倍标准差)
threshold_stat = mean_score + 1.5 * std_score
# 方法2:保底阈值(至少3条或前10%)
min_count = max(3, len(scores) * 0.1)
sorted_scores = sorted(scores, reverse=True)
threshold_adaptive = sorted_scores[min_count - 1]
# 方法3:硬约束保底(考虑90+高优先级文章数量)
high_priority_count = sum(
1 for c in clusters
if any(a['score'] >= 90 for a in c.articles)
)
if high_priority_count >= 3:
# 如果有3个以上簇包含90+文章,降低阈值确保热点被识别
threshold_backup = median_score
else:
threshold_backup = mean_score + 0.5 * std_score
# 取三者中较低值,确保热点不被遗漏
final_threshold = min(threshold_stat, threshold_adaptive, threshold_backup)
# 记录阈值计算日志
logger.info(f"动态阈值计算: 统计={threshold_stat:.1f}, "
f"保底={threshold_adaptive:.1f}, 硬约束保底={threshold_backup:.1f}, "
f"最终={final_threshold:.1f}")
return final_threshold
双层热点判定流程:
def identify_hotspots(clusters: list[Cluster], date: str) -> tuple[list[Cluster], list[Cluster]]:
"""
双层热点识别:硬约束过滤 + 动态阈值筛选
"""
# 第一层:硬约束过滤(单篇层面已处理,此处检查)
valid_clusters = []
for c in clusters:
# 过滤掉所有文章都≤79的簇(非目标领域)
if all(a['score'] <= 79 for a in c.articles):
continue
valid_clusters.append(c)
# 计算各簇热度(融合硬约束分数)
for c in valid_clusters:
c.calculate_hot_score()
# 第二层:计算动态阈值
threshold = calculate_hotspot_threshold(valid_clusters, date)
# 阈值筛选 + 额外条件
hotspots = []
normal = []
for c in valid_clusters:
if c.hot_score >= threshold:
# 额外检查:是否有90+文章 或 超过阈值10分以上
has_high_priority = any(a['score'] >= 90 for a in c.articles)
significantly_above = c.hot_score >= threshold + 10
if has_high_priority or significantly_above:
hotspots.append(c)
else:
normal.append(c)
else:
normal.append(c)
# 排序:先按热度,再按最高单篇分数
hotspots.sort(key=lambda x: (x.hot_score, x.max_article_score), reverse=True)
return hotspots, normal
融合设计优势:
| 层级 | 作用 | 输入 | 输出 |
|---|---|---|---|
| 第一层(硬约束) | 质量控制 | 单篇文章 | 过滤非目标领域,标记高优先级 |
| 第二层(动态阈值) | 热点发现 | 实体簇(多篇聚合) | 识别突发热点,自适应当日分布 |
验收标准:
- 实体簇热度计算正确(融合硬约束分数)
- 动态阈值自适应当日分布
- 双层筛选协同工作(硬约束过滤→动态阈值筛选)
- 热点识别召回率 > 90%,误报率 < 20%
阶段五:Push循环与双层整合(Week 9-10)
目标:实现定时汇总、双层整合(双视角设计)、日报生成
| 序号 | 任务 | 描述 | 输出 | 依赖 |
|---|---|---|---|---|
| 5.1 | Push循环引擎 | 每日定时运行,读取碎片化信息→整合→推送 | push引擎 | 4.4 |
| 5.2 | 摘要级整合Prompt | 多源报道合并为50-80字精炼摘要 | prompts/summary_integrate.txt |
5.1 |
| 5.3 | 洞察级整合Prompt | Top 10生成结构化深度分析(双视角设计) | prompts/insight_integrate.txt |
5.1 |
| 5.4 | Prompt防退化模块 | 禁止套话、要求从素材出发 | 防退化检查器 | 5.2, 5.3 |
| 5.5 | 摘要整合服务 | 小模型批量处理全量簇 | 摘要整合服务 | 5.2, 5.4 |
| 5.6 | 洞察整合服务 | 大模型逐个处理Top 10(双视角输出) | 洞察整合服务 | 5.3, 5.4 |
| 5.7 | 时间线提取 | 从多源报道中提取事件时间线 | 时间线提取模块 | 5.5 |
| 5.8 | 多角度整合 | 同一事件不同角度报道的整合 | 多角度整合模块 | 5.6 |
双视角洞察设计(借鉴AI Daily)
设计理念:metadata(新闻编辑视角,事实压缩)+ 正文(情报分析师视角,趋势判断)解耦
Prompt设计:
## Part 1: Metadata(新闻编辑视角)
请生成以下结构化信息:
- title: 10字以内的标题(事实陈述,无修饰)
- lead: 20字以内的导语(核心事实)
- highlights: 3-5个关键要点(bullet points,纯事实)
约束:只陈述事实,不做趋势判断,不用形容词。
## Part 2: 洞察正文(情报分析师视角)
基于多源报道,识别:
1. 事件脉络:关键时间节点和进展
2. 多角度分析:技术维度、战略维度、舆论维度
3. 影响与展望:短期影响、中长期趋势、值得关注信号
约束:
- 禁止空泛评论(如"意义重大""影响深远")
- 每个观点必须有素材支撑
- 使用具体名称(装备型号/政策名称/组织名称),不用"某些""部分"等模糊指代
输出示例:
---
title: "歼-35A列装部队"
lead: "空军官方确认歼-35A已列装首批作战部队"
highlights:
- 首次公开确认进入实战化部署阶段
- 隐身性能对标F-35C,可能在舰载领域形成优势
- 多国媒体关注其对西太平洋军事平衡的影响
---
## 事件脉络
- 2024-11:珠海航展首次公开亮相
- 2025-03:完成舰载适配测试
- 2025-05:空军确认列装首批作战部队【新进展】
## 多角度分析
- **技术维度**:隐身涂层、航电系统、舰载适配均有突破
- **战略维度**:提升海军航空兵远海作战能力
- **舆论维度**:外媒关注中美舰载机代差缩小
## 影响与展望
短期:提升海军航母编队作战能力
中期:可能在西太平洋形成局部优势
值得关注:后续舰载版测试进展、出口动向
Prompt防退化设计(借鉴AI Daily)
禁止套话列表:
FORBIDDEN_PHRASES = [
"意义重大", "影响深远", "引发关注", "备受瞩目",
"深水区", "拐点", "白热化", "新纪元", "里程碑",
"不容忽视", "值得注意", "值得关注", # 除非后接具体内容
"某些", "部分", "一些", "相关", # 模糊指代
]
def check_degeneration(content: str) -> list[str]:
"""检查内容是否包含禁止套话"""
violations = []
for phrase in FORBIDDEN_PHRASES:
if phrase in content:
violations.append(phrase)
return violations
Prompt中的防退化指令:
## 输出约束(防退化)
1. 禁止使用以下套话:
- "意义重大""影响深远""引发关注""备受瞩目"
- "深水区""拐点""白热化""新纪元""里程碑"
2. 每个观点必须有素材支撑:
- 错误:该装备性能先进
- 正确:该装备隐身系数0.01,优于F-35的0.02
3. 使用具体名称,禁止模糊指代:
- 错误:某些国家表示关注
- 正确:日本防卫省发布关注声明
4. 从素材出发,每次措辞应不同,避免模板化输出
验收标准:
- 摘要信息完整度 > 90%
- 洞察分析覆盖双视角(metadata + 正文)
- 无禁止套话出现
- 整合内容无明显事实错误
阶段六:日报生成与跨日关联(Week 11-12)
目标:生成结构化日报(含Sentinel标记),实现跨日关联
| 序号 | 任务 | 描述 | 输出 | 依赖 |
|---|---|---|---|---|
| 6.1 | 日报模板设计 | Markdown模板,包含热点、速览、数据概览 | templates/daily_report.md |
5.8 |
| 6.2 | Sentinel分段标记 | 单文件多板块精确管理 | src/utils/sentinel.py |
6.1 |
| 6.3 | 跨日关联模块 | 从历史日报提取上下文,追踪事件脉络 | src/processors/cross_day.py |
6.2 |
| 6.4 | 排序算法 | 综合热度、时效、重要性的排序逻辑 | 排序模块 | 4.4 |
| 6.5 | 日报渲染服务 | 按模板组装数据,生成Markdown(含Sentinel) | 日报渲染服务 | 6.1, 6.2, 6.4 |
| 6.6 | Web归档站点 | 部署在线阅览站点 | Web站点 | 6.5 |
| 6.7 | 数据保留策略 | fetch保留2天,notify保留2天,push保留5天 | 清理策略 | 6.6 |
简化版Sentinel分段标记设计
标记格式:
---
title: "每日情报早报"
date: "2026-05-24"
stats:
total_entities: 87
hotspot_count: 10
---
<!-- SECTION:summary BEGIN -->
## 📋 全量新闻速览
| # | 实体 | 摘要 | 来源数 | 热度 |
|---|------|------|--------|------|
| 1 | 歼-35A | 空军确认列装\|隐身性能对标F-35C | 8 | ★★★★★ |
<!-- SECTION:summary END -->
<!-- SECTION:insights BEGIN -->
## 🔥 热点深度洞察
### 1. 歼-35A列装进展 [持续跟踪]
> 速览:空军官方确认歼-35A已列装首批作战部队 [8源报道]
**事件脉络**
- 5月20日:首次公开亮相
- 5月24日:【新进展】确认列装部队
...
<!-- SECTION:insights END -->
核心代码:
import re
from datetime import datetime, timedelta
def extract_section(content: str, section_name: str) -> str:
"""从日报内容中提取指定section"""
pattern = rf'<!-- SECTION:{re.escape(section_name)} BEGIN -->(.*?)<!-- SECTION:{re.escape(section_name)} END -->'
match = re.search(pattern, content, re.DOTALL | re.IGNORECASE)
return match.group(1).strip() if match else ""
def get_historical_context(entity_name: str, days: int = 7) -> dict:
"""获取某实体近N天的历史报道上下文"""
context = {
"first_seen": None,
"previous_summaries": [],
"previous_insights": [],
"mention_count": 0
}
for i in range(days):
date = (datetime.now() - timedelta(days=i)).strftime("%Y-%m-%d")
file_path = f"data/reports/daily-{date}.md"
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
if entity_name in content:
context["mention_count"] += 1
if context["first_seen"] is None:
context["first_seen"] = date
# 提取该实体在摘要中的记录
summary_section = extract_section(content, "summary")
for line in summary_section.split('\n'):
if entity_name in line and line.strip().startswith('|'):
context["previous_summaries"].append({
"date": date,
"content": line.strip()
})
# 提取该实体在洞察中的记录
insights_section = extract_section(content, "insights")
if entity_name in insights_section:
insight_blocks = re.split(r'### \d+\.', insights_section)
for block in insight_blocks:
if entity_name in block:
context["previous_insights"].append({
"date": date,
"content": block.strip()[:500]
})
break
except FileNotFoundError:
continue
return context
def generate_cross_day_marker(entity_name: str) -> str:
"""生成跨日标记"""
history = get_historical_context(entity_name, days=7)
if history["mention_count"] == 0:
return "首次报道"
elif history["mention_count"] == 1:
return "持续跟踪"
else:
return f"持续跟踪({history['mention_count']}次)"
跨日关联应用:
# 在生成洞察时,添加跨日时间线
history = get_historical_context("歼-35A", days=7)
# 输出:
# {
# "first_seen": "2026-05-20",
# "mention_count": 3,
# "previous_summaries": [
# {"date": "2026-05-20", "content": "| 1 | 歼-35A | 首次公开亮相... |"},
# {"date": "2026-05-22", "content": "| 3 | 歼-35A | 专家分析隐身性能... |"}
# ]
# }
# 在洞察中展示时间线
timeline = f"""
**事件脉络**
- 5月20日:首次公开亮相(珠海航展)
- 5月22日:专家分析隐身性能,推测可能上舰
- 5月24日:【新进展】空军官方确认列装首批作战部队
"""
验收标准:
- 日报生成时间 < 20分钟
- Sentinel标记正确,可精确提取summary/insights
- 跨日关联可追踪实体历史报道
- Web站点可正常访问
阶段七:优化与迭代(Week 13-14)
目标:持续优化,功能扩展
| 序号 | 任务 | 描述 | 优先级 |
|---|---|---|---|
| 7.1 | Prompt优化 | 基于实际效果迭代优化提示词 | 高 |
| 7.2 | 反馈闭环 | 收集用户反馈,标注数据,优化模型 | 高 |
| 7.3 | 趋势分析 | 7日热点趋势图,周期性报告 | 中 |
| 7.4 | 个性化推荐 | 基于用户阅读历史的个性化排序 | 低 |
四、技术栈建议
4.1 核心组件
| 组件 | 推荐方案 | 说明 |
|---|---|---|
| 数据采集 | Python + feedparser | RSS解析 |
| 数据存储 | SQLite + JSON文件 | 数据库+文件双存储 |
| LLM调用 | OpenAI SDK / 国产模型SDK | 统一接口封装 |
| 任务调度 | systemd timer | 系统级服务管理 |
| Web展示 | Hugo / Flask | 静态/动态站点 |
| 日志 | Python logging + systemd journal | 集中日志管理 |
4.2 模型选择
| 任务类型 | 推荐模型 | 预估成本 |
|---|---|---|
| 实体提取 | DeepSeek-V3 / Qwen-Plus | ~0.001元/次 |
| 角度分类 | DeepSeek-V3 / Qwen-Plus | ~0.001元/次 |
| 单篇评分 | DeepSeek-V3 / Qwen-Plus | ~0.001元/次 |
| 摘要整合 | DeepSeek-V3 / Qwen-Plus | ~0.002元/次 |
| 实体消歧 | GPT-4o / Claude-3.5-Sonnet | ~0.01元/次 |
| 热点精评 | GPT-4o / Claude-3.5-Sonnet | ~0.02元/次 |
| 洞察整合 | GPT-4o / Claude-3.5-Sonnet | ~0.1元/次 |
日成本估算:
- 200-500篇/日 × 0.001元(小模型)= 0.2-0.5元
- 100个簇 × 0.001元(小模型)= 0.1元
- 10个洞察 × 0.1元(大模型)= 1元
- 总计:约1.3-1.6元/日
五、项目结构
news-intelligence-system/
├── config/
│ ├── rss_sources.json # RSS源配置
│ ├── models.yaml # 模型配置
│ └── systemd/ # systemd服务配置
├── src/
│ ├── collectors/ # 数据采集
│ │ └── rss_collector.py
│ ├── processors/ # 处理管道
│ │ ├── entity_extractor.py
│ │ ├── angle_classifier.py
│ │ ├── cluster_engine.py
│ │ ├── heat_calculator.py
│ │ └── cross_day.py # 跨日关联(新增)
│ ├── integrators/ # 内容整合
│ │ ├── summary_integrator.py
│ │ └── insight_integrator.py
│ ├── generators/ # 报告生成
│ │ ├── daily_report_generator.py
│ │ └── web_renderer.py
│ ├── push/ # 推送平台
│ │ ├── base.py
│ │ ├── feishu.py
│ │ └── discord.py
│ └── utils/ # 工具函数
│ ├── sentinel.py # Sentinel分段标记(新增)
│ └── prompt_checker.py # Prompt防退化检查(新增)
├── prompts/ # 提示词文件
│ ├── article_score.txt # 单篇评分(含硬约束)
│ ├── extract_entities.txt
│ ├── classify_angle.txt
│ ├── quick_heat.txt
│ ├── precise_heat.txt
│ ├── summary_integrate.txt
│ └── insight_integrate.txt # 双视角洞察
├── templates/
│ └── daily_report.md # 含Sentinel标记
├── data/
│ ├── fetch/ # fetch-yyyy-mm-dd.json
│ ├── notify/ # notify-yyyy-mm-dd.json
│ └── reports/ # daily-yyyy-mm-dd.md
├── web/ # Web归档站点
├── tests/
├── scripts/
│ ├── fetch_loop.py
│ ├── push_loop.py
│ └── setup_systemd.sh
├── requirements.txt
└── README.md
六、关键风险与应对
| 风险 | 影响 | 应对措施 |
|---|---|---|
| RSS源失效 | 数据缺失 | 多源备份,监控告警 |
| LLM API限流 | 处理延迟 | 批量处理,重试机制,降级策略 |
| 实体识别错误 | 聚类偏差 | 人工标注反馈,Prompt迭代 |
| 热点漏识别 | 信息缺失 | 动态阈值保底机制,人工复核 |
| 成本超支 | 预算超支 | Token监控,模型降级,配额控制 |
| 进程崩溃 | 服务中断 | systemd自动重启 |
| LLM输出退化 | 质量下降 | Prompt防退化检查 |
七、里程碑与交付物
| 里程碑 | 时间 | 交付物 |
|---|---|---|
| M1 | Week 2 | 稳定运行的数据采集系统 |
| M2 | Week 4 | Fetch循环上线,评分硬约束生效 |
| M3 | Week 6 | 细粒度聚类引擎,实体提取准确率>85% |
| M4 | Week 8 | 动态热点识别系统,召回率>90% |
| M5 | Week 10 | Push循环上线,双视角洞察+Prompt防退化 |
| M6 | Week 12 | Sentinel跨日关联上线,Web归档站点 |
| M7 | Week 14 | 持续优化迭代 |
八、借鉴AI Daily的核心设计总结
8.1 架构层面
- 双循环架构:Fetch循环(实时)+ Push循环(定时)
- systemd服务化:替代Python内部定时,提升稳定性
- 文件存储规范:fetch/notify/reports三种文件类型,明确保留策略
8.2 LLM应用层面
- 评分硬约束:非目标领域≤79、KOL转述≤89,有效控制信息质量
- Prompt防退化:禁止套话、要求从素材出发,避免LLM输出风格趋同
- 双视角洞察:metadata(事实压缩)+ 正文(趋势判断)解耦
8.3 数据管理层面
- Sentinel分段标记:单文件多板块精确管理,支持跨日关联
- 跨日关联:从历史日报提取上下文,追踪事件发展脉络
- 数据保留策略:自动清理过期文件
8.4 工程层面
- 日志集中管理:systemd journal便于问题定位
- 多平台推送:飞书、Discord webhook支持
- 成本可控:每天约1.3-1.6元
文档版本:v2.1
最后更新:2026-05-28
状态:已融合AI Daily四大核心设计(Sentinel、硬约束、防退化、双视角)