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. 保留所有权利。
用新鲜网络数据馈送您的RAG系统(步骤详解)
Ivy Lin Community & Content Lead
用新鲜网络数据来喂养您的RAG系统(一步一步) TL;DR
一个 RAG 摄取管道需要真实来源的网站爬虫、稳定的文档身份和更新路径;仅使用嵌入不够以保持答案的时效性。
使用网站爬虫进行有限的文档发现,然后在清理、分块、嵌入和索引之前验证每个页面。
在每个分块中存储 source_url、crawled_at、content_hash 和一个稳定的页面 ID,以便使更新和引用可管理。
将下面的代码视为一个集成蓝图:API 字段遵循当前的 Nstdata 和库文件,但端到端路径并未使用实时凭证进行测试。
介绍:新鲜的网络数据是一个摄取问题
Nstdata Crawl 是该工作流程中的收集层;其 产品概述 描述了下游数据管道的页面和站点检索。
一个语言模型可以根据其训练数据解释一个 API,但仍然可能给出过时的参数名称。RAG 系统通过在答案时检索文档来缩小这个差距,但检索的时效性仅限于已索引的文档。为了用新鲜的网络数据喂养 RAG 系统,您需要一个从源 URL 到验证记录的可重复路径,并有一种替换或移除旧记录的方法。
本指南为公共文档构建了这一路径:Nstdata Crawl → Markdown 验证 → 识别标题的块 → 嵌入 → Chroma → 检索 。它专注于摄取和时效性,而不是训练模型。Nstdata Crawl 处理页面获取和内容转换;您的应用程序仍然负责数据政策、分块、索引、访问控制和答案评估。当前的 Crawl 指南在其 Crawl 文档 中描述了 Markdown 输出、页面/站点任务、Python SDK、任务状态和大结果引用。
RAG 数据摄取意味着什么
RAG 数据摄取是将源材料转化为检索系统可以搜索的记录的过程。模型训练数据被固化在模型权重中。RAG 索引是一个外部的、可替换的文档和嵌入集合。实时网络数据是您的收集器现在从网站检索到的内容;在您的管道验证并索引之前,这些数据无法到达模型。
如果一个文档页面在 10:00 发生变化,但您的索引每周重建一次,那么在 10:05 进行的查询仍可能检索到上周的说明。答案可能听起来流利,但仍然是过时的。记录 源是在何时收集的 和 哪个内容版本被索引 以使这种延迟显而易见。
一目了然的管道
阶段 输入 → 输出 主要检查 发现 域名、网站地图或 URL 列表 → 允许的 URL URL 是否在范围内并被允许? 爬取 URL → Markdown 和页面元数据 任务是否完成,正文是否包含预期内容? 规范化 抓取的页面 → 规范文档记录 URL、标题、版本和内容哈希是否稳定? 分块 文档 → 可检索的片段 标题、代码和表格是否保持完整? 嵌入和存储 片段 → 向量加元数据 向量维度和记录 ID 是否与索引匹配? 检索和回答 问题 → 证据和引用的答案
先决条件和示例栈 使用 Python 3.10 或更高版本,一个 Nstdata Crawl 令牌,一个嵌入提供者密钥和一个 Chroma 集合。在 staging 运行后安装 SDK 并在项目中锁定解决的版本:
python -m venv .venv
source .venv/bin/activate
pip install nstdata-ai-crawl openai chromadb
export NSTDATA_API_TOKEN = "..."
export OPENAI_API_KEY = "..."
精确的版本应记录在您的锁定文件中,因为 SDK 行为可能会变化。用于准备此草案的环境没有 Crawl 或 OpenAI 凭证,因此下面的服务调用尚未实时执行。
第一步:选择并发现网络来源 先从一个简短的清单开始,而不是爬取整个域。对于文档网站,包含当前的产品和 API 参考页面,然后如果它们不在知识库内,则排除登录、搜索、更新日志档案和无关的营销路径。当您需要将声明的 URL 与可到达的页面进行比较时,请同时使用网站地图和导航链接。网站地图是发现的提示,而不是每个列出页面都是有用或最新的证明。
当已知 URL 是整个输入时,请使用单页面抓取。当您想从起始页面进行有限发现时,请使用全站爬取。当前的 Crawl 请求暴露了 maxDepth、maxPages、includeUrls、excludeUrls、ignoreQuery 和 onlyMainContent;选择保守的边界并在索引之前检查发现的页面列表。如需单独的有关向量数据库方面的查看,请参见 Crawl to Pinecone 。
第二步:将页面爬取为 Markdown 记录的Python SDK公开了submit_scrape_task_sync和get_markdown()。此请求适合已知URL且具有可预测响应时间:
import os
from nstdata_ai_crawl import Format , NstDataClient , ScrapeRequestDto
with NstDataClient ( os . environ [ "NSTDATA_API_TOKEN" ] ) as client :
result = client . submit_scrape_task_sync ( ScrapeRequestDto (
url = "https://docs.example.com/api/authentication" ,
formats = [ Format . MARKDOWN ] ,
timeout = 60_000 ,
onlyMainContent = True ,
) )
markdown = result . data . get_markdown ( )
if not markdown or len ( markdown . strip ( ) ) < 200 :
raise ValueError ( "爬虫返回的内容为空或意外地短" )
成功的HTTP交换并不意味着页面可用。在标记页面为接受之前,检查任务成功、正文长度、预期标题或已知短语以及返回的元数据。对于较慢的页面,请使用异步任务流程并轮询返回的ID;官方指南还记录了页面进度和结果引用。不要假设存在Webhook回调:当前文档表明不支持Webhook。
对于JavaScript渲染的页面,首先检查所需文本是否缺失于正常输出中。仅在页面确实需要时启用浏览器渲染或记录的等待/操作。额外的渲染会增加延迟,并可能使爬取变得更加复杂。
第3步:规范化和保留来源 在分块之前,将获取的结果转变为稳定记录。将源元数据与正文文本分开:
from dataclasses import dataclass
from datetime import datetime , timezone
from hashlib import sha256
@dataclass
class PageRecord :
url : str
title : str
markdown : str
crawled_at : str
content_hash : str
def make_record ( url : str , title : str , markdown : str ) - > PageRecord :
normalized = "\n" . join ( line . rstrip ( ) for line in markdown . splitlines ( ) ) . strip ( )
return PageRecord (
url = url ,
title = title or url ,
markdown = normalized ,
crawled_at = datetime . now ( timezone . utc ) . isoformat ( ) ,
content_hash = sha256 ( normalized . encode ( "utf-8" ) ) . hexdigest ( ) ,
)
内容哈希使得管道可以跳过未更改的页面。仅规范化真正无关的噪音:保留标题、代码围栏、参数表、警告和源链接。删除样板并不意味着可以重写作者的事实。
第4步:围绕文档结构分块 对于技术文档,在应用令牌或字符限制之前按标题拆分。一个块应携带其标题路径,以便检索的段落仍有上下文:
def heading_sections ( markdown : str ) :
current = [ ]
body = [ ]
in_fence = False
for line in markdown . splitlines ( ) :
if line . strip ( ) . startswith ( "```" ) :
in_fence = not in_fence
if line . startswith ( "#" ) and not in_fence and body :
yield " / " . join ( current ) , "\n" . join ( body ) . strip ( )
body = [ ]
if line . startswith ( "#" ) and not in_fence :
level = len ( line ) - len ( line . lstrip ( "#" ) )
current = current [ : level - 1 ] + [ line [ level : ] . strip ( ) ]
body . append ( line )
if body :
yield " / " . join ( current ) , "\n" . join ( body ) . strip ( )
这个小拆分器使得围栏示例保持在一起,但并不强制令牌上限。对较长部分添加一个意识到标记器的第二遍,并将其与您最长的代码示例进行测试。框架用户可以将该基线与当前的LangChain文本拆分器概念 进行比较。避免猜测普遍的块大小:在需要参数详细信息、交叉上下文和代码的问题上进行比较。
第5步:嵌入和存储记录 为每个块创建一个嵌入,并将文本和元数据与之一起写入。Chroma可以保存本地集合;其upsert和query API在Chroma集合指南 中进行记录。如果您传递已计算的向量,则提供者模型和Chroma嵌入维度必须一致。目前的OpenAI嵌入指南 记录了本示例中使用的文本转向量端点。
import chromadb
from openai import OpenAI
client = OpenAI ( )
vector_db = chromadb . PersistentClient ( path = "./chroma-data" )
collection = vector_db . get_or_create_collection ( "public_docs" )
texts = [ section_text ]
embedding = client . embeddings . create (
model = "text-embedding-3-small" ,
input = texts ,
) . data [ 0 ] . embedding
collection . upsert (
ids = [ chunk_id ] ,
embeddings = [ embedding ] ,
documents = texts ,
metadatas = [ {
"source_url" : page . url ,
"title" : page . title ,
"heading_path" : heading_path ,
"crawled_at" : page . crawled_at ,
"content_hash" : page . content_hash ,
} ] ,
)
在生产环境中,将嵌入分批发送,仅重试瞬态提供者错误,并根据提供者限制限制批量大小。使ID具有确定性,例如sha256(canonical_url + heading_path + chunk_text)。当页面发生更改时,在插入其新集合之前删除旧页面的块ID,或使用版本命名空间并在验证后切换。
第6步:检索并提供证据回答 用相同模型嵌入用户的问题,查询集合,并将顶部段落和源URL传递给LLM。要求回答引用提供的URL,并说明所检索的证据何时不足。检索输出是待检查的证据,而不是答案正确的证明。
一个有用的评估集包括直接事实、API参数问题、答案跨越两个部分的问题,以及应返回“未找到”的问题。单独跟踪检索命中率和引用正确性,而不是答案流畅性。
第7步:保持索引新鲜 根据来源波动性和陈旧答案的后果安排重新抓取。存储每个标准URL的最后成功哈希。如果新成功抓取的哈希相同,则跳过重新嵌入。如果不同,则替换旧块。将超时或临时403视为未知 ,而不是源已删除的证明。在删除索引内容之前,通过重复检查或权威网站地图更改确认删除。
Cron作业可以启动Python摄取命令,但作业应写入运行记录:运行ID、开始/结束时间、发现的URL、接受的页面、已更改的哈希、已删除的页面、失败的URL和嵌入计数。有关Crawl处理的内容与应用程序拥有的工作的概述,请参阅Nstdata的网络数据堆栈指南 。
成本、扩展和常见故障模式 页面计数并不是完整的成本估算。包含Crawl请求、在使用时单独计费的代理流量、已更改内容的嵌入令牌、向量写入/存储和答题模型的使用。您自己的公式应为:
每月摄取成本 = 成功抓取单位 + 代理流量 + 更改文本的嵌入令牌 + 向量存储 + 调度程序/操作
衡量接受的页面而不是提交的URL。常见故障包括索引空页面、嵌入维度不匹配、在更新后留下陈旧的向量、在分块期间丢失源URL,以及仅衡量答案质量而忽略检索未命中。在索引之前添加验证门,并在使爬取结果可用于模型之前进行对抗性源测试。
完整的摄取检查清单
保持允许列表和具有规范URL的URL清单。
每次抓取后验证状态、主体完整性、标题和源元数据。
通过归一化保留标题、代码、表格和内容哈希。
使用确定性的块ID,并保留页面到块的映射。
仅重新嵌入更改的内容;将已删除页面与失败的请求区分开。
在固定问题集上评估检索、引用、陈旧答案行为和成本。
结论 新鲜的网络数据仅在您的管道发现、检索、验证、归一化、分块、嵌入和索引后,才能达到RAG答案。Nstdata Crawl可以提供页面检索和Markdown转换层;应用程序仍然必须拥有来源、更新策略、向量生命周期和答案检查。从一小组代表性URL开始,证明覆盖和删除行为,然后扩大调度。
常见问题 RAG数据摄取将源文档转换为经过验证的、分块的、嵌入的记录,供检索系统搜索。
跟踪规范URL和内容哈希,按照源波动性的匹配计划重新抓取,并在验证新源状态后只替换或删除旧块。
RAG索引不会自动从实时网站刷新;收集器和摄取作业必须在检索之前获取并索引新内容。
根据源变化的频率和陈旧答案的影响选择刷新间隔,然后测量实际变化率和更新延迟。
问:Crawl是否替代分块和嵌入?
没有。爬虫检索并转换页面;您的应用程序仍然选择数据块、嵌入模型、向量存储、更新规则和评估。
支持 JavaScript 渲染,成功率达 99.8%
将任意网站转换为 Markdown、HTML、JSON、链接、PDF 等格式,无需管理爬取基础设施。 开始免费爬取 →