资讯动态

AI Agent + RAG:从原理到实践,手把手打造专属知识库

发布时间:2026/9/5 12:26:17 来源:尧图企业网站定制
让我们先把这个技术路线想清楚。最近总有人问我RAG都火了这么久了怎么还要和Agent一起提直接拿向量数据库检索不就行了我的回答是如果你只是做一个“查文档问答机器人”纯RAG确实够用但如果你想让它自动规划、主动调工具、多步推理、从多个数据源交叉验证信息那RAG只是Agent的一只“手”真正的大脑还在Agent的规划能力里。这篇文章就从一个已经跑过完整项目的博主视角把AI Agent和RAG结合起来手把手拆解打造专属知识库的全过程。适合三类人看一是正在做个人知识库、想引入AI问答能力的效率工具党二是企业里要做内部文档问答系统、但不想上来就搞大模型的工程师三是对LangChain/LlamaIndex/Dify这些框架有兴趣、想理解背后原理的学习者。我会把向量化流程、检索优化、HyDE、Graph RAG、Agentic RAG这些热点词都串起来讲最后给一套可以直接“抄作业”的落地配置。1. 内容整体设计与思路拆解1.1 为什么纯RAG不够用Agent才是关键先坦白讲一个问题纯RAG的召回质量很不稳定。你做知识库问答最怕的不是模型答不出而是它“一本正经地胡说八道”——检索回来的片段没逻辑关联或者多个问题叠加在一起时检索器不知道到底该找哪段话。这个时候Agent的价值就出来了。Agent干的事情是“拆问题”用户问“我们公司过去三个季度的销售数据怎么样其中华南区增长最快的是哪个产品线”这个query直接扔给检索器召回质量大概率是崩的。但Agent可以先拆解成三步第一步查销售数据汇总表第二步筛选华南区数据第三步对比产品线增长率并排序。每一步调用一次RAG检索而且可以把上一步的结果当作下一步检索的上下文。这就是热词里经常提到的“Agentic RAG”——检索不再是单次动作而是被Agent编排进整体规划流程中的可控子任务。从架构上看RAG给Agent提供了“记忆的来源”Agent给RAG提供了“决策的骨架”。两者结合之后的整体设计通常分三层数据层处理原始文档完成解析、清洗、切分、向量化落地到向量数据库。检索层负责召回包括向量检索、关键词检索、混合检索、重排序。Agent层负责解析用户意图、编排检索动作、组装上下文、调用LLM生成最终答案。这个分层看起来简单但每层都有无数个“魔鬼细节”。接下来我逐个拆。1.2 架构选型LangChain、LlamaIndex还是Dify很多新手第一个问题就是那我该直接用哪个框架我先把我试过的三个方案实事求是的说一下。LangChain是通用型Agent编排框架生态最全文档也多但版本演进太快API经常breaking change如果你要生产级稳定性得花时间锁版本。它的优势在于自由度极高——你可以用LCELLangChain Expression Language把检索、prompt、模型、输出解析串成一条chain也可以自建Agent Loops。LlamaIndex则是更贴近“知识库场景”的选择它在索引结构和检索细节上做得比LangChain更深比如内置了各种Node Parser、Metadata Extractor、SubQuestionQueryEngine非常适合以文档为中心的RAG应用。Dify则是平台化的代表属于“低代码/可视化”路线热词里也提到了Dify知识库流水线、以及Dify升级后无法保存知识库等问题。Dify适合团队协作、需要快速迭代的场景它的知识库管理界面、文档分段策略、召回测试工具都是现成的但定制能力受限尤其是你想要实现自定义Agent中间步骤时反而会绕一些弯。我的推荐结论是——个人项目或学习用优先LangChain纯文档问答、要精细控制检索质量LlamaIndex更好团队需要快速交付选Dify但要做好被平台限制的心理准备。当然你也可以在Dify里挂外部Agent服务但这就涉及平台能力边界了。1.3 部署路线本地模型还是API模型知识库场景里还有一个绕不开的问题LLM用云上API还是本地部署这直接决定数据隐私、成本和技术复杂度。如果你的文档是公开资料、不涉密直接用OpenAI、Claude或国产大模型API都行。优点是效果稳定、免运维缺点是所有上下文都要发到外部数据安全是个隐患。企业内部合规部门那关很难过。如果你处理的是内部技术文档、客户信息等敏感数据建议走本地部署路线。现在主流选择是Ollama Qwen2.5 / Llama 3.1 / GLM-4等开源模型显存需求大概在7B模型需要8GB显存起14B模型建议16GB以上。我个人的实践是“双轨制”开发调试阶段用API模型速度足够快方便调prompt上线到内网环境再切本地模型配合vLLM做推理加速。这样两者优点都能拿到环境切换只需要改一个base_url非常方便。2. 核心细节解析与实操要点2.1 文档解析与数据清洗决定RAG上限有一个被严重低估的环节——数据清洗。很多人做RAG上来就把PDF往LangChain里一扔文档加载器报个错就换库重试结果召回效果差也不知道问题出在哪。数据层最重要的原则是检索结果的质量受文档解析质量的制约。如果你喂进去的PDF是扫描件那就不能直接用PyPDFLoader得先走OCR流程。如果文档里有复杂的表格结构传统的文本解析会把表格拍扁成一行行无意义的字符检索的时候根本对不上。我把数据清洗拆成四个步骤格式转换PDF/Word/PPT统一转成Markdown便于后续切分和保留结构。工具上推荐MinerU、PaddleOCR处理扫描件docling处理Word类文档。结构标准化统一标题层级去除页眉页脚、页码、重复文本保留列表信息。语义比较完整的切块这一点后面单独说切分是召回效果最直观的影响因素之一。元数据留档记录来源文件名、章节路径、更新日期便于召回后做引用溯源。有人在热词里还提到了“卡帕西知识库”应该是指Karpathy的推文或视频内容整理成知识库的案例。这类个人知识库的文档往往来自多个平台——YouTube字幕、Twitter文本、博客长文格式差异极大更需要在清洗阶段统一样式。2.2 向量化流程与Embedding模型选型热词里有一组“rag向量化流程”这个必须讲透。向量化不是把一段文字塞给模型就能完事的整个流程是文本切块splitting向量化embedding入库indexing检索retrieval**先讲切块。**切分太大会导致信息混杂比如一个chunk里有两三件完全不同的事query只问其中一件那这个chunk的整体向量会“被平均”被迫偏离了用户的真实意图切分太细又会让上下文破碎比如一个表格被切成几十个碎片检索回来缺上下文LLM理解不了。我的切块参数经验值以中文场景为主参数推荐值说明chunk_size500~800字符对中文来说大约300~500字过长会稀释向量chunk_overlap50~150字符保留上下文连接防止信息断档分隔符优先级段落 标题 换行 句号优先按结构切最后才按长度硬切以LangChain为例用RecursiveCharacterTextSplitterfrom langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter RecursiveCharacterTextSplitter( chunk_size600, chunk_overlap100, separators[\n\n, \n, 。, , , ., !, ?, , ;, , ,], length_functionlen, ) chunks text_splitter.split_text(document_text)**再讲Embedding选型。**我实际对比过几款常见的Embedding模型包括text-embedding-3-small、bge-large-zh-v1.5、m3e-base、bge-m3和Cohere的embed-v3。就中文场景而言BGE系列明显能打尤其是bge-m3支持中文、英文、代码等多语言混合检索效果很稳。有一款我最近很喜欢就是Qwen3-Embedding-0.6B/4B/8B系列在多个中文检索任务上表现很突出如果你想本地部署、又不想在效果上妥协太多这个是很值得尝试的选择。关于维度一般中文模型输出1024维或768维就够用了不需要迷信1536维或更高。向量维度直接影响存储占用和检索延迟高维度未必带来更高精度。2.3 Dense Vector Search的真相余弦相似度与Top-K热词里有“rag中dense vector search”翻译过来就是稠密向量检索。它的核心逻辑是把你query用一个Embedding模型转成向量然后在向量数据库里找与这个query向量最相似的doc向量。衡量相似度常用余弦相似度CosSim或欧氏距离。原理上你只需要记住一句话向量是语义坐标检索是坐标近邻。同为“如何提升手机续航”这个问题“手机电量掉得快怎么办”这种query可能比“手机电池健康度如何维护”在向量空间里离得更近。所以找回什么、找回的顺序如何不完全是“词面匹配”而是“语义空间匹配”。实际操作中Dense Search有个问题它对专有名词、缩写、代码变量名非常不敏感。比如你知识库里存了很多“A800”相关的文档用户问“英伟达的卡可以用吗”向量检索很可能找不到“A800”。这种场景就需要混合检索——把关键词检索BM25和向量检索结合起来最后再做Rerank重排。我的做法是先并行召回取并集再用Rerank模型重排选出前5~8个片段。这套流程在很多评测里能把命中率从六成提到九成以上。在LangChain里可以组合实现from langchain.retrievers import BM25Retriever, EnsembleRetriever from langchain.vectorstores import Chroma from langchain.embeddings import HuggingFaceBgeEmbeddings embeddings HuggingFaceBgeEmbeddings(model_nameBAAI/bge-m3) vectorstore Chroma.from_documents(docs, embeddings) bm25_retriever BM25Retriever.from_documents(docs) bm25_retriever.k 10 vector_retriever vectorstore.as_retriever(search_kwargs{k: 10}) ensemble_retriever EnsembleRetriever( retrievers[bm25_retriever, vector_retriever], weights[0.3, 0.7] )这里权重[0.3, 0.7]代表BM25和Dense Search的召回比例实际调参时可以观测不同权重下的命中率变化。我常见的最优区间是BM25占0.2~0.4向量检索占0.6~0.8因为大多数场景还是语义为主、词面为辅。2.4 Rerank决定提问质量的最后一公里排序模型Rerank的作用是把混合召回的结果重新打分排序。它不是另一个Embedding模型而是一个跨编码器Cross-Encoder它会直接拿query和document拼在一起做深度交互所以精确度高很多但计算量也大不适合全库检索只适合对少量候选做重排。推荐两个实用的Rerank模型bge-reranker-v2-m3中文效果好、支持超过100万token的输入长度和Cohere RerankAPI调用非常简单。在LangChain里接入from langchain.retrievers import ContextualCompressionRetriever from langchain.retrievers.document_compressors import CrossEncoderReranker from langchain_community.cross_encoders import HuggingFaceCrossEncoder model HuggingFaceCrossEncoder(model_nameBAAI/bge-reranker-v2-m3) compressor CrossEncoderReranker(modelmodel, top_n5) compression_retriever ContextualCompressionRetriever( base_compressorcompressor, base_retrieverensemble_retriever )这里top_n5表示重排后只保留前5个片段。如果你最终给LLM的上下文窗口不大保留5~8个是常见配置。重排之后检索质量会有肉眼可见提升尤其是在知识库文档多、主题杂的时候。3. 实操过程与核心环节实现3.1 实战案例用LangChain搭建一个“个人知识库”Agent现在进入可以动手的部分。下面这个项目我命名为agentic-kb是我在自己机器上跑过多次的最终版本你可以直接参考。核心流程见代码注释细节我在代码后面逐一解释。项目目录agentic-kb/ ├── data/ # 原始文档 ├── src/ │ ├── ingest.py # 文档加载与向量化 │ ├── agent.py # Agent编排与检索 │ └── config.py # 模型与参数配置 ├── requirements.txt └── main.py第一步向量化入库ingest.pyimport os from langchain_community.document_loaders import DirectoryLoader, TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.embeddings import HuggingFaceBgeEmbeddings from langchain_community.vectorstores import Chroma # 1. 加载目录下所有txt/md文档 loader DirectoryLoader(./data/, glob**/*.txt, loader_clsTextLoader) docs loader.load() # 2. 按语义结构切块 splitter RecursiveCharacterTextSplitter(chunk_size600, chunk_overlap100) chunks splitter.split_documents(docs) # 3. 初始化embedding模型 embeddings HuggingFaceBgeEmbeddings( model_nameBAAI/bge-m3, model_kwargs{device: cuda}, encode_kwargs{normalize_embeddings: True}, ) # 4. 存入Chroma向量库 vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, persist_directory./chroma_db, ) print(f已入库 {len(chunks)} 个文档块)第二步Agent编排agent.py这里我不用复杂的Agent框架而是用LangChain的create_retrieval_chaincreate_history_aware_retriever做一个最容易被理解的版本它有一个“重写query”的中间步骤用户提问时Agent会结合历史会话把模糊query改写为具体的检索query再去知识库里检索。from langchain_community.vectorstores import Chroma from langchain_community.embeddings import HuggingFaceBgeEmbeddings from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.chains import create_history_aware_retriever, create_retrieval_chain from langchain.chains.combine_documents import create_stuff_documents_chain from langchain_openai import ChatOpenAI # 1. 加载已有向量库 embeddings HuggingFaceBgeEmbeddings(model_nameBAAI/bge-m3) vectorstore Chroma(persist_directory./chroma_db, embedding_functionembeddings) retriever vectorstore.as_retriever(search_kwargs{k: 8}) # 2. 用于“重写query”的prompt contextualize_prompt ChatPromptTemplate.from_messages([ (system, 根据聊天历史和最新用户问题提炼出一个不依赖历史就能独立检索的查询语句。), MessagesPlaceholder(chat_history), (human, {input}), ]) # 3. 用于“生成答案”的prompt answer_prompt ChatPromptTemplate.from_messages([ (system, 你是一个知识库问答助手。仅根据以下资料回答问题不要编造资料中没有的内容\n\n{context}), MessagesPlaceholder(chat_history), (human, {input}), ]) # 4. 初始化LLM llm ChatOpenAI(modelgpt-4o-mini, temperature0.1) # 5. 构建Agent/RAG链路 history_aware_retriever create_history_aware_retriever(llm, retriever, contextualize_prompt) question_answer_chain create_stuff_documents_chain(llm, answer_prompt) rag_chain create_retrieval_chain(history_aware_retriever, question_answer_chain)第三步启动入口main.pyfrom src.agent import rag_chain if __name__ __main__: q 我们团队协作指南里关于代码评审的要求有哪些 result rag_chain.invoke({input: q, chat_history: []}) print(答案, result[answer]) print(引用来源) for doc in result[context]: print(-, doc.metadata.get(source, unknown))这套链路里我认为最有价值的是create_history_aware_retriever这个中间层。因为用户在实际问答中不会每次都把上下文说全比如先问“Q2财报里毛利率是多少”再问“和Q1相比呢”第二个问题如果不结合历史检索器根本不知道要搜什么。加了重写步骤后Agent会把“和Q1相比呢”重写成“Q2财报毛利率与Q1的对比”检索质量立刻不一样。3.2 用Dify快速搭一个可视化知识库流水线如果你不想写代码Dify是目前最省事的方案。它在热词里也出现得很多——Dify知识库流水线Dify升级后无法保存知识库等问题。我自己的Dify实践心得如下。Dify创建知识库的流程大致是创建知识库上传文档支持PDF、TXT、Markdown等格式也可以连接Notion、网站同步。分段设置Dify有自动分段和自定义分段两个选项。自动分段按段落和语义切块自定义分段需要自己设置标识符比如\n换行符分割。索引方式Dify支持高质量使用Embedding、经济关键词索引和混合向量全文三种模式。知识库问答场景必选高质量或混合模式。召回测试这是Dify最好用的功能——随时用一句话测试当前知识库的召回结果观察Hit Testing里返回了哪些chunk快速判断索引效果。Dify的Agent能力也很直白在“编排”页面你可以给Agent配置多个工具节点其中“知识检索”就是一个典型的RAG节点。你可以同时配多个知识库Agent根据用户问题自动选择调用哪个库。这其实就是最简版的多知识库Agent路由。但Dify的坑也要提醒我遇到过升级后保存知识库报internal server error网上搜了一圈多数是版本升级后旧的向量索引字段不兼容。解决办法是备份后用Docker重新初始化数据库然后重新做一次索引。说白了平台化工具虽然省事但一旦出问题排查路径很长你得有一定的Docker和PostgreSQL/Weaviate基础。3.3 更进一步Graph RAG与Ontology RAG热词里出现了graph rag和ontology rag包括agentic rag这几个词确实代表了RAG发展的几个方向。Graph RAG的核心思路传统RAG把文档切成互不相干的chunk然后靠向量相似度去匹配但文档中的实体和关系被完全打散了。Graph RAG则是先通过LLM抽取文档中的实体和关系建图检索时沿着图谱路径进行多跳查询。举个实际例子你问“张三的团队里谁负责过和李四合作的项目”传统RAG只能靠关键词“张三”“李四”去召回运气成分很大Graph RAG可以直接从图谱中查询张三-属于-团队X-成员-李四-合作项目-项目Y的路径答案确定性强得多。Ontology RAG则是更“规则化”的Graph RAG。它要求先定义一套知识本体比如“人、项目、公司、职位、合作关系”这些类型以及它们之间允许的关系边然后用LLM按这个本体模板抽取信息。好处是知识库变得可查询、可约束、可推理代价是需要提前做领域建模配置成本高。Agentic RAG把Agent引入检索决策链。不只做一次检索而是允许Agent在回答过程中多次检索、交叉验证、甚至调用不同的外部API。比如用户问“帮我调研一下AI Agent在客服领域的落地案例”一个Agentic RAG系统会自己决定先检索“AI Agent客服案例”看召回结果不足再改写为“智能客服机器人案例”“大模型客服实践”等直到凑够足够的上下文才作答。这三类方向不是互斥的你可以把Graph RAG当作检索层的一种特殊索引把Ontology RAG当作预处理阶段的约束把Agentic RAG当作整体控制流程。我们上一节用LangChain搭的只是最基础的Agentic RAG雏形真正的Agentic RAG还需要工具调用和多轮决策后面有机会再单独写一篇。4. 常见问题与排查技巧实录4.1 为什么知识库回答总是“答非所问”这是我被问得最多的一个问题。遇到答非所问先别急着调prompt按照下面顺序排查第一步召回测评。把用户问题拿到召回测试里跑一遍看召回的前5个chunk跟问题是不是真的相关。如果chunk就不相关问题一定出在索引侧调prompt是白费力。第二步检查切块粒度。如果召回的相关chunk里混着大量无关内容大概率是chunk_size太大信息太杂。把chunk_size从800降到400试试。第三步检查Embedding模型是否匹配。中文知识库却用了一个纯英文Embedding模型召回效果必然差。第四步检查检索模式。如果你用的是纯向量检索试试混合检索重排。第五步才看prompt。确认prompt里有没有明确“只根据材料回答”有没有禁止“编造”。4.2 RAG绩效评估怎么做指标与流程热词里有“rag知识库指标有哪些”和“rag测评怎么做”。我先直接说结论RAG评测不能只看最终答案的“像不像”要拆环节测。我把评测分成三个层面检索层核心指标是RecallK正确答案是否出现在召回的前K个片段中MRR第一个正确答案的排序位置NDCGK考虑了排序位置的加权指标PrecisionK前K个结果里有多少是相关的。生成层核心指标是忠实性Faithfulness生成的答案是否忠于上下文不编造答案相关性Answer Relevancy答案是否针对问题上下文相关性Context Relevancy被召回的上下文是否足够回答问题。端到端评估最常用的是用RAGAS框架跑完整评测。RAGAS支持你把这个metrics一次性算完只需要准备question、answer、contexts、ground_truth四个字段from datasets import Dataset from ragas import evaluate from ragas.metrics import faithfulness, answer_relevancy, context_precision, context_recall eval_dataset Dataset.from_dict({ question: [什么是RAG], answer: [RAG是检索增强生成...], contexts: [[检索增强生成是一种结合检索和生成的技术...]], ground_truth: [RAG是检索增强生成Retrieval Augmented Generation...], }) result evaluate(eval_dataset, metrics[faithfulness, answer_relevancy, context_precision, context_recall]) print(result)评测数据集建议准备50~100条真实用户问题覆盖常见的、边界性的、模糊的提问。没有评测优化就是瞎调有了这组指标你才能判断改动是变好了还是变差了。4.3 Dify类平台常见报错清单这里把平台化工具常见的坑一次性列个表现象原因排查方法Dify升级后无法保存知识库版本升级导致向量库索引冲突备份数据后用Docker重新初始化重建索引修改知识库报Internal Server ErrorAPI Key过期或数据库连接异常看Dify容器日志确认Postgres和向量库状态文档上传后索引为0文档格式不支持或分段失败换用PDF/TXT或手动设置分段标识符检索结果总是旧的知识库更新后未触发重新索引在知识库设置里手动执行“重新索引”用了一段时间后回答质量骤降向量库数据膨胀产生了大量脏数据定期清理已删除文档对应的向量重建索引4.4 几个值得一试的周边工具最后补充几个跟知识库强相关的工具。热词里面出现的AnythingLLM很适合做个人知识库桌面应用它支持本地模型和大模型API混合使用直接把文档拖进去就能问答。Obsidian知识库搭建则是笔记党的最爱——用Obsidian管理Markdown笔记再搭配Smart Connections或Copilot for Obsidian插件就能实现基于笔记的本地语义检索。如果你有“代码Agent”需求比如Claude Code Agent如何调用已有知识库我的建议是不要搞太复杂的RAG直接把项目文档转成Markdown放到项目根目录的CLAUDE.md文件里让Agent在对话开始时自动读取。Agent对长上下文的利用方式比RAG更适合简单粗暴但效果非常好。5. 个人实操心得与扩展建议这套东西我前前后后折腾了几个月几个时间段里反复调参的有效结论收个尾。第一检索层优先级永远高于生成层。很多人一上来就研究prompt技巧其实RAG效果差大多数是索引和检索没做好。把召回测试跑透Top-5精确率提到80%以上生成层的压力就小很多。第二不要迷信单一Embedding模型。没有最佳模型只有最适配数据集的模型。建议你手头准备两个模型一个通用型的如bge-m3一个领域微调过的如果你有预算和时间在真实业务数据上跑评测选效果好的上线。第三给知识库留“成长空间”。从一开始就设计好元数据方案——每个chunk记录来源、更新时间、目录层级。这样后续要做过滤、做权限、做增量更新都不用推倒重来。第四Agent和RAG的结合核心在检索的“主动性”。现在业界更前沿的做法是Self-RAG和CRAG让模型自己判断该不该检索、检索结果可不可信、要不要启动二次检索。这套动态检索逻辑建议你以后往这个方向深挖它能解决大量真实场景里的“僵化问答”问题。最后分享一个落地技巧在做增量更新时可以按文档摘要建立“内容指纹”缓存同一份文件内容没变就不重新向量化文档变了才重新切块入库。这样可以极大降低向量库膨胀和维护成本也是我后来在几十万级文档场景下保住检索性能的关键。希望这套从原理到实践的拆解能帮你在“AI Agent RAG 打造专属知识库”这件事上少走些弯路。踩过坑的、有更好方案的欢迎评论区交流。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价