父子片段检索与向量数据库


在随着大语言模型(LLM)的爆发,检索增强生成(RAG, Retrieval-Augmented Generation)技术成为了解决模型幻觉、引入私有领域知识的主流方案。而在 RAG 系统中,向量数据库和文档的切分(Chunking)策略起着至关重要的作用。

本文将通俗易懂地介绍向量数据库的基础概念,并深入探讨一种高级的文档检索策略——父子片段检索(Parent-Child Chunking / Small-to-Big Retrieval)

1. 什么是向量数据库?

在传统的数据库(如 MySQL, Elasticsearch)中,我们通常使用关键词匹配进行搜索(比如搜索“苹果”,只能查到包含“苹果”两个字的记录)。

但在 AI 时代,我们需要的是语义搜索。比如搜索“手机”,系统应该能返回“iPhone”或“华为”相关的结果,因为它们在语义上是高度相关的。

向量数据库(Vector Database)就是为了解决这个问题而诞生的:

  1. 向量化(Embedding):利用模型将文本、图像、音频等数据转化为一串多维数组(即“向量”)。在多维空间中,语义相近的内容,它们对应的向量距离也越近。
  2. 存储与索引:向量数据库专门针对这种高维向量数据进行了存储优化,并提供高效的近似最近邻(ANN)搜索算法(如 HNSW)。
  3. 检索:当用户提问时,将问题也转化为向量,然后在数据库中计算距离,找出最相似的几个片段。

主流的向量数据库包括 Milvus, Qdrant, Chroma, Pinecone,以及支持向量扩展的传统数据库(如 pgvector, Redis)。

2. RAG 系统中“切块”的痛点

在构建 RAG 系统时,我们不能把一整本书直接扔给大模型,因为大模型有上下文窗口限制,而且输入的内容越多,模型处理的成本就越高、注意力也越容易分散。

因此,我们需要将长文档进行切块(Chunking)。但是在切块粒度上,存在一个两难的困境:

  • 切得太大(比如 1000 字/块):包含的上下文很丰富,但里面杂糅了很多不同的主题,导致其向量表达“模糊”,在向量检索时精度很低(容易找不到或者找到不相关的)。
  • 切得太小(比如 100 字/块):内容非常聚焦,向量检索的精度很高。但把这 100 个字丢给大模型去生成回答时,由于缺乏前因后果(上下文丢失),大模型可能无法理解这段话到底在说什么。

如何才能兼顾“检索时的高精度”“生成时的丰富上下文”?这就引出了“父子片段检索”。

3. 破局之道:父子片段检索(Parent-Child Retrieval)

父子片段检索(又称“从小到大检索”,Small-to-Big Retrieval)是一种优雅解决上述痛点的高级检索策略。

它的核心思想是:用小块(子片段)来做精准搜索,用大块(父片段)来提供上下文。

具体原理

  1. 构建父片段(Parent Chunk)
    先将文档按照较大的粒度进行切块,比如按“段落”或每块 1000 字进行切分。这些大块构成了大模型的上下文素材库,通常存储在传统的文档数据库中。
  2. 构建子片段(Child Chunk)
    将上述每一个“父片段”进一步细分,切成更小的“子片段”,比如每块 100-200 字,或者直接按“句子”切分。
  3. 建立关联与向量化
    • 将所有“子片段”通过 Embedding 模型转化为向量,并存入向量数据库。
    • 在子片段的元数据(Metadata)中,记录它所属的“父片段 ID”。
  4. 检索与还原
    • 当用户提问时,在向量数据库中检索最相似的子片段(因为子片段内容单一,检索精度极高)。
    • 找到目标子片段后,不直接把它给大模型,而是通过“父片段 ID”把对应的整个父片段提取出来,丢给大模型作为上下文。

为什么这样做更好?

  • 检索更准:子片段很短,主题专一。比如其中一句子片段是“向量数据库使用HNSW算法”,如果用户提问“HNSW是什么”,这个子片段能被极其精准地命中。
  • 回答更好:当子片段被命中后,系统返回给大模型的是它所在的整个段落(父片段),大模型能够结合前后的解释、举例,给出更加全面、准确的回答。

4. 落地实现思路(以 LangChain/LlamaIndex 为例)

在目前主流的 LLM 开发框架中,这种策略已经有了成熟的封装。

  • LangChain 中,可以使用 ParentDocumentRetriever 来实现。它在底层维护了一个向量数据库(存子块向量)和一个文档存储(如 InMemoryStore 或 Redis,存父块原文)。
  • LlamaIndex 中,这种模式可以通过 AutoMergingRetriever 或节点间的父子关联(Node Relationships)机制来实现。

简单的工作流示意

  1. Raw Document -> Split into Parent Chunks (存入 DocStore)
  2. Parent Chunks -> Split into Child Chunks -> Embed (存入 Vector DB,带上 parent_id)
  3. User Query -> Embed -> Search in Vector DB -> Match Child Chunks
  4. Child Chunks -> Read parent_id -> Fetch Parent Chunks from DocStore
  5. Parent Chunks + User Query -> LLM -> Final Answer

5. 总结

在深入应用大模型和构建生产级 RAG 系统的过程中,我们不仅需要了解如何使用向量数据库来做基础的语义检索,更需要掌握如何通过数据结构的巧妙设计来提升检索的效果。

父子片段检索完美地解决了切块大小带来的两难问题,是目前 RAG 优化(Advanced RAG)中性价比极高、必不可少的一项实战技巧。无论是知识库问答、智能客服还是企业级文档搜索,这项技术都能显著提升系统的智能程度和回答准确率。