本文首发地址 https://h89.cn/archives/595.html

这个五一我哪也没去,在家把一个想了很久的项目做完了。

事情是这样的:每天早上刷 Twitter、Hacker News、微博、知乎、36氪……每个平台都有自己的热点,但它们散落各处。更烦的是,算法推荐的"猜你喜欢"往往让真正重要的事件被淹没在信息流里。刷半小时,感觉看了很多东西,但脑子里一团浆糊。

我不是缺新闻,我是缺组织好的信息

五一假期第一天,我脑子里突然闪过一个念头:能不能让系统自动把"同一件事"的几十篇报道聚合成一条热点,每天只需要看最重要的 10-20 件事?

五天之后,Agent Hot News 有了第一个能跑的版本。

整体架构

系统走的是一个典型 Pipeline 路线:

多源采集 → 原始文章库 → AI Pipeline → 热点事件库 → API/前端
  • 采集层:RSS、API、爬虫三种方式接入 9 个平台
  • 存储层:PostgreSQL + pgvector,同时存文章原文和 Embedding 向量
  • AI 层:Embedding → 聚类 → LLM 提炼 → 热度评分
  • 服务层:FastAPI + SSE 实时推送
  • 前端层:React 热点大盘 + 管理后台

下面拆解几个我觉得最有意思的技术决策。

核心模块拆解

1. 多源采集:配置化接入,不硬编码

系统接入了 9 个来源:

来源 接入方式 说明
36氪 RSS 科技创业媒体
Hacker News API 全球技术社区热帖
TechCrunch RSS 国际科技媒体
Solidot RSS 开源/科技资讯
GitHub Trending 爬虫 当日趋势仓库
知乎 API 全站热榜
微博热搜 爬虫 实时热搜榜
百度热搜 爬虫 百度实时热点
天行 API API 抖音/网络/微博等热点

关键设计是配置化接入。每个来源只需要定义 endpoint 和解析规则,不需要改核心代码。这套 Collector 抽象统一处理了重试、速率限制、错误降级。新增一个来源,写个配置文件就行。

2. 热点发现:Embedding + DBSCAN

这是整个系统的核心。100 篇文章可能只讲了 20 件事,怎么把"同一件事"的不同来源归到一组?

为什么不用 K-Means?

因为每天的热点数量是不固定的。今天可能有 15 个大事,明天可能只有 8 个。K-Means 需要预先指定 K 值,这在热点发现场景里不现实。

为什么选择 DBSCAN?

密度聚类有两个好处:

  • 不需要预设簇数,系统自动发现今天有多少个热点
  • 能过滤噪声,孤立的文章不会强行归入某个簇

具体参数:cosine 距离,eps=0.25,min_samples=2。

这个 eps 是调出来的。0.2 的时候会把同一事件的不同角度报道拆成多个簇;0.3 的时候容易把不相关的新闻混在一起。0.25 是个比较甜的点。

min_samples=2 意味着至少两篇报道才算一个"事件"。单篇孤立文章要么是噪声,要么是某个还没发酵的小众话题,暂时不值得展示。

Embedding 模型选择

默认用 qwen3-embedding-8b(4096 维),通过 OpenRouter 调用。选它是因为中文效果确实好——这个系统主要处理中文内容。

模型 维度 特点
qwen/qwen3-embedding-8b 4096 当前默认,中文效果最佳
nvidia/llama-nemotron-embed-vl-1b-v2:free 2048 NVIDIA 多语言,免费
text-embedding-3-small 1536 OpenAI 出品

换模型时需要同步改 EMBEDDING_DIMENSION 并重建向量索引。不同模型的向量空间不一样,cosine similarity 的阈值也要重新调。

3. LLM 提炼:从 N 篇文章到 1 个结构化事件

聚类完成后,每个簇里有若干篇报道。下一步是让 LLM 读这个簇里的所有文章,输出一个结构化摘要。

用的是 deepseek/deepseek-v4-flash(通过 OpenRouter),输出格式是严格 JSON:

{
  "title": "标题,≤8个字",
  "summary": "摘要,≤60个字",
  "category": "分类",
  "sentiment": "情感倾向",
  "entities": ["关键实体"]
}

为什么用 Flash 而不是 Pro?因为提炼摘要是个"结构化提取"任务,不是深度推理任务。Flash 足够快、足够便宜,成本大概是 Pro 的 1/10。实测下来输出质量没有明显差异。

4. 热度评分:不只是计数

早期版本按报道数量排序,结果单一平台刷屏的事件会霸占榜首。后来设计了一个多维度评分公式:

H = 0.3 × avg_raw + 5.0 × count + 10.0 × sources - 0.5 × hours_old

拆解一下:

  • count(5.0):报道数量,越多人讨论越热
  • sources(10.0):来源多样性,跨平台讨论比单一平台刷屏更有价值。这是权重最高的一项,因为跨平台验证往往意味着真大事
  • hours_old(-0.5):时间衰减,老新闻自然降权
  • avg_raw(0.3):原始平台的热度值,比如微博热搜排名、HN 分数

系数都是经验值。sources 权重最高,是因为我发现真正的热点往往是在多个平台同时出现的。某个话题只在微博热搜上爆,很可能是娱乐圈八卦;但如果微博、知乎、百度、36氪都在讨论,大概率是科技/社会大事。

5. 去重:48 小时滑动窗口

热点不是一次性事件,往往有后续报道。系统维护了一个 48 小时的滑动窗口,新事件的向量 centroid 与已有事件做 cosine similarity,超过 0.75 就合并到已有事件里,同时更新摘要和时间线。

这个阈值也要看 Embedding 模型。Qwen 的向量空间里,0.75 能比较好地平衡"同一事件的新进展"和"不同事件的巧合相似"。

6. 实时推送:SSE 比 WebSocket 简单

前端通过 SSE(Server-Sent Events)接收实时更新。新热点出现或排名大幅变动时,服务端主动推送。

选 SSE 而不是 WebSocket,纯粹因为单向推送场景下 SSE 更简单:

  • 基于 HTTP,不需要额外协议握手
  • 自动重连、事件 ID 断点续传都是浏览器原生支持的
  • 不需要处理 WebSocket 的连接状态管理

对于"新闻监控大盘"这种单向数据流场景,SSE 完全够用。

踩过的坑

DBSCAN 的 eps 参数没有银弹

不同 Embedding 模型、不同语言的内容,最优 eps 是不一样的。Qwen 3 Embedding 在中文内容上 0.25 合适,但换到英文内容可能需要调到 0.2 或 0.3。这个参数必须根据实际数据分布来调,不能抄一个值就用。

聚类结果的质量取决于 Embedding 质量

如果 Embedding 把"苹果发布新机"和"苹果股价下跌"映射到几乎相同的向量,DBSCAN 也无能为力。好在文本 Embedding 在这个粒度上区分度还不错,但遇到同义词多的领域(比如政治新闻)会有混淆。

LLM 提炼需要严格的 prompt 工程

早期让 LLM 自由发挥,标题忽长忽短,摘要有的 30 字有的 200 字。后来强制要求 JSON 输出 + 长度限制,前端展示才稳定下来。关键是 prompt 里要明确"超过长度就截断,不要返回超长的字段"。

技术启示

做这个项目的几个实际收获:

  1. 聚类比分类更适合热点发现。不需要预定义类别,系统自动发现今天有什么热点。K-Means 不适用是因为热点数量不固定。

  2. 多源交叉验证比单一平台热度更可靠。评分公式里 sources 的权重最高,这是我观察了一段时间数据后做的调整。跨平台出现的热点,质量明显更高。

  3. 向量相似度阈值和 Embedding 模型强耦合。换模型一定要重新调参,没有通用的魔法数字。

  4. Flash 模型做结构化提取性价比极高。不要什么任务都上最强的模型,提炼摘要、情感分析这类任务,小模型足够用。

如果你也在为信息过载困扰,可以看看这个项目的实现:Agent Hot News,在线预览:https://f.h89.cn:51130/

参考文献

[1] Agent Hot News 项目地址 — https://github.com/chenjim/agent-hot-news
[2] 在线预览 — https://f.h89.cn:51130/
[3] OpenRouter API — https://openrouter.ai/
[4] Qwen3 Embedding 模型 — https://huggingface.co/Qwen
[5] pgvector — PostgreSQL 向量扩展 — https://github.com/pgvector/pgvector


本文链接:五一假期没出门,憋了个 AI 热点聚合系统 - https://h89.cn/archives/595.html

版权声明:原创文章 遵循 CC 4.0 BY-SA 版权协议,转载请附上原文链接和本声明。

标签: Agent, News, Embedding, pgvector, DBSCAN

🎓 呈言英语 智能英语学习平台
📚单词学习 🎧听说练习 📖阅读理解 ✏️拼写练习 🌟 AI智能推荐 · 科学记忆曲线
🚀 立即开始免费学习

添加新评论