RAG 在新闻摘要中的应用:多源信息聚合和时效性敏感的检索策略
RAG 在新闻摘要中的应用多源信息聚合和时效性敏感的检索策略一、深度引言与场景痛点大家好我是赵咕咕。今年初我们给一个资讯平台做新闻摘要 RAG。需求是每天早上 8 点Agent 自动整合过去 24 小时的多源新闻生成一份 500 字的中文摘要简报。原型用标准 RAG 管道——每天凌晨跑一次批量检索把新闻做 embedding 存入向量库然后按 topic 聚类 LLM 摘要。结果第一版上线后用户投诉摘要里有一条新闻是三天前的。排查发现同一事件的多家媒体报道时间标签不一样Reuters 的报道是今天发的但新华网的相关报道是三天前发的。向量检索把三天前的文章也捞进来了——因为语义上高度相关。这就是新闻摘要 RAG 的核心挑战时间敏感度。普通知识库 RAG 不在意文档是三个月前还是三年前写的但新闻 RAG 里时效性是检索引擎的一等约束。二、底层机制与原理深度剖析2.1 新闻 RAG 与普通 RAG 的关键区别维度通用 RAG新闻 RAG时间敏感度低极高小时级信息来源单一内部知识库多源100 媒体重复与冗余低极高同一事件多源报道检索目标最相关最新 最全面 不重复更新频率周/月级小时/分钟级去重需求低核心功能2.2 时效性敏感的检索流水线2.3 核心创新点时间衰减 事件去重这个流水线有两个普通 RAG 不具备的能力时间衰减加权不是简单地把过去 24 小时的新闻筛出来而是对检索结果的向量相似度乘上一个时间衰减函数final_score similarity_score * exp(-λ * age_hours)这样1 小时前的新闻和 23 小时前的新闻在语义相同的条件下1 小时前的分数更高。λ的值取决于场景——即时新闻λ0.5深度分析λ0.05。事件去重同一个事件被多家媒体重复报道如美联储加息在检索结果中会占据大量槽位。需要通过文本相似度聚类同一个事件只保留一篇最有代表性的报道通常是发布时间最新 来源权重最高的那篇。三、生产级代码实现import asyncio import logging import math import hashlib from dataclasses import dataclass, field from datetime import datetime, timedelta, timezone from typing import Any logger logging.getLogger(__name__) dataclass class NewsArticle: 标准化新闻文章。 article_id: str title: str content: str source: str # Reuters / 新华网 / Bloomberg source_weight: float 1.0 # 来源权威权重 published_at: datetime field(default_factorylambda: datetime.now(timezone.utc)) event_id: str # 事件聚类 ID embedding: list[float] | None None language: str zh class NewsRAGAgent: 新闻摘要 RAG Agent。 核心特性 1. 时间衰减加权检索 2. 事件去重 3. 来源多样性保证 def __init__( self, llm_client: Any, vector_store: Any, decay_lambda: float 0.1, # 时间衰减系数 max_age_hours: int 24, top_k_per_event: int 1, # 每个事件最多保留几篇 min_source_diversity: int 3, # 最少来源多样性 ): self._llm llm_client self._vector_store vector_store self._decay_lambda decay_lambda self._max_age_hours max_age_hours self._top_k_per_event top_k_per_event self._min_source_diversity min_source_diversity async def generate_daily_brief( self, topic: str | None None, max_articles: int 10 ) - str: 生成每日新闻简报。 # 1) 检索候选文章 candidates await self._retrieve_news(topic) # 2) 事件去重 deduped await self._deduplicate_events(candidates) # 3) 来源多样性保证 diverse self._ensure_source_diversity(deduped) # 4) 时间排序最新优先 diverse.sort(keylambda a: a.published_at, reverseTrue) selected diverse[:max_articles] # 5) LLM 摘要生成 summary await self._generate_summary(selected, topic) return summary async def _retrieve_news( self, topic: str | None None ) - list[NewsArticle]: 时效性感知的新闻检索。 # 构建查询 query topic or 今日重要新闻 try: response await self._llm.embeddings.create( modeltext-embedding-3-small, inputquery, ) query_emb response.data[0].embedding except Exception as e: logger.error(Embedding 失败: %s, e) return [] # 检索取更多候选后续过滤 try: raw_results self._vector_store.search( query_emb, top_k100 ) except Exception as e: logger.error(向量检索失败: %s, e) return [] # 时间衰减 过滤 now datetime.now(timezone.utc) articles [] for r in raw_results: published r.get(published_at) if isinstance(published, str): published datetime.fromisoformat(published) # 时间过滤 age_hours (now - published).total_seconds() / 3600 if published else 0 if age_hours self._max_age_hours: continue # 时间衰减 time_decay math.exp(-self._decay_lambda * max(0, age_hours - 1)) adjusted_score r.get(score, 0) * time_decay # 来源权重 source_weight r.get(source_weight, 1.0) adjusted_score * source_weight articles.append(NewsArticle( article_idr.get(article_id, ), titler.get(title, ), contentr.get(content, ), sourcer.get(source, unknown), source_weightsource_weight, published_atpublished, event_idr.get(event_id, ), embeddingr.get(embedding), )) # 按调整后分数排序 articles.sort(keylambda a: a.source_weight, reverseTrue) return articles async def _deduplicate_events( self, articles: list[NewsArticle] ) - list[NewsArticle]: 事件去重同一事件只保留一篇最佳报道。 if not articles: return [] # 按发布时间排序 sorted_articles sorted( articles, keylambda a: a.published_at, reverseTrue ) # 方法一基于 event_id 的去重 seen_events: set[str] set() deduped: list[NewsArticle] [] for article in sorted_articles: event_key article.event_id or self._generate_event_key( article.title ) if event_key not in seen_events: deduped.append(article) seen_events.add(event_key) continue # 如果已存在但当前文章更新 → 替换 for i, existing in enumerate(deduped): existing_key existing.event_id or self._generate_event_key( existing.title ) if existing_key event_key: if article.published_at existing.published_at: deduped[i] article break # 方法二对没有 event_id 的文章做语义去重 final_deduped await self._semantic_dedup(deduped) return final_deduped staticmethod def _generate_event_key(title: str) - str: 基于标题生成事件聚类 key。 使用简化的 SimHash 思想提取关键词生成 hash。 # 去除标点、数字 import re clean re.sub(r[^\u4e00-\u9fff\w], , title) return hashlib.md5(clean.encode()).hexdigest()[:12] async def _semantic_dedup( self, articles: list[NewsArticle], threshold: float 0.85 ) - list[NewsArticle]: 基于语义相似度的二次去重。 if len(articles) 1: return articles keep: list[NewsArticle] [articles[0]] for article in articles[1:]: is_dup False for kept in keep: sim await self._compute_similarity(article, kept) if sim threshold: is_dup True # 保留来源权重更高的 if article.source_weight kept.source_weight: keep[keep.index(kept)] article break if not is_dup: keep.append(article) return keep async def _compute_similarity( self, a: NewsArticle, b: NewsArticle ) - float: 计算两篇文章的语义相似度。 优先使用已有的 embedding否则调用 API。 # 简化标题 Jaccard 相似度 a_words set(a.title) b_words set(b.title) if not a_words or not b_words: return 0.0 return len(a_words b_words) / len(a_words | b_words) def _ensure_source_diversity( self, articles: list[NewsArticle] ) - list[NewsArticle]: 确保来源多样性至少包含 N 个不同来源。 if len(articles) self._min_source_diversity: return articles result [] seen_sources: set[str] set() remaining: list[NewsArticle] [] # 第一轮每个来源取一篇 for article in articles: if article.source not in seen_sources: result.append(article) seen_sources.add(article.source) else: remaining.append(article) if len(seen_sources) self._min_source_diversity: break # 第二轮填充剩余槽位 result.extend(remaining) return result async def _generate_summary( self, articles: list[NewsArticle], topic: str | None None, ) - str: LLM 生成新闻摘要。 if not articles: return 今日无相关重要新闻。 # 构建文章列表 article_texts [] for i, article in enumerate(articles, 1): pub_time article.published_at.strftime(%H:%M) article_texts.append( f[{i}] {article.title}\n f 来源: {article.source} | 时间: {pub_time}\n f 摘要: {article.content[:150]}... ) articles_str \n\n.join(article_texts) topic_hint f主题聚焦: {topic}\n if topic else prompt f请根据以下新闻文章生成一份简洁的每日简报。 {topic_hint} 要求 1. 500 字以内 2. 按重要性排序最重要的新闻在前 3. 每条新闻包含来源和发布时间 4. 不重复报道同一事件 5. 仅使用提供的文章内容不要编造信息 ## 四、边界分析与架构权衡 {articles_str} 请生成简报 try: response await self._llm.chat.completions.create( modelgpt-4o, messages[{role: user, content: prompt}], temperature0.3, max_tokens1000, ) return response.choices[0].message.content or 生成失败 except Exception as e: logger.error(摘要生成失败: %s, e) return f摘要生成失败: {e} async def main(): # Mock 测试 agent NewsRAGAgent( llm_clientNone, vector_storeNone, decay_lambda0.1, max_age_hours24, ) summary await agent.generate_daily_brief(topic科技) print(summary) if __name__ __main__: asyncio.run(main())代码关键设计时间衰减公式exp(-λ * age_hours)。对 1 小时内的新闻不衰减age_hours - 1保证新鲜内容不受影响1 小时后指数衰减。双重去重event_id 去重快速 语义相似度去重精确。对于没有 event_id 的文章通过标题 hash 和语义相似度双重保障。来源多样性先确保每个来源至少有一篇再填充剩余。避免摘要全部来自单一媒体。来源权重Reuters、Bloomberg 等权威媒体的文章分数更高在事件去重时优先保留。五、总结4.1 实时性 vs 完整性新闻 RAG 的最大挑战是如何在 24 小时内覆盖尽可能多的新闻同时不遗漏重要事件。策略分时检索不是一次性拉取 100 篇而是分 6 个时间窗口每 4 小时一段每个窗口取 Top-20最终合并去重。这样保证了时效分布均匀。增量更新突发新闻出现时如地震、重大事件触发增量检索和摘要更新。4.2 事件去重的粒度控制去重阈值0.85的选择太严0.95只有几乎相同的文章才被去重摘要中仍然存在大量重复。太松0.70不同但相关的文章被误判为重复摘要中丢失重要信息。新闻摘要场景建议从 0.85 开始根据实际效果调整。建议做 A/B 测试对比人工摘要来判断去重质量。4.3 来源可信度管理不同来源的权重设置来源类型权重说明Reuters / AP / AFP1.5国际通讯社事实核查最严格Bloomberg / WSJ1.3权威财经媒体新华网 / 人民日报1.2国内官方媒体新浪 / 腾讯新闻0.9商业媒体转载为主自媒体 / 博客0.5需额外核查权重影响检索排序和事件去重时的保留优先级。4.4 什么时候新闻 RAG 足够好场景是否适用通用新闻摘要无特定领域适用财经/政治新闻需专业分析需领域模型 RAG突发新闻报道分钟级需实时流处理 RAG深度调查报道不适用需要人工采访和分析五、总结新闻 RAG 和传统知识库 RAG 的根本区别在于时间是检索的核心维度而不是辅助过滤条件。设计方案时需要注意时间衰减是必修课新鲜度必须嵌入到检索评分中而不是事后过滤。事件去重比检索召回更重要新闻场景的最大问题是同一事件 50 篇报道而不是找不到相关新闻。来源多样性是质量保证单一来源的摘要缺乏视角用户能感知到偏颇。增量更新是生产必需早上的摘要到中午可能已经过时了需要支持增量更新。时间在 RAG 系统中有一种降维打击的能力——一条 1 小时前的高质量报道对用户的效用远超一条 23 小时前的更高语义相似度的报道。传统向量检索假设相似度 相关性但在新闻场景中这个假设需要被时间重新加权。下一篇预告Redis 连接管理优化连接池大小、空闲超时和健康检查的最佳配置。

相关新闻

Python 部署优化:使用 Docker 多阶段构建缩小 RAG 服务镜像体积

Python 部署优化:使用 Docker 多阶段构建缩小 RAG 服务镜像体积

Python 部署优化:使用 Docker 多阶段构建缩小 RAG 服务镜像体积 一、深度引言与场景痛点 大家好,我是赵咕咕。 去年我们第一次把 RAG 服务部署到 Kubernetes 时,镜像体积是 1.8GB。每次滚动更新,从拉镜像到服务就绪需要 3 分钟。如…

2026/7/23 9:56:17阅读更多 →
LangChain RunnableBranch:条件路由在 Agent 决策树中的实战应用

LangChain RunnableBranch:条件路由在 Agent 决策树中的实战应用

LangChain RunnableBranch:条件路由在 Agent 决策树中的实战应用 一、深度引言与场景痛点 大家好,我是赵咕咕。 Agent 系统最常见的架构模式是意图路由:用户的 query 进来 → 判断意图 → 路由到不同的处理链路。简单意图走缓存,复…

2026/7/23 9:56:17阅读更多 →
UE5中实现二次元角色Q弹物理摆动:KawaiiPhysics核心原理与5分钟蓝图实践

UE5中实现二次元角色Q弹物理摆动:KawaiiPhysics核心原理与5分钟蓝图实践

1. 项目概述:什么是KawaiiPhysics? 如果你在开发二次元风格或者任何带有可爱元素的游戏时,总觉得角色或物件的动态有点“硬”,少了点那种Q弹、软萌的感觉,那你很可能需要了解一下KawaiiPhysics。这不是一个官方的Unrea…

2026/7/23 9:54:17阅读更多 →
Django毕设项目:基于 Django 的农产品溯源直售电商网站设计与实现 农户直卖模式生鲜交易信息化平台 (源码+文档,讲解、调试运行,定制等)

Django毕设项目:基于 Django 的农产品溯源直售电商网站设计与实现 农户直卖模式生鲜交易信息化平台 (源码+文档,讲解、调试运行,定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/23 11:25:18阅读更多 →
Python毕设项目:基于 Python 的数字化数学自主学习测评管理系统 自适应数学练习与成绩统计系统 (源码+文档,讲解、调试运行,定制等)

Python毕设项目:基于 Python 的数字化数学自主学习测评管理系统 自适应数学练习与成绩统计系统 (源码+文档,讲解、调试运行,定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/23 11:25:18阅读更多 →
私有属性的特点及其构造方法的作用(java)

私有属性的特点及其构造方法的作用(java)

1. 私有属性(private)的特点私有属性是 Java 中封装的核心实现方式,主要特点如下:表格特点说明访问权限限制只能在当前类的内部直接访问,外部类(包括子类)都无法直接读取或修改数据安全性避免外…

2026/7/23 11:25:18阅读更多 →
设备全生命周期成本怎么分析?维修、能耗、停机和产能都要算清楚

设备全生命周期成本怎么分析?维修、能耗、停机和产能都要算清楚

很多工厂判断一台设备贵不贵,只看两笔账:买设备花了多少钱;每年维修花了多少钱。但设备真正昂贵的地方,往往不在采购价,也不只在维修费。有些设备买得便宜,后面却能耗高、故障多、备件贵;有些设…

2026/7/23 11:25:18阅读更多 →
Django毕业设计-基于 Django 的农产品产地直售电商网站的设计与实现 乡村特色农产品农户直卖交易平台设计(源码+LW+部署文档+全bao+远程调试+代码讲解等)

Django毕业设计-基于 Django 的农产品产地直售电商网站的设计与实现 乡村特色农产品农户直卖交易平台设计(源码+LW+部署文档+全bao+远程调试+代码讲解等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/23 11:25:18阅读更多 →
嵌入式AES硬件加速器实战:从ECB到GCM的配置与优化

嵌入式AES硬件加速器实战:从ECB到GCM的配置与优化

1. AES硬件加速器:嵌入式安全的基石 在嵌入式系统开发中,数据安全正从一个“加分项”演变为“必需品”。无论是智能家居设备间的通信、工业传感器的数据上报,还是穿戴设备的健康信息同步,数据在传输和存储过程中的机密性与完整性都…

2026/7/23 11:23:17阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/23 0:56:31阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/23 0:56:31阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 0:56:31阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:00:28阅读更多 →
从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:28阅读更多 →
油泥处理设备哪里能买到

油泥处理设备哪里能买到

油泥处理设备哪里有?这是许多从事油田、炼化、清罐业务的从业者最关心的问题。根据河南三丰环保设备有限公司的行业经验,选购油泥处理设备的核心在于设备能否适配当地环保法规与原料特性,而非单纯看价格。该公司总经理王钦田先生指出&#xf…

2026/7/23 0:00:28阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/22 22:56:18阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/22 18:55:50阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/22 18:55:50阅读更多 →