
网上关于 LangChain 的教程非常多但绝大多数都存在两个问题一是版本太旧照着敲很快就报错二是只讲概念不写代码看完还是不知道怎么把链、模型、向量库串起来。如果你正打算系统学习 LangChain或者已经踩过一些版本坑这篇文章会把从环境搭建到 RAG 实战、Agent 工具调用的完整路径走一遍。考虑到 LangChain 版本迭代比较快本文以 LangChain 1.3 作为示例版本重点讲解稳定通用的 API 设计思路你在实际项目中遇到其他版本时也能快速迁移。1. LangChain 到底是什么为什么值得学1.1 一句话理解 LangChainLangChain 是一个基于大语言模型LLM的应用开发框架它的核心价值是把“调用模型”这件事从单纯的 API 请求升级成一套可组合、可维护、可观测的应用流水线。在没有 LangChain 之前你要开发一个带知识库问答的 AI 应用通常需要自己处理这些环节调用模型接口处理 Prompt 拼接把文档切分、向量化存入向量数据库根据用户问题做相似度检索把检索结果拼进 Prompt再请求模型解析模型输出处理超时、重试、错误。这些环节单独看不难但放在一起之后代码会越来越乱而且每个环节都有大量重复逻辑。LangChain 把这些能力抽象成标准组件比如模型、提示词、输出解析器、检索器、记忆、Agent开发者只需要按需组合即可。1.2 LangChain 解决了什么问题LangChain 解决的问题可以概括为让 LLM 应用从“脚本调用”走向“工程化构建”。具体来说有几点标准化模型调用 不同厂商的模型接口格式不一样LangChain 用统一的接口封装 OpenAI、Anthropic、国产模型等切换模型时只需要换配置不用重写业务代码。组件化能力拆分 Prompt 模板、模型、输出解析、记忆、检索都是独立模块按需组合成一条链测试和维护成本都明显降低。支持复杂应用编排 单个模型调用只能解决简单问题真实项目往往需要“先检索、再判断、再调用工具、再总结”的多步流程LangChain 的链和 Agent 机制就是为此设计的。接入生态工具 LangChain 生态里有文档加载器、文本分割器、向量库适配器、API 工具等社区活跃很多常见功能都有现成实现。1.3 适用场景LangChain 适合以下场景知识库问答系统把内部文档做成可检索的问答机器人数据分析助手让模型学会写 SQL、Python 代码并执行自动化办公机器人读取邮件、生成周报、整理工单多步推理应用比如选品分析、竞品调研、方案对比Agent 智能体模型自主规划步骤并调用工具完成任务。需要说明的是LangChain 并不是唯一的大模型开发框架类似方案还有 LlamaIndex、Spring AI、Semantic Kernel 等。但在社区生态、文档丰富度和学习资料方面LangChain 对初学者仍然比较友好。1.4 版本变化的现实问题LangChain 的版本迭代速度非常快早期 0.1、0.2 时代的很多写法在 0.3、1.x 中已经不再推荐比如直接使用LLMChain、ConversationChain这种方式现在更推荐基于 LCEL 表达式语言来组合链。因此网上很多旧教程没有参考价值你更需要掌握的是“版本无关”的核心概念和稳定 API。2. 环境准备与版本说明2.1 运行环境本文示例基于以下环境操作系统Windows 10/11、macOS、Linux 都可以Python3.9 及以上推荐 3.10 或 3.11包管理工具pip 或 poetryIDEPyCharm、VS Code 都可以大模型 APIOpenAI 兼容接口或国内大模型厂商接口。如果你的电脑上没有 Python 环境建议先安装 Anaconda 或 Miniconda用虚拟环境隔离项目依赖避免污染系统环境。2.2 安装 LangChain 相关依赖先创建一个虚拟环境python -m venv langchain-demo source langchain-demo/bin/activate # Linux/macOS # Windows 使用langchain-demo\Scripts\activate然后升级 pippip install --upgrade pip安装核心依赖pip install langchain pip install langchain-openai pip install langchain-community pip install langchain-text-splitters pip install python-dotenv如果是做 RAG 向量检索还需要安装pip install faiss-cpu pip install pypdf pip install tiktoken这里要特别说明LangChain 1.3 是示例版本不同小版本的 API 会有调整。安装时不要直接裸装最新版建议在项目里锁版本比如pip install langchain1.3.* pip install langchain-openai*具体版本号以你实际安装结果为准。锁定版本后即使将来 LangChain 升级你的项目也能保持稳定。2.3 准备模型 API KeyLangChain 本身不包含大模型它只是调用模型的能力层。你需要准备一个模型接口OpenAI 接口需要OPENAI_API_KEY国产模型比如智谱、通义、DeepSeek 等通常提供 OpenAI 兼容接口本地模型通过 Ollama 或 vLLM 部署后配置 base_url 指向本地服务。为了安全不要把 API Key 直接写在代码里推荐使用.env文件管理。项目根目录创建.env文件OPENAI_API_KEY你的密钥 OPENAI_BASE_URLhttps://api.openai.com/v1 MODEL_NAMEgpt-4o-mini如果你的模型走的是国内代理或兼容接口就把OPENAI_BASE_URL改成对应地址MODEL_NAME改成服务商支持的模型名称。加载.env文件from dotenv import load_dotenv load_dotenv()3. 核心概念与 LCEL 基础拆解3.1 LCEL 是什么LCEL 全称 LangChain Expression Language是 LangChain 提供的一种声明式组合语法。它用|符号把多个组件连接成一条链类似 Unix 管道。举个例子from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain_core.output_parsers import StrOutputParser prompt ChatPromptTemplate.from_template(请用一句话解释{topic}) model ChatOpenAI(modelgpt-4o-mini, temperature0) parser StrOutputParser() chain prompt | model | parser这条链的执行顺序是传入topic给 prompt 模板模板生成完整 Prompt 字符串模型接收 Prompt 并返回响应解析器把模型输出转换成字符串。调用方式result chain.invoke({topic: 什么是大模型}) print(result)这种写法和传统命令式代码相比最大的优势是组件完全解耦。你可以调换中间某个环节而不影响其他部分比如把ChatOpenAI换成其他模型或者把StrOutputParser换成 JSON 解析器。3.2 Runnable 接口LCEL 里的每个组件都实现了 Runnable 接口最常用的方法是invoke(input)同步调用返回结果ainvoke(input)异步调用stream(input)流式输出边生成边返回batch(inputs)批量调用。正因为所有组件都遵循同一个接口它们才能被任意组合。理解这一点之后你看到 LangChain 报错时排查思路就会清晰很多报错大多是数据类型不匹配比如上一个组件返回了字符串下一个组件期待字典。3.3 Prompt 模板Prompt 模板用来解决提示词复用问题。不要在业务代码里写死一段长长的 Prompt应该把变量部分抽出来。普通模板from langchain_core.prompts import PromptTemplate template 你是一个资深 Java 技术专家。 请根据以下问题给出通俗易懂的解释。 问题{question} prompt PromptTemplate.from_template(template)聊天模型模板from langchain_core.prompts import ChatPromptTemplate messages [ (system, 你是一个严谨的代码审查专家。), (human, 请审查下面这段代码\n{code}) ] prompt ChatPromptTemplate.from_messages(messages)聊天模型模板按role区分角色比如system、human、ai更符合 Chat API 的对话结构。多轮对话场景推荐使用 ChatPromptTemplate。3.4 输出解析器模型返回的内容是纯文本但实际项目中通常需要结构化输出比如 JSON、Python 列表、Markdown 表格。输出解析器负责把模型输出转换成 Python 对象。字符串解析from langchain_core.output_parsers import StrOutputParser parser StrOutputParser()JSON 解析from langchain_core.output_parsers import JsonOutputParser parser JsonOutputParser()CommaSeparatedListOutputParser 可以把模型返回的逗号分隔内容解析成列表from langchain_core.output_parsers import CommaSeparatedListOutputParser parser CommaSeparatedListOutputParser()使用输出解析器时建议在 Prompt 中明确告诉模型输出格式否则解析容易失败。更稳妥的做法是使用结构化输出方法让模型直接按约束输出 JSON。3.5 Memory 记忆机制大模型本身没有记忆每次调用都是独立请求。LangChain 提供 Memory 组件来管理对话历史。常用的内存记忆from langchain.memory import ConversationBufferMemory不过在新版本的 LangChain 中官方更推荐把历史消息直接放在链的状态里而不是依赖 Memory 类。比如在多轮对话中直接把chat_history作为变量传入 Prompt 模板。实际项目中内存记忆只适合临时演示生产环境应该把历史记录存储到 Redis 或数据库里并且控制 Token 长度。3.6 Agent 与 ToolAgent 是 LangChain 中比较复杂的模块它让模型不再只是“生成文本”而是可以“决定调用哪个工具、按什么顺序调用、根据工具结果继续推理”。工具可以是函数、API、数据库查询、计算器、搜索引擎等。LangChain 使用tool装饰器把普通函数包装成工具。from langchain_core.tools import tool tool def add(a: int, b: int) - int: 计算两个整数的和。 return a b这里要注意工具函数必须写清楚 docstring因为模型会通过函数名、参数描述和 docstring 来理解这个工具是干什么的描述越清晰模型的选择越准确。4. 实战案例一基于 LCEL 的简单问答链4.1 项目结构先创建一个简单的项目结构langchain-demo/ ├── .env ├── requirements.txt └── simple_chain.py4.2 requirements.txtlangchain1.3.* langchain-openai* langchain-community* langchain-text-splitters* python-dotenv1.* faiss-cpu1.* pypdf4.* tiktoken0.*版本号中的*表示安装符合条件的最新版实际使用时建议安装后执行pip freeze锁住具体版本。4.3 编写简单问答链创建simple_chain.pyimport os from dotenv import load_dotenv from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain_core.output_parsers import StrOutputParser load_dotenv() model ChatOpenAI( modelos.getenv(MODEL_NAME, gpt-4o-mini), temperature0.7, ) prompt ChatPromptTemplate.from_messages([ (system, 你是一个乐于助人的技术助手。), (human, {question}), ]) chain prompt | model | StrOutputParser() if __name__ __main__: result chain.invoke({question: 请用三句话介绍 FastAPI。}) print(result)4.4 运行与验证python simple_chain.py如果配置正确控制台会输出模型生成的介绍内容。如果出现认证错误说明 API Key 没配置好如果出现模型不存在错误说明MODEL_NAME和你的模型服务不匹配。4.5 错误排查问题现象常见原因解决思路AuthenticationErrorAPI Key 错误检查 .env 文件是否加载成功NotFoundError模型名称不存在查看模型服务商文档修改名称RateLimitError请求频率超限增加重试或降低并发TypeError: str object is not callable链组件类型不匹配检查上一个组件的返回类型5. 实战案例二文档问答 RAG 系统RAGRetrieval-Augmented Generation检索增强生成是目前 LangChain 最广泛的落地场景。它的核心思想是先从外部知识库检索出与问题相关的文档片段再把这些片段作为上下文交给模型生成回答。这样做的价值是解决大模型“不了解私有知识”和“容易编造”的问题。5.1 项目结构langchain-demo/ ├── .env ├── requirements.txt ├── docs/ │ └── 说明文档.pdf └── rag_demo.py5.2 加载文档LangChain 提供大量文档加载器这里使用 PyPDFLoader 加载 PDFfrom langchain_community.document_loaders import PyPDFLoader loader PyPDFLoader(docs/说明文档.pdf) documents loader.load()加载完成后documents是一个 Document 列表每个 Document 包含page_content和metadata两个属性。metadata里通常有页码、来源文件等信息后续可以用来追溯答案来源。如果你的文档是 Markdown、Word、CSVLangChain 社区包也提供了对应加载器from langchain_community.document_loaders import TextLoader, UnstructuredWordDocumentLoader, CSVLoader5.3 文本切片大模型输入有 Token 限制不能把整篇文档直接塞进 Prompt所以需要把文档切分成小块。推荐使用RecursiveCharacterTextSplitterfrom langchain_text_splitters import RecursiveCharacterTextSplitter text_splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap50, separators[\n\n, \n, 。, , , ., !, ?, , ], ) chunks text_splitter.split_documents(documents)关键参数chunk_size每个切片的字符数不宜过大chunk_overlap相邻切片之间的重叠字符数防止一个问题被从中间截断separators优先按段落、句子切分保证语义完整。切片大小没有绝对标准一般根据你的文档类型和模型上下文窗口来调。建议从 500 到 800 字符起步做实验对比检索效果。5.4 向量化与存储文本切片本身是字符串机器无法直接计算相似度需要先通过 Embedding 模型转换成向量。from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import FAISS embeddings OpenAIEmbeddings( modeltext-embedding-3-small ) vectorstore FAISS.from_documents(chunks, embeddings)这里使用了 FAISS 向量库它的特点是轻量、本地化适合学习和中小型项目。如果文档规模很大可以换成 Milvus、Chroma、Qdrant 等专业向量数据库。FAISS 支持本地持久化避免每次启动都重新计算向量vectorstore.save_local(faiss_index)再次启动时直接加载vectorstore FAISS.load_local( faiss_index, embeddings, allow_dangerous_deserializationTrue, )需要注意的是allow_dangerous_deserializationTrue是因为 FAISS 加载本地文件存在反序列化风险。只加载你自己生成的索引文件时才能开启不要随意加载来源不明的索引。5.5 构建检索问答链完整代码rag_demo.pyimport os from dotenv import load_dotenv from langchain_community.document_loaders import PyPDFLoader from langchain_community.vectorstores import FAISS from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnablePassthrough from langchain_openai import ChatOpenAI, OpenAIEmbeddings from langchain_text_splitters import RecursiveCharacterTextSplitter load_dotenv() PDF_PATH docs/说明文档.pdf FAISS_PATH faiss_index def format_docs(docs): return \n\n.join(doc.page_content for doc in docs) def build_vectorstore(): # 1. 加载文档 loader PyPDFLoader(PDF_PATH) documents loader.load() # 2. 文本切片 text_splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap50, ) chunks text_splitter.split_documents(documents) # 3. 向量化并存储 embeddings OpenAIEmbeddings() vectorstore FAISS.from_documents(chunks, embeddings) vectorstore.save_local(FAISS_PATH) return vectorstore def main(): # 4. 加载向量库 embeddings OpenAIEmbeddings() if os.path.exists(FAISS_PATH): vectorstore FAISS.load_local( FAISS_PATH, embeddings, allow_dangerous_deserializationTrue, ) else: vectorstore build_vectorstore() retriever vectorstore.as_retriever( search_typesimilarity, search_kwargs{k: 4}, ) # 5. 构建 Prompt prompt ChatPromptTemplate.from_messages([ (system, 你是一个企业内部知识库助手。请仅根据给定的上下文回答问题如果上下文中没有相关信息请直接回答“知识库中暂无相关信息”不要编造。), (human, 上下文\n{context}\n\n问题{question}), ]) # 6. 构建 LCEL 链 chain ( {context: retriever | format_docs, question: RunnablePassthrough()} | prompt | ChatOpenAI(modelos.getenv(MODEL_NAME, gpt-4o-mini), temperature0) | StrOutputParser() ) while True: question input(请输入问题输入 exit 退出) if question.lower() exit: break result chain.invoke(question) print(\n回答, result) print(- * 60) if __name__ __main__: main()这段代码的执行流程是用户输入问题retriever 根据问题在向量库中检索 Top4 相关文档片段format_docs 把多个片段拼接成上下文Prompt 模板把上下文和问题组合成完整提示词模型生成回答输出解析器返回字符串。5.6 运行效果python rag_demo.py输入问题后模型会结合 PDF 内容回答。因为设置了temperature0回答会尽量稳定减少随机编造。这个案例中的retriever | format_docs是一个值得注意的写法retriever 返回 Document 列表经过 format_docs 函数转成字符串然后填入 Prompt。RunnablePassthrough 表示原样传递用户输入所以question字段也是字符串最终符合 Prompt 模板的输入要求。5.7 RAG 常见优化方向优化点方案检索不准确调整 chunk_size、chunk_overlap换成更小的检索 k 值答案不完整增加检索片段数量或使用 rerank 重排序知识库更新不及时保存向量索引后定期增量更新文档格式复杂先做 OCR 或转成纯文本再做切片响应太慢使用异步接口、缓存相似问题答案6. 实战案例三Agent 工具调用开发6.1 Agent 解决什么问题普通链是固定流程输入问题经过固定的处理步骤输出结果。Agent 则不同模型会根据用户的问题自主判断需要调用哪些工具然后循环执行“推理 - 调用工具 - 观察结果 - 再推理”的过程直到得出最终答案。举个例子用户问“今天北京适合穿什么衣服”如果 Agent 有天气查询工具和穿衣建议 Prompt它就会先调用天气工具拿到天气数据后再生成建议。这个过程不需要开发者硬编码判断逻辑。6.2 定义一个简单工具创建agent_demo.pyimport os from dotenv import load_dotenv from langchain_core.tools import tool from langchain_openai import ChatOpenAI from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_core.prompts import ChatPromptTemplate load_dotenv() tool def get_city_temperature(city: str) - str: 查询指定城市的当前温度返回一个示例温度值。 fake_data { 北京: 25 摄氏度晴, 上海: 28 摄氏度多云, 广州: 31 摄氏度雷阵雨, } return fake_data.get(city, 暂无该城市数据) def main(): model ChatOpenAI( modelos.getenv(MODEL_NAME, gpt-4o-mini), temperature0, ) tools [get_city_temperature] prompt ChatPromptTemplate.from_messages([ (system, 你是一个天气助手可以根据工具查询结果回答用户问题。), (human, {input}), (placeholder, {agent_scratchpad}), ]) agent create_tool_calling_agent(model, tools, prompt) executor AgentExecutor(agentagent, toolstools, verboseTrue) result executor.invoke({input: 北京现在多少度适合穿什么衣服}) print(result[output]) if __name__ __main__: main()6.3 代码执行过程执行这段代码Agent 会输出类似下面的日志 Entering new AgentExecutor chain... Invoking: get_city_temperature with {city: 北京} 北京 25 摄氏度晴 北京现在是 25 摄氏度天气晴朗适合穿短袖或薄长袖。 Finished chain.从这个日志可以看出Agent 不是一次调用模型就结束而是先调用工具再把工具结果作为上下文继续推理。6.4 Agent 使用注意事项工具描述要准确模型依赖描述做决策工具参数要声明类型Agent 才能正确传参生产环境必须限制工具权限不能把删除、更新等危险操作直接暴露给模型Agent 的推理会增加 Token 消耗和响应延迟适合任务链路不固定的场景。7. 常见问题与排查思路7.1 版本不兼容LangChain 版本更新经常导致 API 变化。最典型的是from langchain.llms import OpenAI在老版本可用新版本提示移到langchain_openaiLLMChain用法被弃用推荐 LCELConversationBufferMemory用法不再推荐。解决方案统一依赖版本阅读当前版本的迁移文档不要照抄旧代码。建议项目使用requirements.txt或pyproject.toml固定版本同时保留pip freeze的锁文件。7.2 API Key 没生效.env文件加载失败的原因通常是dotenv 加载顺序在创建模型之后环境变量名不匹配比如OPENAI_API_KEY拼写错误.env文件不在当前工作目录。排查方法from dotenv import load_dotenv import os load_dotenv() print(KEY存在 if os.getenv(OPENAI_API_KEY) else KEY不存在)7.3 向量库 loaded 报错加载 FAISS 时提示allow_dangerous_deserialization相关错误是因为新版本默认禁止反序列化不可信数据。如果你是加载自己保存的索引可以显式传入参数但不建议关闭安全检查。7.4 Prompt 中 context 为空如果检索结果为空模型就缺少上下文。可能是文档没加载成功、切片为空、向量库没有数据。可以通过打印retriever.invoke(测试)来验证。7.5 模型输出格式解析失败如果使用 JsonOutputParser但模型不按要求输出 JSON可以在 Prompt 中补充格式示例使用with_structured_output()方法增加解析失败后的重试机制。8. 最佳实践与工程建议8.1 使用 LCEL 而不是旧式 ChainLCEL 是 LangChain 目前推荐的链式写法它从设计上就保证了组件之间的通用性、流式支持和异步调用。新项目建议直接使用 LCEL不要再去学已经过时的LLMChain。8.2 管理好 API Key 与模型配置API Key 是敏感信息必须放入环境变量或密钥管理服务不要把密钥提交到代码仓库。生产环境建议由配置中心统一管理模型名称、base_url、temperature 等参数。8.3 设置重试与超时大模型接口经常因为网络波动或限流而失败。建议在客户端配置重试和超时model ChatOpenAI( modelos.getenv(MODEL_NAME), temperature0, request_timeout30, max_retries2, )8.4 控制上下文长度和成本对话系统必须限制历史消息数量否则历史消息越长Token 成本越高响应也越慢。可以设置最多保留最近 10 轮消息或者把历史做摘要。8.5 日志与可观测性LangChain 提供了回调机制可以在链执行过程中记录输入输出、耗时、Token 消耗。生产环境中建议接入 LangSmith 或自建日志系统方便排查问题。8.6 防止提示词注入在 RAG 和 Agent 场景中用户输入和文档内容都不可信。文档中可能包含恶意指令试图让模型忽略系统 Prompt。建议在 Prompt 中明确“只根据上下文回答”并且对工具调用权限做最小化约束。8.7 版本锁定LangChain 变化极快建议在requirements.txt中锁定主版本并在 CI 流程中加入依赖检查和测试避免升级依赖导致生产环境出问题。9. 总结与后续学习路线这篇文章从 LangChain 的核心概念讲起覆盖了环境搭建、LCEL 链式写法、Prompt 模板、输出解析器、RAG 检索增强、Agent 工具调用以及常见问题排查和工程化建议。最重要的不是记住某个 API而是理解 LangChain 的组合思想把模型、提示词、解析器、检索器、工具当作积木按业务需求拼装成一条可执行的链。接下来你可以继续按下面的路径深入巩固 LCEL重点练习invoke、stream、batch的差异用不同的文档加载器处理 Word、Markdown、CSV、HTML尝试接入 Milvus、Chroma 等向量数据库写一个多工具 Agent让模型自主完成“查天气 - 计算温差 - 生成建议”的完整流程学习 LangSmith 或自建日志体系把控线上质量。如果在实践中遇到报错建议优先去官方迁移文档和对应版本的源码里找答案比看旧博客更可靠。动手写代码永远是学习 LangChain 最快的方式。把上面的示例跑通之后试着改一改 Prompt、换一个模型、增加一个工具很快你就能体会到这套框架的真正价值。