RAG 数据摄取与索引流水线:别让脏数据进入向量库
设计生产级 RAG 的数据摄取、解析、清洗、增量索引、权限元数据、Embedding 缓存和索引发布流程。
RAG 的线上质量,很多时候在用户提问前就已经决定了。文档有没有解析对,表格有没有丢列,旧版本有没有清掉,权限有没有带进索引,Embedding 是否复用缓存,都会直接影响后面的召回和生成。
数据摄取流水线的目标不是“把文档塞进向量库”,而是把原始内容变成可检索、可引用、可授权、可回滚、可评测的知识单元。
核心判断
如果索引里没有 document_id、chunk_id、source、updated_at、acl、pipeline_version,就很难做生产级 RAG。你能回答问题,但很难解释、修复和回滚问题。
调研摘要
主流 RAG 工程方案在数据摄取上有几个共同点:
- LlamaIndex 的 ingestion pipeline 把加载、切分、元数据抽取、Embedding 等步骤看作 transformations,并通过缓存避免重复处理相同节点。
- LangChain 的 indexing 思路强调记录源文档和派生文档的关系,避免重复写入和无效重建。
- Azure AI Search 的 RAG 文档强调多源数据接入、增量索引、chunking、vectorization、hybrid search、semantic ranking 和查询时权限裁剪。
- Elastic 的 RAG 资料强调外部知识更新、引用可验证、document-level access control,以及文本、向量、混合和语义检索组合。
落到工程实践里,可以把摄取流水线拆成八个阶段。
总体流水线
这条链路最好是可重放的。任意一个版本的索引都应该能回答:它来自哪些数据源、用什么解析器、什么分块策略、什么 embedding 模型、什么权限快照生成。
1. 数据源接入
生产 RAG 往往不是单一文档目录,而是 Wiki、PDF、网页、对象存储、数据库、客服工单、代码仓库和内部系统的混合体。
| 数据源 | 接入重点 | 常见风险 |
|---|---|---|
| Wiki / Markdown | 标题层级、页面路径、更新时间、作者。 | 链接失效、重复页面、草稿页混入。 |
| PDF / Office | OCR、页码、表格、图片说明、版面顺序。 | 断行、表格错列、页眉页脚重复。 |
| Web 页面 | 正文抽取、导航去噪、canonical URL。 | 菜单、脚注、广告进入索引。 |
| 数据库 | 字段解释、主键、更新时间、权限映射。 | 结构化字段直接拼文本导致语义丢失。 |
| 代码仓库 | 文件路径、函数/类边界、版本分支。 | 按长度切断函数或配置块。 |
接入层不要急着生成 embedding。先把 source manifest 建好,记录每个源的同步范围、频率、owner 和权限策略。
2. 变更检测
没有增量机制的 RAG 索引,很快会遇到两个问题:全量重建太慢,旧内容无法清理。
建议为每份文档计算稳定指纹:
{
"source_id": "wiki:rag-playbook",
"source_url": "https://example.com/wiki/rag-playbook",
"content_hash": "sha256:...",
"metadata_hash": "sha256:...",
"updated_at": "2026-07-07T10:00:00Z",
"deleted": false
}增量索引至少要识别四种事件:新增、内容更新、元数据更新、删除。元数据更新也很重要,因为 ACL、owner、业务标签变化可能不改变正文,但会改变检索边界。
3. 解析与抽取
解析阶段的产物不应该只是一段纯文本。生产系统更需要结构化中间表示。
推荐中间结构包含:
| 字段 | 用途 |
|---|---|
| block_id | 后续 chunk 和引用映射的基础。 |
| block_type | paragraph、heading、table、image、code。 |
| text | 规范化后的文本。 |
| page / position | PDF、PPT、扫描件定位。 |
| heading_path | 保留文档层级。 |
| source_span | 回溯到原文位置。 |
不要过早丢掉页码、标题路径和表格结构。后面做 citation、bad case 复现和人工审核时,这些字段很关键。
4. 清洗与规范化
清洗不是把文本“变干净”这么简单,而是减少会污染检索的噪声。
| 清洗项 | 处理方式 |
|---|---|
| 页眉页脚 | 统计重复文本,按页删除。 |
| 导航菜单 | 对网页抽取正文区域,过滤导航和版权信息。 |
| 断行 | 合并 OCR 或 PDF 抽取造成的异常换行。 |
| 重复版本 | 通过 canonical URL、文档 ID、版本号去重。 |
| 过期内容 | 保留状态字段,不一定物理删除,但默认不召回。 |
| 空内容 | 图片、扫描件、空表格需要补 OCR 或标记不可用。 |
清洗规则要版本化。否则一次规则调整导致召回变化时,很难判断是数据变了还是 pipeline 变了。
5. 元数据和权限
元数据不是附加字段,而是 RAG 的控制面。没有元数据,就做不了权限过滤、时间过滤、业务路由、引用和回滚。
{
"document_id": "doc_rag_playbook",
"chunk_id": "doc_rag_playbook_0042",
"source": "wiki",
"source_url": "https://example.com/wiki/rag-playbook#release-gate",
"title_path": ["RAG Playbook", "Release Gate"],
"owner": "ai-platform",
"updated_at": "2026-07-07",
"doc_status": "active",
"acl_groups": ["team:ai-platform"],
"pipeline_version": "ingest_2026_07_07",
"embedding_model": "text-embedding-v3"
}权限建议在检索前就裁剪,而不是把无权内容放进 prompt 再要求模型不要泄露。缓存 key 也要包含用户权限上下文,避免跨租户或跨团队污染。
6. 分块与父子关系
分块策略在 Chunking 工程指南 里已经展开。摄取流水线里需要额外关注的是:分块结果要能增量更新和回溯。
一个常见错误是:文档某一段更新后,整篇文档所有 chunk_id 都变化。这会破坏引用、评测样本和 bad case trace。chunk_id 应尽量稳定。
7. Embedding 与索引写入
Embedding 是昂贵步骤,也会成为质量漂移来源。生产系统需要把 embedding 模型、维度、归一化方式和生成时间写进 manifest。
索引写入通常至少有两类目标:
| 索引 | 内容 |
|---|---|
| 全文索引 | text、title、heading、keywords、metadata,用于 BM25 / keyword search。 |
| 向量索引 | embedding、chunk_id、metadata,用于 semantic / vector search。 |
如果使用 hybrid retrieval,两个索引的 chunk_id 和过滤字段必须一致。否则线上 trace 很难解释“为什么 BM25 找到了而 vector 没有”,也很难合并排序结果。
8. 索引发布
不要直接把新索引写到线上 collection。更稳的方式是构建新版本索引,评测通过后切 alias。
每个索引版本都应该有 manifest:
| 字段 | 说明 |
|---|---|
| index_version | 索引版本。 |
| source_snapshot | 数据源快照或同步时间。 |
| parser_version | 解析器版本。 |
| chunker_version | 分块策略版本。 |
| embedding_model | Embedding 模型和维度。 |
| doc_count / chunk_count | 文档数和 chunk 数。 |
| eval_report | 发布前评测报告链接。 |
上线后如果出现集中 bad case,先看 manifest,而不是直接猜 prompt 有问题。
质量门禁
摄取流水线完成后,至少跑一组数据质量和检索质量检查。
| 检查 | 失败信号 |
|---|---|
| 文档数量 | 文档数突然大幅变化。 |
| Chunk 数量 | 平均 chunk 数异常,说明解析或切分可能出问题。 |
| 空文本比例 | OCR、正文抽取或过滤规则异常。 |
| 重复率 | 重复页面、历史版本或导航噪声进入索引。 |
| 权限覆盖 | chunk 缺少 ACL 或 ACL 分布异常。 |
| Recall@K | Golden Set 正确证据召回下降。 |
| Citation Sample | 抽样引用无法回到原文位置。 |
这些检查应该在索引发布前执行,而不是等用户线上报错。
常见反模式
最小实现清单
如果从零开始,先做到这些:
- 为每个数据源建立 source manifest。
- 为每份文档计算 content_hash 和 metadata_hash。
- 解析阶段保留 block、page、heading_path、source_span。
- Chunk schema 包含 document_id、chunk_id、parent_id、source_url、updated_at、acl。
- Embedding 结果按 chunk hash 缓存。
- 全文索引和向量索引共享 chunk_id 和过滤字段。
- 新索引先评测,再通过 alias 发布。
- 旧索引保留至少一个回滚窗口。
- 每次发布生成 index manifest 和 eval report。
相关阅读
- RAG 的真实架构:从文档摄取到可引用答案
- Chunking 工程指南:文档怎么切,RAG 上限就在哪
- 混合检索:BM25、向量召回与 RRF
- RAG 发布门禁:让每次改动都可比较、可回滚
- RAG 上线检查清单:从 Demo 到 Production
参考资料
- LlamaIndex Ingestion Pipeline
- LangChain Indexing
- Azure AI Search RAG Overview
- Elastic: What is Retrieval Augmented Generation
结论
RAG 数据摄取不是离线杂活,而是生产质量的第一道门禁。把解析、清洗、元数据、权限、分块、Embedding、索引发布和回滚做成可观测流水线,后面的检索、生成和评测才有稳定基础。
讨论
继续讨论这篇笔记
有问题、补充案例或不同观点,可以通过 GitHub Discussions 继续交流。