新闻详情

新闻详情

首页 / 资讯中心 / 详情

AI Agent知识获取管道:RAG从稠密嵌入到混合检索实战

发布时间:2026/9/28 16:02:03来源:尧图网络
AI Agent知识获取管道:RAG从稠密嵌入到混合检索实战
1. 为什么知识获取管道是 AI Agent 落地的第一道坎做 AI Agent 开发的人绕不开一个尴尬的现实模型本身很聪明但它对你电脑里的文档、公司内部的规范、你个人的笔记一无所知。你问它一个关于你项目里某个配置文件的问题它要么一本正经地胡说八道要么礼貌地告诉你“我无法访问你的本地文件”。这不是模型不行而是它的知识边界被训练数据锁死了。知识获取管道要解决的就是这个问题。它的核心任务只有一句话在模型生成回答之前把与用户问题最相关的知识片段找出来塞进模型的上下文窗口里。这个“找出来”的过程就是 RAGRetrieval-Augmented Generation检索增强生成要干的事。我见过太多团队在搭建 AI Agent 时把 80% 的精力花在调 Prompt 和换模型上结果 Agent 回答质量始终上不去。问题往往出在知识获取管道上——检索回来的内容要么不相关要么不完整要么格式混乱模型再强也巧妇难为无米之炊。这一篇作为“走进 AI Agent”系列的第四篇专门把 RAG 的基础打牢从稠密嵌入到稀疏嵌入从文档切分到检索策略把这条管道的每个环节拆开讲清楚。适合谁看如果你正在从零搭建 AI Agent或者已经有一个能跑但效果不稳定的 RAG 系统这篇内容能帮你建立一套完整的知识获取管道认知框架。不需要你精通深度学习但需要你对 Python 和基本的向量检索概念有了解。2. RAG 基础架构拆解从文档到答案的完整链路2.1 RAG 到底在解决什么问题先把这个概念说透。RAG 的本质是一个“开卷考试”系统。模型是考生知识库是参考书检索器是索引。考生不需要把所有知识背下来只需要在答题时能快速翻到正确的页码。传统做法是把知识微调进模型参数里成本高、更新慢、容易灾难性遗忘。RAG 的做法是把知识放在外部存储里模型只负责理解和生成。这样做的好处很明显知识可以随时更新不需要重新训练模型检索过程可解释能追溯到具体来源成本低一个向量数据库加一个嵌入模型就能跑起来。但 RAG 不是银弹。它引入了一个新的失败模式检索失败。如果检索器没找到正确的知识片段模型要么说“我不知道”要么基于错误信息编造答案。所以知识获取管道的质量直接决定了整个 Agent 的可靠性上限。2.2 知识获取管道的四个核心环节一条完整的知识获取管道包含四个环节每个环节都有坑文档加载与解析。你的知识可能来自 PDF、Markdown、Word、网页、数据库。不同格式的解析质量差异巨大。PDF 里的表格和公式是重灾区扫描件更是需要 OCR 才能处理。我见过一个项目PDF 解析时把两栏排版的文字按行读取结果每句话都是半截的检索出来的内容完全没法用。文本切分。把长文档切成小块每块作为一个检索单元。切分策略直接影响检索精度。切得太碎语义不完整切得太大噪声太多。常见的做法是按固定长度切分配合重叠窗口但更好的做法是按语义边界切分比如按段落、按标题层级。向量化与索引。把文本块转换成向量存入向量数据库。这里涉及嵌入模型的选择稠密嵌入和稀疏嵌入的取舍以及索引结构的优化。检索与重排。用户提问后把问题也向量化在数据库中找最相似的文本块。基础做法是余弦相似度检索进阶做法会加入重排模型对初步检索结果做二次排序。2.3 稠密嵌入与稀疏嵌入两种检索哲学的碰撞这是 RAG 基础里最容易被忽略但最关键的一个选择。稠密嵌入和稀疏嵌入代表了两种完全不同的检索思路。稠密嵌入把文本映射成一个固定长度的稠密向量比如 768 维或 1024 维。每个维度都是一个浮点数整个向量编码了文本的语义信息。它的优势是能捕捉语义相似性——用户问“怎么提升系统响应速度”即使文档里写的是“优化接口性能”稠密嵌入也能匹配上因为它们在语义空间里距离很近。稀疏嵌入则是高维稀疏向量维度等于词表大小比如 30000 维但只有少数几个维度有非零值。每个维度对应一个词值表示这个词的权重。它的优势是精确匹配——用户搜“Spring AI RAG”文档里必须出现这些词才能匹配上。稀疏嵌入对关键词、专有名词、代码标识符的检索效果远好于稠密嵌入。实际项目中我强烈建议用混合检索稠密嵌入负责语义召回稀疏嵌入负责关键词召回两路结果融合后重排。这样既能处理“意思相近但用词不同”的情况又能保证专有名词不被漏掉。对比维度稠密嵌入稀疏嵌入向量维度低维768-1024高维词表大小语义捕捉强弱关键词匹配弱强计算成本较高较低典型模型text-embedding-3-small、BGEBM25、SPLADE适用场景语义问答、模糊查询精确检索、代码搜索3. 从零搭建 RAG 知识获取管道的实操步骤3.1 文档加载与预处理别让脏数据毁掉整条管道这一步的投入产出比最高也最容易被跳过。我的经验是文档预处理花的时间至少应该占总开发时间的 30%。先看一个典型的文档加载代码结构from langchain_community.document_loaders import PyPDFLoader, UnstructuredMarkdownLoader from langchain.text_splitter import RecursiveCharacterTextSplitter # PDF 加载注意指定提取模式 pdf_loader PyPDFLoader(technical_manual.pdf, extraction_modelayout) pdf_docs pdf_loader.load() # Markdown 加载保留标题层级 md_loader UnstructuredMarkdownLoader(project_docs.md, modeelements) md_docs md_loader.load()这里有几个实操细节值得展开。extraction_modelayout会尽量保留 PDF 的版面结构对多栏排版和表格更友好但速度会慢一些。如果 PDF 是扫描件需要先走 OCR 流程推荐用 PaddleOCR 或 Tesseract但 OCR 结果一定要人工抽检错字率可能高达 5%-10%。Markdown 加载用modeelements会保留标题、列表、代码块等结构信息后续切分时可以按标题层级来切语义完整性更好。注意不要直接用TextLoader读所有文件。不同格式的解析质量差异巨大统一用文本读取会丢失大量结构信息后续检索精度会大打折扣。预处理阶段还要做几件事去除页眉页脚、合并断行、统一标点符号、过滤空内容。这些看似琐碎的操作对检索质量的影响是立竿见影的。我做过对比测试同样的文档做了预处理和没做预处理检索命中率能差 20 个百分点。3.2 文本切分策略粒度决定检索精度切分是 RAG 里最需要“手感”的环节。没有万能参数只有适合你数据的策略。固定长度切分是最简单的做法text_splitter RecursiveCharacterTextSplitter( chunk_size512, chunk_overlap64, separators[\n\n, \n, 。, , , , , , ] ) chunks text_splitter.split_documents(pdf_docs)chunk_size512意味着每个文本块大约 512 个字符chunk_overlap64表示相邻块之间有 64 个字符的重叠防止语义在边界处被切断。separators列表定义了切分的优先级先按段落切段落太长再按句子切依次递进。但固定长度切分有个致命问题它可能把一个完整的语义单元切成两半。比如一个函数定义被从中间切开检索时只能拿到半截代码模型根本没法用。语义切分是更好的选择。按 Markdown 标题层级切分每个二级标题下的内容作为一个块按代码函数切分每个函数作为一个块按问答对切分每个问答对作为一个块。这样切出来的块语义完整性有保障。from langchain.text_splitter import MarkdownHeaderTextSplitter headers_to_split_on [ (#, Header 1), (##, Header 2), (###, Header 3), ] markdown_splitter MarkdownHeaderTextSplitter(headers_to_split_onheaders_to_split_on) md_chunks markdown_splitter.split_text(md_docs[0].page_content)实操心得切分粒度没有标准答案但有一个判断标准——把切出来的块单独拿给一个没看过原文的人看他能不能理解这块内容在说什么。如果看不懂说明切得太碎或上下文丢失太多。3.3 嵌入模型选型稠密与稀疏的实战取舍嵌入模型的选择直接决定了检索质量的上限。我的建议是分场景中文通用场景首选 BGE 系列BAAI/bge-large-zh-v1.5或 M3E 系列。这些模型在中文语义相似度任务上表现稳定而且可以本地部署不依赖外部 API。代码检索场景用 CodeBERT 或 UniXcoder它们对代码标识符和语法结构有更好的理解。多语言场景用 multilingual-e5-large 或 paraphrase-multilingual-MiniLM。稠密嵌入的生成很简单from sentence_transformers import SentenceTransformer model SentenceTransformer(BAAI/bge-large-zh-v1.5) embeddings model.encode([chunk.page_content for chunk in chunks])稀疏嵌入的生成稍微复杂一些BM25 是最经典的方案from rank_bm25 import BM25Okapi import jieba tokenized_corpus [list(jieba.cut(chunk.page_content)) for chunk in chunks] bm25 BM25Okapi(tokenized_corpus)中文需要先分词jieba 是常用选择。BM25 的优势是无需训练、解释性强、对关键词敏感。缺点是纯词频统计无法捕捉语义。提示如果你的知识库里有大量专有名词、产品型号、代码标识符稀疏嵌入是必须的。我踩过的坑是只用稠密嵌入结果用户搜“ERR_CONNECTION_REFUSED”时检索器返回了一堆关于“网络连接问题”的泛泛内容完全没命中这个具体错误码。3.4 向量数据库选型与索引构建向量数据库的选择取决于数据规模和部署环境。个人项目和小团队Chroma 或 FAISS 足够用零配置、本地运行。企业级应用Milvus 或 Qdrant 更合适支持分布式、高可用、混合检索。import chromadb client chromadb.PersistentClient(path./chroma_db) collection client.create_collection( nameknowledge_base, metadata{hnsw:space: cosine} ) collection.add( embeddingsembeddings.tolist(), documents[chunk.page_content for chunk in chunks], metadatas[chunk.metadata for chunk in chunks], ids[fchunk_{i} for i in range(len(chunks))] )hnsw:spacecosine指定用余弦相似度作为距离度量。对于归一化后的嵌入向量余弦相似度和点积是等价的但余弦相似度更直观取值范围在 -1 到 1 之间。索引构建时要注意HNSW 的参数M和ef_construction影响检索速度和精度。M越大索引越稠密检索越准但内存占用越高。一般从M16开始调数据量大再往上加。3.5 混合检索与重排把召回率拉满单一检索策略总有盲区。稠密嵌入漏关键词稀疏嵌入漏语义。混合检索把两路结果融合取长补短。def hybrid_search(query, dense_model, bm25, collection, top_k10): # 稠密检索 query_embedding dense_model.encode([query]) dense_results collection.query( query_embeddingsquery_embedding.tolist(), n_resultstop_k ) # 稀疏检索 tokenized_query list(jieba.cut(query)) bm25_scores bm25.get_scores(tokenized_query) sparse_indices sorted(range(len(bm25_scores)), keylambda i: bm25_scores[i], reverseTrue)[:top_k] # 融合RRFReciprocal Rank Fusion fused_scores {} for rank, idx in enumerate(dense_results[ids][0]): fused_scores[idx] fused_scores.get(idx, 0) 1 / (60 rank) for rank, idx in enumerate(sparse_indices): idx_str fchunk_{idx} fused_scores[idx_str] fused_scores.get(idx_str, 0) 1 / (60 rank) return sorted(fused_scores.items(), keylambda x: x[1], reverseTrue)[:top_k]RRF 是融合两路结果的经典算法公式是1/(krank)k通常取 60。它的好处是不需要归一化分数直接按排名融合对两路检索的分数尺度不敏感。如果预算允许加一个重排模型Reranker能进一步提升精度。BGE-reranker 系列是常用选择它会对初步检索的 top-50 结果做精细打分重新排序后取 top-5 送给模型。实测下来加 Reranker 后检索命中率能提升 15%-25%。4. 常见问题与排查技巧实录4.1 检索结果不相关从五个维度排查这是 RAG 最高频的问题。用户问 A检索器返回 B。排查思路按优先级排列第一检查嵌入模型是否匹配语言和领域。用英文模型处理中文文档效果必然差。用通用模型处理法律或医疗文档专业术语的语义捕捉也会失真。换一个在目标领域微调过的嵌入模型往往能立竿见影。第二检查切分粒度是否合理。切得太碎每个块信息量不足切得太大噪声淹没信号。一个实用的调试方法是随机抽 20 个检索结果人工判断每个块是否包含回答用户问题所需的信息。如果命中率低于 60%说明切分策略需要调整。第三检查查询改写是否到位。用户的问题往往口语化、简短、有指代。直接拿原始问题去检索效果可能很差。加一个查询改写步骤把“它怎么用”改写成“XXX 功能的使用方法”检索命中率会明显提升。第四检查是否缺少稀疏检索。如果用户查询包含专有名词、代码、型号纯稠密检索很容易漏掉。加上 BM25 混合检索这类查询的召回率能提升 30% 以上。第五检查向量数据库的索引参数。HNSW 的ef_search参数控制检索时的搜索范围值越大越准但越慢。如果检索结果不稳定尝试调大ef_search。4.2 模型回答“我不知道”检索为空或阈值过高有时候检索器返回了结果但模型还是说“根据提供的信息无法回答”。这通常是两个原因一是相似度阈值设得太高。很多向量数据库支持设置score_threshold低于阈值的结果被过滤掉。如果阈值设成 0.8而实际相关文档的相似度只有 0.75就会被误杀。建议初期把阈值设低一些0.5-0.6观察实际检索结果的分数分布后再调整。二是检索结果虽然相关但信息不完整。比如用户问“如何配置数据库连接池”检索到的块只讲了“连接池的最大连接数”没讲“如何配置”。这时候需要调整切分策略确保每个块包含完整的操作步骤。4.3 检索速度慢从索引和批量处理入手数据量上来后检索延迟会成为瓶颈。优化方向有几个索引层面HNSW 比 IVF 快但内存占用高。如果内存充足优先用 HNSW。如果数据量超过千万级考虑 IVF_PQ 量化索引用精度换速度。批量处理嵌入生成和检索都支持批量操作。把多个查询合并成一个批次能显著提升吞吐量。缓存对高频查询的结果做缓存。用户的问题往往有重复缓存命中率能达到 20%-30%。降维如果嵌入维度是 1024可以降到 256 或 128。降维会损失一些精度但检索速度能提升 2-3 倍。用 PCA 或 OPQ 做降维实测精度损失在可接受范围内。4.4 常见问题速查表问题现象可能原因排查方法解决方案检索结果不相关嵌入模型不匹配人工抽检 top-20 结果换领域适配的嵌入模型专有名词漏检缺少稀疏检索用关键词查询测试加入 BM25 混合检索回答“我不知道”阈值过高或切分不当检查检索分数分布降低阈值调整切分粒度检索速度慢索引参数或数据量测量单次检索延迟调 HNSW 参数加缓存重复内容多切分重叠过大检查 chunk_overlap减小重叠窗口长文档检索差切分粒度过大检查块长度分布按语义边界切分5. 进阶方向从基础 RAG 到 Agentic RAG基础 RAG 跑通后你会遇到新的瓶颈单次检索不够用复杂问题需要多跳推理检索策略需要根据问题类型动态调整。这就是 Agentic RAG 要解决的问题。Agentic RAG 的核心思路是把检索过程 Agent 化。Agent 不再是一次性检索而是可以判断是否需要检索、选择检索哪个知识库、改写查询、多轮检索、验证检索结果、决定何时停止检索。这相当于给知识获取管道加了一个“调度中心”。实现上可以用 LangChain 的 AgentExecutor 或 LangGraph 来编排检索流程。一个典型的 Agentic RAG 流程是用户提问 → Agent 判断问题类型 → 如果是事实型问题走单次检索如果是分析型问题拆解成子问题分别检索 → 汇总检索结果 → 生成回答 → 验证回答是否有据可依 → 如果依据不足重新检索。这个方向目前还在快速演进中但核心思想已经清晰知识获取管道不应该是静态的而应该根据任务需求动态调整。我在实际项目中试过对于复杂查询Agentic RAG 的准确率比基础 RAG 高出 20%-30%代价是延迟增加 2-3 倍。所以是否上 Agentic RAG取决于你的场景对准确率和延迟的权衡。最后分享一个我在搭建知识获取管道时反复验证的原则检索质量的上限由数据质量决定检索策略只是逼近这个上限。与其花大量时间调检索参数不如先把文档解析和切分做扎实。我见过太多项目在脏数据上反复调参效果始终上不去最后发现是 PDF 解析时把表格内容全丢了。先把数据管道打通再谈优化。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Python3函数参数详解 2026/9/28 20:33:21

Python3函数参数详解

在 Python 中,函数参数是函数的重要组成部分,它们允许函数接收外部传入的数据,从而使函数具有更强的通用性和灵活性。理解和掌握 Python 函数参数的各种类型和使用方法,对于编写高效、可维护的代码至关重要。本文将详细介绍 Pytho…

阅读更多 →
投资框架怎么建?周期、耐心与仓位管理,一份写给新手的完整指南 2026/9/28 20:33:21

投资框架怎么建?周期、耐心与仓位管理,一份写给新手的完整指南

投资框架怎么建?周期、耐心与仓位管理,一份写给新手的完整指南 【免费下载链接】investing-for-beginners 美股、期权与加密货币知识框架 项目地址: https://gitcode.com/gh_mirrors/in/investing-for-beginners 这是《投资入门指南》中最核心的一…

阅读更多 →
JEV编码代理深度实战:长上下文重构、Codex接入与避坑指南 2026/9/28 20:33:21

JEV编码代理深度实战:长上下文重构、Codex接入与避坑指南

1. 从一次代码评审说起:我为什么突然被 JEV 吸引大概两周前,我在整理一个老项目的依赖升级清单,同事随口提了一句“你试过 JEV 没有,那个模型写代码的风格很对我胃口”。我当时没太当回事,毕竟现在每天冒出来的模型代号…

阅读更多 →
NanoVNA实用指南:矢量网络分析、校准与天线测量要点 2026/9/28 20:33:21

NanoVNA实用指南:矢量网络分析、校准与天线测量要点

如果你平时喜欢捣腾天线、滤波器、对讲机手台,或者在做射频小板的阻抗匹配,NanoVNA这个名字应该早就躺在你的购物车和收藏夹里了。作为一台能把“矢量网络分析”这件事做到几百块价位的掌上仪器,它几乎成了DIY射频圈子的标配工具:…

阅读更多 →
Hypit实战:一行命令复刻爆款视频的完整流程与避坑指南 2026/9/28 20:33:21

Hypit实战:一行命令复刻爆款视频的完整流程与避坑指南

说实话,看到 Hypit 的 README 上写着"一行命令复刻爆款视频"的时候,我第一反应是"又一个把复杂事说简单了的项目"。但最近我在整理一批短视频素材时,确实被这种需求折磨得够呛——想复刻一支爆款视频的镜头节奏&#xff…

阅读更多 →
值得偷师的生产级测试文化:Open Glean 的 Vitest 回归测试与 SpendGuard 限流设计完整解读 2026/9/28 20:33:14

值得偷师的生产级测试文化:Open Glean 的 Vitest 回归测试与 SpendGuard 限流设计完整解读

值得偷师的生产级测试文化:Open Glean 的 Vitest 回归测试与 SpendGuard 限流设计完整解读 【免费下载链接】open-glean An open-source AI platform for knowledge work. Connect your apps, find answers, and get work done. 项目地址: https://gitcode.com/gh…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉