# 为什么选择 LangChain:从 LLM 调用到可维护的 AI 应用工程
直接调用大模型 API 并不难。真正麻烦的是,把一次“能返回结果的调用”变成一个稳定、可维护、可观测、可扩展的 AI 应用。
一个基础聊天接口可能只需要几行代码:收集用户输入、拼接 messages、请求模型、返回结果。但只要需求往前走一步,复杂度就会迅速堆起来:要兼容多个模型供应商,要管理提示词版本,要接入知识库,要让模型调用工具,要记录 token 和成本,要做错误重试,要追踪每一步输入输出,还要在生产环境里定位为什么某次回答不对。
LangChain 的价值就在这里。它不是为了让你少写一行模型调用代码,而是把 LLM 应用里反复出现的工程问题抽象出来,让模型、提示词、工具、检索、记忆、Agent、观测和评估可以被组合、替换和治理。
# 直接调模型会遇到什么问题
先看一个最常见的模型调用流程:
from openai import OpenAI
client = OpenAI()
def chat(user_input: str) -> str:
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "你是一个有帮助的助手。"},
{"role": "user", "content": user_input},
],
)
return completion.choices[0].message.content
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这段代码能跑,但它只解决了最简单的问题。一旦进入真实业务,很快就会出现下面这些需求:
- 切换模型供应商,例如 OpenAI、Anthropic、Gemini、本地模型。
- 对不同模型适配不同输入、输出、错误结构。
- 把提示词模板化,而不是散落在业务代码里。
- 对输出做结构化解析,例如 JSON、枚举、数据类。
- 接入企业私有知识库,做 RAG 检索增强。
- 让模型调用搜索、数据库、HTTP API、代码执行等工具。
- 保留对话记忆,但不能无限堆历史消息。
- 记录每次调用的耗时、token、成本、提示词和中间步骤。
- 对失败调用做重试、降级、熔断和审计。
如果这些逻辑都手写在业务层,代码会很快变成一堆 if provider == ...、try except、JSON 修补、上下文拼接和日志埋点。短期看能交付,长期看会把 AI 能力锁死在不可维护的胶水代码里。
LangChain 要解决的不是“调用模型”,而是“治理模型调用周围的一整套应用工程”。
# LangChain 解决的核心矛盾
LLM 应用和传统后端最大的不同在于:模型不是一个确定性函数。
传统接口里,请求、业务逻辑和数据库操作相对可控。LLM 应用里,输入是自然语言,输出可能不稳定,工具调用可能失败,检索结果可能不足,模型还会受上下文长度、提示词细节、模型版本和供应商差异影响。
因此,一个可上线的 LLM 应用至少需要几层能力:
- 模型抽象:统一不同模型供应商的调用方式。
- Prompt 管理:把提示词当成可维护资产。
- Output Parser:把自然语言输出转成业务可用结构。
- Retrieval:把外部知识注入模型上下文。
- Tools:让模型从“会说”变成“能做”。
- Memory:让多轮对话保留必要上下文。
- Agent:让模型在任务执行过程中选择工具和步骤。
- Observability:记录、调试、评估和复盘每一次运行。
LangChain 把这些能力做成一组可组合的模块。早期 LangChain 常被概括为 Models、Prompts、Indexes、Memory、Chains、Agents 六大组件。随着框架演进,新的 LangChain 更强调 Agent harness、LangGraph 和 LangSmith:LangChain 负责高层应用组合,LangGraph 负责更底层的流程编排和状态管理,LangSmith 负责追踪、调试和评估。
这个演进方向很清晰:AI 应用不只是 prompt demo,而是需要像后端系统一样被设计、部署、观察和迭代。
# 为什么选择 LangChain
选择 LangChain 通常不是因为它能做一件别人完全做不了的事,而是因为它在工程上把大量常见问题放进了同一套生态。
# 统一模型接口
不同模型供应商的 API 风格、参数、消息格式、工具调用格式、错误结构都不完全一样。直接写业务代码适配每一家,会让模型切换变得很痛苦。
使用 LangChain 后,可以把模型看成一个可替换组件:
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个资深后端工程师。"),
("human", "{question}"),
])
model = ChatOpenAI(model="gpt-4o-mini")
chain = prompt | model | StrOutputParser()
answer = chain.invoke({"question": "Flask 项目如何设计数据库迁移?"})
2
3
4
5
6
7
8
9
10
11
12
13
14
这里的重点不是少写了多少代码,而是 prompt、model、parser 变成了可组合单元。后面要替换模型、加解析器、加检索、加日志,都可以沿着同一条链路扩展。
# 降低模型切换成本
真实项目里,模型选择经常会变化。今天用 OpenAI,明天可能要接企业私有模型,后天可能要按任务类型动态路由到不同模型。
如果业务代码直接依赖某个模型 SDK,那么模型切换会影响大量接口。LangChain 把模型适配封装在集成层里,业务更关心“我要一个聊天模型”或“我要一个 embedding 模型”,而不是每个供应商的细节。
当然,这不意味着完全没有迁移成本。不同模型的上下文长度、工具调用能力、结构化输出稳定性、费用和速度仍然不同。LangChain 解决的是接口层和组合层的问题,模型能力差异本身仍然需要工程上评估。
# Prompt 可以被工程化管理
提示词不是写在代码里的几句字符串。生产项目里的 Prompt 通常会经历版本迭代、AB 实验、灰度发布、效果回归和安全审查。
LangChain 的 PromptTemplate 让提示词有了明确输入变量:
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你是 {role},回答要简洁、准确,并给出必要的依据。"),
("human", "{question}"),
])
messages = prompt.invoke({
"role": "Python 后端工程师",
"question": "SQLAlchemy Session 应该在哪里 commit?",
})
2
3
4
5
6
7
8
9
10
11
12
这比在业务函数里手动拼字符串更容易检查,也更适合和测试、评估、版本管理结合。
# 支持 RAG 和知识库应用
大模型训练数据不可能覆盖企业内部知识,也无法天然知道最新业务状态。RAG 的基本思路是:先从外部知识库检索相关内容,再把内容作为上下文交给模型回答。
一个 RAG 应用通常需要这些步骤:
- 加载文档。
- 清洗和切分文本。
- 生成 embedding。
- 写入向量数据库。
- 用户提问时检索相关片段。
- 把检索结果和问题一起交给模型。
- 生成答案并返回引用来源。
LangChain 在文档加载、文本切分、向量数据库集成、Retriever、Prompt 组合上都有现成抽象,适合快速搭建知识库问答、文档助手、客服助手、内部搜索等应用。
但要注意,RAG 不是“接了向量库就结束”。生产 RAG 的关键在于数据质量、切分策略、召回评估、重排、引用校验、权限过滤和答案评估。LangChain 提供工具箱,真正的效果仍然取决于工程设计。
# 工具调用和 Agent 生态成熟
只会回答问题的模型,能力边界很窄。很多业务场景需要模型去调用工具:
- 查数据库。
- 调接口。
- 搜索网页。
- 创建工单。
- 读取文件。
- 执行计算。
- 调用内部业务系统。
LangChain 的 Tools 和 Agents 把这些能力组织起来。Agent 的核心可以理解为一个循环:模型观察当前状态,决定是否调用工具,拿到工具结果后继续思考,直到完成任务。
在简单场景里,可以直接用高层 Agent 接口。在复杂场景里,应该用 LangGraph 设计更明确的状态机和控制流,把确定性流程和模型决策分开。
这个边界非常重要:不是所有事情都应该交给 Agent 自由发挥。支付、删除数据、审批、发消息这类敏感动作,必须有权限、确认、审计和人工介入机制。
# 可观测性更容易落地
LLM 应用最难排查的问题通常不是“代码报错”,而是“为什么这次回答不对”。
要回答这个问题,至少要知道:
- 用户原始输入是什么。
- 最终发送给模型的上下文是什么。
- 检索到了哪些文档。
- 调用了哪些工具。
- 每一步模型输出是什么。
- token 和耗时分别是多少。
- 哪个 Prompt 版本产生了这个结果。
LangSmith 就是 LangChain 生态里用于追踪、调试、评估 LLM 应用的平台。没有可观测性,LLM 应用很容易停留在“感觉好像能用”的阶段;有了追踪和评估,团队才能持续定位问题、沉淀测试集、比较不同 Prompt 和模型版本。
# LangChain 的核心概念
从掌握路径上看,可以按下面几个概念理解 LangChain。
# Models
Models 是对大语言模型和 embedding 模型的抽象。
常见类型包括:
- Chat Model:多轮对话模型。
- LLM:传统文本输入输出模型。
- Embedding Model:把文本转成向量,用于检索和相似度计算。
现在的应用大多优先使用 Chat Model,因为主流模型都围绕 message 格式、多模态输入、工具调用和结构化输出发展。
# Prompts
Prompts 负责把业务变量变成模型可读的上下文。它不只是字符串模板,还包含消息角色、系统约束、用户输入、少样本示例和格式要求。
Prompt 工程化的目标是:让提示词可读、可测、可复用、可版本化。
# Output Parsers
模型输出天然是文本,但业务代码往往需要结构化数据。
例如:
{
"intent": "create_ticket",
"priority": "high",
"summary": "用户无法登录"
}
2
3
4
5
Output Parser 的作用就是把模型输出约束并解析成业务可消费的结构。对于强约束场景,还应该结合模型的结构化输出能力、JSON schema 校验和失败重试。
# Retrievers
Retriever 负责根据用户问题取回相关上下文。它可以连接向量数据库、搜索引擎、数据库、文件系统或自定义检索服务。
Retriever 的质量直接决定 RAG 上限。召回不到正确材料,再强的模型也只能猜。
# Memory
Memory 负责处理多轮对话上下文。
简单做法是把历史消息全部塞进上下文,但这会带来成本、延迟和上下文窗口问题。更合理的做法是按场景使用短期记忆、摘要、重要事实提取、长期用户画像和线程级状态。
在新的 LangChain 生态里,复杂记忆和状态管理更多交给 LangGraph 来做。
# Tools
Tools 是模型可以调用的外部能力。工具设计要像 API 设计一样认真:
- 名称要清楚。
- 描述要准确。
- 入参要结构化。
- 返回值要稳定。
- 错误要可解释。
- 敏感操作要有权限和确认。
工具不是越多越好。工具太多会增加模型选择难度,也会放大误调用风险。
# Agents
Agent 是模型加工具和控制循环。它适合开放式、多步骤、需要动态决策的任务,例如研究、数据分析、代码辅助、复杂客服和运维排障。
但如果业务流程非常确定,例如“提取字段 -> 查数据库 -> 生成固定模板回复”,用普通 Chain 或明确的流程编排更稳。Agent 适合不确定性任务,不适合替代所有业务逻辑。
# LangChain、LangGraph、LangSmith 怎么分工
现在使用 LangChain,最好同时理解这三个名字。
# LangChain
LangChain 是高层应用开发框架,提供模型、工具、Prompt、Agent harness 和各种集成。它适合快速构建 LLM 应用的主体逻辑。
# LangGraph
LangGraph 是更底层的编排框架,用图来表达状态、节点和边。它适合更复杂的 Agent 和工作流:需要分支、循环、人工审批、持久化状态、恢复执行、多 Agent 协作时,LangGraph 比简单链式调用更合适。
# LangSmith
LangSmith 负责观测、调试和评估。它可以记录每次运行的 trace,帮助团队分析 Prompt、模型、工具调用、检索结果和最终答案之间的关系。
一个生产级组合通常是:
- LangChain 负责应用层抽象。
- LangGraph 负责复杂流程和状态。
- LangSmith 负责调试、评估和线上观测。
# 什么时候适合用 LangChain
下面这些场景适合使用 LangChain:
- 要接多个模型供应商。
- 需要 Prompt 模板和输出解析。
- 要做 RAG、知识库问答、文档助手。
- 需要工具调用或 Agent。
- 需要追踪、调试、评估模型调用链。
- 希望快速集成向量库、搜索、数据库、第三方 API。
- 团队希望把 LLM 应用变成可维护工程,而不是散落的 SDK 调用。
如果只是一个非常简单的接口,比如把用户输入转发给某个模型并原样返回,直接使用模型 SDK 可能更轻。
# 什么时候不要盲目使用 LangChain
LangChain 不是所有场景的默认答案。
下面这些情况要谨慎:
- 需求只是一次简单模型调用。
- 团队还没有明确抽象边界,引入框架反而增加掌握成本。
- 对延迟极其敏感,每一层抽象都要精细控制。
- 业务需要非常严格的确定性流程,不希望模型自由选择步骤。
- 项目已经有成熟的内部 LLM 网关、Prompt 平台和观测体系。
框架的价值来自“复用复杂度”。如果复杂度还没有出现,过早引入会让项目变重。
# 生产落地时的设计原则
真正上线 LangChain 应用时,可以遵循几条原则。
# 模型调用不要散落在业务代码里
建议把模型、Prompt、Parser、Retriever、Tool 组合封装在应用服务层。Controller 只负责接收请求和返回响应,不直接拼 Prompt。
# Prompt 要版本化
Prompt 修改会影响线上效果,应该像代码一样 review。重要 Prompt 可以保存在独立文件、数据库或 Prompt 管理平台里,并记录版本号。
# 输出必须校验
不要相信模型一定按格式输出。结构化输出要做 schema 校验,失败要有重试、降级或人工兜底。
# 工具调用要有权限边界
读操作和写操作分开。删除、支付、发消息、改配置这类工具要有人类确认、审计日志和幂等设计。
# RAG 要做评估
至少要准备一批黄金问题,评估召回是否命中、答案是否引用正确、是否出现幻觉。没有评估集,RAG 优化很容易靠感觉。
# Trace 是必需品
没有 trace 的 LLM 应用很难排障。上线前就应该设计好请求 ID、用户 ID、模型版本、Prompt 版本、检索结果和工具调用记录。
# 一个简单的 LangChain 调用示例
下面是一个最小可理解的 LangChain 调用链:
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个严谨的 Python 后端工程师。"),
("human", "{question}"),
])
model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
parser = StrOutputParser()
chain = prompt | model | parser
answer = chain.invoke({
"question": "为什么生产环境需要数据库迁移工具?"
})
print(answer)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
这段代码体现了 LangChain 的基本思想:每一段能力都是一个可组合组件。后续可以把 model 换掉,把 parser 换成 JSON 解析器,把 prompt 前面接检索器,把链路放进 Agent 或 LangGraph。
# 小结
LangChain 的核心价值不是“让模型调用更简单”,而是“让 LLM 应用更像一个可维护的软件系统”。
当你的项目开始涉及多模型适配、Prompt 管理、RAG、工具调用、Agent、记忆、追踪和评估时,LangChain 能把大量重复工程抽象成统一的组件生态。但也要保持克制:简单场景可以直接调 SDK,确定性强的业务流程不要硬塞 Agent,生产系统必须补上权限、观测、评估和回滚方案。
一句话概括:LangChain 适合用来搭建 LLM 应用的工程骨架,但真正决定系统质量的,仍然是你对业务边界、数据质量、工具安全和评估闭环的设计。