Files
my-daily/20260529_新闻智能分析系统开发计划_v2.md

33 KiB
Raw Permalink Blame History

新闻智能分析系统开发计划 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 参考资源

2.4 从AI Daily借鉴的核心设计

  1. 双循环架构Fetch循环(实时)+ Push循环(定时)
  2. systemd服务化:使用systemd timer替代Python内部定时,提升稳定性
  3. 文件存储规范fetch/notify/push三种文件类型,明确保留策略
  4. 评分硬约束:非目标领域上限、KOL转述上限,有效控制信息质量
  5. Prompt防退化:禁止套话、要求从素材出发,避免LLM输出风格趋同
  6. 双视角洞察:metadata(事实压缩)+ 正文(趋势判断)解耦
  7. 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("非目标领域")
    
    # 约束2KOL转述上限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 架构层面

  1. 双循环架构Fetch循环(实时)+ Push循环(定时)
  2. systemd服务化:替代Python内部定时,提升稳定性
  3. 文件存储规范fetch/notify/reports三种文件类型,明确保留策略

8.2 LLM应用层面

  1. 评分硬约束:非目标领域≤79、KOL转述≤89,有效控制信息质量
  2. Prompt防退化:禁止套话、要求从素材出发,避免LLM输出风格趋同
  3. 双视角洞察:metadata(事实压缩)+ 正文(趋势判断)解耦

8.3 数据管理层面

  1. Sentinel分段标记:单文件多板块精确管理,支持跨日关联
  2. 跨日关联:从历史日报提取上下文,追踪事件发展脉络
  3. 数据保留策略:自动清理过期文件

8.4 工程层面

  1. 日志集中管理systemd journal便于问题定位
  2. 多平台推送:飞书、Discord webhook支持
  3. 成本可控:每天约1.3-1.6元

文档版本:v2.1
最后更新:2026-05-28
状态:已融合AI Daily四大核心设计(Sentinel、硬约束、防退化、双视角)