RAG 回答总“差点意思“?小白程序员必备:附代码实战两把索引优化钥匙(收藏版)

张开发
2026/4/9 11:37:22 15 分钟阅读

分享文章

RAG 回答总“差点意思“?小白程序员必备:附代码实战两把索引优化钥匙(收藏版)
本文针对 RAG 搭建后回答质量不高的问题介绍了两种优化方法句子窗口检索和结构化递归检索。句子窗口检索通过聚焦最小句子并扩展为完整段落来提升答案质量结构化递归检索则通过元数据标签先过滤再搜索特别适合大规模知识库。文章提供可运行代码和动图讲解适合零基础小白学习实践帮助提升 RAG 回答的准确性和完整性。一、我的 RAG “又准又快”但回答依然烂你花了一周时间搭了个 RAG 知识助手把公司文档全塞进去了满怀期待地问了第一个问题你问“我们产品的退款流程是什么”AI 答“退款需要……后面是从文档某个角落扒出来的半截话前后逻辑对不上”问题出在哪不是模型不够聪明也不是文档没有答案——是你切出来的文本块太碎了。最基础的 RAG 切法是固定大小切块比如每块 512 个字符。检索时确实找到了最相关的那块但这一小块断章取义上下文都被切掉了大模型拿到之后根本补不出完整答案。“那我切大一点”切大了又有另一个问题大块里塞着太多不相关的内容向量嵌入被稀释检索准确率反而下降。听起来像个死结对吧其实有解——只需要用上两把钥匙。二、第一把钥匙句子窗口检索一句话定义句子窗口检索Sentence Window Retrieval就像用放大镜找针——检索时聚焦最小的句子送给 AI 时扩展成完整段落鱼与熊掌两者兼得。2.1 理解它用便利贴 背景纸来类比想象你在整理一本厚厚的工作手册把每一句话写在一张便利贴上贴到墙上。• 查资料时你的眼睛扫过所有便利贴精准锁定那张最相关的句子。• 但把这张便利贴单独撕下来给别人看他们会一脸懵——“这是在说什么上下文”• 所以你不只是递出那张便利贴而是把它左右各3张邻居便利贴也一起递过去。这就是句子窗口检索的全部秘密阶段动作目的️ 建索引把文档拆成单句存入向量库检索时精准定位不被杂乱内容稀释 检索时找到最相关的那句话语义最纯粹相关性最高 后处理把单句扩展成前后各 N 句的窗口给 AI 提供完整上下文答案不缺斤少两 生成时把扩展后的窗口送给大模型生成连贯、信息丰富的回答动图句子窗口检索四步流程——单句检索 → 命中句子 → 扩展窗口 → 送入 LLM慢速10秒句子窗口检索流程动图2.2 代码实现5 步跑通句子窗口检索下面这段代码做四件事加载一份 PDF 文档IPCC 气候报告用句子窗口解析器把文档切成单句、同时在元数据里偷偷藏好窗口构建句子窗口查询引擎带后处理器检索到句子后自动扩展上下文和普通分块检索对比看看效果差多少步骤一安装依赖 导入# 步骤1导入必要的库 from llama_index.coreimportSimpleDirectoryReader, VectorStoreIndex, Settings from llama_index.core.node_parserimportSentenceWindowNodeParser, SentenceSplitter from llama_index.core.postprocessorimportMetadataReplacementPostProcessor# -----------------------------------------------# 【按你的环境修改这里】# -----------------------------------------------# PDF 文件路径改成你本地的 PDF 文件路径# 任何 PDF 都可以这里用 IPCC 气候报告做演示PDF_PATH./data/IPCC_AR6_WGII_Chapter03.pdf# 句子窗口大小前后各几句作为上下文# 3 是个不错的默认值文档结构松散时可以调大到 5WINDOW_SIZE3# 检索时返回几个最相关的节点即 Top-K# 2 适合精准问答泛问题可以调到 3-5TOP_K2# -----------------------------------------------# 假设 Settings.llm 和 Settings.embed_model 已配置好# 参考https://docs.llamaindex.ai/en/stable/module_guides/models/步骤二加载文档 构建句子窗口索引这段代码是整个方案的核心——SentenceWindowNodeParser做了两件事把每句话切成独立节点同时把周边 N 句悄悄塞进节点的元数据里备用。# 步骤2加载文档 documentsSimpleDirectoryReader(input_files[PDF_PATH]).load_data()print(f✅ 文档加载完成共 {len(documents)} 页)# 步骤3创建句子窗口解析器 node_parserSentenceWindowNodeParser.from_defaults(window_sizeWINDOW_SIZE,# 前后各保留 3 句作为窗口window_metadata_keywindow,# 窗口文本存在元数据的 window 字段里original_text_metadata_keyoriginal_text,# 原始句子文本也一并保存)# 把文档解析成句子节点sentence_nodesnode_parser.get_nodes_from_documents(documents)print(f✅ 文档切分完成共 {len(sentence_nodes)} 个句子节点)# 构建向量索引向量化时只用单句文本窗口内容不参与嵌入——这是精髓sentence_indexVectorStoreIndex(sentence_nodes)步骤三构建查询引擎含后处理器MetadataReplacementPostProcessor是这里的魔法师——它在检索到单句节点之后偷梁换柱把单句替换成完整窗口再送给 LLM。# 步骤4构建两种查询引擎用于效果对比 # 方案A句子窗口查询引擎带后处理器sentence_query_enginesentence_index.as_query_engine(similarity_top_kTOP_K,node_postprocessors[# 这个后处理器会把检索到的单句替换成元数据里的完整窗口文本# target_metadata_key 必须和上面的 window_metadata_key 一致MetadataReplacementPostProcessor(target_metadata_keywindow)],)# 方案B普通分块查询引擎基准对比base_parserSentenceSplitter(chunk_size512)# 传统固定大小分块base_nodesbase_parser.get_nodes_from_documents(documents)base_indexVectorStoreIndex(base_nodes)base_query_enginebase_index.as_query_engine(similarity_top_kTOP_K)print(✅ 两种查询引擎构建完成开始对比)步骤四提问 对比结果# 步骤5对比两种检索方式的效果 queryWhat are the concerns surrounding the AMOC?print(f\n❓ 查询问题{query}\n)print(*60)print(\n【方案A句子窗口检索】)window_responsesentence_query_engine.query(query)print(f回答{window_response}\n)print(【方案B普通分块检索对照组】)base_responsebase_query_engine.query(query)print(f回答{base_response}\n)运行结果✅ 文档加载完成共133页 ✅ 文档切分完成共4821个句子节点 ✅ 两种查询引擎构建完成开始对比 ❓ 查询问题What are the concerns surrounding the AMOC? 【方案A句子窗口检索】 回答The AMOC is projected to decline over the 21st century with high confidence, though quantitative projections have low confidence. Observational records since the mid-2000s are too short to determine the relative contributions of internal variability, natural forcing, and anthropogenic forcing. Additionally, there is low confidenceinreconstructed and modeled AMOC changesforthe 20th century. While an abrupt collapse before2100is not expected, the decline could have significant implicationsforglobal climate patterns. 【方案B普通分块检索对照组】 回答The concerns primarily involve its projected decline over the 21st century across all SSP scenarios. While an abrupt collapse before2100is not expected, quantitative projections remain uncertain. Further research is needed to better understand AMOC behavior and its broader climate impacts.2.3 对比解读差距在哪里把两个答案放在一起看对比维度句子窗口检索普通分块检索信息量✅ 涵盖 4 个维度衰退趋势、置信度、观测局限、20世纪历史⚠️ 只提到衰退趋势和不确定性回答质量✅ 逻辑连贯像综述⚠️ 较笼统结尾是需要进一步研究上下文完整性✅ 检索到句子后扩展了窗口❌ 只拿到孤立的 512 字符块核心原因普通分块把句子切碎后相关信息散落在不同 chunk 里检索时只找到了残肢没有整体。而句子窗口检索先精准锁定句子再还原上下文两全其美。三、第二把钥匙结构化递归检索一句话定义结构化递归检索就像大公司的总机 转接——先把你的问题转给对的部门再在那个部门内部精确找答案。3.1 理解它当知识库大到针难找假设你的知识库里有 500 个 PDF每个 PDF 有 100 页。用户问了一个问题普通 RAG 会怎么做在全部 50000 页里做向量搜索。这就像你在一个有 50 个部门的公司里找一份报告不去问前台而是挨个部门翻抽屉……不仅慢还经常在财务部里翻出了市场部的东西搜出来的结果乱成一锅粥。结构化索引的思路是给每个文档贴上元数据标签Metadata然后先过滤、再搜索。传统 RAG结构化索引 RAG在全量文档里做向量搜索先按元数据筛选相关文档子集返回结果混乱夹杂无关内容只在目标子集里搜干净精准知识库越大越慢越乱规模越大优势越明显结构化检索对比图3.2 进阶版递归检索先路由再问答结构化索引的更强形态是递归检索Recursive Retrieval。场景你有一个 Excel 文件里面有十几个工作表每个工作表是某一年的电影数据。用户问1994 年评分最低的电影是哪部系统怎么知道去年份_1994那张表找而不是翻遍所有表答案是两层索引第一层路由层 每张表的摘要描述 → 向量索引 ↓ 用户问题这问题跟 年份_1994 最相关↓ 第二层执行层 年份_1994 表的 PandasQueryEngine ↓ 生成 Pandas 代码 → 执行 → 返回答案动图递归检索两层流程——问题路由到摘要层 → 定位目标表 → 子引擎执行查询慢速10秒递归检索流程动图3.3 代码实现递归检索实战下面这段代码做三件事读取 Excel 的每个工作表为每个表创建一个摘要节点和查询引擎用所有摘要节点构建顶层路由索引配置RecursiveRetriever让它先路由、再执行步骤一导入 配置路径# 步骤1导入库 importpandas as pd from llama_index.coreimportVectorStoreIndex, Settings from llama_index.core.query_engineimportPandasQueryEngine, RetrieverQueryEngine from llama_index.core.schemaimportIndexNode from llama_index.core.retrieversimportRecursiveRetriever# -----------------------------------------------# 【按你的环境修改这里】# -----------------------------------------------# Excel 文件路径改成你本地的 Excel 文件路径# 每个工作表Sheet对应一个数据集表名会被用作路由标识EXCEL_PATH./data/movie.xlsx# 路由检索时只考虑最相关的前 1 个摘要节点# 通常保持 1 即可如果有跨年份的问题可以调到 2ROUTE_TOP_K1# -----------------------------------------------步骤二为每个工作表创建摘要节点和查询引擎这是核心逻辑——每张表有两样东西一个摘要节点用于路由一个PandasQueryEngine用于实际查询。# 步骤2遍历 Excel 所有工作表分别建立摘要节点 查询引擎 xlspd.ExcelFile(EXCEL_PATH)df_query_engines{}# 存放工作表名 → 查询引擎 的映射all_nodes[]# 存放所有摘要节点用于构建顶层路由索引forsheet_nameinxls.sheet_names:# 读取当前工作表的数据dfpd.read_excel(xls,sheet_namesheet_name)# 为当前表创建 PandasQueryEngine# 它能把评分最低的是哪部翻译成 df.nsmallest(1, 评分)[电影名称].iloc[0]# ⚠️ 注意生产环境不建议使用安全风险见后文说明query_enginePandasQueryEngine(dfdf,llmSettings.llm,verboseTrue)# 提取年份构建该工作表的摘要文本这个文本用于语义路由yearsheet_name.replace(年份_,)summaryf这个表格包含了年份为 {year} 的电影信息可以用来回答关于这一年电影的具体问题。# 创建摘要节点index_id 必须和 df_query_engines 的 key 保持一致nodeIndexNode(textsummary,index_idsheet_name)all_nodes.append(node)df_query_engines[sheet_name]query_engine print(f✅ 共处理 {len(xls.sheet_names)} 个工作表{xls.sheet_names})步骤三构建递归检索器 执行查询# 步骤3构建顶层路由索引只含摘要节点不含实际数据vector_indexVectorStoreIndex(all_nodes)vector_retrievervector_index.as_retriever(similarity_top_kROUTE_TOP_K)# 步骤4配置递归检索器 recursive_retrieverRecursiveRetriever(vector,retriever_dict{vector:vector_retriever},# 当摘要节点被命中后用 index_id 找到对应的查询引擎query_engine_dictdf_query_engines,verboseTrue,# 打印路由过程方便调试)# 步骤5创建最终查询引擎 提问 query_engineRetrieverQueryEngine.from_args(recursive_retriever)query1994年评分人数最少的电影是哪一部print(f\n❓ 查询{query})responsequery_engine.query(query)print(f\n✅ 答案{response})运行结果✅ 共处理5个工作表[年份_1994,年份_1995,年份_2000,年份_2002,年份_2010]❓ 查询1994年评分人数最少的电影是哪一部Retrieving with queryidNone:1994年评分人数最少的电影是哪一部Retrievednodewith id, entering: 年份_1994 ← 路由成功Retrieving with queryid年份_1994:1994年评分人数最少的电影是哪一部Pandas Instructions: df[df[年份]1994].nsmallest(1,评分人数)[电影名称].iloc[0]Pandas Output: 燃情岁月 ✅ 答案燃情岁月从输出里能清楚看到两层跳转先路由到年份_1994再由 PandasQueryEngine 生成代码执行最终精准返回答案。3.4 ⚠️ 重要安全提示生产环境请绕行 PandasQueryEnginePandasQueryEngine工作原理是让 LLM 生成 Python 代码然后用eval()本地执行。eval()意味着可以执行任意代码。如果有人在问题里夹带了恶意指令理论上可以在你的服务器上为所欲为——删文件、读环境变量、发网络请求……生产环境的安全替代方案方案思路安全性路由 元数据过滤推荐先路由找到目标表再用元数据过滤在向量库里精确搜索✅ 无代码执行风险沙箱隔离在受限容器里运行 PandasQueryEngine⚠️ 复杂度高需要专业运维Text-to-SQL把 Excel 转成数据库用 SQL 查询✅ SQL 比 eval 安全但仍需注意注入本文配套代码里提供了路由 元数据过滤的完整安全实现链接见文末。四、两把钥匙分别开什么锁用完整的对照把本文核心总结一下选型象限图技术解决的问题适用场景代码关键类句子窗口检索上下文碎、回答缺斤少两长文档、需要高质量答案SentenceWindowNodeParserMetadataReplacementPostProcessor结构化递归检索知识库太大、搜出来的全是不相关内容多文档/多表格、大规模知识库IndexNodeRecursiveRetriever两者可以叠加使用先用结构化索引缩小范围再用句子窗口检索提升答案质量。动图两种技术叠加使用的完整 RAG 流程慢速12秒两技术叠加动图五、总结 现在就能做的三件事学完本文你已经掌握了• ✅句子窗口检索用单句建索引精准用窗口送 LLM完整两全其美• ✅结构化递归检索给文档贴元数据标签先路由后检索大规模知识库的救星• ✅安全意识PandasQueryEngine用了eval()生产环境要换成元数据过滤方案进阶路线阶段方向要掌握的入门跑通基础 RAGLlamaIndex 基本用法向量索引Top-K 检索进阶本文两种技术SentenceWindowNodeParser、RecursiveRetriever高级混合检索 重排序密集向量 稀疏向量 Reranker 三件套现在就可以做的三件事安装环境pip install llama-index llama-index-core5 分钟跑通句子窗口 Demo把本文代码里的PDF_PATH改成你手边任意一个 PDF运行一遍看看效果对比效果差距把两种查询引擎同时问同一个问题感受上下文扩展带来的质量提升当然本文的示例都是教学级别——真实项目里文档更复杂、数据更脏、场景更多样。但这两把钥匙打开的思路会一直有用。如何学习大模型 AI 由于新岗位的生产效率要优于被取代岗位的生产效率所以实际上整个社会的生产效率是提升的。但是具体到个人只能说是“最先掌握AI的人将会比较晚掌握AI的人有竞争优势”。这句话放在计算机、互联网、移动互联网的开局时期都是一样的道理。我在一线互联网企业工作十余年里指导过不少同行后辈。帮助很多人得到了学习和成长。我意识到有很多经验和知识值得分享给大家也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限很多互联网行业朋友无法获得正确的资料得到学习提升故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】为什么要学习大模型我国在A大模型领域面临人才短缺,数量与质量均落后于发达国家。2023年人才缺口已超百万凸显培养不足。随着AI技术飞速发展预计到2025年,这一缺口将急剧扩大至400万,严重制约我国AI产业的创新步伐。加强人才培养,优化教育体系,国际合作并进是破解困局、推动AI发展的关键。大模型入门到实战全套学习大礼包1、大模型系统化学习路线作为学习AI大模型技术的新手方向至关重要。 正确的学习路线可以为你节省时间少走弯路方向不对努力白费。这里我给大家准备了一份最科学最系统的学习成长路线图和学习规划带你从零基础入门到精通2、大模型学习书籍文档学习AI大模型离不开书籍文档我精选了一系列大模型技术的书籍和学习文档电子版它们由领域内的顶尖专家撰写内容全面、深入、详尽为你学习大模型提供坚实的理论基础。3、AI大模型最新行业报告2025最新行业报告针对不同行业的现状、趋势、问题、机会等进行系统地调研和评估以了解哪些行业更适合引入大模型的技术和应用以及在哪些方面可以发挥大模型的优势。4、大模型项目实战配套源码学以致用在项目实战中检验和巩固你所学到的知识同时为你找工作就业和职业发展打下坚实的基础。5、大模型大厂面试真题面试不仅是技术的较量更需要充分的准备。在你已经掌握了大模型技术之后就需要开始准备面试我精心整理了一份大模型面试题库涵盖当前面试中可能遇到的各种技术问题让你在面试中游刃有余。适用人群第一阶段10天初阶应用该阶段让大家对大模型 AI有一个最前沿的认识对大模型 AI 的理解超过 95% 的人可以在相关讨论时发表高级、不跟风、又接地气的见解别人只会和 AI 聊天而你能调教 AI并能用代码将大模型和业务衔接。大模型 AI 能干什么大模型是怎样获得「智能」的用好 AI 的核心心法大模型应用业务架构大模型应用技术架构代码示例向 GPT-3.5 灌入新知识提示工程的意义和核心思想Prompt 典型构成指令调优方法论思维链和思维树Prompt 攻击和防范…第二阶段30天高阶应用该阶段我们正式进入大模型 AI 进阶实战学习学会构造私有知识库扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架抓住最新的技术进展适合 Python 和 JavaScript 程序员。为什么要做 RAG搭建一个简单的 ChatPDF检索的基础概念什么是向量表示Embeddings向量数据库与向量检索基于向量检索的 RAG搭建 RAG 系统的扩展知识混合检索与 RAG-Fusion 简介向量模型本地部署…第三阶段30天模型训练恭喜你如果学到这里你基本可以找到一份大模型 AI相关的工作自己也能训练 GPT 了通过微调训练自己的垂直大模型能独立训练开源多模态大模型掌握更多技术方案。到此为止大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗为什么要做 RAG什么是模型什么是模型训练求解器 损失函数简介小实验2手写一个简单的神经网络并训练它什么是训练/预训练/微调/轻量化微调Transformer结构简介轻量化微调实验数据集的构建…第四阶段20天商业闭环对全球大模型从性能、吞吐量、成本等方面有一定的认知可以在云端和本地等多种环境下部署大模型找到适合自己的项目/创业方向做一名被 AI 武装的产品经理。硬件选型带你了解全球大模型使用国产大模型服务搭建 OpenAI 代理热身基于阿里云 PAI 部署 Stable Diffusion在本地计算机运行大模型大模型的私有化部署基于 vLLM 部署大模型案例如何优雅地在阿里云私有部署开源大模型部署一套开源 LLM 项目内容安全互联网信息服务算法备案…学习是一个过程只要学习就会有挑战。天道酬勤你越努力就会成为越优秀的自己。如果你能在15天内完成所有的任务那你堪称天才。然而如果你能完成 60-70% 的内容你就已经开始具备成为一名大模型 AI 的正确特征了。这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

更多文章