第15章:LangChain 框架——Agent 开发的瑞士军刀
系列导读:LangChain 是 Agent 开发的主流框架。本章讲框架架构、核心概念和实战决策——“什么时候用 LangChain,什么时候应该甩开它”。
一、LangChain 要解决的问题
手工实现一个 Agent,你需要写:
- Tool 注册与解析
- Prompt 模板管理
- Memory 存储维护
- Agent 循环逻辑(ReAct / Plan-and-Execute)
- 错误处理和重试
- 多 Agent 协作(如果需要)
LangChain 把这些都封装成了可复用的组件和链式工具,让 Agent 开发从"从零搭建"变成"组装积木"。
二、LangChain 核心概念
1. Chain(链)
将多个组件按顺序串起来执行:
chain = prompt_template | llm | output_parser
result = chain.invoke({"input": "分析这份数据"})
每个 | 表示前一个组件的输出经过变换传给下一个组件。
2. Agent
预先封装好的 Agent 循环:
agent = create_react_agent(
tools=tools,
llm=llm,
prompt=prompt
)
agent_executor = AgentExecutor(agent=agent, tools=tools, max_iterations=10)
result = agent_executor.invoke({"input": "帮我查天气"})
预置的 Agent 类型:
- ReAct Agent:Thought → Action → Observation 循环
- Plan-and-Execute Agent:先规划计划,再按步骤执行
- Structured Chat Agent:支持多参数工具调用
- Conversational Agent:带记忆的对话型 Agent
3. Tool
from langchain.tools import tool
@tool
def get_weather(city: str) -> str:
"""查询指定城市的天气信息。"""
return f"{city}今天天气晴朗,25度"
tools = [get_weather]
装饰自动提取函数签名和 docstring 作为 tool schema,非常简洁。
4. Memory
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory()
memory.save_context({"input": "我喜欢简洁风格"}, {"output": "好的,我会注意"})
# memory 会自动维护对话历史,在 Agent 调用时作为 context 注入
5. Retriever(检索器)
把 RAG 的检索部分封装好:
retriever = Chroma.from_documents(docs, embeddings).as_retriever()
result = retriever.invoke("什么是 RAG?")
三、LangChain 的优势
- 快速原型:组装积木的方式,几小时就能跑通一个 Agent
- 生态丰富:内置大量 ready-to-use 的 tools、retrievers、memory 模块
- 标准接口:统一的 invoke/stream/batch 接口,切换底层模型无痛
- 调试友好:链式调用的中间步骤都能打印出来
四、LangChain 的天坑
坑1:过度封装
LangChain 的链式抽象堆了太多层,理解一个简单调用背后实际发生了什么,需要追踪好几层源码。
坑2:性能问题
链式调用每层都有类型转换、验证、异常捕获,对高频场景来说有不可忽视的 overhead。
坑3:版本迭代快
API 变动频繁,一个用 v0.1 写的项目,几个月后 v0.2 就 break。
坑4:不适合深度定制
你要做一个高度定制的推理流程,LangChain 的约束框架可能碍手碍脚。
五、“什么时候用 LangChain,什么时候手搓?”
| 场景 | 推荐方案 |
|---|---|
| 快速原型验证 / MVP | 用 LangChain |
| 标准 Agent 模式(ReAct、工具调用) | 用 LangChain |
| 内部工具/低频应用 | 用 LangChain |
| 高并发生产服务 | 手搓核心关键路径 |
| 极度定制化的推理流程 | 手搓 |
| 需要极致性能优化 | 手搓 |
| 大规模 Multi-Agent 系统 | 手搓核心编排,局部用框架 |
最务实的做法:用 LangChain 快速做出 MVP,验证业务价值后再决定哪些部分需要重写。
六、LangChain 实战:一个完整的 RAG Agent
from langchain import hub
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
# 1. 加载文档
loader = WebBaseLoader("https://docs.python.org/3/")
docs = loader.load()
# 2. 切割
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
splits = text_splitter.split_documents(docs)
# 3. 存入向量库
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())
retriever = vectorstore.as_retriever()
# 4. 构建 RAG Chain
prompt = hub.pull("rlm/rag-prompt")
llm = ChatOpenAI(model="gpt-4o")
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# 5. 使用
response = rag_chain.invoke("Python 的 GIL 是什么?")
七、LangChain 的替代者
| 框架 | 特点 | 适用场景 |
|---|---|---|
| LangGraph | LangChain 官方出的图编排工具,比链更灵活 | 复杂 Multi-Agent 编排 |
| LlamaIndex | 专注 RAG,文档加载和索引更强 | 知识库/文档问答 |
| CrewAI | 专注 Multi-Agent 协作场景 | 多智能体项目 |
| AutoGen | 微软出的 Multi-Agent 对话框架 | 研究/多轮讨论 |
| 直接 SDK | 不用框架,直接调 OpenAI/Anthropic SDK | 简单/高性能场景 |
八、本章小结
- LangChain 是 Agent/RAG 快速开发和原型验证的首选框架
- 核心概念:Chain、Agent、Tool、Memory、Retriever
- 优势是组装敏捷和生态丰富,劣势是过度封装和性能开销
- 选型建议:MVP 用 LangChain,生产级核心路径可重写
- LlamaIndex(RAG 更强)、CrewAI(Multi-Agent 更强)是重要替代方案
思考题
- 你在什么情况下会用 LlamaIndex 而不是 LangChain?两个框架的核心差异在哪?
- 如果你的 Agent 需要同时走 “向量检索 + API 调用 + 代码执行 + 最终报告生成” 四条路径,LangChain 的链式抽象够用吗?你会怎么设计架构?