【60.Python+AI】LlamaIndex高级检索:从基础向量搜索到知识图谱增强

📖 文章简介: 本文深入LlamaIndex的高级检索策略,在基础向量搜索之上,系统讲解四种进阶索引技术:递归检索(Recursive Retrieval)在文档层级之间逐层缩小范围、句子窗口检索(Sentence Window Retrieval)利用上下文窗口还原语义完整性、自动合并检索(Auto-Merging Retrieval)解决分块过细导致的碎片化问题,以及知识图谱+向量双索引融合带来的多跳推理能力。每种策略均配有Mermaid检索流程图、配置代码和适用场景,适合已入门LlamaIndex、想让RAG召回率再上一个台阶的开发者。


在这里插入图片描述

🎬 个人主页: 源码骑士

专栏传送门: 《Android开发基础》《python基础课程》

⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂


🎬 源码骑士的简介:
5年Android Framework系统开发经验,曾主导多项系统级性能优化专项
技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)
累计产出原创技术文章100+篇,文章以流程图为特色,被读者评价为"看一篇胜过啃一周源码"


导入语

你搭好了一个基础的RAG系统——文档分块、embedding、向量检索、大模型生成,跑通了。但用户开始抱怨:“明明答案就在文档里,为什么搜不到?”

问题不在大模型,在检索。基础向量搜索在面对复杂文档时就像一个只会查字典的人——他只能找到包含关键字的页面,但做不了"上下文推理"和"跨段落关联"。

这篇文章的目标很明确:在基础向量搜索之上,一层一层往上叠加LlamaIndex的高级检索策略。 看完之后你会知道,面对层次化文档用递归检索、面对碎片化问答用句子窗口、面对跨实体推理用知识图谱——每种问题都有对应的检索武器。


1 ~> 基础向量搜索的局限性

1.1 基础RAG的检索流程

用户提问

Embedding向量化

向量相似度搜索

返回Top-K文档块

拼接后交给LLM生成答案

这个流程的问题在于:你的文档已经被切成了小块,每个块都丢失了上下文信息。

1.2 三个典型翻车场景

场景 基础向量搜索的表现
一个定义分散在三个相邻段落 只检索到其中一个段落,LLM拿到不完整信息
用户问"第三章讲了什么" 第三章被切成40个小块,没有一个能概括全貌
需要跨实体推理 A提到B、B提到C、问A和C的关系——向量检索完全做不到

2 ~> 句子窗口检索:还原文块上下文

2.1 核心思路

基础检索只返回匹配的那一小块。句子窗口检索在返回结果时,把匹配块的前后各扩展N个句子一起返回。

2.2 检索流程

用户提问

Embedding检索

匹配到第5块文档

句子窗口扩展

窗口大小=3

返回块 4,5,6

交给LLM生成

2.3 LlamaIndex 配置代码

from llama_index.core.node_parser import SentenceWindowNodeParser
from llama_index.core.indices.postprocessor import MetadataReplacementPostProcessor

# 创建句子窗口解析器
node_parser = SentenceWindowNodeParser.from_defaults(
    window_size=3,                    # 前后各扩展3个句子
    window_metadata_key="window",     # 元数据key
    original_text_metadata_key="original_text"
)

nodes = node_parser.get_nodes_from_documents(documents)

# 检索后处理器:用小块的embedding去搜索,但返回窗口上下文
postprocessor = MetadataReplacementPostProcessor(
    target_metadata_key="window"
)

2.4 适用场景

场景 是否推荐 原因
定义类文档(术语分散在多行) ✅ 强烈推荐 补足上下文避免断章取义
结构化问答(FAQ) ❌ 不需要 每条FAQ本身就是独立完整单元
长报告、论文 ✅ 推荐 概念经常跨段分布

3 ~> 自动合并检索:解决碎片化问题

3.1 问题根源

如果你的文档切得太细(比如每256 token一块),一个完整的论述可能被切成十几块。向量搜索只能返回其中一部分,LLM看到的是"碎片化"的信息。

3.2 核心思路

自动合并检索做了两件事:

  1. 建索引时:构建层级结构——大块(父节点)包含多个小块(子节点)
  2. 检索时:从最底层的小块开始搜,如果某个父节点下的子节点被命中了足够多,就把整个父节点替换回来

3.3 检索流程

用户提问

向量搜索

返回Top-K小块

检查命中分布

某个父节点下
命中>=阈值?

用父节点替换
所有命中的子节点

保持小块返回

交给LLM

3.4 LlamaIndex 配置代码

from llama_index.core.node_parser import HierarchicalNodeParser
from llama_index.core.retrievers import AutoMergingRetriever

# 层级分块:小块512,大块2048
node_parser = HierarchicalNodeParser.from_defaults(
    chunk_sizes=[2048, 512],   # 父节点大小, 子节点大小
    chunk_overlap=50
)

nodes = node_parser.get_nodes_from_documents(documents)

# 自动合并检索器
retriever = AutoMergingRetriever(
    vector_retriever,
    storage_context,
    verbose=True
)

3.5 什么时候用

你的文档切得越细(为了更精准的向量匹配),就越需要用自动合并来保证LLM收到的不是一堆碎片。


4 ~> 递归检索:层级文档的对策

4.1 问题场景

你有一本300页的技术手册,用户问"第三章的整体框架是什么?"

基础向量检索在这个问题上完全失败——因为第三章的框架不存在于任何一个段落里,它是跨50个段落的宏观概念。

4.2 核心思路

递归检索相当于"先查目录,再看章节,最后读段落"的人类阅读方式:

  1. 第一层:在摘要/章节标题级别检索,确定"这个话题在第三章"
  2. 第二层:深入到第三章的内容节点中检索相关内容
  3. 把两层的检索结果合并后交给LLM

4.3 检索流程

用户提问

第一层检索:
在摘要/章节级搜索

定位到相关章节

第二层检索:
在该章节内做向量搜索

返回章节内相关块

合并两层结果交给LLM

4.4 实现示例

from llama_index.core.schema import IndexNode
from llama_index.core import SummaryIndex, VectorStoreIndex

# 第一层:为每个章节建摘要索引
chapter_summaries = IndexNode(
    index_id="chapter_3",
    text="第三章主要讲解异步编程与协程...",
)

summary_index = VectorStoreIndex(chapter_summaries)

# 第二层:每个章节有自己的向量索引
chapter_3_index = VectorStoreIndex(chapter_3_nodes)

# 递归检索器
from llama_index.core.retrievers import RecursiveRetriever

retriever = RecursiveRetriever(
    "vector",  # 第一层用向量检索定位章节
    retriever_dict={
        "chapter_3": chapter_3_index.as_retriever(),
    },
    verbose=True
)

5 ~> 知识图谱+向量双索引融合

5.1 向量检索做不到的事

向量检索本质上是语义相似度匹配——找到和问题最相似的段落。但有些问题需要的不是相似度,而是推理

  • “A公司和B公司有什么关系?”
  • “这个技术方案依赖哪些前置条件?”
  • “这本书里前后矛盾的地方在哪?”

5.2 知识图谱能做什么

知识图谱抽取出实体关系,构建成一张图:

知识图谱示例
[Python] --被用于--> [后端开发]
[Python] --被用于--> [数据分析]
[后端开发] --需要--> [Django框架]
[数据分析] --需要--> [Pandas库]

当你问"做后端开发需要学什么"时,知识图谱可以沿着"后端开发→Django框架"这条关系链推理,而不是靠简单的语义匹配。

5.3 双索引融合流程

用户提问

向量检索

知识图谱检索

语义相关的Top-K块

沿关系链推理出的相关实体

合并与去重

融合后的上下文
既有语义又有推理

LLM生成答案

5.4 LlamaIndex 中的知识图谱索引

from llama_index.core import KnowledgeGraphIndex
from llama_index.core import StorageContext

# 从文档中构建知识图谱
kg_index = KnowledgeGraphIndex.from_documents(
    documents,
    storage_context=storage_context,
    max_triplets_per_chunk=10,          # 每块最多抽取10个三元组
    include_embeddings=True              # 同时保留向量索引
)

# 查询时可以指定使用KG
query_engine = kg_index.as_query_engine(
    include_text=True,                   # 包含原文
    response_mode="tree_summarize",
    retriever_mode="hybrid"              # 混合模式:KG+向量
)

5.5 适用场景总结

检索策略 适合的文档类型 解决的核心问题
基础向量搜索 独立、短小的文档
句子窗口检索 知识点分散的教程 上下文缺失
自动合并检索 细粒度分块的文档 信息碎片化
递归检索 层级化的书籍/手册 宏观概念搜索
KG+向量融合 实体关系密集的文档 跨实体推理

思考 && 总结

LlamaIndex 真正拉开与普通RAG差距的地方就在于这些高级检索策略:

  1. 句子窗口检索是最容易上手也最立竿见影的优化: 用小块embedding保证匹配精度,用窗口扩展保证上下文完整。一个参数就能显著改善答案质量。
  2. 自动合并检索对付的是"分块强迫症": 为了高召回率把文档切得很细,但LLM又需要完整的上下文,自动合并正好解决了这个矛盾——搜的时候用小块,返回的时候合并成大块。
  3. 递归检索是处理书籍和手册级长篇文档的唯一选择: 先用摘要/标题层定位到章节,再在章节内做细粒度检索,这完全模拟了人类的阅读方式。
  4. 知识图谱补上了向量检索最大的短板——推理能力: 语义相似度≠逻辑关系。当你的文档里实体关系密集(企业关系、技术依赖、因果链条),KG+向量的双索引融合是不二之选。
  5. 四种策略可以组合使用: 句子窗口+自动合并、递归+KG,它们不是互斥的。实际的RAG系统往往是多策略的组合拳。

基础RAG做到60分很容易,但从60分到90分,靠的就是这些高级检索策略。下一节我们对比LangChain和LlamaIndex在这方面的差异。


结尾

各位小伙伴,本文的内容到这里就全部结束了,源码骑士在这里再次感谢您的阅读!

源码骑士 — Android Framework & 全栈开发

👀 关注:跟博主一起从源码视角深耕底层原理,见证每一次成长

❤️ 点赞:让优质内容被更多人看见,让知识传递更有力量

收藏:把核心知识点存好,在需要时随时查、随时用

💬 评论:分享你的经验或疑问,评论区一起交流避坑

🔄 一键四连:不要忘记给博主"一键四连"哦!

🗡️ 寄语:技术之路难免有困惑,但同行的人会让前进更有方向

结语:检索是RAG的"嗓子眼"——向量搜索再准、分块策略再好,如果检索策略用错了,整个系统的答案质量就卡在这里。把本文的四种高级检索策略记牢,下次用户反馈"搜不到"时,你就知道该换哪把武器了。不要忘记给博主"一键四连"哦!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐