LangChain五大核心概念解析:从组件化到智能体构建 在实际 AI 应用开发中直接调用大语言模型 API 往往只能完成简单的问答。当需求变得复杂例如需要模型记住对话历史、调用外部工具、处理长文档或执行多步骤推理时代码会迅速变得臃肿且难以维护。这正是 LangChain 这类框架要解决的核心问题。它通过提供一套标准化的抽象组件将复杂的 AI 应用流程模块化让开发者能像搭积木一样构建功能强大的 AI Agent。本文面向已经了解大语言模型基础调用希望构建更复杂、更智能应用的开发者。我们将深入 LangChain 的五个核心概念Model I/O、Retrieval、Chains、Memory和Agents。理解这些概念不仅是使用 LangChain 的基础更是理解现代 AI Agent 架构设计思想的关键。通过本文你将能清晰地知道每个组件的作用、如何组合它们并能够动手搭建一个具备记忆、工具调用和知识检索能力的简易 AI Agent。1. 理解 LangChain 的核心设计思想组件化与编排在深入具体概念前必须先理解 LangChain 的设计哲学。它不是一个黑盒的“AI 应用生成器”而是一个组件化框架和编排工具。其核心价值在于将 AI 应用开发中常见的模式抽象为可复用、可互换的“乐高积木”。1.1 为什么需要组件化想象一下你要开发一个能查询公司内部文档的聊天机器人。你需要处理以下问题将用户问题自然语言转换为模型能理解的格式Prompt。从海量文档中快速找到相关片段Retrieval。将找到的片段和用户问题组合成一个有效的指令发给模型Prompt Engineering。让模型能参考之前的对话历史Memory。当问题涉及计算或实时信息时让模型能调用计算器或搜索引擎Tool Calling。如果不使用框架你可能需要自己编写大量的胶水代码来处理这些环节之间的数据传递、错误处理和流程控制。LangChain 将这些环节标准化为组件例如LLM模型、PromptTemplate提示词模板、DocumentLoader文档加载器、VectorStore向量数据库、Memory记忆和Tool工具。1.2 编排Orchestration是关键仅有组件还不够如何将它们有序地连接起来执行一个任务这就是编排。LangChain 提供了Chain和Agent两种主要的编排范式。Chain链预定义的、线性的执行流程。例如“检索文档 - 组合提示词 - 调用模型 - 解析输出”就是一个链。它稳定、可预测适用于流程固定的任务。Agent智能体由模型根据当前情况动态决定下一步执行哪个动作如使用哪个工具。它引入了推理和决策能力适用于需要多步骤、条件判断的复杂任务。理解了“组件化”和“编排”这两大支柱我们再去看具体的五个核心概念就会明白它们各自在架构中扮演的角色。2. 核心概念一Model I/O —— 与模型对话的标准化接口Model I/O是 LangChain 中最基础的模块它封装了与语言模型交互的整个过程使其变得统一和可配置。这个过程主要分为三个子环节输入Prompt、调用模型LLM/ChatModel、输出解析OutputParser。2.1 Prompts从字符串模板到动态构建Prompt 是指导模型行为的指令。LangChain 的PromptTemplate允许你创建带有变量的模板。from langchain.prompts import PromptTemplate # 创建一个简单的提示词模板 template “请根据以下上下文回答问题。\n\n上下文{context}\n\n问题{question}\n\n答案” prompt_template PromptTemplate.from_template(template) # 动态填充变量 filled_prompt prompt_template.format(context“LangChain 是一个用于开发大语言模型应用的框架。” question“LangChain 是什么”) print(filled_prompt)输出将是请根据以下上下文回答问题。 上下文LangChain 是一个用于开发大语言模型应用的框架。 问题LangChain 是什么 答案为什么重要它实现了逻辑与内容的分离。你可以像管理配置文件一样管理不同的提示词模板而无需在代码中拼接字符串。2.2 Models统一的模型调用层LangChain 支持多种模型提供商OpenAI Anthropic Google 本地模型等。通过抽象层你可以用几乎相同的代码切换不同的模型。from langchain_openai import ChatOpenAI from langchain_anthropic import ChatAnthropic # 使用 OpenAI GPT-4 llm_openai ChatOpenAI(model“gpt-4” temperature0) # 使用 Anthropic Claude llm_claude ChatAnthropic(model“claude-3-sonnet-20240229” temperature0) # 调用方式完全一致 # response llm_openai.invoke(filled_prompt) # response llm_claude.invoke(filled_prompt)关键参数解释model指定使用的模型名称。temperature控制输出的随机性0-1。值越低输出越确定和一致值越高输出越有创造性。2.3 Output Parsers将模型输出结构化模型的原始输出是文本。OutputParser负责将其解析为程序可用的结构化数据如 JSON、列表或自定义对象。from langchain.output_parsers import CommaSeparatedListOutputParser from langchain.prompts import PromptTemplate parser CommaSeparatedListOutputParser() format_instructions parser.get_format_instructions() # 获取格式说明如“你的回答应该是一个用逗号分隔的列表。” prompt PromptTemplate( template“列举三种主要的水果。\n{format_instructions}\n” input_variables[] partial_variables{“format_instructions”: format_instructions} ) chain prompt | llm_openai | parser # 使用 LangChain 表达式语言LCEL组合 result chain.invoke({}) print(result) # 输出例如 [‘苹果’ ‘香蕉’ ‘橙子’]为什么重要它使得从模型获取的信息可以直接用于后续的程序逻辑是实现自动化工作流的关键。3. 核心概念二Retrieval —— 让模型拥有“长期记忆”大语言模型本身的知识受限于其训练数据且无法记住非公开或实时信息。Retrieval检索模块通过从外部知识源文档、数据库、API中动态查找相关信息并注入到提示词中来扩展模型的能力。这是构建“知识库问答”系统的核心。3.1 检索流程从文档到答案一个典型的检索流程包含以下步骤加载Loading从源文件、网页、数据库读取数据。分割Splitting将长文档切分成语义相关的小块chunks。向量化Embedding使用嵌入模型将文本块转换为数值向量。存储Storing将向量存入向量数据库。检索Retrieval将用户问题也向量化并在数据库中查找最相似的文本块。生成Generation将检索到的文本块作为上下文与问题一起发送给模型生成答案。3.2 关键组件与代码示例from langchain_community.document_loaders import TextLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings from langchain_chroma import Chroma # 1. 加载文档 loader TextLoader(“./company_handbook.txt”) documents loader.load() # 2. 分割文档 text_splitter RecursiveCharacterTextSplitter(chunk_size500 chunk_overlap50) docs text_splitter.split_documents(documents) # 3. 初始化嵌入模型并存入向量数据库 embeddings OpenAIEmbeddings() vectorstore Chroma.from_documents(documentsdocs embeddingembeddings persist_directory“./chroma_db”) # 4. 创建检索器 retriever vectorstore.as_retriever(search_kwargs{“k”: 2}) # 检索最相关的2个片段 # 5. 使用检索到的内容进行问答 from langchain.chains import RetrievalQA from langchain_openai import ChatOpenAI llm ChatOpenAI(model“gpt-3.5-turbo” temperature0) qa_chain RetrievalQA.from_chain_type(llmllm retrieverretriever) answer qa_chain.invoke({“query”: “公司的年假政策是怎样的”}) print(answer[“result”])参数与注意事项chunk_size每个文本块的大小。太小可能丢失上下文太大可能包含无关信息。通常 500-1000 字符是常见起点。chunk_overlap块之间的重叠字符数。这有助于保持上下文的连贯性。search_kwargs{“k”: n}控制返回多少个相关片段。需要平衡信息完整性和提示词长度限制。注意向量检索的质量高度依赖于文本分割策略和嵌入模型。生产环境中需要根据实际文档类型技术文档、对话记录、代码调整分割参数并可能测试不同的嵌入模型。4. 核心概念三Chains —— 将组件串联成固定流程Chain是 LangChain 得名的原因。它将多个组件或其他 Chain按预定顺序连接起来形成一个可执行的序列。这是实现复杂但流程固定的 AI 应用的主要方式。4.1 链的类型与 LCELLangChain 提供了两种主要的构建链的方式传统Chain类和更灵活强大的LangChain 表达式语言LCEL。LCEL 使用管道运算符|来连接组件推荐在新项目中使用。from langchain.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain.schema.output_parser import StrOutputParser # 使用 LCEL 构建一个翻译链 prompt ChatPromptTemplate.from_template(“将以下英文翻译成中文{text}”) llm ChatOpenAI(model“gpt-3.5-turbo” temperature0) output_parser StrOutputParser() translation_chain prompt | llm | output_parser result translation_chain.invoke({“text”: “Hello, LangChain!”}) print(result) # 输出你好LangChain4.2 构建复杂链顺序链与检索链一个链可以包含多个步骤。例如一个总结链可以先提取关键词再根据关键词进行总结。from langchain.prompts import PromptTemplate from langchain.chains import LLMChain SimpleSequentialChain # 链1生成关键词 keyword_prompt PromptTemplate( input_variables[“document”] template“请从以下文档中提取三个核心关键词\n{document}” ) keyword_chain LLMChain(llmllm promptkeyword_prompt) # 链2根据关键词总结 summary_prompt PromptTemplate( input_variables[“keywords”] template“请基于这三个关键词{keywords} 生成一段简短的文档摘要。” ) summary_chain LLMChain(llmllm promptsummary_prompt) # 顺序组合链 overall_chain SimpleSequentialChain(chains[keyword_chain summary_chain] verboseTrue) document_text “LangChain 是一个开源框架...此处为长文档内容” final_result overall_chain.invoke(document_text) print(final_result[‘output’])当verboseTrue时你会看到链的每一步执行过程和中间结果这对于调试非常有用。常见链类型LLMChain最基本的链组合一个 PromptTemplate 和一个 LLM。SequentialChain按顺序执行多个链可以传递多个输入输出。RetrievalQA我们之前用过的是专门为“检索-问答”模式封装的链。ConversationalRetrievalChain在RetrievalQA基础上增加了对话历史管理。5. 核心概念四Memory —— 为对话赋予上下文Memory使链或 Agent 能够记住跨多次交互的信息。这对于聊天机器人、多轮对话分析等场景至关重要。5.1 记忆的类型LangChain 提供了多种记忆类型适用于不同场景记忆类型描述适用场景ConversationBufferMemory简单地将所有对话历史以字符串形式保存在缓冲区。对话轮次较少需要完整历史。ConversationBufferWindowMemory只保留最近 K 轮对话。避免提示词因历史过长而超出模型限制。ConversationSummaryMemory使用 LLM 定期总结之前的对话只保留总结。长对话需要保留核心信息但节省 token。ConversationEntityMemory记忆对话中提到的具体实体人物、地点等及其属性。需要跟踪具体对象细节的复杂对话。5.2 在链中使用记忆以下示例展示如何将一个普通的链升级为带记忆的对话链。from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationChain from langchain_openai import ChatOpenAI # 初始化记忆和模型 memory ConversationBufferMemory() llm ChatOpenAI(model“gpt-3.5-turbo” temperature0.7) # 创建对话链 conversation ConversationChain(llmllm memorymemory verboseTrue) # 进行多轮对话 print(conversation.invoke({“input”: “你好我叫小明。”})[‘response’]) print(conversation.invoke({“input”: “我的名字是什么”})[‘response’]) # 模型会记得名字运行上述代码在verbose模式下你可以看到发送给模型的提示词中包含了之前的对话历史。5.3 记忆与检索的结合在RetrievalQA中如果需要结合历史对话应使用ConversationalRetrievalChain。它会自动将当前问题与历史对话重新组合rewrite形成一个独立的、包含上下文的问题再去检索和回答。from langchain.chains import ConversationalRetrievalChain from langchain.memory import ConversationBufferMemory memory ConversationBufferMemory(memory_key“chat_history” return_messagesTrue) qa_chain ConversationalRetrievalChain.from_llm( llmllm retrieverretriever # 上一节定义的检索器 memorymemory verboseTrue ) # 现在可以进行多轮基于知识库的问答了6. 核心概念五Agents —— 让模型自主决策与执行Agent是 LangChain 中最能体现“智能体”概念的部分。与固定流程的Chain不同Agent将语言模型作为“大脑”动态地决定为了完成一个目标需要执行哪些动作调用哪些工具并根据执行结果决定下一步。6.1 Agent 的核心组件一个 Agent 通常由以下几部分组成LLM负责推理和决策的大脑。ToolsAgent 可以调用的函数。例如搜索引擎、计算器、数据库查询、代码执行器等。Toolkits为特定领域如 SQL、文件系统预置的一组工具。Agent Executor运行 Agent 的引擎负责调用模型、解析输出、执行工具、并将结果反馈给模型循环直到任务完成或达到限制。6.2 构建一个简单的 Agent以下示例创建一个能使用搜索引擎和计算器的 Agent。from langchain.agents import AgentExecutor create_react_agent from langchain import hub from langchain.tools import Tool from langchain_community.utilities import SerpAPIWrapper from langchain.agents import load_tools import math # 1. 定义自定义工具 def calculate_power(base: float exponent: float) - float: “”“计算幂。”“” return math.pow(base exponent) # 2. 创建工具列表 search SerpAPIWrapper() # 需要 SERPAPI_API_KEY 环境变量 tools [ Tool( name“Search” funcsearch.run description“在互联网上搜索当前事件或事实信息。当你需要回答关于近期事件或具体事实的问题时使用。” ) Tool( name“Calculator” funclambda x: eval(x) # 注意生产环境请使用更安全的计算库如 numexpr description“执行数学计算。输入一个数学表达式字符串如 ‘2 2’ 或 ‘sqrt(16)’。” ) Tool( name“Power” funclambda x: calculate_power(**eval(x)) description“计算幂。输入一个字典字符串如 ‘{\“base\“: 2 \“exponent\“: 3}’ 返回 base^exponent。” ) ] # 3. 获取 ReAct 提示词模板并创建 Agent prompt hub.pull(“hwchase17/react”) llm ChatOpenAI(model“gpt-4” temperature0) agent create_react_agent(llm tools prompt) # 4. 创建执行器 agent_executor AgentExecutor(agentagent toolstools verboseTrue handle_parsing_errorsTrue) # 5. 运行 Agent result agent_executor.invoke({“input”: “苹果公司最新的股价是多少然后用这个股价计算一下如果我买100股需要多少钱。”}) print(result[“output”])关键点解释create_react_agent使用 ReActReasoning Acting框架该框架鼓励模型以“思考 - 行动 - 观察”的循环来解决问题。Tool的description至关重要模型根据工具的描述来决定在什么情况下使用哪个工具。描述必须清晰准确。verboseTrue会打印出 Agent 的完整思考过程包括它的“Thought”思考、“Action”选择工具、“Action Input”工具输入和“Observation”工具输出。handle_parsing_errorsTrue当模型输出的指令无法被解析为有效的工具调用时让执行器尝试修复而不是直接崩溃。6.3 Agent 执行流程与排错运行上述代码你会看到类似以下的输出已简化Thought: 用户问了两个问题。首先需要获取苹果公司的最新股价这是一个事实性问题我需要搜索。然后需要用这个股价进行计算。 Action: Search Action Input: 苹果公司最新股价 Observation: [搜索引擎返回的结果例如苹果公司AAPL最新股价为 $172.33] Thought: 我已经获得了股价 $172.33。现在需要计算购买100股的总金额。这是一个数学计算应该使用计算器。 Action: Calculator Action Input: 172.33 * 100 Observation: 17233.0 Thought: 我计算出了总金额是17233美元。现在可以给出最终答案了。 Final Answer: 苹果公司最新股价约为172.33美元。购买100股需要大约17233美元。常见问题与排查Agent 不调用工具直接回答检查工具描述是否清晰。模型可能认为自己的知识足以回答问题。尝试在问题中明确要求“请使用搜索工具查找”。解析错误Parsing Error模型输出的格式不符合工具调用指令。确保使用handle_parsing_errorsTrue并检查提示词模板是否合适。ReAct 模板通常比较稳定。无限循环模型可能陷入“思考-行动”的死循环。通过max_iterations和max_execution_time参数限制执行器的运行次数和时间。7. 综合实战构建一个具备记忆、知识和工具调用能力的 AI Agent现在我们将前面所有概念组合起来构建一个相对完整的 AI Agent。这个 Agent 能够记住与用户的对话历史Memory。从内部知识库中查找信息Retrieval。在需要时使用计算和搜索工具Agent Tools。通过一个统一的接口处理用户请求。7.1 架构设计与组件选择我们将采用“路由”的思想。设计一个主 Agent它根据用户问题的类型决定走哪条子链通用聊天使用带记忆的ConversationChain。知识库问答使用带记忆的ConversationalRetrievalChain。需要计算或实时信息使用Tool-calling Agent。由于 LangChain 本身不直接提供这种高级路由我们可以通过一个简单的判断逻辑或使用LLMRouterChain来模拟。这里为了清晰我们用一个基于关键词的简单路由逻辑来演示。7.2 代码实现from langchain.chains import ConversationChain ConversationalRetrievalChain from langchain.agents import AgentExecutor create_react_agent from langchain.memory import ConversationBufferMemory from langchain.prompts import PromptTemplate from langchain import hub import re class MultiCapabilityAgent: def __init__(self llm retriever tools): self.llm llm self.retriever retriever self.tools tools # 初始化通用聊天记忆和链 self.chat_memory ConversationBufferMemory() self.chat_chain ConversationChain(llmllm memoryself.chat_memory) # 初始化知识库问答记忆和链 self.qa_memory ConversationBufferMemory(memory_key“chat_history” return_messagesTrue) self.qa_chain ConversationalRetrievalChain.from_llm( llmllm retrieverretriever memoryself.qa_memory verboseFalse ) # 初始化工具调用 Agent agent_prompt hub.pull(“hwchase17/react”) agent create_react_agent(llm tools agent_prompt) self.agent_executor AgentExecutor(agentagent toolstools verboseFalse handle_parsing_errorsTrue max_iterations3) def route_question(self query): “”“简单的基于关键词的路由逻辑。”“” query_lower query.lower() # 如果包含“计算”、“多少”、“”、“-”、“*”、“/”等优先考虑工具 Agent尤其是计算 if re.search(r‘计算|多少|^[\d\s\\-\*\/\(\)]$’ query_lower): return “agent” # 如果包含公司、产品、政策等特定名词假设需要知识库 elif re.search(r‘公司|产品|政策|流程|手册’ query_lower): return “qa” # 否则走通用聊天 else: return “chat” def invoke(self query): route self.route_question(query) print(f“路由决策{route}”) if route “agent”: try: result self.agent_executor.invoke({“input”: query}) return result[“output”] except Exception as e: return f“工具调用失败将转为通用聊天。错误{e}” elif route “qa”: result self.qa_chain.invoke({“question”: query}) return result[“answer”] else: # chat result self.chat_chain.invoke({“input”: query}) return result[“response”] # 初始化组件假设 retriever 和 tools 已按前文定义好 # llm ChatOpenAI(...) # retriever vectorstore.as_retriever(...) # tools [Tool(...) ...] # 创建全能 Agent my_agent MultiCapabilityAgent(llmllm retrieverretriever toolstools) # 进行多轮交互 questions [ “你好” “我们公司的年假有多少天” “计算一下 15 天的年假折算成小时是多少按每天8小时计”, “刚才我们聊了什么” ] for q in questions: print(f“用户{q}”) response my_agent.invoke(q) print(f“Agent{response}\n”)7.3 运行分析与优化方向这个简易的 Agent 展示了如何整合多个 LangChain 模块。在实际生产中你需要考虑以下优化更智能的路由使用一个 LLM 来决策路由LLMRouterChain而不是简单的关键词匹配。记忆共享目前聊天记忆和问答记忆是分离的。可以考虑使用更高级的记忆结构或在路由时传递相关历史。错误处理与降级如代码所示当工具调用失败时应有降级策略如转为聊天或直接搜索。提示词工程为每个链和 Agent 精心设计提示词以优化其表现。性能与成本检索和工具调用可能涉及网络 I/O 和额外费用。需要考虑缓存、异步调用和成本控制。8. 生产环境部署与最佳实践将基于 LangChain 的 AI Agent 从开发环境推向生产需要关注稳定性、可维护性和性能。8.1 配置管理切勿将 API 密钥等敏感信息硬编码在代码中。使用环境变量或专业的配置管理工具。# .env 文件 OPENAI_API_KEYsk-... SERPAPI_API_KEY...# 在代码中读取 from dotenv import load_dotenv import os load_dotenv() openai_api_key os.getenv(“OPENAI_API_KEY”)8.2 日志与监控LangChain 内置的verboseTrue在开发时很有用但在生产环境应接入结构化的日志系统如 Logging 模块 JSON 格式输出并监控关键指标每次调用的 Token 消耗。链/Agent 的执行耗时。工具调用的成功/失败率。用户反馈如有。8.3 性能优化向量检索优化索引优化、选择合适的嵌入模型、调整chunk_size和检索的k值。缓存对频繁且结果不变的 LLM 调用或检索结果进行缓存。LangChain 提供了Cache接口可以对接内存InMemoryCache或数据库如RedisCache。异步调用对于 I/O 密集型的操作如调用多个工具、批量处理文档使用异步接口ainvokeabatch可以显著提升吞吐量。8.4 安全与合规工具调用安全像eval()这样的函数极其危险。为工具提供严格的输入验证和白名单机制或使用沙箱环境。内容过滤在 LLM 的输入和输出端部署内容安全过滤器防止生成有害或不当内容。数据隐私确保上传到外部 API如 OpenAI的数据不包含敏感个人信息。考虑对数据进行脱敏或使用本地模型。8.5 版本管理与测试依赖锁定使用poetry或pipenv锁定 LangChain 及其组件的版本避免因自动升级导致的不兼容。集成测试为你的关键链和 Agent 编写测试模拟用户输入并验证输出是否符合预期。这有助于在迭代提示词或升级组件时快速发现回归问题。理解 LangChain 的五大核心概念是构建可维护、可扩展 AI 应用的基石。从标准化的Model I/O开始用Retrieval扩展模型的知识用Chains编排固定流程用Memory引入上下文最后用Agents实现动态决策。在实际项目中你很少会用到所有概念但清晰理解每个组件的职责和边界能让你在设计和调试时游刃有余。下一步可以深入探索 LangChain 更高级的特性如LangGraph用于构建有状态的、循环的复杂工作流或者研究如何将你构建的 Agent 封装为 API 服务。

本月热点