
1. 项目概述为什么我们需要一个LangChain教程如果你最近在AI应用开发领域尤其是围绕大语言模型LLM做点东西大概率听过“LangChain”这个名字。它火得有点不讲道理但当你真正上手时又常常被它庞杂的概念和快速迭代的版本搞得一头雾水。我自己也是这么过来的从最初的“这玩意儿到底怎么用”到后来能基于它搭建起相对复杂的AI应用踩过的坑不计其数。所以当看到“ConnectAI-E/LangChain-Tutior”这个项目标题时我立刻明白了它的价值这绝不是一个简单的API调用指南而是一个旨在系统化、实战化地教会开发者如何驾驭LangChain这个强大但复杂的框架的“导航图”。LangChain本质上是一个用于构建由LLM驱动的应用程序的框架。它的核心价值在于“链”Chain—— 将调用LLM、处理数据、执行工具等多个步骤像乐高一样组合起来完成复杂的任务。但问题在于官方文档虽然详尽却更像一本“零件说明书”对于如何从零开始设计并搭建一个完整的、可用的应用缺乏一条清晰的路径。新手很容易迷失在“Agents”、“Memory”、“Indexes”这些抽象概念里。而这个教程项目其潜在需求就是填补这个空白提供一个从环境搭建、核心概念理解到典型场景实战、高级特性剖析的完整学习路径让开发者不仅能“会用”LangChain更能“用好”它理解其设计哲学从而构建出稳定、高效的应用。2. 核心架构与设计哲学拆解2.1 LangChain的核心抽象不止于“链”要学好LangChain首先得跳出“链即一切”的误区。LangChain的架构是分层和模块化的理解这一点至关重要。模型 I/OModel I/O这是最底层负责与LLM如OpenAI的GPT、Anthropic的Claude或嵌入模型Embedding Model交互。教程在这里需要讲清楚不同模型提供商OpenAI, Azure OpenAI, 本地部署模型如Ollama的接入方式以及如何统一处理它们的输入Prompt模板和输出解析器。一个常见的坑是不同模型对Prompt格式的敏感度不同直接套用可能会效果不佳。检索Retrieval这是让LLM“拥有”外部知识的关键。核心是将文档你的知识库通过嵌入模型向量化存入向量数据库如Chroma, Pinecone, Weaviate然后根据用户问题检索相关片段。教程必须深入讲解文档加载、文本分割Text Splitting、向量化Embedding和检索Retrieval的全流程。这里的关键是文本分割策略按字符分割太死板按语义分割又依赖模型通常推荐使用递归字符分割RecursiveCharacterTextSplitter并配合重叠overlap来保持上下文连贯。链Chains这是LangChain的招牌。但链分为多种LLMChain最基础的链就是Prompt LLM。SequentialChain顺序执行多个链前一个的输出作为后一个的输入。RouterChain根据输入决定调用哪个子链实现分支逻辑。TransformChain对输入/输出进行自定义转换。一个高质量的教程应该引导学习者从简单的LLMChain开始逐步组合成复杂的SequentialChain并最终理解如何用RouterChain构建具备决策能力的应用。代理Agents这是LangChain最强大的部分之一。代理 LLM 工具Tools 思考过程。LLM作为“大脑”通过ReAct等模式决定何时、使用哪个工具如搜索、计算、查数据库来解决问题。教程的重点在于如何定义工具、如何设计清晰的指令Prompt来引导代理的思考以及如何处理代理可能出现的循环或错误决策。记忆Memory为了让对话或交互具有连续性需要记忆。LangChain提供了多种记忆后端从简单的对话缓冲区ConversationBufferMemory到更复杂的、基于向量存储的长期记忆。选择哪种记忆取决于你的应用场景是需要记住最近几句对话还是需要从漫长的历史中回忆相关片段。2.2 项目教程的预期结构设计基于以上核心概念一个优秀的LangChain-Tutior项目应该遵循“由浅入深、案例驱动”的结构。我推测其内容骨架可能如下基础入门篇环境配置Python, 安装LangChain及相关包、第一个“Hello World”程序调用OpenAI API、理解PromptTemplate和OutputParser。核心概念实战篇深入讲解并实战Chains、Agents、Memory、Retrieval。每个概念配以1-2个完整的、可运行的代码示例。例如用Retrieval构建一个本地文档问答机器人用Agents创建一个能联网搜索和计算的助手。高级应用与集成篇如何将LangChain应用部署为Web服务如使用FastAPI、如何与外部系统集成如Slack机器人、微信机器人、如何处理流式响应Streaming以提升用户体验、如何进行链的追踪和评估LangSmith。性能优化与最佳实践如何管理API调用成本缓存、限流、如何设计健壮的Prompt以提高任务成功率、如何对检索结果进行重排序Re-ranking以提升精度、错误处理与重试机制。这个教程的价值就在于它能把官方文档中分散的知识点通过一条清晰的、有逻辑的路径串联起来并在每个环节注入实战经验和避坑指南。3. 环境准备与工具链选型3.1 基础开发环境搭建工欲善其事必先利其器。一个稳定的开发环境是高效学习的前提。Python版本管理强烈推荐使用pyenvMac/Linux或pyenv-winWindows来管理Python版本。LangChain与较新的Python版本兼容性更好建议使用Python 3.10或3.11。避免使用系统自带的Python以免包依赖冲突。# 示例使用pyenv安装并切换Python版本 pyenv install 3.11.8 pyenv local 3.11.8 # 在当前目录使用指定版本虚拟环境隔离每个LangChain项目都应创建独立的虚拟环境。使用venv或conda。# 使用venv python -m venv .venv # 激活环境 (Linux/Mac) source .venv/bin/activate # 激活环境 (Windows) .venv\Scripts\activate核心包安装基础安装命令很简单但要注意版本。pip install langchain langchain-community langchain-openailangchain核心框架。langchain-community社区维护的第三方集成如很多工具、向量库。langchain-openaiOpenAI模型的官方集成比旧版的openai包集成度更高。注意LangChain版本迭代很快API变动较大。教程最好能锁定主要依赖的版本号例如pip install langchain0.1.0 langchain-openai0.0.5以确保示例代码的稳定性。学习时建议先跟随教程使用指定版本待熟悉后再尝试升级。3.2 关键外部服务配置LangChain的强大在于连接因此需要配置一些外部服务。LLM提供商OpenAI是最常用的。你需要一个API Key。安全第一永远不要将API Key硬编码在代码中或上传到GitHub。使用环境变量管理。# 在终端中设置临时 export OPENAI_API_KEYyour-api-key-here # 或者使用.env文件配合python-dotenv包加载# 在Python中读取 import os from dotenv import load_dotenv load_dotenv() # 加载 .env 文件中的环境变量 api_key os.getenv(OPENAI_API_KEY)向量数据库对于本地学习和开发Chroma DB是首选。它轻量、无需外部服务、纯Python实现。pip install chromadb在代码中你可以直接实例化一个临时的、内存中的Chroma客户端非常适合教程和原型开发。可选工具如果你要学习Agents可能需要一些工具比如SerpAPI谷歌搜索或Wikipedia查询。这些通常也需要API Key同样通过环境变量配置。4. 从零构建第一个LangChain智能应用4.1 你好LangChain与LLM的第一次对话让我们跳过理论直接写代码。第一个例子是使用OpenAI的GPT模型进行简单问答。# 1_hello_llm.py from langchain_openai import ChatOpenAI from langchain.schema import HumanMessage # 初始化聊天模型指定模型名称和温度创造性 llm ChatOpenAI(modelgpt-3.5-turbo, temperature0.7) # 构建消息列表。LangChain使用消息SystemMessage, HumanMessage, AIMessage来管理对话。 messages [ HumanMessage(content请用一句话介绍LangChain是什么) ] # 调用模型并获取响应 response llm.invoke(messages) print(response.content)关键点解析ChatOpenAI这是与OpenAI聊天模型交互的类。temperature参数控制输出的随机性0-1值越高回答越多样值越低越确定。对于事实性问答建议设低如0.1对于创意写作可以设高如0.8。invoke这是LangChain新版v0.1推荐的统一调用方法。旧版的predict、run等方法已逐渐被取代。4.2 使用Prompt模板让交互标准化直接拼接字符串构造Prompt容易出错且难以维护。PromptTemplate是解决方案。# 2_prompt_template.py from langchain_openai import ChatOpenAI from langchain.prompts import ChatPromptTemplate # 定义Prompt模板。{input}是一个变量占位符。 prompt_template ChatPromptTemplate.from_messages([ (system, 你是一个专业的AI技术翻译助手。), (human, 将以下英文技术术语翻译成中文并给出简短解释{input}) ]) # 初始化模型 llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 将模板和变量组合成完整的Prompt然后调用模型 chain prompt_template | llm # 使用新的管道操作符非常直观 # 等价于旧版的 LLMChain(promptprompt_template, llmllm) result chain.invoke({input: Transformer}) print(result.content)核心技巧管道操作符|是LangChain v0.1引入的语法糖它让链的组合像Unix管道一样直观A | B | C表示数据从A流到B再到C。这是当前最推荐的构建链的方式。SystemMessage用于设定AI的角色和行为指令对输出质量影响巨大。好的系统指令是成功的一半。4.3 构建检索式问答链打造你的知识库助手这是LangChain最经典的应用场景。我们将创建一个能基于自定义文档回答问题的机器人。步骤1准备并加载文档# 3_retrieval_qa.py - 第一部分加载与分割 from langchain_community.document_loaders import TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter # 假设我们有一个 my_article.txt 文件 loader TextLoader(./my_article.txt) documents loader.load() # 分割文档。chunk_size是每个文本块的大小chunk_overlap是块之间的重叠字符数。 text_splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap50, separators[\n\n, \n, 。, , , , , ] # 中文分隔符 ) split_docs text_splitter.split_documents(documents) print(f原始文档数{len(documents)} 分割后块数{len(split_docs)})步骤2向量化并存储# 3_retrieval_qa.py - 第二部分向量化存储 from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma # 初始化嵌入模型 embeddings OpenAIEmbeddings(modeltext-embedding-3-small) # 使用较小的嵌入模型以节省成本 # 将分割后的文档转换为向量并存入Chroma。persist_directory指定持久化目录为空则仅存内存。 vectorstore Chroma.from_documents( documentssplit_docs, embeddingembeddings, persist_directory./chroma_db # 可选持久化到磁盘 ) # 向量库现在包含了我们文档的所有知识。步骤3创建检索链并提问# 3_retrieval_qa.py - 第三部分检索与回答 from langchain.chains import create_retrieval_chain from langchain.chains.combine_documents import create_stuff_documents_chain from langchain_openai import ChatOpenAI from langchain.prompts import ChatPromptTemplate # 1. 定义回答问题的Prompt模板 qa_prompt ChatPromptTemplate.from_messages([ (system, 请根据以下上下文回答用户的问题。如果你不知道答案就说不知道不要编造。\n\n上下文{context}), (human, {input}) ]) # 2. 初始化LLM llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 3. 创建“组合文档”链它负责将检索到的多个文档片段context和问题组合成最终Prompt。 combine_docs_chain create_stuff_documents_chain(llm, qa_prompt) # 4. 创建“检索”链它负责从向量库中根据问题检索相关文档片段。 retrieval_chain create_retrieval_chain( vectorstore.as_retriever(search_kwargs{k: 4}), # 检索最相关的4个片段 combine_docs_chain ) # 5. 提问 question 这篇文章主要讲了什么 result retrieval_chain.invoke({input: question}) print(f问题{question}) print(f答案{result[answer]}) # 你可以查看检索到的源文档 # print(参考来源, result[context])实操心得chunk_size和chunk_overlap需要根据你的文档类型技术文档、小说、对话和模型上下文长度进行微调。500-1000的chunk_size是常见的起点。search_kwargs{“k”: 4}表示检索4个最相关的文档块。k值越大提供的上下文越丰富但也会增加Token消耗和可能引入无关信息。需要权衡。这个流程是构建知识库应用的基石。后续的优化如更好的分割器、重排序、混合检索等都是在此基础上进行的。5. 深入核心代理Agents与工具Tools实战代理模式是让AI从“问答机”变为“执行者”的关键。我们构建一个能调用计算器和搜索工具的代理。5.1 定义自定义工具工具本质上是一个函数加上一些描述让LLM知道何时调用它。# 4_agent_tools.py from langchain.tools import tool import math # 使用tool装饰器定义一个计算平方根的工具 tool def sqrt(input: float) - float: 计算一个数的平方根。 return math.sqrt(input) # 定义一个模拟网络搜索的工具实际项目中应接入SerpAPI等真实API tool def search_web(query: str) - str: 执行一次网络搜索。用于获取实时信息或未知领域知识。 # 这里是模拟返回真实情况应调用搜索API print(f[模拟搜索] 搜索词{query}) return f关于{query}的搜索结果这是一个模拟的搜索结果摘要。5.2 创建代理并执行# 4_agent_tools.py (续) from langchain_openai import ChatOpenAI from langchain.agents import create_react_agent, AgentExecutor from langchain.prompts import PromptTemplate # 1. 准备工具列表 tools [sqrt, search_web] # 2. 初始化LLM。代理任务通常需要更强的推理能力建议使用GPT-4或Claude。 llm ChatOpenAI(modelgpt-4-turbo, temperature0) # 3. 使用ReAct提示模板。这是引导代理“思考-行动-观察”循环的关键。 prompt_template PromptTemplate.from_template( 你是一个有帮助的助手可以访问以下工具 {tools} 请严格按照以下格式回答 问题用户提出的问题 思考你需要思考如何一步步解决问题 行动你要调用的工具名称 行动输入调用该工具所需的输入 观察工具返回的结果 ... (这个思考/行动/观察循环可以重复多次) 最终答案基于所有观察得出的最终答案 开始 问题{input} 思考{agent_scratchpad} ) # 4. 创建ReAct代理 agent create_react_agent(llm, tools, prompt_template) # 5. 创建代理执行器它负责管理代理的循环执行、解析输出、调用工具。 agent_executor AgentExecutor(agentagent, toolstools, verboseTrue, handle_parsing_errorsTrue) # 6. 运行代理 result agent_executor.invoke({ input: 请先计算256的平方根然后搜索一下这个结果在数学史上有什么特别的意义 }) print(\n--- 最终输出 ---) print(result[output])运行观察与解析 当verboseTrue时你会在控制台看到代理的完整思考过程 进入新的AgentExecutor链... 思考用户的问题分为两部分。首先我需要计算256的平方根。我有一个计算平方根的工具。然后我需要用计算结果去搜索数学史意义。 行动sqrt 行动输入256 观察16.0 思考我已经得到平方根是16。现在我需要搜索“16 平方根 数学史 意义”。 行动search_web 行动输入16 平方根 数学史 意义 观察关于16 平方根 数学史 意义的搜索结果这是一个模拟的搜索结果摘要。 思考根据搜索结果虽然是模拟的我可以组织答案。16是4的平方也是2的4次方在数论和几何中是一个完全平方数历史上常被用作例子。 最终答案256的平方根是16。在数学史上16作为一个完全平方数4²常出现在早期的算术和几何研究中例如在毕达哥拉斯学派的数字理论中平方数具有特殊的几何意义可以排列成正方形。16也是2的4次幂在计算机科学和二进制系统中非常重要。 链结束。避坑指南工具描述至关重要LLM完全依赖工具函数的docstring即计算一个数的平方根。来决定是否以及如何调用它。描述必须清晰、准确。处理解析错误handle_parsing_errorsTrue参数非常重要。代理的输出有时可能不符合预期的格式如缺少“行动”行这个参数能防止整个链因解析失败而崩溃通常会尝试让LLM重试或返回友好错误。控制循环与成本代理可能会陷入“思考-行动”的死循环。AgentExecutor有max_iterations和max_execution_time参数来强制限制务必设置否则可能产生巨额API调用费用。模型选择简单的工具调用gpt-3.5-turbo可能够用。但对于需要复杂规划和推理的多步骤任务gpt-4或claude-3系列模型的成功率会高得多尽管成本也更高。6. 记忆Memory实现让对话拥有上下文无状态的LLM无法记住之前的对话。Memory模块就是为了解决这个问题。6.1 对话缓冲区记忆这是最简单的记忆形式保存所有历史对话。# 5_conversation_memory.py from langchain_openai import ChatOpenAI from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationChain # 初始化记忆和模型 memory ConversationBufferMemory(return_messagesTrue) # return_messagesTrue返回消息对象便于使用 llm ChatOpenAI(modelgpt-3.5-turbo, temperature0.7) # 创建对话链 conversation ConversationChain(llmllm, memorymemory, verboseTrue) print(第一轮对话) response1 conversation.invoke({input: 你好我叫小明。}) print(fAI: {response1[response]}) print(\n第二轮对话依赖记忆) response2 conversation.invoke({input: 你还记得我的名字吗}) print(fAI: {response2[response]}) # 查看当前记忆内容 print(\n当前记忆缓冲区) print(memory.load_memory_variables({}))6.2 对话摘要记忆当对话很长时缓冲区记忆会消耗大量Token。摘要记忆则只保存一个不断更新的对话摘要。from langchain.memory import ConversationSummaryMemory from langchain_openai import ChatOpenAI from langchain.chains import ConversationChain llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 使用一个专门的LLM来生成摘要可以是另一个更便宜的模型 summary_llm ChatOpenAI(modelgpt-3.5-turbo-16k, temperature0) # 使用长上下文模型 memory ConversationSummaryMemory( llmsummary_llm, return_messagesTrue, memory_keychat_history # 指定记忆在Prompt中的变量名 ) conversation ConversationChain(llmllm, memorymemory, verboseFalse) # 进行多轮对话 conversation.invoke({input: 我喜欢编程和爬山。}) conversation.invoke({input: 编程里我最喜欢Python语言。}) conversation.invoke({input: 爬山我喜欢去四川的四姑娘山。}) print(当前的对话摘要) print(memory.load_memory_variables({})[chat_history])内存方案选型建议ConversationBufferMemory适合短对话、调试场景信息完整。ConversationSummaryMemory适合长对话能节省Token但摘要可能丢失细节。ConversationSummaryBufferMemory混合模式保留最近N条原始对话更早的则摘要。这是平衡效果和成本的常用选择。VectorStoreRetrieverMemory将历史对话向量化存储根据当前问题检索相关历史片段。适用于需要从很长历史中精准回忆特定信息的场景但实现更复杂。7. 常见问题、调试与性能优化7.1 高频错误与解决方案问题现象可能原因解决方案ModuleNotFoundError: No module named ‘langchain.xxx’LangChain版本更新模块路径已变更。检查导入语句。v0.1后很多模块移到了langchain-community。使用from langchain_community.xxx import yyy。查看官方文档或GitHub源码确认正确路径。OpenAIError: Invalid API KeyAPI Key未设置或错误。1. 确认环境变量OPENAI_API_KEY已设置且正确。2. 在代码中打印os.getenv(“OPENAI_API_KEY”)的前几位检查切勿打印全部。3. 检查是否在代理后需要设置openai.proxy。代理陷入循环不停调用工具工具描述不清、Prompt引导不力或模型推理能力不足。1. 优化工具描述确保精确。2. 在系统Prompt中明确限制步骤如“最多思考3步”。3. 设置max_iterations如5。4. 升级到更强的模型GPT-4。检索问答的答案与文档无关1. 文档分割不合理。2. 检索到的片段不相关。3. LLM“幻觉”。1. 调整chunk_size和chunk_overlap。2. 尝试不同的embedding模型。3. 增加检索数量k或使用MMR搜索来平衡相关性与多样性。4. 在Prompt中加强指令“严格依据上下文回答”。RateLimitErrorAPI调用频率超限。1. 增加重试逻辑和指数退避。2. 使用langchain的OpenAI类时可配置max_retries参数。3. 对于批量处理主动控制请求速率如time.sleep。7.2 成本控制与性能优化1. 缓存Caching 重复的相同请求浪费钱。可以使用InMemoryCache或SQLiteCache。from langchain.globals import set_llm_cache from langchain.cache import InMemoryCache set_llm_cache(InMemoryCache()) # 设置全局缓存 # 之后完全相同的LLM调用会直接从缓存返回结果大幅节省成本。2. 流式响应Streaming 对于需要长时间生成的文本流式输出能极大提升用户体验。from langchain_openai import ChatOpenAI llm ChatOpenAI(modelgpt-3.5-turbo, streamingTrue) chain prompt_template | llm for chunk in chain.stream({input: 写一个关于LangChain的故事}): if hasattr(chunk, content): print(chunk.content, end, flushTrue) # 逐块打印3. 跟踪与评估LangSmith 对于生产应用你需要知道链的每一步发生了什么、耗时多少、效果如何。LangChain官方提供了LangSmith平台。作用记录每次链的执行轨迹Trace可视化输入输出监控Token消耗和延迟进行测试和评估。配置设置环境变量LANGCHAIN_TRACING_V2true和LANGCHAIN_API_KEY你的所有链调用会自动记录到LangSmith。心得在开发调试阶段就接入LangSmith它能帮你快速定位是哪个环节如工具调用、检索出了问题是优化应用不可或缺的工具。7.3 部署考量当你的LangChain应用从脚本变成服务时Web框架使用FastAPI或Flask将你的链包装成REST API端点。状态管理对于记忆Memory需要将其与用户会话Session关联并持久化到数据库如Redis而不是放在内存里。异步支持LangChain支持异步调用ainvoke,astream。在Web服务中使用异步可以更好地处理并发请求。配置管理将所有模型参数、API密钥、向量库连接信息等通过配置文件如config.yaml或环境变量管理便于不同环境开发、生产切换。构建一个健壮的LangChain应用远不止调用API那么简单。它涉及提示工程、数据管道设计、错误处理、成本控制和运维监控等一系列工程化问题。一个好的教程正是要带领开发者穿越这片“迷雾之地”从完成第一个Demo到最终交付一个稳定、可维护的生产级应用。这个过程充满挑战但当你看到自己构建的AI智能体能够可靠地解决复杂任务时那种成就感也是无与伦比的。