1. 先搞清楚 RAG、LangChain、GraphRAG 和微调到底解决什么问题如果你正在接触大模型应用开发尤其是想把手头的文档、数据用起来那么 RAG、LangChain、GraphRAG 和微调这几个词肯定绕不开。但很多人一开始容易晕感觉概念很多不知道从哪下手。其实这几个技术解决的是不同层面的问题选错了方向后面会越做越别扭。简单来说你可以这么理解RAG是核心思路它解决的是“如何让大模型回答它没学过的问题”。比如你想让模型回答你公司内部的规章制度或者分析一份它没见过的财报。核心方法是从你的资料库里找到相关片段和问题一起喂给模型让它基于这些“参考资料”生成答案。这比直接问模型要靠谱得多。LangChain是一个工具箱它解决的是“如何把 RAG 这个思路工程化实现”。自己从头写代码处理文档加载、文本分割、向量化、检索、组装提示词、调用模型、管理对话历史……非常繁琐。LangChain 把这些环节都封装成了标准化的“链”和“组件”让你能像搭积木一样快速构建一个可用的 RAG 应用。GraphRAG是 RAG 的一个高级变种它解决的是“传统 RAG 只能找零散片段无法理解文档间复杂关系”的问题。传统 RAG 检索到的可能只是几个孤立的句子而 GraphRAG 会先把你所有的文档构建成一个知识图谱检索时不仅能找到实体还能找到实体之间的关系。这特别适合处理需要深度推理、连接多源信息的复杂问题。微调是另一条路它解决的是“如何让大模型本身变得更懂某个特定领域或任务”。比如你想让模型生成的代码完全符合你们公司的编码规范或者让它用特定的风格写邮件。微调是通过用你准备好的高质量数据去调整模型内部的参数让它“学习”你的需求。这效果好但成本高、数据要求也高。所以一个典型的误区是一上来就纠结用哪个框架或者要不要微调。更务实的路径是先想清楚你的场景到底需要什么。如果只是想让模型基于你的文档回答问题RAGLangChain 是性价比最高的起点。如果你的数据里充满了人物、事件、地点之间的复杂关联GraphRAG 值得研究。而微调通常是当你对模型输出的风格、格式有非常稳定且统一的要求时才需要考虑的“重型武器”。2. 环境准备别在配置上浪费第一天在开始写任何代码之前把环境理顺能避免 80% 的“跑不起来”问题。对于 RAG 和 LangChain 这类项目环境的核心是 Python 版本、包管理和 API 密钥。2.1 Python 与虚拟环境我强烈建议使用 Python 3.10 或 3.11。3.12 虽然新但有些库的兼容性可能还没完全跟上容易踩坑。不要用系统自带的 Python用conda或venv创建一个独立的虚拟环境。# 使用 conda如果已安装 conda create -n rag-demo python3.11 conda activate rag-demo # 或者使用 venv python -m venv rag-demo # Windows rag-demo\Scripts\activate # macOS/Linux source rag-demo/bin/activate创建好环境后第一件事是升级pip和setuptools这能减少一些奇怪的安装错误。pip install --upgrade pip setuptools wheel2.2 核心依赖安装LangChain 是一个庞大的生态全装没必要。根据你的目标选择性安装核心包。对于入门 RAG我建议先装下面这些# LangChain 核心库 pip install langchain langchain-core # 用于连接 OpenAI、通义千问等大模型 pip install langchain-openai langchain-community # 文本嵌入用于将文本转成向量和向量数据库客户端 pip install langchain-embeddings-openai # 如果用 OpenAI 的嵌入模型 # 或者使用开源嵌入模型例如 BGE # pip install langchain-embeddings-huggingface # 一个轻量级、本地的向量数据库适合学习和演示 pip install chromadb # 用于加载各种格式的文档PDF, Word, TXT, HTML等 pip install pypdf python-docx beautifulsoup4 # 环境变量管理用于安全存储 API Key pip install python-dotenv这里注意langchain-community是一个“大杂烩”包包含很多第三方集成初期可以装上避免找不到某些组件。生产环境可以考虑按需安装更具体的子包。2.3 API 密钥与网络配置这是新手最容易卡住的地方。无论你用 OpenAI、通义千问还是智谱 AI都需要一个 API Key。获取 Key去对应平台的官网注册账号通常能在个人设置或控制台找到创建 API Key 的地方。安全存储永远不要将 API Key 硬编码在代码里。在项目根目录创建一个.env文件OPENAI_API_KEYsk-your-openai-key-here # 或者 DASHSCOPE_API_KEYyour-dashscope-key-here # 阿里云通义千问代码中加载from dotenv import load_dotenv load_dotenv() # 加载 .env 文件中的环境变量 # 现在 os.getenv(‘OPENAI_API_KEY’) 就能获取到值了网络问题如果你在国内直接调用api.openai.com可能会超时。一些平台提供了通过云服务商中转的渠道或者你可以使用国内模型平台的 API如通义千问、智谱 GLM、百度文心等它们的速度和稳定性通常更好。LangChain 对这些平台都有很好的支持只需更换一下 API Base URL 和模型名称即可。环境配好之后不要急着写复杂应用先用两三行代码测试一下到模型的连接是否通畅。from langchain_openai import ChatOpenAI from dotenv import load_dotenv import os load_dotenv() llm ChatOpenAI(model“gpt-3.5-turbo”) # 或者使用 “qwen-max” 等国内模型 response llm.invoke(“Hello, world!”) print(response.content)如果这一步能成功打印出模型的回复恭喜你最基础的通道已经打通了。如果报错优先检查1) 虚拟环境是否激活2).env文件是否在正确位置且 Key 有效3) 网络是否通畅。3. 构建你的第一个 RAG 流水线从单文档问答开始理解了概念配好了环境我们现在用 LangChain 把 RAG 的核心流程串起来。我建议从处理一个简单的 TXT 或 PDF 文件开始目标是能针对文件内容进行问答。3.1 文档加载与分割别让坏数据进去RAG 的效果一半取决于喂进去的文档质量。LangChain提供了大量的DocumentLoader。from langchain_community.document_loaders import TextLoader, PyPDFLoader # 加载一个文本文件 loader TextLoader(“./data/my_document.txt”, encoding“utf-8”) documents loader.load() # 或者加载一个 PDF 文件 # loader PyPDFLoader(“./data/report.pdf”) # documents loader.load()加载出来的documents是一个列表每个元素是一个Document对象有page_content文本内容和metadata元数据如来源、页码属性。直接整篇文档塞给检索器是不行的需要分割成较小的“块”。这里的关键是分割策略。RecursiveCharacterTextSplitter是最常用的它尝试按字符如换行、句号、空格递归地分割尽量保持语义完整。参数chunk_size和chunk_overlap至关重要。chunk_size决定每个块的大小按字符数或 Token 数chunk_overlap是块之间的重叠部分防止一个句子被腰斩。from langchain_text_splitters import RecursiveCharacterTextSplitter text_splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个块大约500字符 chunk_overlap50, # 块之间重叠50字符 separators[“\n\n”, “\n”, “。”, “”, “”, “,”, “ “, “”] # 分割符优先级 ) all_splits text_splitter.split_documents(documents) print(f“将文档切分成了 {len(all_splits)} 个块”)经验之谈不要一上来就用默认参数。先看看你的文档特点。如果是技术文档chunk_size可以小点300-500如果是论文或报告可以大点800-1000。chunk_overlap一般设为chunk_size的 10%-20%。切完后随机打印几个块检查一下分割得是否自然。3.2 向量化与存储构建你的“记忆库”分割好的文本块需要转换成向量一组数字才能进行相似度检索。这需要两个东西嵌入模型和向量数据库。from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma # 1. 初始化嵌入模型 embeddings OpenAIEmbeddings(model“text-embedding-3-small”) # 性价比高 # 如果用开源模型例如 BGE # from langchain_community.embeddings import HuggingFaceEmbeddings # embeddings HuggingFaceEmbeddings(model_name“BAAI/bge-small-zh-v1.5”) # 2. 将文本块向量化并存入向量数据库这里用 Chroma本地运行 vectorstore Chroma.from_documents( documentsall_splits, embeddingembeddings, persist_directory“./chroma_db” # 指定持久化目录 ) vectorstore.persist() # 将数据写入磁盘这一步可能会耗时取决于文档大小和嵌入模型的速度。Chroma会把向量数据保存在本地的./chroma_db目录。下次启动应用时你可以直接加载这个数据库无需重新计算向量。# 后续加载 vectorstore Chroma( persist_directory“./chroma_db”, embedding_functionembeddings )3.3 检索与生成组装答案现在我们有了一个“记忆库”向量数据库。当用户提问时流程是这样的1) 将问题也转换成向量2) 在库中查找最相似的几个文本块3) 把这些块和问题一起组装成提示词送给大模型生成答案。from langchain.chains import RetrievalQA from langchain_openai import ChatOpenAI # 1. 初始化大语言模型 llm ChatOpenAI(model“gpt-3.5-turbo”, temperature0) # temperature0 让输出更确定 # 2. 将向量数据库包装成一个检索器 retriever vectorstore.as_retriever( search_type“similarity”, # 相似度检索 search_kwargs{“k”: 4} # 返回最相似的4个块 ) # 3. 创建 RetrievalQA 链 qa_chain RetrievalQA.from_chain_type( llmllm, chain_type“stuff”, # 最常用的类型将所有检索到的文档“塞”进提示词 retrieverretriever, return_source_documentsTrue, # 非常重要返回参考来源 verboseTrue # 调试时打开可以看到链的中间过程 ) # 4. 进行问答 question “我的文档中提到了哪些主要挑战” result qa_chain.invoke({“query”: question}) print(“答案”, result[“result”]) print(“\n--- 参考来源 ---”) for doc in result[“source_documents”]: print(f“内容片段{doc.page_content[:200]}...”) # 打印前200字符 print(f“来源{doc.metadata}\n”)这个RetrievalQA链是 LangChain 的精华之一它把检索、提示词组装、模型调用、输出解析这些步骤都封装好了。chain_type“stuff”适合文档块不多的情况。如果检索到的文档块很大很多可能会超出模型上下文长度这时需要考虑“map_reduce”或“refine”等更复杂的链类型。第一个可运行的 RAG 应用到此就完成了。你能针对你的文档提问并且看到模型引用了哪些原文片段。这是所有后续优化的基础。4. 从 Demo 到可用优化策略与常见坑点一个能跑通的 Demo 和一个真正可用的系统之间隔着很多细节。下面是我在实战中总结的几个必须关注的优化点和避坑指南。4.1 检索质量优化找得准才是王道RAG 效果不好十有八九是检索没找对资料。多路检索不要只依赖向量相似度。可以结合关键词搜索如 BM25进行混合检索取长补短。LangChain 的EnsembleRetriever可以轻松实现。from langchain.retrievers import EnsembleRetriever from langchain_community.retrievers import BM25Retriever # 创建 BM25 检索器基于文本 bm25_retriever BM25Retriever.from_documents(all_splits) bm25_retriever.k 2 # 创建向量检索器 vector_retriever vectorstore.as_retriever(search_kwargs{“k”: 2}) # 集成两者 ensemble_retriever EnsembleRetriever( retrievers[bm25_retriever, vector_retriever], weights[0.5, 0.5] # 权重可调 )重排序初步检索可能返回很多相关文档用一个更小、更精的模型或交叉编码器对它们进行重排序把最相关的排在最前面能显著提升最终答案质量。元数据过滤如果你的文档有清晰的元数据如部门、日期、类型检索时可以加上过滤器。例如只检索“财务部2024年”的文档。retriever vectorstore.as_retriever( search_kwargs{“k”: 4, “filter”: {“department”: “finance”}} )4.2 提示工程优化问得好答得妙检索到的文档块是“原材料”如何把它们“烹饪”成答案提示词是关键。明确指令在RetrievalQA链中你可以自定义提示词模板要求模型“基于且仅基于提供的上下文回答”不知道就说不知道。from langchain.prompts import PromptTemplate custom_prompt PromptTemplate( template“””请根据以下上下文来回答问题。如果你不知道答案就说你不知道不要编造。 上下文{context} 问题{question} 答案”””, input_variables[“context”, “question”] ) qa_chain RetrievalQA.from_chain_type( llmllm, chain_type“stuff”, retrieverretriever, chain_type_kwargs{“prompt”: custom_prompt}, # 传入自定义提示词 return_source_documentsTrue )Few-Shot 示例对于复杂任务可以在提示词里提供一两个输入输出的例子引导模型按照你想要的格式和风格回答。4.3 评估与迭代不要凭感觉怎么知道你的 RAG 系统变好了还是变差了需要评估。人工评估准备一组标准问题人工检查答案的准确性、相关性和流畅度。这是黄金标准但成本高。自动评估可以用大模型本身作为裁判LLM-as-a-Judge或者用一些开源评估框架如RAGAS、TruLens从答案相关性、上下文相关性、真实性等维度打分。虽然不完全可靠但能快速给出相对趋势指导迭代。核心指标关注命中率检索到的文档是否包含答案、答案准确率、以及幻觉率模型是否胡编乱造。4.4 生产环境考量当你想把系统给别人用时这些点必须处理并发与性能Chroma本地模式不适合高并发。需要考虑PgVectorPostgreSQL 扩展、Qdrant、Weaviate等支持服务化部署的向量数据库。对话历史简单的RetrievalQA是无状态的。要实现多轮对话需要引入ConversationBufferMemory等记忆组件并小心设计流程避免历史对话干扰当前检索。引用溯源与可解释性return_source_documentsTrue是基础。在生产界面中最好能把答案中的关键部分高亮并链接回原文出处增加可信度。日志与监控记录每一次问答的提问、检索到的文档、生成的答案、耗时和 Token 消耗。这是排查问题和优化成本的基础。5. GraphRAG 与 Agentic RAG当简单检索不够用时如果你的数据关联性极强比如人物关系网、事件时间线、复杂的产品知识图谱传统 RAG 检索孤立文本块的方式就会显得力不从心。这时需要更高级的模式。5.1 GraphRAG引入知识图谱的力量GraphRAG 的核心思想是两步走知识提取与图谱构建从你的文档集合中自动提取实体人、组织、地点和关系任职于、位于、发生于构建一个知识图谱。基于图谱的检索与推理当用户提问时系统不仅检索相关文本还会在知识图谱上进行查询和推理。例如问“A 和 C 是什么关系”即使文档中没有直接句子系统也能通过图谱路径A - B - C推断出来。实现方式专用框架微软开源的GraphRAG项目提供了一个端到端的解决方案但相对较重这也是为什么有“GraphRAG 太重”的说法。它集成了大模型进行实体关系抽取、图谱查询和答案生成。基于现有工具组合你可以用LangChainNeo4j图数据库 LLM自己搭建。用 LLM 从文本中抽取三元组头实体关系尾实体存入 Neo4j然后使用 Cypher 查询语言在图谱上进行检索。适用场景金融风控分析企业关联、学术研究梳理理论发展脉络、人物传记分析、复杂事件调查等需要深度关系推理的场景。5.2 Agentic RAG让系统学会“思考”和“使用工具”传统的 RAG 是被动的你问它检索然后生成。Agentic RAG 引入了智能体Agent的概念让系统能主动规划、决策、使用工具。例如一个用户问题可能是“总结我们上季度所有产品在华东区的销售情况并对比一下前年同期。”传统 RAG 可能直接检索“销售报告”文档然后生成一个笼统的总结。Agentic RAG 中的智能体会先进行任务规划1需要找到“上季度”和“前年同期”的销售数据2需要筛选“华东区”和“所有产品”3需要计算对比4需要生成报告。然后它会自主调用不同的工具用 RAG 检索器找销售报告用计算器工具做对比用代码解释器画图表最后用 LLM 整合成文。在 LangChain 中实现这涉及到LangChain Agents和LangGraph。Agents赋予 LLM 使用工具的能力而LangGraph让你能以图状态机的方式定义更复杂、多步骤的智能体工作流支持循环、分支和并行。# 一个极简的 Agent 示例让 LLM 能使用搜索和计算器 from langchain.agents import AgentExecutor, create_react_agent from langchain.tools import Tool from langchain_community.utilities import SerpAPIWrapper from langchain import hub # 定义工具 search SerpAPIWrapper() calculator ... # 假设有一个计算器工具 tools [ Tool(name“Search”, funcsearch.run, description“用于回答关于当前事件的问题”), Tool(name“Calculator”, funccalculator, description“用于数学计算”), ] # 获取一个预设的提示词ReAct 框架 prompt hub.pull(“hwchase17/react”) # 创建智能体 agent create_react_agent(llm, tools, prompt) agent_executor AgentExecutor(agentagent, toolstools, verboseTrue) # 运行智能体 result agent_executor.invoke({“input”: “苹果公司最新的股价是多少如果我现在买10股总价是多少美元”})核心区别LangChain的 Agent 是单个决策单元而LangGraph更适合编排多个 Agent 或复杂步骤的工作流。如果你的任务只是“检索-生成”用简单的链就够了。如果任务需要动态决定调用哪个工具、或者需要多轮交互和状态保持就需要 Agent。6. 微调 vs. RAG如何选择你的技术路线这是最后一个也是最重要的决策点。很多人会问我到底该用 RAG 还是微调这张对比表可以帮你快速决策特性维度RAG (检索增强生成)微调 (Fine-Tuning)核心原理外部知识检索 上下文注入调整模型内部参数数据需求相对较低需要文档库对标注要求低非常高需要大量高质量、结构化的 prompt-completion 对成本与耗时低主要是 API 调用和工程开发成本高涉及训练计算资源时间长知识更新实时/快速更新文档库即可缓慢需要重新训练或增量训练解决什么问题知识密集型问答事实准确性减少幻觉改变模型风格、格式、遵循特定指令、学习新技能可解释性高答案可溯源到具体文档低模型成为一个黑盒适用阶段绝大多数企业知识库、客服、分析场景的首选对输出有极其稳定、统一要求的场景如代码生成规范、特定风格写作更实际的建议是RAG 优先必要时结合。绝大多数场景先用 RAG。它能快速让你的数据“活”起来成本可控效果立竿见影。你遇到的 90% 的“基于文档的问答”需求RAG 都能很好地解决。当 RAG 不够时再考虑微调。比如你希望模型生成的 SQL 语句永远符合你们公司的命名规范。你希望模型写的邮件永远用一种特定的、刻板的商务口吻。你希望模型能学会一种它原本完全不理解的、高度专业领域的推理模式。RAG 和微调可以结合。这是一种更强大的模式用一个经过微调、更懂你领域和风格的模型作为“大脑”再结合 RAG 提供的实时外部“知识”既能保证专业性又能保证信息的时效性和准确性。最后关于学习路径的建议 不要试图一口吃成胖子。按这个顺序来掌握基础 RAG用 LangChain Chroma OpenAI/国内大模型 API跑通一个单文档问答 Demo。理解加载、分割、向量化、检索、生成的完整流程。优化你的 RAG尝试不同的分割策略、检索器、提示词加入元数据过滤学会评估效果。探索生产化组件换用生产级向量数据库如 Qdrant, Weaviate学习如何管理对话记忆设计 API 接口。涉足高级模式当你的场景需要处理复杂关系时研究 GraphRAG当你的任务需要多步骤规划和工具调用时研究 Agentic RAG 和 LangGraph。在确有需要时研究微调收集高质量数据尝试使用 OpenAI 的 Fine-tuning API 或开源框架如 LLaMA-Factory对中小模型进行微调实验。记住所有这些技术的最终目的都是为了让大模型更可靠、更可控地为你服务。从最小的、可验证的闭环开始逐步迭代远比一开始就设计一个庞大复杂的系统要实在得多。