1. 引言:LangChain 到底解决了什么问题
很多初学者第一次接触 LangChain 时,都会被它庞大的模块体系吓到:模型封装、提示词模板、记忆、工具调用、Agent、检索……看起来什么都有,却又说不清它到底帮你干了什么活。本文不打算罗列 API,而是从「它替你省掉了哪些重复劳动」这个角度,把 LangChain 在 Agent 开发中的价值讲透,并给出可运行的代码实战。
一句话总结:LangChain 帮你把「调模型」这件小事,升级成了「编排一套会思考、会调用工具、会记忆、会检索的完整系统」这件大事。它把 AI 应用开发中大量重复、易错、与业务无关的胶水代码抽象成标准组件,让你专注于业务逻辑本身。
2. 核心价值拆解:LangChain 替你干了五类活
在进入代码之前,先建立整体认知。LangChain 在 Agent 开发中主要替你承担以下五类工作:
- 模型接入的统一封装:无论你用的是 OpenAI、Anthropic 还是本地模型,LangChain 都提供一致的调用接口,切换模型时业务代码几乎不用改。
- 提示词工程的结构化:把提示词从「裸字符串」升级为「可复用、可组合、可版本管理的模板」,并自动处理变量注入。
- 对话记忆的自动管理:帮你维护历史消息、控制上下文窗口长度,避免「聊着聊着就忘了前面说了什么」。
- 工具调用的协议标准化:把普通 Python 函数包装成模型可识别的 Tool,让模型能按需调用外部能力。
- Agent 决策循环的编排:模型「思考 → 决定调用哪个工具 → 观察结果 → 再思考」的循环,由框架替你跑起来。
下面我们逐一用代码验证这些能力。
3. 环境准备与基础依赖
本文所有代码基于 Python 3.10+ 和 LangChain 0.3.x。建议先创建虚拟环境并安装依赖:
pip install langchain langchain-openai langchain-community如果你使用 OpenAI 兼容接口(例如本地部署的模型服务),可以通过环境变量或直接传入参数配置 API Key 和 Base URL:
import os os.environ["OPENAI_API_KEY"] = "your-api-key" os.environ["OPENAI_BASE_URL"] = "https://api.openai.com/v1"4. 第一类活:模型接入的统一封装
没有 LangChain 时,你直接调用各家 SDK,代码风格完全不同。有了 LangChain,你只需要面向统一的ChatModel接口编程。
from langchain_openai import ChatOpenAI 统一接口:换模型只改这一行 llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7) response = llm.invoke("用一句话解释什么是 Agent") print(response.content)如果你想换成 Anthropic 的 Claude,只需要把导入和实例化部分替换为ChatAnthropic,下游的调用方式llm.invoke(...)完全不变。这就是「统一封装」带来的直接收益:模型供应商被抽象成可替换的插件。
5. 第二类活:提示词工程的结构化
裸字符串拼接提示词容易出错且难以维护。LangChain 的PromptTemplate把提示词变成可复用的模板:
from langchain_core.prompts import ChatPromptTemplate prompt = ChatPromptTemplate.from_messages([ ("system", "你是一位资深的{domain}专家,回答要简洁、准确。"), ("human", "请解释一下:{question}"), ]) 渲染模板 messages = prompt.invoke({ "domain": "人工智能", "question": "什么是检索增强生成(RAG)?", }) print(messages)更进一步,LangChain 还支持FewShotPromptTemplate(少样本示例)、PipelinePromptTemplate(模板组合)等高级能力,让提示词像代码一样具备结构性和可维护性。
6. 第三类活:对话记忆的自动管理
大模型本身是无状态的,每次调用都是「全新对话」。LangChain 的 Memory 模块帮你维护历史上下文,并自动处理窗口截断。
from langchain.memory import ConversationBufferMemory from langchain_core.chat_history import InMemoryChatMessageHistory from langchain_core.messages import HumanMessage, AIMessage 使用内存消息历史 history = InMemoryChatMessageHistory() history.add_user_message("我叫小明,是一名后端工程师。") history.add_ai_message("你好小明!很高兴认识你。") 把历史注入到下一次对话 llm = ChatOpenAI(model="gpt-4o-mini") messages = [ {"role": "system", "content": "你是一个友好的助手。"}, *history.messages, {"role": "user", "content": "我叫什么名字?"}, ] response = llm.invoke(messages) print(response.content) # 输出:你叫小明对于长对话,ConversationSummaryMemory会自动总结早期内容以节省 Token,ConversationBufferWindowMemory则只保留最近 N 轮。这些策略如果手写,既繁琐又容易出错。
7. 第四类活:工具调用的协议标准化
Agent 的核心能力是「调用工具」。LangChain 用@tool装饰器把普通函数变成模型可识别的工具,并自动生成 JSON Schema 描述。
from langchain_core.tools import tool @tool def get_weather(city: str) -> str: """查询指定城市的当前天气。""" # 这里可以替换为真实天气 API return f"{city}今天晴,气温 26℃,适合出行。" @tool def calculate(expression: str) -> str: """计算数学表达式,例如 '1+2*3'。""" return str(eval(expression)) 查看工具自动生成的 Schema print(get_weather.name) print(get_weather.description) print(get_weather.args)LangChain 会自动从函数签名和 docstring 中提取参数名、类型和描述,生成符合 OpenAI Function Calling 规范的 JSON Schema。你不需要手写任何协议代码。
8. 第五类活:Agent 决策循环的编排
把前面所有组件组合起来,就得到了一个完整的 Agent。它会在「思考 → 调用工具 → 观察结果 → 再思考」的循环中自主完成任务。
from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_core.prompts import ChatPromptTemplate 1. 准备工具列表 tools = [get_weather, calculate] 2. 定义提示词 prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个智能助手,可以调用工具来回答问题。"), ("human", "{input}"), ("placeholder", "{agent_scratchpad}"), ]) 3. 创建 Agent agent = create_tool_calling_agent(llm, tools, prompt) 4. 创建执行器 executor = AgentExecutor(agent=agent, tools=tools, verbose=True) 5. 运行 result = executor.invoke({"input": "帮我算一下 (23+45)*2 等于多少,顺便查一下北京的天气。"}) print(result["output"])运行这段代码,你会看到 Agent 自动完成以下动作:先调用calculate计算表达式,再调用get_weather查询天气,最后把两个结果整合成自然语言回答。整个过程你只写了十几行代码,决策循环、工具选择、结果解析全部由框架替你完成。
9. 进阶实战:带检索能力的 RAG Agent
真实业务中,Agent 往往还需要结合私有知识库。下面演示如何把向量检索(RAG)接入 Agent,让它能回答「训练数据之外」的问题。
from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import FAISS from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_core.tools import tool 1. 准备知识库文档 documents = [ "LangChain 是一个用于构建大语言模型应用的框架。", "Agent 是能够自主决策并调用工具的智能体。", "RAG 通过检索外部知识来增强模型的回答能力。", ] 2. 切分并向量化 splitter = RecursiveCharacterTextSplitter(chunk_size=50, chunk_overlap=10) chunks = splitter.create_documents(documents) embeddings = OpenAIEmbeddings() vectorstore = FAISS.from_documents(chunks, embeddings) 3. 把检索封装成工具 @tool def search_knowledge(query: str) -> str: """从内部知识库检索与问题相关的信息。""" docs = vectorstore.similarity_search(query, k=2) return "\n".join([d.page_content for d in docs]) 4. 构建带检索能力的 Agent tools = [search_knowledge] prompt = ChatPromptTemplate.from_messages([ ("system", "你是企业内部知识助手,优先使用检索到的知识回答。"), ("human", "{input}"), ("placeholder", "{agent_scratchpad}"), ]) agent = create_tool_calling_agent(llm, tools, prompt) executor = AgentExecutor(agent=agent, tools=tools, verbose=True) result = executor.invoke({"input": "什么是 RAG?它有什么作用?"}) print(result["output"])这个例子展示了 LangChain 的另一个关键价值:组件可插拔。检索、记忆、工具、模型都是独立模块,你可以像搭积木一样自由组合,构建出适合自己业务的复杂系统。
10. 常见坑与避坑建议
在实际开发中,有几个高频问题值得注意:
- 上下文窗口溢出:Agent 每轮循环都会把历史追加到 prompt 中,长任务容易超限。建议使用
ConversationSummaryMemory或限制最大迭代次数。 - 工具调用失败无重试:默认情况下工具抛异常会导致整个 Agent 失败。建议在工具内部做异常捕获,返回友好的错误信息让模型自行调整。
- 过度依赖模型判断:Agent 的决策质量取决于底层模型能力。复杂任务建议用更强的模型(如 gpt-4o),简单任务用轻量模型以节省成本。
- 忽略安全校验:如果 Agent 能调用执行类工具(如执行 Shell 命令),务必做好权限控制和输入校验,防止注入攻击。
11. 总结
回到开篇的问题:LangChain 到底帮你干了什么活?答案是:它把 AI 应用开发中的重复性、易错性、与业务无关的胶水工作全部抽象成了标准组件。你不再需要手写各家模型的 SDK 适配、不再需要手工拼接提示词、不再需要自己维护对话历史、不再需要为工具调用设计协议、更不需要自己实现 Agent 的决策循环。
你只需要专注于两件事:定义好你的工具,以及设计好你的提示词。剩下的编排工作,交给 LangChain。
希望本文的代码实战能帮你建立起对 LangChain 的整体认知。下一步,建议你从自己的业务场景出发,挑一个最简单的工具(比如查天气、算日期),把它接入 Agent,跑通第一个端到端的智能体应用。