60-LlamaIndex高级检索-递归检索-句子窗口-知识图谱增强

文章目录

  • 【60.Python+AI】LlamaIndex高级检索:从基础向量搜索到知识图谱增强
    • 导入语
    • [1 ~> 基础向量搜索的局限性](#1 ~> 基础向量搜索的局限性)
      • [1.1 基础RAG的检索流程](#1.1 基础RAG的检索流程)
      • [1.2 三个典型翻车场景](#1.2 三个典型翻车场景)
    • [2 ~> 句子窗口检索:还原文块上下文](#2 ~> 句子窗口检索:还原文块上下文)
      • [2.1 核心思路](#2.1 核心思路)
      • [2.2 检索流程](#2.2 检索流程)
      • [2.3 LlamaIndex 配置代码](#2.3 LlamaIndex 配置代码)
      • [2.4 适用场景](#2.4 适用场景)
    • [3 ~> 自动合并检索:解决碎片化问题](#3 ~> 自动合并检索:解决碎片化问题)
      • [3.1 问题根源](#3.1 问题根源)
      • [3.2 核心思路](#3.2 核心思路)
      • [3.3 检索流程](#3.3 检索流程)
      • [3.4 LlamaIndex 配置代码](#3.4 LlamaIndex 配置代码)
      • [3.5 什么时候用](#3.5 什么时候用)
    • [4 ~> 递归检索:层级文档的对策](#4 ~> 递归检索:层级文档的对策)
      • [4.1 问题场景](#4.1 问题场景)
      • [4.2 核心思路](#4.2 核心思路)
      • [4.3 检索流程](#4.3 检索流程)
      • [4.4 实现示例](#4.4 实现示例)
    • [5 ~> 知识图谱+向量双索引融合](#5 ~> 知识图谱+向量双索引融合)
      • [5.1 向量检索做不到的事](#5.1 向量检索做不到的事)
      • [5.2 知识图谱能做什么](#5.2 知识图谱能做什么)
      • [5.3 双索引融合流程](#5.3 双索引融合流程)
      • [5.4 LlamaIndex 中的知识图谱索引](#5.4 LlamaIndex 中的知识图谱索引)
      • [5.5 适用场景总结](#5.5 适用场景总结)
    • [思考 && 总结](#思考 && 总结)
    • 结尾

【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的检索流程

#mermaid-svg-McS4On1BBW7eUHPp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-McS4On1BBW7eUHPp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-McS4On1BBW7eUHPp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-McS4On1BBW7eUHPp .error-icon{fill:#552222;}#mermaid-svg-McS4On1BBW7eUHPp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-McS4On1BBW7eUHPp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-McS4On1BBW7eUHPp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-McS4On1BBW7eUHPp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-McS4On1BBW7eUHPp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-McS4On1BBW7eUHPp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-McS4On1BBW7eUHPp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-McS4On1BBW7eUHPp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-McS4On1BBW7eUHPp .marker.cross{stroke:#333333;}#mermaid-svg-McS4On1BBW7eUHPp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-McS4On1BBW7eUHPp p{margin:0;}#mermaid-svg-McS4On1BBW7eUHPp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-McS4On1BBW7eUHPp .cluster-label text{fill:#333;}#mermaid-svg-McS4On1BBW7eUHPp .cluster-label span{color:#333;}#mermaid-svg-McS4On1BBW7eUHPp .cluster-label span p{background-color:transparent;}#mermaid-svg-McS4On1BBW7eUHPp .label text,#mermaid-svg-McS4On1BBW7eUHPp span{fill:#333;color:#333;}#mermaid-svg-McS4On1BBW7eUHPp .node rect,#mermaid-svg-McS4On1BBW7eUHPp .node circle,#mermaid-svg-McS4On1BBW7eUHPp .node ellipse,#mermaid-svg-McS4On1BBW7eUHPp .node polygon,#mermaid-svg-McS4On1BBW7eUHPp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-McS4On1BBW7eUHPp .rough-node .label text,#mermaid-svg-McS4On1BBW7eUHPp .node .label text,#mermaid-svg-McS4On1BBW7eUHPp .image-shape .label,#mermaid-svg-McS4On1BBW7eUHPp .icon-shape .label{text-anchor:middle;}#mermaid-svg-McS4On1BBW7eUHPp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-McS4On1BBW7eUHPp .rough-node .label,#mermaid-svg-McS4On1BBW7eUHPp .node .label,#mermaid-svg-McS4On1BBW7eUHPp .image-shape .label,#mermaid-svg-McS4On1BBW7eUHPp .icon-shape .label{text-align:center;}#mermaid-svg-McS4On1BBW7eUHPp .node.clickable{cursor:pointer;}#mermaid-svg-McS4On1BBW7eUHPp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-McS4On1BBW7eUHPp .arrowheadPath{fill:#333333;}#mermaid-svg-McS4On1BBW7eUHPp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-McS4On1BBW7eUHPp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-McS4On1BBW7eUHPp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-McS4On1BBW7eUHPp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-McS4On1BBW7eUHPp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-McS4On1BBW7eUHPp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-McS4On1BBW7eUHPp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-McS4On1BBW7eUHPp .cluster text{fill:#333;}#mermaid-svg-McS4On1BBW7eUHPp .cluster span{color:#333;}#mermaid-svg-McS4On1BBW7eUHPp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-McS4On1BBW7eUHPp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-McS4On1BBW7eUHPp rect.text{fill:none;stroke-width:0;}#mermaid-svg-McS4On1BBW7eUHPp .icon-shape,#mermaid-svg-McS4On1BBW7eUHPp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-McS4On1BBW7eUHPp .icon-shape p,#mermaid-svg-McS4On1BBW7eUHPp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-McS4On1BBW7eUHPp .icon-shape .label rect,#mermaid-svg-McS4On1BBW7eUHPp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-McS4On1BBW7eUHPp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-McS4On1BBW7eUHPp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-McS4On1BBW7eUHPp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户提问
Embedding向量化
向量相似度搜索
返回Top-K文档块
拼接后交给LLM生成答案

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

1.2 三个典型翻车场景

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

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

2.1 核心思路

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

2.2 检索流程

#mermaid-svg-n40TXSh9ebv3Ccqo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-n40TXSh9ebv3Ccqo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-n40TXSh9ebv3Ccqo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-n40TXSh9ebv3Ccqo .error-icon{fill:#552222;}#mermaid-svg-n40TXSh9ebv3Ccqo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-n40TXSh9ebv3Ccqo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-n40TXSh9ebv3Ccqo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-n40TXSh9ebv3Ccqo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-n40TXSh9ebv3Ccqo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-n40TXSh9ebv3Ccqo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-n40TXSh9ebv3Ccqo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-n40TXSh9ebv3Ccqo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-n40TXSh9ebv3Ccqo .marker.cross{stroke:#333333;}#mermaid-svg-n40TXSh9ebv3Ccqo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-n40TXSh9ebv3Ccqo p{margin:0;}#mermaid-svg-n40TXSh9ebv3Ccqo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-n40TXSh9ebv3Ccqo .cluster-label text{fill:#333;}#mermaid-svg-n40TXSh9ebv3Ccqo .cluster-label span{color:#333;}#mermaid-svg-n40TXSh9ebv3Ccqo .cluster-label span p{background-color:transparent;}#mermaid-svg-n40TXSh9ebv3Ccqo .label text,#mermaid-svg-n40TXSh9ebv3Ccqo span{fill:#333;color:#333;}#mermaid-svg-n40TXSh9ebv3Ccqo .node rect,#mermaid-svg-n40TXSh9ebv3Ccqo .node circle,#mermaid-svg-n40TXSh9ebv3Ccqo .node ellipse,#mermaid-svg-n40TXSh9ebv3Ccqo .node polygon,#mermaid-svg-n40TXSh9ebv3Ccqo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-n40TXSh9ebv3Ccqo .rough-node .label text,#mermaid-svg-n40TXSh9ebv3Ccqo .node .label text,#mermaid-svg-n40TXSh9ebv3Ccqo .image-shape .label,#mermaid-svg-n40TXSh9ebv3Ccqo .icon-shape .label{text-anchor:middle;}#mermaid-svg-n40TXSh9ebv3Ccqo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-n40TXSh9ebv3Ccqo .rough-node .label,#mermaid-svg-n40TXSh9ebv3Ccqo .node .label,#mermaid-svg-n40TXSh9ebv3Ccqo .image-shape .label,#mermaid-svg-n40TXSh9ebv3Ccqo .icon-shape .label{text-align:center;}#mermaid-svg-n40TXSh9ebv3Ccqo .node.clickable{cursor:pointer;}#mermaid-svg-n40TXSh9ebv3Ccqo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-n40TXSh9ebv3Ccqo .arrowheadPath{fill:#333333;}#mermaid-svg-n40TXSh9ebv3Ccqo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-n40TXSh9ebv3Ccqo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-n40TXSh9ebv3Ccqo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-n40TXSh9ebv3Ccqo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-n40TXSh9ebv3Ccqo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-n40TXSh9ebv3Ccqo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-n40TXSh9ebv3Ccqo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-n40TXSh9ebv3Ccqo .cluster text{fill:#333;}#mermaid-svg-n40TXSh9ebv3Ccqo .cluster span{color:#333;}#mermaid-svg-n40TXSh9ebv3Ccqo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-n40TXSh9ebv3Ccqo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-n40TXSh9ebv3Ccqo rect.text{fill:none;stroke-width:0;}#mermaid-svg-n40TXSh9ebv3Ccqo .icon-shape,#mermaid-svg-n40TXSh9ebv3Ccqo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-n40TXSh9ebv3Ccqo .icon-shape p,#mermaid-svg-n40TXSh9ebv3Ccqo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-n40TXSh9ebv3Ccqo .icon-shape .label rect,#mermaid-svg-n40TXSh9ebv3Ccqo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-n40TXSh9ebv3Ccqo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-n40TXSh9ebv3Ccqo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-n40TXSh9ebv3Ccqo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户提问
Embedding检索
匹配到第5块文档
句子窗口扩展
窗口大小=3
返回块 4,5,6
交给LLM生成

2.3 LlamaIndex 配置代码

python 复制代码
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 检索流程

#mermaid-svg-rLOcZfGy2aijHio1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rLOcZfGy2aijHio1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rLOcZfGy2aijHio1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rLOcZfGy2aijHio1 .error-icon{fill:#552222;}#mermaid-svg-rLOcZfGy2aijHio1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rLOcZfGy2aijHio1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rLOcZfGy2aijHio1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rLOcZfGy2aijHio1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rLOcZfGy2aijHio1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rLOcZfGy2aijHio1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rLOcZfGy2aijHio1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rLOcZfGy2aijHio1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rLOcZfGy2aijHio1 .marker.cross{stroke:#333333;}#mermaid-svg-rLOcZfGy2aijHio1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rLOcZfGy2aijHio1 p{margin:0;}#mermaid-svg-rLOcZfGy2aijHio1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rLOcZfGy2aijHio1 .cluster-label text{fill:#333;}#mermaid-svg-rLOcZfGy2aijHio1 .cluster-label span{color:#333;}#mermaid-svg-rLOcZfGy2aijHio1 .cluster-label span p{background-color:transparent;}#mermaid-svg-rLOcZfGy2aijHio1 .label text,#mermaid-svg-rLOcZfGy2aijHio1 span{fill:#333;color:#333;}#mermaid-svg-rLOcZfGy2aijHio1 .node rect,#mermaid-svg-rLOcZfGy2aijHio1 .node circle,#mermaid-svg-rLOcZfGy2aijHio1 .node ellipse,#mermaid-svg-rLOcZfGy2aijHio1 .node polygon,#mermaid-svg-rLOcZfGy2aijHio1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rLOcZfGy2aijHio1 .rough-node .label text,#mermaid-svg-rLOcZfGy2aijHio1 .node .label text,#mermaid-svg-rLOcZfGy2aijHio1 .image-shape .label,#mermaid-svg-rLOcZfGy2aijHio1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-rLOcZfGy2aijHio1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rLOcZfGy2aijHio1 .rough-node .label,#mermaid-svg-rLOcZfGy2aijHio1 .node .label,#mermaid-svg-rLOcZfGy2aijHio1 .image-shape .label,#mermaid-svg-rLOcZfGy2aijHio1 .icon-shape .label{text-align:center;}#mermaid-svg-rLOcZfGy2aijHio1 .node.clickable{cursor:pointer;}#mermaid-svg-rLOcZfGy2aijHio1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rLOcZfGy2aijHio1 .arrowheadPath{fill:#333333;}#mermaid-svg-rLOcZfGy2aijHio1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rLOcZfGy2aijHio1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rLOcZfGy2aijHio1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rLOcZfGy2aijHio1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rLOcZfGy2aijHio1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rLOcZfGy2aijHio1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rLOcZfGy2aijHio1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rLOcZfGy2aijHio1 .cluster text{fill:#333;}#mermaid-svg-rLOcZfGy2aijHio1 .cluster span{color:#333;}#mermaid-svg-rLOcZfGy2aijHio1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rLOcZfGy2aijHio1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rLOcZfGy2aijHio1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-rLOcZfGy2aijHio1 .icon-shape,#mermaid-svg-rLOcZfGy2aijHio1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rLOcZfGy2aijHio1 .icon-shape p,#mermaid-svg-rLOcZfGy2aijHio1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rLOcZfGy2aijHio1 .icon-shape .label rect,#mermaid-svg-rLOcZfGy2aijHio1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rLOcZfGy2aijHio1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rLOcZfGy2aijHio1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rLOcZfGy2aijHio1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

用户提问
向量搜索
返回Top-K小块
检查命中分布
某个父节点下

命中>=阈值?
用父节点替换

所有命中的子节点
保持小块返回
交给LLM

3.4 LlamaIndex 配置代码

python 复制代码
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 检索流程

#mermaid-svg-G83L3GhXWTkXMWgx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-G83L3GhXWTkXMWgx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-G83L3GhXWTkXMWgx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-G83L3GhXWTkXMWgx .error-icon{fill:#552222;}#mermaid-svg-G83L3GhXWTkXMWgx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-G83L3GhXWTkXMWgx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-G83L3GhXWTkXMWgx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-G83L3GhXWTkXMWgx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-G83L3GhXWTkXMWgx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-G83L3GhXWTkXMWgx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-G83L3GhXWTkXMWgx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-G83L3GhXWTkXMWgx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-G83L3GhXWTkXMWgx .marker.cross{stroke:#333333;}#mermaid-svg-G83L3GhXWTkXMWgx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-G83L3GhXWTkXMWgx p{margin:0;}#mermaid-svg-G83L3GhXWTkXMWgx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-G83L3GhXWTkXMWgx .cluster-label text{fill:#333;}#mermaid-svg-G83L3GhXWTkXMWgx .cluster-label span{color:#333;}#mermaid-svg-G83L3GhXWTkXMWgx .cluster-label span p{background-color:transparent;}#mermaid-svg-G83L3GhXWTkXMWgx .label text,#mermaid-svg-G83L3GhXWTkXMWgx span{fill:#333;color:#333;}#mermaid-svg-G83L3GhXWTkXMWgx .node rect,#mermaid-svg-G83L3GhXWTkXMWgx .node circle,#mermaid-svg-G83L3GhXWTkXMWgx .node ellipse,#mermaid-svg-G83L3GhXWTkXMWgx .node polygon,#mermaid-svg-G83L3GhXWTkXMWgx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-G83L3GhXWTkXMWgx .rough-node .label text,#mermaid-svg-G83L3GhXWTkXMWgx .node .label text,#mermaid-svg-G83L3GhXWTkXMWgx .image-shape .label,#mermaid-svg-G83L3GhXWTkXMWgx .icon-shape .label{text-anchor:middle;}#mermaid-svg-G83L3GhXWTkXMWgx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-G83L3GhXWTkXMWgx .rough-node .label,#mermaid-svg-G83L3GhXWTkXMWgx .node .label,#mermaid-svg-G83L3GhXWTkXMWgx .image-shape .label,#mermaid-svg-G83L3GhXWTkXMWgx .icon-shape .label{text-align:center;}#mermaid-svg-G83L3GhXWTkXMWgx .node.clickable{cursor:pointer;}#mermaid-svg-G83L3GhXWTkXMWgx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-G83L3GhXWTkXMWgx .arrowheadPath{fill:#333333;}#mermaid-svg-G83L3GhXWTkXMWgx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-G83L3GhXWTkXMWgx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-G83L3GhXWTkXMWgx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-G83L3GhXWTkXMWgx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-G83L3GhXWTkXMWgx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-G83L3GhXWTkXMWgx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-G83L3GhXWTkXMWgx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-G83L3GhXWTkXMWgx .cluster text{fill:#333;}#mermaid-svg-G83L3GhXWTkXMWgx .cluster span{color:#333;}#mermaid-svg-G83L3GhXWTkXMWgx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-G83L3GhXWTkXMWgx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-G83L3GhXWTkXMWgx rect.text{fill:none;stroke-width:0;}#mermaid-svg-G83L3GhXWTkXMWgx .icon-shape,#mermaid-svg-G83L3GhXWTkXMWgx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-G83L3GhXWTkXMWgx .icon-shape p,#mermaid-svg-G83L3GhXWTkXMWgx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-G83L3GhXWTkXMWgx .icon-shape .label rect,#mermaid-svg-G83L3GhXWTkXMWgx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-G83L3GhXWTkXMWgx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-G83L3GhXWTkXMWgx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-G83L3GhXWTkXMWgx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户提问
第一层检索:

在摘要/章节级搜索
定位到相关章节
第二层检索:

在该章节内做向量搜索
返回章节内相关块
合并两层结果交给LLM

4.4 实现示例

python 复制代码
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 知识图谱能做什么

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

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

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

5.3 双索引融合流程

#mermaid-svg-pXbsElnItDOcyigR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pXbsElnItDOcyigR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pXbsElnItDOcyigR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pXbsElnItDOcyigR .error-icon{fill:#552222;}#mermaid-svg-pXbsElnItDOcyigR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pXbsElnItDOcyigR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pXbsElnItDOcyigR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pXbsElnItDOcyigR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pXbsElnItDOcyigR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pXbsElnItDOcyigR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pXbsElnItDOcyigR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pXbsElnItDOcyigR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pXbsElnItDOcyigR .marker.cross{stroke:#333333;}#mermaid-svg-pXbsElnItDOcyigR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pXbsElnItDOcyigR p{margin:0;}#mermaid-svg-pXbsElnItDOcyigR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pXbsElnItDOcyigR .cluster-label text{fill:#333;}#mermaid-svg-pXbsElnItDOcyigR .cluster-label span{color:#333;}#mermaid-svg-pXbsElnItDOcyigR .cluster-label span p{background-color:transparent;}#mermaid-svg-pXbsElnItDOcyigR .label text,#mermaid-svg-pXbsElnItDOcyigR span{fill:#333;color:#333;}#mermaid-svg-pXbsElnItDOcyigR .node rect,#mermaid-svg-pXbsElnItDOcyigR .node circle,#mermaid-svg-pXbsElnItDOcyigR .node ellipse,#mermaid-svg-pXbsElnItDOcyigR .node polygon,#mermaid-svg-pXbsElnItDOcyigR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pXbsElnItDOcyigR .rough-node .label text,#mermaid-svg-pXbsElnItDOcyigR .node .label text,#mermaid-svg-pXbsElnItDOcyigR .image-shape .label,#mermaid-svg-pXbsElnItDOcyigR .icon-shape .label{text-anchor:middle;}#mermaid-svg-pXbsElnItDOcyigR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pXbsElnItDOcyigR .rough-node .label,#mermaid-svg-pXbsElnItDOcyigR .node .label,#mermaid-svg-pXbsElnItDOcyigR .image-shape .label,#mermaid-svg-pXbsElnItDOcyigR .icon-shape .label{text-align:center;}#mermaid-svg-pXbsElnItDOcyigR .node.clickable{cursor:pointer;}#mermaid-svg-pXbsElnItDOcyigR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pXbsElnItDOcyigR .arrowheadPath{fill:#333333;}#mermaid-svg-pXbsElnItDOcyigR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pXbsElnItDOcyigR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pXbsElnItDOcyigR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pXbsElnItDOcyigR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pXbsElnItDOcyigR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pXbsElnItDOcyigR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pXbsElnItDOcyigR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pXbsElnItDOcyigR .cluster text{fill:#333;}#mermaid-svg-pXbsElnItDOcyigR .cluster span{color:#333;}#mermaid-svg-pXbsElnItDOcyigR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pXbsElnItDOcyigR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pXbsElnItDOcyigR rect.text{fill:none;stroke-width:0;}#mermaid-svg-pXbsElnItDOcyigR .icon-shape,#mermaid-svg-pXbsElnItDOcyigR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pXbsElnItDOcyigR .icon-shape p,#mermaid-svg-pXbsElnItDOcyigR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pXbsElnItDOcyigR .icon-shape .label rect,#mermaid-svg-pXbsElnItDOcyigR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pXbsElnItDOcyigR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pXbsElnItDOcyigR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pXbsElnItDOcyigR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户提问
向量检索
知识图谱检索
语义相关的Top-K块
沿关系链推理出的相关实体
合并与去重
融合后的上下文

既有语义又有推理
LLM生成答案

5.4 LlamaIndex 中的知识图谱索引

python 复制代码
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的"嗓子眼"------向量搜索再准、分块策略再好,如果检索策略用错了,整个系统的答案质量就卡在这里。把本文的四种高级检索策略记牢,下次用户反馈"搜不到"时,你就知道该换哪把武器了。不要忘记给博主"一键四连"哦!

相关推荐
jinggongszh2 小时前
智能硬件对接与系统落地:开发岗在制造现场的经验沉淀
大数据·人工智能
ZeekerLin2 小时前
AI 原生团队协作机制:角色、分工与工程文化变化
大数据·人工智能
我是坏垠2 小时前
Crypto、Cipher与Password:Java加密开发的三个核心概念
java·开发语言·python
城中南小2 小时前
零基础认识大语言模型(LLM)工作原理(5.Transformer的FFN模块到底是什么?)
人工智能·语言模型·transformer
碧口科技2 小时前
AI3D模型生成会不会结构不完整?判断标准与修复流程
人工智能·3d
测试秃头怪3 小时前
如何评估自动化测试脚本的编写时间和维护工作量?
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例
战族狼魂3 小时前
GPT-5.6与Grok 4.5重磅发布
人工智能·算法·大模型·大语言模型
姚青&3 小时前
测试左移体系
python·自动化
技术民工之路3 小时前
Python Socket编程零基础实战教程(TCP/UDP通信完整版)
python·tcp/ip·udp
m沐沐3 小时前
【深度学习】dlib 人脸关键点检测
人工智能·深度学习·opencv·计算机视觉·pycharm·人脸识别·关键点检测