做 AI Agent 相关的开发最容易出现的一种现象是教程收藏了几十个概念名词背得滚瓜烂熟但一打开 IDE 就不知道从哪里写起。RAG、Agent、LangChain、LangGraph、Embedding、向量库、工具调用……每个字都认识连起来却不知道它们之间到底是什么关系。这篇文章想解决的就是这个断层。我会从零开始把 RAG检索增强生成和智能代理Agent这两条主流技术路线拆开讲清楚然后用 LangChain 和 LangGraph 各自写一个最小可运行示例。你不需要有很深的机器学习背景只要会 Python能装依赖就能跟着跑通。读完这篇文章你应该能回答这几个问题RAG 的完整链路是什么Agent 和普通 API 调用有什么区别LangGraph 和 LangChain 到底是什么关系以及最关键的一条——在真实项目里你究竟该用 RAG、Agent 还是 Agentic RAG。先说一个我的判断LangChain 的 API 变化很快但它的核心抽象——把 LLM、提示词、文档、检索、外部工具组合成一条可编排的链路——并没有过时。真正值钱的不是记住某个类名而是理解链路本身。1. 这篇文章真正要解决的问题过去一年里每次有同学问我AI Agent 该怎么入门我的回答都不是甩资料链接而是反问一句你是想做一个能回答私有知识问题的机器人还是想让 AI 自主调用工具完成多步任务这两个目标对应的是两条不同的技术路线。如果要做知识问答比如帮我总结这份 30 页合同里的风险条款那么核心是 RAG把文档拆碎、向量化、存进向量库用户提问时先检索相关片段再交给大模型生成回答。这条路线解决的是大模型不知道你的私有数据和容易编造事实这两个问题。如果要做任务执行比如把这家店铺过去 30 天的订单按品类汇总生成一张图表发给我那么核心是 Agent大模型先理解意图再把任务拆成多个步骤每一步都可能调用一个外部工具然后把工具结果带回来继续推理。这条路线解决的是大模型只能聊天、不能行动的边界问题。而 LangChain 在整个故事里的位置是一个中间层框架。它把大模型、向量库、文档加载器、提示词模板、工具调用这些散落的零件统一成一套 Python 对象和编排方式。这样你就不用给每家 API 单独写胶水代码。这篇文章会先走通 RAG 的最小链路再基于 RAG 扩展出 Agent 工具调用最后用 LangGraph 把 Agent 的流程改造成显式状态图。这样安排是有意的RAG 是你最容易在真实业务里落地的第一站Agent 是第二步LangGraph 则是让复杂 Agent 可维护的工程化选择。2. RAG、Agent、LangChain 与 LangGraph 的核心概念2.1 RAG给大模型配一个外接知识库RAG 的全称是 Retrieval-Augmented Generation检索增强生成。它不是什么高深算法而是一种工程架构思路。传统的 LLM 问答是你把问题直接丢给模型模型靠训练时记住的知识来回答。问题有两个一是知识有截止日期二是模型对细粒度、私有化的内容几乎一无所知。你问它我们公司内部系统的登录流程是什么它只能编一个看起来合理的答案给你。RAG 的解决方式是在模型回答之前先从一个外部知识库中检索出与问题最相关的若干片段把这些片段和原始问题一起塞进提示词让模型参考着资料回答。它的核心链路可以拆成五个环节文档加载把 PDF、Word、Markdown、HTML 等原始文件读成纯文本。文本分块把长文本切成长度合适的片段。切得太长检索不精准还容易超过模型上下文限制切得太短语义不完整模型没法理解。向量化用 Embedding 模型把每个文本片段变成一个高维向量向量空间里语义相近的文本距离更近。向量检索用户提问时把问题也向量化然后在向量库里搜索最相似的 K 个片段。融合生成把检索到的片段作为上下文拼进提示词交给大模型生成答案。你关心的RAG 知识库指标本质上就是逐环节评估检索环节看召回率和准确率生成环节看忠实度和答案相关性整体效果可以用端到端的问答评测集来衡量。这部分我在第 7 节展开。2.2 Agent让大模型从回答问题变成完成动作Agent 和 RAG 解决的完全不是同一个问题。RAG 的最终产物是一段文字答案Agent 的最终产物是一个结果这个结果可能是调用了某个 API、写入了数据库、发送了一封邮件也可能只是经过多步推理后确定不需要调用任何工具直接回答。实现 Agent 的主流方式是利用大模型的工具调用能力Function Calling / Tool Calling。你可以定义一组工具每个工具有名称、描述、参数结构。模型收到用户请求后会先判断这个问题需不需要调用工具如果需要就返回一个结构化的调用请求工具名参数。你的程序负责真正执行这个工具把执行结果返回给模型模型继续决定下一步做什么。所以 Agent 的本质是一个循环用户输入 - 模型推理 - 需要工具- 执行工具 - 把结果喂回模型 - 再次推理 - …… - 给出最终回复注意这个循环中的每一步都是模型自主决策的。这意味着你的程序可能走了一个没法预判的路径。这也是 Agent 比普通程序更难调试的原因——你需要有日志、有追溯能力最好还有超时和中断机制。2.3 LangChain 与 LangGraph框架和编排器LangChain 是一个开发框架它提供了一套统一的接口来操作大模型、提示词、文档、向量库和工具。它的价值在于标准化你换一个向量库、换一个大模型供应商不需要重写整条链路。LangGraph 是 LangChain 生态里的一个图编排库它解决的问题是 Agent 流程的可控性。老的 LangChain Agent 用的是AgentExecutor内部是一个黑盒循环它会一直循环调用工具直到模型认为任务完成或者达到最大迭代次数。这个抽象很方便但问题是不透明——你不知道它现在执行到哪一步了想在中间插入一个人工审核、想加一个步骤超时自动终止都比较困难。LangGraph 把 Agent 的流程建模成一张有向图。节点是做什么边是下一步去哪里状态是节点之间传递的数据。你可以显式写出每个分支也可以在任何两个节点之间插入新的处理逻辑。所以LangGraph 和 LangChain 的区别严格来说不是互相替代而是 LangGraph 继承了 LangChain 的消息、模型、工具抽象但在流程控制层面走得更工程化。我用一个类比解释LangChain 是标准零件库LangGraph 是图纸AgentExecutor 是图纸里的一种固定流水线。你的业务场景越复杂越需要自己画图纸而不是照搬固定流水线。3. 环境准备与前置条件在开始写代码之前先把环境准备好。本文的示例基于 Python版本请以实际项目为准但建议使用 Python 3.10 或更高版本避免依赖冲突。需要说明的是LangChain 以及相关组件版本更新非常快接口变动也频繁。本文给出的代码是当前常见写法的演示如果你的环境版本不同优先以官方文档和实际报错为准。更重要的是理解链路而不是死记 API。3.1 创建虚拟环境推荐用 venv 或 conda 创建独立虚拟环境避免污染系统 Python。python -m venv .venv source .venv/bin/activate # Windows 下使用 .venv\Scripts\activate3.2 安装依赖本文会用到以下几个包langchain核心框架。langchain-openaiOpenAI 兼容接口的封装。langchain-community社区贡献的组件比如文档加载器。langchain-text-splitters文本分块器。langchain-core核心抽象比如 Prompt、OutputParser。chromadb本地向量数据库。langgraphLangChain 官方图编排库。安装命令如下pip install langchain langchain-openai langchain-community langchain-text-splitters langchain-core chromadb langgraph如果你使用的是国产大模型或其他提供 OpenAI 兼容接口的服务也可以只调整模型服务地址和 API Key整体代码结构不变。3.3 配置模型 API本文示例使用 OpenAI 兼容接口通过环境变量读取密钥不要把密钥写死在代码里。export OPENAI_API_KEY你的API密钥 export OPENAI_BASE_URLhttps://api.openai.com/v1 # 如果使用兼容服务改成对应地址如果你希望完全本地运行也可以使用 Ollama 加载本地模型然后通过langchain_ollama的ChatOllama和OllamaEmbeddings接入。思路完全相同只差模型初始化这一段。4. 核心流程拆解RAG 五步链路在写完整代码之前我先把 RAG 每一步的关键决策讲清楚因为大部分运行效果不好问题都出在这些细节上而不是代码本身。4.1 文档加载干净文本是第一优先级文档加载看起来很基础其实是整个 RAG 里最容易被低估的环节。PDF 扫描件、有复杂排版的 Word、带大量广告的网页加载出来往往是一堆乱码或无意义字符。你要做的第一件事是尽量拿到干净的纯文本而不是把注意力全放在后面的向量检索上。常见工具TextLoader读取 txt 和 Markdown。PyPDFLoader或PyMuPDFLoader读取 PDF。BSHTMLLoader读取 HTML 网页。自研解析服务针对复杂 PDF 或扫描件可能需要 OCR 能力。判断加载是否成功不要看文件数量要看加载后的文本内容。抽出前 500 个字符扫一眼确认结构完整、编码正常再继续。4.2 文本分块大小和重叠度要一起调分块策略是 RAG 检索质量最敏感的杠杆之一。理论上chunk 越短检索越精准但单块携带的上下文越少chunk 越长单块上下文越完整但可能混入无关信息导致召回结果跑偏。RecursiveCharacterTextSplitter是多数场景下的默认选择。它的逻辑是按照一组分隔符比如换行符、句号、空格递归切分优先在语义边界处切断尽量不让一句话被拦腰截断。通常建议先设置chunk_size500, chunk_overlap50作为起点然后根据实际问答效果调整。chunk 大小没有绝对标准和你文档的语言、格式、上下文密度都有关系。中文文档建议多关注分隔符配置默认分隔符对中文的语义边界识别效果一般。4.3 向量化与向量库模型和距离度量要匹配Embedding 模型负责把文本变成向量。选模型时要注意两个点一是模型对中文的支持程度二是向量维度是否满足后续应用的兼容要求。向量库方面Chroma 是本地开发的轻量选择不需要额外启动服务能快速验证链路。生产环境通常考虑 Milvus、Weaviate、Elasticsearch 等更成熟的方案但原理一致。距离度量通常用余弦相似度。需要注意不同向量库的默认相似度度量可能不同切换向量库时要先确认你的查询和文档向量是否在使用同一种度量方式否则会出现相似度很高但语义完全不相关的异常现象。4.4 检索召回和重排是两件事基础检索是先向量相似度取 TopK。TopK 太小可能漏掉关键文本太大噪声信息会把模型带偏。一般先设 4 到 6。检索精准度不够时不要急着调大 TopK先做这两件事查询改写用户的问题往往很口语化和文档里的书面表达不完全匹配。可以先用一个小模型把问题改写成更适合检索的关键词组合再去做向量检索。召回后重排ReRank先召回 20 条再用一个专门的重排模型Cross-Encoder对召回结果重新打分把真正相关的排到前面。这是目前提升 RAG 效果最立竿见影的手段之一。4.5 融合生成提示词要约束引用最后一步是把检索到的文本和用户问题一起交给大模型。这里最容易出现的问题是模型仍然依据自己的内部知识自由发挥忽略了你给的资料。所以提示词里一定要写清楚仅根据提供的上下文回答不要使用内部知识如果上下文中没有答案直接回答不知道。此外强烈建议要求模型在回答中标注引用了哪段上下文。这样不仅方便用户核查也方便你定位为什么答错了——是检索没召回相关内容还是模型没正确引用。5. 完整示例代码实现一个最小可用的 RAG 问答链路现在来看代码。这是一个可以直接运行的最小 RAG 原型文件结构如下rag_demo/ ├── knowledge.txt # 你的知识文档 ├── rag_chain.py # RAG 主程序 └── .env # API 密钥配置不要提交到 Git先准备一份测试文档knowledge.txt内容随意但要尽量包含一些模型内部知识不太可能知道的信息这样才能看出 RAG 的效果。示例内容可以是你自己项目的说明文档、内部流程规范等。接下来是rag_chain.py# 文件路径rag_demo/rag_chain.py from langchain_community.document_loaders import TextLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings, ChatOpenAI from langchain_community.vectorstores import Chroma from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough # 1. 加载文档 loader TextLoader(knowledge.txt, encodingutf-8) documents loader.load() # 2. 文本分块 text_splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap50, separators[\n\n, \n, 。, , , , ], ) chunks text_splitter.split_documents(documents) print(f文档已切分为 {len(chunks)} 个片段) # 3. 向量化并写入向量库 embedding_model OpenAIEmbeddings(modeltext-embedding-3-small) vectorstore Chroma.from_documents( documentschunks, embeddingembedding_model, collection_namedemo_collection, persist_directory./chroma_db, ) # 4. 构建检索器 retriever vectorstore.as_retriever(search_kwargs{k: 4}) # 5. 构建提示词 prompt ChatPromptTemplate.from_messages([ (system, 你是一个严谨的问答助手。请仅根据以下上下文回答用户问题 不要使用你的内部知识。如果上下文中没有足够信息请直接回答 “根据提供的资料无法回答”。\n\n上下文\n{context}), (human, 问题{question}), ]) # 6. 构建 LLM llm ChatOpenAI(modelgpt-4o-mini, temperature0) # 7. 组装 RAG 链路 def format_docs(docs): return \n\n.join(doc.page_content for doc in docs) rag_chain ( {context: retriever | format_docs, question: RunnablePassthrough()} | prompt | llm | StrOutputParser() ) # 8. 执行问答 if __name__ __main__: question 根据提供的资料该项目的部署步骤是什么 result rag_chain.invoke(question) print(问题, question) print(答案, result)代码说明OpenAIEmbeddings(modeltext-embedding-3-small)使用的是 OpenAI 的向量模型如果你接入的是兼容服务只需调整模型名和 API 地址。Retriever默认按向量相似度返回 TopK4 的文本片段。format_docs负责把这些片段拼成提示词里的上下文。使用 LCELLangChain Expression Language组合链路可读性比传统 Chain 好也便于后续插入日志和中间步骤。整个链路是一个 RunnableLCEL 会自动把上一步的输出传给下一步。运行方式python rag_chain.py如果一切正常你会先看到切分出的片段数量然后看到基于文档内容生成的答案。把knowledge.txt换成你自己的内部文档这个最小问答机器人就基本可用了。6. 从 RAG 到 Agent构建会调用工具的智能代理RAG 跑通之后下一步就是 Agent。请你先想一个场景用户问今天是几号你希望模型能调用系统时间工具而不是猜测一个日期用户问12 的 17 次方等于多少你希望模型调用计算器而不是硬答。这时候就需要给模型挂上工具。下面是一个使用 LangChain 工具调用接口实现的最小 Agent。# 文件路径agent_demo/basic_agent.py from datetime import datetime from langchain_openai import ChatOpenAI from langchain_core.tools import tool from langchain_core.prompts import ChatPromptTemplate from langchain.agents import create_tool_calling_agent, AgentExecutor # 工具 1获取当前时间 tool def get_current_time() - str: 获取当前系统的日期和时间。当你被问到日期、时间、今天是几号时使用这个工具。 return datetime.now().strftime(%Y-%m-%d %H:%M:%S) # 工具 2计算数学表达式 tool def calculate(expression: str) - str: 计算数学表达式的值。输入应该是一个数学表达式例如 12 ** 3。 注意这个工具仅用于演示生产环境不要直接使用 eval。 return str(eval(expression, {__builtins__: {}}, {})) # 初始化模型 llm ChatOpenAI(modelgpt-4o-mini, temperature0) # 构造 Agent 提示词 prompt ChatPromptTemplate.from_messages([ (system, 你是一个智能助手需要根据用户问题判断是否调用工具。 如果问题需要外部信息才能回答你必须先调用工具。), (human, {input}), (placeholder, {agent_scratchpad}), ]) # 创建 Agent tools [get_current_time, calculate] agent create_tool_calling_agent(llm, tools, prompt) executor AgentExecutor(agentagent, toolstools, verboseTrue) if __name__ __main__: result executor.invoke({input: 今天是几号请使用工具确认后回答}) print(最终回答, result[output])运行这段代码你会看到 Agent 的思考过程它先调用get_current_time拿到时间字符串再把它组织成最终回答。verboseTrue会把这一过程打印出来这是学习 Agent 调试最重要的入口。这里有个容易踩的坑工具描述写得不好模型就不调用工具。get_current_time的 docstring 里明确写了当你被问到日期、时间、今天是几号时使用这个工具这样模型才能准确匹配意图。calculate示例中使用了eval仅用于演示。真实项目中如果要执行用户表达式一定要使用安全沙箱或专门的计算库否则会有严重的安全风险。7. 使用 LangGraph 编排 Agent状态图让流程可控理解了基础 Agent 之后你应该问一个问题如果我的 Agent 有 10 个工具有分支逻辑有中途需要人来确认的步骤AgentExecutor这种黑盒循环还够用吗答案是不太够。这时候需要用 LangGraph 把流程显式画出来。我用一个最小示例说明 LangGraph 的核心用法。这个示例没有复杂的循环只演示节点 状态 边的基本模型。真正的 Agent 通常是一个带循环的图模型节点 - 工具节点 - 如果还需要工具回到模型节点否则结束。# 文件路径agent_demo/langgraph_basic.py from typing import TypedDict from langchain_openai import ChatOpenAI from langgraph.graph import StateGraph, START, END llm ChatOpenAI(modelgpt-4o-mini, temperature0) # 定义节点之间传递的 State class State(TypedDict): question: str answer: str # 定义一个生成答案的节点 def generate_answer(state: State): response llm.invoke(f请用一句话回答{state[question]}) return {answer: response.content} # 建立状态图 graph StateGraph(State) # 添加节点 graph.add_node(generate, generate_answer) # 添加边 graph.add_edge(START, generate) graph.add_edge(generate, END) # 编译图 app graph.compile() # 执行 if __name__ __main__: result app.invoke({question: LangGraph 是什么}) print(答案, result[answer])LangGraph 的编程心智模型和 LangChain 完全不同。LangChain 的 Chain 是线性的管道LangGraph 是图——你需要在脑子里面先画清楚状态State每个节点共享的数据结构。节点Node一个普通 Python 函数输入整个 State返回要更新的部分。边Edge从哪个节点到哪个节点。条件边Conditional Edge根据当前状态决定下一步去哪个节点。这个例子里还没有循环但你可以明显感觉到如果想加一个先检索、再生成、生成质量不合格就重新生成的逻辑LangGraph 的表达会比AgentExecutor清晰得多。真实工程项目中我建议的路线是先用AgentExecutor快速验证工具调用这件事能不能跑通等工具数量变多、流程分支变复杂、需要插入人工审核或超时控制时再迁移到 LangGraph。8. 运行结果与效果验证不要只看答对了很多新手验证 RAG 效果就是问一两个问题看到答案通顺就认为做好了。这是最大的误区。一个可维护的 RAG 知识库需要从多个维度分别评估。你不能用一条问题代表所有场景也不能因为答案文字通顺就判断检索没问题。8.1 检索质量指标RecallK前 K 条检索结果里有多少条是真正相关的。PrecisionK前 K 条结果里有多少比例是相关的。MRRMean Reciprocal Rank第一个正确答案排在第几反应最相关的那条有没有排在最前面。NDCG考虑位置因素的排序质量指标越靠前的相关结果权重越高。这些指标的作用是把检索不好从生成不好中剥离出来。如果 Recall 低说明你的分块或向量检索有问题优化生成提示词没用如果 Recall 高但最终答案仍然不对问题大概率出在生成环节或提示词约束不够。8.2 生成质量指标Faithfulness / 忠实度答案内容是否严格基于给定的上下文有没有编造。Answer Relevance / 答案相关性答案是否真正回答了用户的问题。Context Relevance / 上下文相关性给模型的上下文片段是否与问题相关。当你发现答案看起来通顺但没回答用户的问题时优先怀疑上下文相关性。当你发现答案回答得很流畅但细节是编的时优先怀疑忠实度。8.3 手工验证建议在你的开发初期强烈建议准备一组固定的测试问题称为评测集。每个问题标注标准答案或应有信息来自文档哪一段。每次改动分块策略、Embedding 模型、检索 TopK、提示词之后用同一组问题跑一遍对比答对数量。没有评测集的 RAG 优化基本等于盲人摸象。9. 常见问题与排查方法我用表格整理一下 LangChain RAG Agent 开发中最常遇到的问题和排查思路。问题现象可能原因排查方式解决方案启动时报 OpenAI API Key 错误环境变量未正确加载或密钥无效打印os.environ.get(OPENAI_API_KEY)确认在启动脚本或.env中正确配置环境变量向量库写入时报维度不匹配Embedding 模型切换后向量维度不一致检查当前 Embedding 模型输出维度检查向量库 Collection 创建时的维度清空旧 Collection重新写入向量分块后文档内容丢失或乱码文档加载阶段编码处理错误打印documents的前 500 个字符针对文件格式换用专用 Loader检查编码参数检索结果与问题完全不相关分块策略不合理、TopK 太小、Embedding 模型对中文支持弱打印检索器返回的片段人工判断片段与问题是否相关调整 chunk_size/chunk_overlap增大或减小 TopK换 Embedding 模型引入重排模型不使用工具而是直接回答工具描述不清晰或模型不支持工具调用查看 Agent verbose 输出确认模型是否收到了工具列表重写工具描述加入触发条件和示例换用支持工具调用的模型回答内容仍是编造的不引用上下文提示词约束不足或检索片段质量差在提示词中禁用内部知识要求逐条引用设置仅根据上下文回答必要时用更高温度改为 0Agent 循环次数过多迟迟不结束工具返回结果格式不明确模型无法判断已完成增大max_iterations前先查看每次工具返回内容设计清晰、结构化的工具返回格式增加终止条件LangGraph 运行报状态类型错误节点函数返回的 key 不在 State 定义中检查节点返回字典和TypedDict字段是否一致保持 State 字段和节点返回值严格一致10. 最佳实践与工程建议10.1 RAG 场景内容质量先于技术选型如果你的知识文档本身是混乱的、过时的、互相矛盾的换什么向量库、调什么分块参数都没用。建议在建立知识库之前先做一轮文档清理、版本确认、格式统一。RAG 的上限由你的知识库质量决定而不是由技术栈决定。10.2 分块策略用元数据给检索留后路分块时不要只保存文本内容还要把来源文件名、章节标题、页码等元数据一并存入向量库。这个习惯非常有用当检索结果不对劲时你可以快速定位是哪个文档、哪个章节被召回了从而判断是分块问题还是文档本身的问题。10.3 安全与权限Agent 的工具要最小授权Agent 工具调用比普通 API 更危险的地方在于模型会自主决定调用哪个工具以及传什么参数。如果工具内部没有权限校验一个帮我删掉项目里的缓存文件的请求就可能真的执行了删除操作。建议遵循几个原则每个工具使用最小权限只暴露必要的操作。对高风险操作删除、写入、支付、发送消息强制加入人工确认。工具日志要完整记录谁在什么时候调用了什么工具、参数是什么、结果是什么。API Key 只放在服务端环境变量中绝不打包进前端或客户端。10.4 版本锁定LangChain 系列依赖要固定版本LangChain、LangGraph、langchain-openai 这些包更新速度快接口变动频繁。今天能跑的代码过三个月就可能因为某个包的 breaking change 跑不起来。建议在项目内使用requirements.txt或pyproject.toml锁定版本号并且在升级任何依赖后先跑一遍你的评测集。不要盲目追求最新版本。10.5 评测与可观测性从 Demo 到生产的两个台阶Demo 阶段的 RAG 只需要能跑通生产阶段你需要三样东西评测集一组成熟的问题和期望答案每次改动后自动跑一遍。可观测性记录每次查询的检索片段、Token 消耗、响应延迟、模型输出。告警当检索召回率下降到阈值以下或模型连续输出根据资料无法回答时需要收到通知。很多项目死在demo 效果不错但没人知道线上到底怎么样可观测性就是解决办法。10.6 性能优化检索和生成分开扩缩容真实业务里Embedding 模型的向量化常常是性能瓶颈尤其是大批量文档入库。检索服务和生成服务LLM 调用的负载特征完全不同一个偏读密集一个偏计算密集。如果条件允许把文档入库、向量检索、LLM 生成拆成独立服务单独扩缩容性价比更高。11. 总结与后续学习方向到这里你已经走通了三条关键路径RAG 五步链路、Agent 工具调用、LangGraph 状态图编排。这三条路径是当前 AI 应用开发最核心的技能组合。接下来你可以朝这几个方向深入如果你想精进 RAG去研究查询改写、混合检索向量检索 关键词检索、重排模型、多路召回。这能解决检索不精准这一核心痛点。如果你想做复杂的 Agent 应用去研究 LangGraph 的条件边、记忆机制、多 Agent 协作、人工介入审核节点。如果你关心知识库效果可衡量去搭建一个评测集上线一遍检索指标和生成指标用数据驱动优化。建议你先别急着把技术栈全部铺开。把本文的 RAG 最小示例换成你自己的文档运行三天记录它回答不了的 10 个问题然后针对这 10 个问题倒推是分块、检索还是提示词的问题。这个过程比读 30 篇教程都管用。等你把最小链路跑通之后再回头看那些收藏夹里的资料会发现真正拦住你的不是知识量而是缺少一条从文档到答案的完整链路。先跑通它再谈优化。