Nstproxy 现已升级为 Nstdata。了解此次变化。
周一至周五 09:00 - 18:00(UTC+08:00) 公司地址
19H MAXGRAND PLAZA NO.3 TAI YAU STREET SAN PO KONG, KOWLOON HONG KONG ©2026 NST LABS TECH LTD. 保留所有权利。
Marcus Chen Product & Network Architect
如何自动保持您的RAG知识库最新 TL;DR
RAG 新鲜度有三个时钟:源新鲜度、索引新鲜度和答案新鲜度。分别测量它们。
构建 URL 清单并比较规范化内容的哈希值;仅重新嵌入更改过的页面,并保持页面与块的映射以进行替换和删除。
失败的爬取是未知状态,并不能证明页面已被移除。在删除索引记录之前,请确认 404、重定向和站点地图的更改。
Nstdata Crawl 当前文档记录任务轮询,而不是外发 Webhook,因此您的调度程序或工作线程必须负责状态检查和恢复。
引言:当索引停止移动时,RAG 会变得陈旧
Nstdata Crawl 是此工作流中的收集层;其 产品概述 描述了下游数据管道的页面和网站检索。
RAG 系统可能在每次请求时查询其向量数据库,但仍然返回旧信息。源页面可能已经更改,但索引可能尚未重新爬取。或者新的向量可能存在,而检索缓存仍然包含旧结果。因此,“新鲜”不仅仅描述模型的回答时间。
本指南设计了一个公共文档和知识页面的定时更新管道:库存 → 爬取 → 验证 → 比较 → 块/嵌入 → 插入/删除 → 验证 。它假定您的应用程序控制源白名单和向量数据库。Nstdata Crawl 处理检索并返回任务/页面结果;它不决定文档是否对您的产品过时。有关当前任务和结果端点的更多信息,请参见 Crawl API 文档 。
RAG 新鲜度实际上意味着什么
新鲜度层 问题 示例时间戳 源新鲜度 页面本身最后一次更改是什么时候? source_updated_at(如有提供)索引新鲜度 您接受的内容何时到达向量存储? last_indexed_at答案新鲜度 哪个源快照提供了此答案的依据? 检索的 crawled_at
爬取时间戳并不证明页面已被更新,而索引时间戳也不证明检索到了最新的源。保留您的系统实际上可以观察到的时间戳;如果网站未暴露 source_updated_at,则不要编造它。
自动更新知识库的架构
生产作业有一个调度程序,一个持久化的任务记录,一个爬取工作线程,一个标准化器,一个内容哈希比较,一个嵌入阶段,一个向量存储写入器和一个验证检查。每一步都需要一个幂等性密钥和一个可见结果。一个运行在工作线程崩溃后应安全重复。
对于任何页面,至少存储 canonical_url、last_attempt_at、last_success_at、content_hash、version、 和当前块 ID。如果可审计性很重要,请单独保留历史爬取文档。清单是控制平面,告诉管道哪些记录需要替换。
status
第一步:建立 URL 清单 从公开页面的显式白名单或受限发现过程开始。站点地图有助于枚举可能的 URL;链接有助于查找被省略的页面。规范化片段和跟踪参数,但如果它们更改页面内容,则不要合并查询字符串。版本化文档应保持独立(/v1/ 和 /v2/),除非应用程序有明确的规则来淘汰其中一个。
CREATE TABLE page_manifest (
canonical_url TEXT PRIMARY KEY ,
content_hash TEXT ,
status TEXT NOT NULL ,
last_attempt_at TEXT ,
last_success_at TEXT ,
current_chunk_ids TEXT ,
redirect_to TEXT
) ;
在大规模运行之前持久化清单。如果新的爬取被中断,您可以从上一个完成的 URL 继续,而不是重新发现任务已经完成的内容。
第二步:在合适的间隔调度重新爬取 刷新调度应反映源的波动性和商业风险。定价或 API 行为可能需要比存档的公司历史页面更短的间隔。开始时设定一个计划,观察更改页面的百分比,并进行调整。避免将“每分钟重新爬取所有内容”作为默认设置:这会增加请求而不一定改善答案。
对于简单的部署,可以通过 Cron 条目调用一个幂等的作业:
*/30 * * * * cd /srv/rag-ingest && .venv/bin/python -m ingest.run >> /var/log/rag-ingest.log 2>&1
当作业需要重试、并发限制、每个站点的节奏或持久的检查点时,使用托管的调度程序或队列更佳。Nstdata 当前文档显示异步 Crawl 任务 ID 和状态查询;他们指出目前不支持 Webhook。让工作线程使用截止日期和退避轮询状态,而不是无限期等待外部回调。
完全重新爬取与增量重新爬取 A full recrawl can simplify discovery when the site is small and bounded. Incremental processing reduces embedding and vector writes when most pages are unchanged, but it requires a URL manifest and reliable hash comparison. Many systems combine both: rediscover URLs on a slower schedule, then recrawl known high-priority pages more frequently.
Step 3: Detect changed, new, and deleted pages Hash normalized content, not the raw HTML bytes. Raw markup can change because of request IDs, timestamps, or layout while the useful text stays the same. Keep the canonical URL and normalized body with the hash so you can reproduce the comparison.
from hashlib import sha256
import re
def normalize_for_hash ( markdown : str ) - > str :
text = markdown . replace ( "\r\n" , "\n" )
text = re . sub ( r"\n{3,}" , "\n\n" , text )
return text . strip ( )
def content_hash ( markdown : str ) - > str :
return sha256 ( normalize_for_hash ( markdown ) . encode ( "utf-8" ) ) . hexdigest ( )
如果哈希与上一次成功记录相符,则跳过嵌入。如果不同,则构建替换块集合并在退休旧 ID 之前验证它。如果页面是新的,则创建其初始记录。如果一个 URL 从站点地图中消失,则将其标记为删除候选;仅仅从站点地图中遗漏不够以删除文档。
Handle removed pages and redirects safely
成功页面: 验证内容,比较哈希,然后在更改时更新。
404 或 410: 记录状态,并根据您的网站政策在删除之前确认。
301 或 302: 保留原始 URL 映射并评估规范目标;不要盲目重复两个版本。
403、429、超时或网络错误: 将尝试标记为失败/未知,并保留最后已知良好索引。
页面可能暂时无法访问。在删除之前使用确认窗口或第二个独立检查。当重定向合并两个页面时,故意更新引用和参考。
Step 4: Rechunk and re-embed only the new version 在正常化文本更改或块算法更改时重新分块。在文本更改或嵌入模型更改时重新嵌入。记录 embedding_model、chunker_version 和页面内容哈希与索引生成,以便回滚时能识别哪些记录兼容。
The OpenAI embeddings guide describes the input-to-vector API. 保持一个队列或重试表以应对瞬态嵌入失败,以便一个失败的批次不会导致所有成功处理的 URL 重复。
Step 5: Replace vectors without leaving duplicates
在新 ID 或版本命名空间下写入候选生成。
查询候选记录,确认预期的源和段落是可检索的。
切换应用程序的活动生成或替换清单指针。
在新的生成通过验证后删除旧 ID。
如果您的向量存储无法提供便利的版本切换,请在清单中保留旧 ID,并仅在完整 upsert 成功后替换它们。权衡是短暂的重叠窗口,您可以通过过滤活动版本元数据来处理。
Step 6: Validate freshness with known changes 使用少量您可以安全编辑或变化可预测的页面。记录一个查询,其正确答案依赖于新的措辞。摄取后,验证最新块是否可检索,以及旧块是否不在活动命名空间中。还测试一个不可用页面,以确认管道不会删除其先前良好的记录。
Metric Definition Crawl-to-index delay last_indexed_at - last_successful_crawl_atChange detection rate changed pages / successfully crawled pages Failed-page rate failed page attempts / submitted page attempts Stale chunk rate known old versions still active / sampled changed pages Citation age answer time minus retrieved record’s crawl time
这些是操作指标,而不是答案质量的保证。将它们与标记的检索和引用测试集配对。
Step 7: Monitoring, recovery, and costs 写一个运行记录,包含 run_id、发现的数量、尝试的数量、成功的数量、变化的数量、删除的数量、嵌入令牌、向量写入、失败的 URL 和经过的时间。在日志中删除令牌和任何敏感页面内容。对于瞬态错误,使用带有指数退避的有界重试,对于持久性失败使用死信队列进行审查。添加运行锁,以便两个调度程序不会同时替换同一页面。
对于一个包含 10,000 页的语料库,假设每日变化率为 5%,则在页面级失败和重新发现效应之前,变化集大约为 500 页。估算你实际请求的页面的爬虫成本,然后是变化文本的嵌入成本、向量写入/存储,如果使用了代理流量,以及工作者/调度程序操作。这是一个模型,而不是一个报价。在预算之前,查看最新的 Nstdata 爬虫定价 和你的嵌入/向量提供商的计费文档。
事件驱动与定期更新 当内容发生变化时,CMS、Git 仓库或文档平台可能会发出事件。仅在源系统能够可靠识别页面且事件被授权的情况下,使用该事件将 URL 放入队列。定期的对账作业对于遗漏的事件和删除仍然是有用的。应用程序中的事件触发并不意味着爬虫 API 本身提供 webhook;当前的爬虫文档指示用户查询任务状态。
常见更新失败 最具破坏性的错误是在超时后删除页面、对不稳定的导航进行哈希而不是标准化内容、在每次运行时生成新的 ID、在没有生成新索引的情况下更改嵌入模型,以及忘记在编辑后删除旧块。即使在索引是当前的情况下,缓存的答案也可能看起来陈旧;使检索/应用缓存失效或将索引生成纳入缓存键。
完整的自动更新清单
存储规范 URL 清单和页面到块的清单。
区分成功、失败、重定向和删除状态。
哈希标准化内容,并跳过未更改的嵌入。
保持最后一个已知的良好版本,直到新的向量通过验证。
测试已知的变化、删除、重定向和临时失败。
监控爬虫到索引的延迟、失败率、陈旧版本、引用和成本。
结论 保持 RAG 知识库的最新状态是一个数据生命周期问题。调度程序开始工作,但新鲜度取决于持久身份、仔细的变化检测、安全的向量替换,和与实际问题的验证。将失败视为未知,而不是删除,并记录解释系统在回答时所知道的时间戳。
常见问题 调度 URL 清单作业,爬虫并验证页面,比较标准化内容哈希,重新嵌入已更改的页面,并安全地替换旧的向量记录。
根据每个源的变化率和过时答案的风险设置间隔,然后根据观察到的变化和爬虫到索引的延迟进行调整。
增量索引仅处理新的、已更改的或已删除的源记录,而不是在每次运行时重建整个索引。
保持页面到块 ID 清单,验证替换记录,然后删除旧 ID 或放弃以前的索引生成。
是的,当你的应用程序运行定期或事件触发的摄取作业以检索、验证并索引源变更时。
支持 JavaScript 渲染,成功率达 99.8%
将任意网站转换为 Markdown、HTML、JSON、链接、PDF 等格式,无需管理爬取基础设施。 开始免费爬取 →