LangChain 是 LLM 应用框架里争议最大的一个:爱的人说它是生态标准,烦的人说它是"过度抽象的样板代码发生器"。两边都有道理,因为 LangChain 自己一直在剧烈演进。把它的发展史捋清楚,选型自然就清楚了。

演进三部曲

第一阶段:链(Chains)。 0.1 时代的核心抽象是 LLMChain 一类的线性管道:提示模板 → 模型 → 输出解析,像 Unix 管道一样串起来。适合直线流程,但真实 Agent 是有分支、有循环、有状态的——硬塞进链抽象,代码很快变成"链里嵌链、回调套回调"的迷宫。

第二阶段:LCEL(LangChain Expression Language)。 用 | 运算符组合组件(prompt | model | parser),配合流式、并行、重试的统一语义。这一步解决了表达力问题,但本质仍是 DAG——循环(Agent 的"思考→行动→观察"回路)表达依然别扭。

第三阶段:LangGraph。 彻底换成状态机范式:节点是步骤,边是转移,状态是一个显式的、可检查的对象。循环是一等公民,人机协同(human-in-the-loop)有原生支持(节点可以暂停等待人工审批),断点恢复(checkpoint)内建。今天做严肃 Agent 应用,LangChain 官方的答案其实就是 LangGraph。

状态机范式为什么对路

Agent 的本质是带循环的状态转移:

from langgraph.graph import StateGraph, END

class AgentState(TypedDict):
    messages: list
    plan: list[str]
    results: dict

g = StateGraph(AgentState)
g.add_node("plan", plan_node)
g.add_node("act", act_node)        # 调工具
g.add_node("reflect", reflect_node) # 检查结果,决定继续还是收敛

g.set_entry_point("plan")
g.add_edge("plan", "act")
g.add_conditional_edges("reflect", lambda s: "act" if s["plan"] else END)

app = g.compile(checkpointer=...)   # 状态可持久化、可恢复

状态显式化带来三个工程收益:可测试(给定状态断言转移)、可恢复(checkpoint 恢复中断的长任务)、可观测(每步的状态快照就是 trace)。

框架的真实成本

框架不是免费的,尤其要警惕:

  1. 抽象税:报错栈穿过五层装饰器,定位问题从"看代码"变成"考古"
  2. 版本快跑:0.x 版本间 breaking change 频繁,锁版本是纪律
  3. 调试黑盒:框架替你发的 prompt,优化时找不着北

选型的务实标准

我的判断矩阵,按场景给答案:

场景 建议
单次调用 + 结构化输出 直连官方 SDK,不需要任何框架
固定流程的 RAG 管道 轻框架或自写 200 行胶水,够用且全透明
多步 Agent、有循环分支 LangGraph(状态机范式目前最成熟)
需要跨团队复用组件/观测体系 框架生态(LangSmith 观测、组件市场)开始值回票价

先写无框架版本,痛了再上框架——很多时候你只是需要一个 while 循环加一个工具分发表,那 100 行自己写的代码比任何框架都好维护。

结语

LangChain 的演进史其实是整个行业的认知史:从"prompt 是管道"到"Agent 是状态机"。理解这条线,用不用框架、用哪家框架,都只是实现细节。