LangChain:构建大语言模型应用与智能体
LangChain 的模型、消息、工具、智能体、记忆、结构化输出、中间件与 RAG 工作流学习笔记。
LangChain
1. 概念
LangChain 是用于构建大语言模型应用和智能体的开发框架,提供模型、消息、工具、智能体、结构化输出、记忆和中间件等可组合组件。
LangChain 的核心目标不是替代大语言模型,而是把模型调用、工具调用和应用逻辑组织成可复用的程序。
当前 LangChain 的智能体入口是 create_agent。一个智能体可以概括为:
其中:
- Model:负责理解输入、生成响应和决定是否调用工具
- Harness:负责提示词、工具、状态管理以及对模型行为的控制
2. LangChain、LangGraph 和 LangSmith
| 组件 | 主要职责 |
|---|---|
| LangChain | 提供模型、工具、消息和智能体等高层抽象 |
| LangGraph | 提供有状态工作流和智能体的底层编排运行时 |
| LangSmith | 提供追踪、调试、评估和部署相关能力 |
LangChain 的智能体构建在 LangGraph 之上,因此可以使用 LangGraph 提供的持久化、人工介入和可恢复执行能力。
适用场景
- 需求较明确,希望快速构建一个带工具的智能体:优先使用 LangChain
- 需要复杂分支、循环、持久化或人工审批:使用 LangGraph
- 需要查看调用链、调试工具调用和评估输出:配合 LangSmith
3. 安装
pip install -U langchain
模型提供商通常需要额外安装对应的集成包,例如 OpenAI、Anthropic、Google 或 Ollama。
pip install -U langchain langchain-openai
4. 基本组成
4.1 模型
模型负责处理消息并生成响应。LangChain 为不同提供商提供统一接口,因此更换模型时通常只需要更换模型标识或集成包。 模型可以使用提供商标识字符串,也可以先初始化成模型对象。
from langchain.chat_models import init_chat_model
model = init_chat_model("openai:gpt-4.1-mini")
response = model.invoke("请解释什么是机器学习")
print(response.content)
4.2 消息
对话通常由不同角色的消息组成:
- System:定义模型的行为和任务边界
- Human:用户输入
- AI:模型输出
- Tool:工具执行结果 使用消息列表可以保留多轮对话上下文。
4.3 工具
工具是模型可以请求程序执行的函数。工具应当有清晰的名称、参数类型和说明。
from langchain.tools import tool
@tool
def get_weather(city: str) -> str:
"""获取指定城市的天气。"""
return f"{city}:晴,25°C"
工具的执行过程通常是:
- 用户提出问题
- 模型判断是否需要工具
- 模型生成工具调用及参数
- LangChain 执行工具
- 工具结果返回给模型
- 模型根据结果生成最终答案
4.4 系统提示词
系统提示词用于规定智能体的角色、行为方式、输出格式和限制条件。
system_prompt = "你是一名准确、简洁的天气助手。"
系统提示词不等同于业务逻辑。需要强制执行的权限、审批和数据校验,应当放在程序代码或中间件中。
5. 创建智能体
使用 create_agent 可以快速创建一个能够调用工具的智能体。
from langchain.agents import create_agent
def get_weather(city: str) -> str:
"""获取指定城市的天气。"""
return f"{city}:晴,25°C"
agent = create_agent(
model="openai:gpt-4.1-mini",
tools=[get_weather],
system_prompt="你是一名准确、简洁的天气助手。",
)
result = agent.invoke({
"messages": [
{"role": "user", "content": "北京今天天气怎么样?"}
]
})
print(result["messages"][-1].content)
智能体会在模型响应中发现工具调用,然后执行工具并继续循环,直到任务完成或达到限制。
6. 智能体调用方式
6.1 invoke
invoke 等待整个执行过程结束并返回最终结果,适合普通请求。
result = agent.invoke({
"messages": [{"role": "user", "content": "你好"}]
})
6.2 多轮对话与短期记忆
为智能体配置 checkpointer,并在每次调用中使用相同的 thread_id,可以保存同一会话的消息历史。
from langgraph.checkpoint.memory import InMemorySaver
agent = create_agent(
model="openai:gpt-4.1-mini",
tools=[],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": "conversation-1"}}
agent.invoke(
{"messages": [{"role": "user", "content": "我叫小明"}]},
config=config,
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "我叫什么?"}]},
config=config,
)
thread_id 标识一段会话,context 则适合传递本次运行的用户信息、配置或依赖项。二者职责不同。
6.3 流式输出
当智能体需要多次调用模型或工具时,可以使用流式输出展示中间过程,减少用户等待最终结果的感受。
for chunk in agent.stream(
{"messages": [{"role": "user", "content": "搜索并总结人工智能新闻"}]},
stream_mode="updates",
):
print(chunk)
实际项目中还应根据需要区分模型文本、工具调用、工具结果和状态更新。
7. 结构化输出
当程序需要稳定地读取模型结果时,不应只依赖自然语言文本,而应指定结构化输出格式。
from pydantic import BaseModel
from langchain.agents import create_agent
class Answer(BaseModel):
summary: str
confidence: float
agent = create_agent(
model="openai:gpt-4.1-mini",
tools=[],
response_format=Answer,
)
result = agent.invoke({
"messages": [{"role": "user", "content": "总结人工智能的定义"}]
})
answer = result["structured_response"]
结构化输出适合用于 API 返回值、数据库写入、表单提取和工作流节点之间的数据传递。
8. 中间件
中间件是在智能体执行循环的关键位置插入逻辑的机制,可以用于:
- 动态修改提示词
- 记录和检查模型调用
- 重试模型或工具调用
- 限制调用次数和成本
- 检测或脱敏个人信息
- 在高风险工具执行前请求人工审批
- 实现路由、降级和模型切换 提示词适合表达软性行为要求;中间件和工具代码适合实现必须执行的规则。
9. 工具设计原则
- 每个工具只负责一个清晰的任务
- 参数使用明确的类型和描述
- 返回结构稳定、简洁且便于模型理解
- 对外部 API、数据库和文件操作处理超时与异常
- 高风险操作增加权限校验和人工审批
- 不要把未经验证的用户输入直接拼接进高权限操作
- 对有副作用的工具设计幂等性,避免重复执行造成重复写入
10. 常见应用模式
10.1 RAG
RAG(Retrieval-Augmented Generation,检索增强生成)通常包括:
- 加载文档
- 切分文档
- 生成向量表示
- 写入向量数据库
- 根据用户问题检索相关内容
- 将检索结果放入模型上下文
- 生成带依据的回答
10.2 工具型智能体
让模型根据任务选择搜索、数据库、计算、文件或业务 API 等工具。
10.3 结构化信息提取
从自然语言、网页或文档中提取字段,并使用 Pydantic 等模式进行校验。
10.4 多智能体
将复杂任务拆分给不同角色的智能体,例如检索、分析、写作和审核。任务之间的路由与状态管理较复杂时,通常应使用 LangGraph。
11. LangChain 的执行逻辑
普通模型调用可以表示为:
带工具的智能体则是循环:
LangChain 负责提供这些环节的接口和组合方式;具体的业务流程、权限和错误处理仍需要由开发者设计。
12. LangChain 的架构层次
LangChain 可以按从底层到高层理解为几个层次:
12.1 模型与集成层
这一层负责连接 OpenAI、Anthropic、Google、Ollama 等模型提供商,并尽量使用统一的调用接口。 主要能力包括:
- 对话模型调用
- 文本嵌入模型调用
- 向量存储集成
- 文档加载器
- 第三方搜索、数据库和业务 API 集成 更换模型时,通常只需要替换模型标识、集成包或初始化参数,应用上层逻辑可以保持不变。
12.2 核心数据结构层
这一层定义应用中传递的数据:
- Message:对话消息
- Tool Call:模型请求调用工具的结构化信息
- Tool Result:工具执行结果
- Document:文档内容及其元数据
- Structured Response:符合指定模式的结果 统一的数据结构有利于把不同提供商和不同业务组件组合起来。
12.3 组合与执行层
多个模型调用、提示词、解析器和工具可以组合为处理链。简单任务可以使用固定的顺序;需要模型自主决定下一步时,则使用智能体循环。 固定链路强调开发者控制顺序,智能体强调模型根据上下文选择工具和下一步动作。
12.4 Agent Harness 层
create_agent 提供智能体运行所需的外壳,通常包括:
- 系统提示词
- 模型
- 工具集合
- 消息状态
- 工具调用循环
- 中间件
- 结构化输出
- 流式输出
- 检查点和运行配置 LangChain 的智能体不是单独的模型,而是模型周围的一套执行机制。
13. Chain、Agent 和 Workflow
13.1 Chain
Chain 是预先确定的步骤序列:
例如:读取文档 → 提取信息 → 格式化结果。 Chain 的优点是流程稳定、容易测试、成本和延迟更可预测。
13.2 Agent
Agent 的下一步由模型根据当前上下文决定:
Agent 适合工具选择不固定、任务步骤数量不确定的场景,但行为更难预测,需要设置工具权限、调用次数和错误处理。
13.3 Workflow
Workflow 是开发者明确规定的业务流程,模型只参与其中某些节点。复杂 Workflow 通常需要显式分支、循环、并行或人工审批,此时 LangGraph 更适合承担流程编排。
13.4 选择原则
- 步骤固定:优先 Chain
- 步骤由模型动态决定:使用 Agent
- 流程复杂且需要持久化、恢复或人工介入:使用 LangGraph 编排 Workflow
14. 提示词管理
提示词通常由系统指令、用户输入、上下文和格式要求组成。
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你是一名严谨的技术助手。"),
("human", "请解释:{question}"),
])
messages = prompt.invoke({"question": "什么是向量数据库?"})
提示词设计应注意:
- 明确任务目标和输出格式
- 说明可使用的工具及其边界
- 区分可信上下文和不可信用户输入
- 为无法回答、工具失败和证据不足定义行为
- 对重要结果使用结构化输出进行校验
15. RAG 的完整流程
RAG 的目标不是让模型记住全部资料,而是在回答前检索相关内容。
15.1 离线索引阶段
- 加载 PDF、Markdown、网页或数据库内容
- 清洗文本并保留来源信息
- 将长文档切分为适合检索的片段
- 使用 Embedding 模型把片段转换为向量
- 将向量、文本和元数据写入向量数据库
15.2 在线问答阶段
- 接收用户问题
- 将问题转换为向量
- 检索相似片段
- 根据元数据过滤或重新排序
- 将片段、来源和用户问题放入提示词
- 调用模型生成答案
- 返回答案和引用来源
15.3 RAG 的常见问题
- 切分过大导致检索不精确
- 切分过小导致上下文缺失
- 只检索相似度最高的片段而忽略关键词
- 没有保存文档来源,导致无法溯源
- 检索结果超过上下文窗口
- 模型把检索内容之外的信息当成事实 因此,RAG 不只是“向量搜索加提示词”,还包括文档处理、检索策略、上下文压缩和答案评估。
16. 模型与工具调用的执行循环
一个工具型智能体的典型循环是:
- 将用户消息和系统提示词送入模型
- 判断模型是否返回工具调用
- 如果没有工具调用,直接得到最终回答
- 如果有工具调用,校验工具名称和参数
- 执行工具并记录工具结果
- 将工具结果追加到消息状态
- 再次调用模型
- 重复直到完成、失败或达到限制 可以表示为:
生产环境中不能只相信模型生成的工具参数,还应在工具层进行权限、类型、范围和业务状态校验。
17. 记忆、状态和 Context
17.1 短期记忆
短期记忆保存当前会话的消息和中间结果,通常通过 checkpointer 与 thread_id 实现。
17.2 长期记忆
长期记忆保存跨会话的用户偏好、事实或业务记录。它不应与当前对话消息简单混在一起,而应通过检索或显式加载进入上下文。
17.3 State
State 是智能体执行期间不断变化的状态,例如消息列表、工具结果、任务进度和结构化字段。
17.4 Context
Context 是本次运行需要使用、但不一定属于对话历史的外部信息,例如用户 ID、权限、模型配置和数据库连接。 区分 State 和 Context 可以避免把敏感配置或临时依赖错误地写入对话历史。
18. 可靠性与安全性
18.1 可靠性
- 为模型和工具调用设置超时
- 对临时网络错误使用有限次数重试
- 为智能体设置最大迭代次数
- 对工具结果进行类型和格式校验
- 为关键流程保留调用日志和追踪信息
- 对不可恢复错误设计降级或人工处理
18.2 安全性
- 工具最小权限原则
- 高风险工具默认需要人工审批
- 对用户输入和检索文档防范提示词注入
- 不让模型直接决定文件路径、SQL 或系统命令的全部内容
- 对敏感信息进行脱敏和访问控制
- 把权限判断放在程序代码中,而不是只写在提示词里
19. LangChain 与 LangGraph 的详细区别
19.1 一句话区别
LangChain 主要解决“如何方便地使用模型、工具和智能体”;LangGraph 主要解决“如何精确地编排一个有状态、可恢复的复杂执行流程”。
19.2 抽象层级
| 对比项 | LangChain | LangGraph |
|---|---|---|
| 定位 | 较高层的 LLM 应用和智能体框架 | 较底层的工作流与智能体编排运行时 |
| 核心入口 | create_agent、模型、工具等 | StateGraph、节点、边和状态 |
| 默认思路 | 组装一个现成的智能体循环 | 自己定义完整的执行图 |
| 学习成本 | 较低,适合快速开始 | 较高,需要理解状态、路由和图执行 |
| 控制程度 | 通过参数、中间件和工具进行配置 | 可以控制每个节点、边和状态更新 |
19.3 核心单元
LangChain 的核心单元是模型、消息、工具和智能体。开发者通常告诉智能体“有哪些工具”和“应该遵守什么提示词”,然后由模型决定是否调用工具。 LangGraph 的核心单元是 State、Node 和 Edge。开发者需要明确:
- 哪些数据进入 State
- 哪些逻辑放在 Node
- 节点之间如何连接
- 哪些条件会产生分支
- 何时循环和终止
19.4 控制流
LangChain 的 Agent 循环通常是预先设计好的通用循环:模型决定是否调用工具,工具结束后再次调用模型。 LangGraph 可以表达更复杂的控制流:
- 固定顺序
- 条件分支
- 多路并行
- 循环和重试
- 子图
- 人工审批后恢复
- 根据状态跳转到父图或其他智能体
19.5 状态管理
LangChain Agent 可以通过消息列表和 checkpointer 保存会话,但多数简单应用只需要关心输入消息和最终输出。 LangGraph 把 State 作为核心设计对象。状态可以包含消息、任务阶段、检索结果、审批结果、错误信息和结构化业务字段,并为每个字段定义覆盖或合并规则。
19.6 持久化和恢复
LangChain 适合短请求和普通多轮对话。复杂持久化能力通常来自它底层使用的 LangGraph。 LangGraph 原生围绕检查点设计,可以在长任务、中断、人工审批、失败重试和进程恢复后继续执行。
19.7 人工介入
LangChain 可以通过中间件或智能体配置加入人工审批。
LangGraph 使用 interrupt 暂停图,并使用 Command(resume=...) 在同一个线程上恢复。对于审批、人工补充信息和高风险操作,LangGraph 的流程边界更清晰。
19.8 可预测性
LangChain Agent 的下一步部分由模型决定,因此灵活但不完全确定,可能出现不必要的工具调用或循环。 LangGraph 可以把关键业务规则写成确定性的节点和边,只让模型负责需要推理的部分,因此更容易审计、测试和限制风险。
19.9 失败处理
LangChain 通常在工具包装器、中间件或 Agent 配置中处理重试、回退和错误提示。 LangGraph 可以把错误作为 State 的一部分,路由到重试节点、备用节点、人工处理节点或结束节点,形成可观察的错误流程。
19.10 多智能体
LangChain 可以快速创建多个角色不同的 Agent,但复杂的角色移交和共享状态需要额外设计。 LangGraph 可以把每个智能体作为节点或子图,并明确描述它们之间的消息、共享状态和交接条件,更适合多智能体协作。
19.11 适用场景
| 场景 | 更适合的工具 | 原因 |
|---|---|---|
| 单轮模型问答 | LangChain | 代码少,直接调用模型 |
| 一个模型加几个工具 | LangChain | create_agent 可以快速完成 |
| 简单 RAG | LangChain | 文档、检索和生成组件易于组合 |
| 固定的文档处理链 | LangChain Chain 或 LangGraph | 流程简单时 Chain 足够,需持久化时用 LangGraph |
| 多步审批流程 | LangGraph | 需要状态、分支和人工中断 |
| 长时间运行任务 | LangGraph | 支持检查点和恢复 |
| 多智能体协作 | LangGraph | 方便编排角色交接和共享状态 |
| 高风险工具操作 | LangGraph | 可明确插入审批节点和恢复路径 |
| 需要精确审计的业务流程 | LangGraph | 节点和边构成可检查的执行路径 |
19.12 二者不是互斥关系
LangChain 和 LangGraph 不是二选一的两个完全独立产品:
- LangChain 提供模型、消息、工具等组件
- LangGraph 提供执行这些组件的状态图和运行时
- LangChain 的智能体可以建立在 LangGraph 之上
- LangGraph 可以使用 LangChain 组件,也可以只使用普通 Python 函数 因此,常见架构是“LangChain 负责组件,LangGraph 负责编排”。
19.13 迁移路径
- 使用 LangChain 直接调用模型
- 使用 LangChain 工具和
create_agent快速验证需求 - 当出现多个阶段、分支、循环或审批时,定义明确的 State
- 把原有模型和工具调用封装为 LangGraph 节点
- 使用边和条件路由重建流程
- 加入 checkpointer、interrupt、重试和 LangSmith 追踪 迁移时不必重写模型和工具,通常只需要改变它们被调用和编排的方式。
20. LangChain 与 LangGraph 的选择流程
可以按以下问题判断:
- 是否只是一次模型调用?是:直接使用 LangChain 模型接口。
- 是否只需要一个简单工具循环?是:使用 LangChain
create_agent。 - 是否需要多个明确阶段、条件分支或循环?是:考虑 LangGraph。
- 是否需要任务跨进程、跨时间恢复?是:优先 LangGraph。
- 是否需要人工审批、复杂错误路径或多智能体交接?是:优先 LangGraph。
- 是否仍处于原型阶段?可以先用 LangChain,流程稳定后再迁移。
21. 学习顺序
- 先掌握模型调用和消息结构
- 学习工具定义与工具调用
- 使用
create_agent构建简单智能体 - 学习结构化输出和错误处理
- 学习会话记忆、流式输出和中间件
- 学习 State、Node、Edge 和 LangGraph
- 需要复杂工作流时使用 LangGraph 编排
- 使用 LangSmith 进行追踪、调试和评估
22. 关键术语
- LLM:Large Language Model,大语言模型
- Chat Model:以消息列表为输入的对话模型接口
- Prompt:发送给模型的提示内容
- Tool Calling:模型生成结构化工具调用,由程序实际执行
- Agent:能够根据任务循环调用模型和工具的程序
- Chain:步骤固定的模型应用处理链
- Workflow:由开发者定义的业务流程
- RAG:检索增强生成
- Middleware:插入模型或工具执行流程的中间逻辑
- State:智能体执行期间不断变化的数据
- Context:本次运行所需的外部配置和依赖
- Checkpointer:保存执行状态和会话历史的组件
- Structured Output:符合指定模式的模型输出