Skip to content

LangChain 与 LangGraph

LangChain 是 AI 应用开发最广泛使用的框架,LangGraph 在此基础上支持有状态的 Agent 编排。本页讲解核心架构、组件和两者的关系,帮助开发者选型并快速上手。

先说应不应该用框架

这一章讲框架,但我想先说一件容易被忽略的事:用框架不是必须的,也不总是对的。

如果你刚学完 Agent 基础原理,代码里已经有了一个能跑的 Agent Loop,这时候加 LangChain 可能只是在给自己加一层你还不熟悉的抽象,出了问题更难排查。

框架的价值,在你已经理解了它帮你隐藏了什么之后才会真正体现出来。如果你还不清楚 Tool Calling 怎么工作、消息历史为什么要手动管理、状态在哪里维护,建议先把手写版的 Agent Loop 做稳,再来看框架。

带着这个前提来理解 LangChain 和 LangGraph,会更有收获。

LangChain 是什么

LangChain 是一个帮你组织"模型调用链路"的框架。它的核心抽象是这几个:

Model / LLM:对各家模型 API 的统一封装,换模型不用改调用代码。

Prompt Template:把静态字符串变成带变量的模板,方便复用和测试不同版本的 prompt。

Chain:把多个步骤串成一个可执行的链,输出自动作为下一步的输入。

Memory:对话历史的管理抽象,包括全量保留、固定窗口、摘要压缩等。

Agent:基于工具调用的 Agent 封装,内置多种推理策略(ReAct、Function Calling 等)。

Retriever:检索器抽象,向量库、BM25、混合检索都可以接进来。

如果你已经做过 RAG 知识库,LangChain 的一个典型使用场景是把"检索 + 生成"这条链路封装成一个 RetrievalQAConversationalRetrievalChain,省去手动拼 prompt 和管理上下文的步骤:

python
from langchain_openai import ChatOpenAI
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain.chains import RetrievalQA

llm = ChatOpenAI(model="gpt-4o")
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(embedding_function=embeddings, persist_directory="./db")

qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
    return_source_documents=True
)

result = qa_chain.invoke({"query": "申请退款需要多少天?"})
print(result["result"])
print(result["source_documents"])

十几行代码就跑通了一个带检索的问答链。对比手写版,少了 embedding 调用、向量检索、prompt 拼装这些步骤。

LangChain 适合的场景

  • 快速搭 RAG 原型,不想从零实现检索 + 生成链路
  • 需要支持多个模型切换,想用统一接口
  • 需要标准的 Memory 实现,不想自己处理消息历史

LangChain 不适合的场景

  • 你还不清楚框架底层在做什么,调试困难时无从下手
  • 你的 Agent 逻辑很特殊,需要精细控制每一步,框架反而是束缚
  • 项目对包依赖很敏感,LangChain 的依赖树比较重

LangChain 的生态很大,但它并不总是最好的选择。手写版的 Tool Calling + 消息管理,在很多场景里更透明、更容易维护。

LangGraph 是什么

LangGraph 是 LangChain 团队在 LangChain 之上做的 Agent 编排框架,专门处理"有状态、多步、可恢复"的 Agent 流程。

它的核心模型是图(Graph):把 Agent 的执行流程建模成节点和边,每个节点是一个处理步骤,边定义了步骤之间的跳转逻辑(包括条件分支)。

为什么要引入图结构?因为普通的 while 循环处理不好这几种情况:

  • 条件分支:根据当前状态决定下一步是继续搜索、还是直接输出结论,还是请求用户确认
  • 循环:某些步骤需要重复执行(比如搜索失败要重试)
  • 持久化中断:Agent 执行到一半,可以暂停、存档,等待人工审批,再继续
  • 并行分支:多个子任务可以并行跑,等所有结果回来再合并

LangGraph 把这些控制流需求变成了显式的图结构,而不是混在 if/elsewhile 里。

LangGraph 的基本用法

LangGraph 里最关键的概念是 StateGraph:定义一个带有共享状态的图,每个节点都可以读写这个状态。

用 Research Agent 的场景来看一个最小例子:

python
from typing import TypedDict, Annotated
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
import operator

# 1. 定义状态结构
class ResearchState(TypedDict):
    question: str
    search_results: Annotated[list[str], operator.add]  # 支持追加
    final_answer: str
    steps_taken: int

# 2. 定义节点函数
llm = ChatOpenAI(model="gpt-4o")

def search_node(state: ResearchState) -> dict:
    """执行搜索"""
    # 实际场景里调用真实搜索工具
    results = [f"搜索 '{state['question']}' 的结果(模拟)"]
    return {
        "search_results": results,
        "steps_taken": state["steps_taken"] + 1
    }

def summarize_node(state: ResearchState) -> dict:
    """整合结果,生成结论"""
    context = "\n".join(state["search_results"])
    response = llm.invoke(
        f"基于以下搜索结果,回答问题:{state['question']}\n\n{context}"
    )
    return {"final_answer": response.content}

def should_continue(state: ResearchState) -> str:
    """条件分支:决定下一步"""
    if state["steps_taken"] >= 3:
        return "summarize"  # 步数够了,生成结论
    if len(state["search_results"]) == 0:
        return "search"  # 还没搜,继续搜
    return "summarize"  # 默认进入总结

# 3. 构建图
graph = StateGraph(ResearchState)
graph.add_node("search", search_node)
graph.add_node("summarize", summarize_node)

graph.set_entry_point("search")

# 条件跳转:search 结束后,根据 should_continue 决定下一步
graph.add_conditional_edges(
    "search",
    should_continue,
    {
        "search": "search",      # 继续搜索
        "summarize": "summarize" # 进入总结
    }
)
graph.add_edge("summarize", END)

app = graph.compile()

# 4. 执行
result = app.invoke({
    "question": "2025 年最主流的前端框架是什么?",
    "search_results": [],
    "final_answer": "",
    "steps_taken": 0
})
print(result["final_answer"])

这个例子比实际用到的功能简单,但结构是真实的:状态定义、节点函数、条件边、入口设定。

LangGraph 的关键能力在 add_conditional_edges:根据当前状态选择走哪条边,这比手写 if/else 更结构化,也更容易可视化和调试。

人工审批(Human-in-the-Loop)

LangGraph 的 interrupt 机制让 Agent 可以在执行到某个敏感节点时暂停,等待人工确认再继续。这个能力在纯手写版 Agent Loop 里很难优雅地实现。

python
from langgraph.checkpoint.memory import MemorySaver
from langgraph.types import interrupt

def risky_action_node(state: ResearchState) -> dict:
    """需要人工确认的高风险操作"""
    # 暂停执行,把问题抛给人工
    approval = interrupt({
        "message": "即将执行以下操作,请确认",
        "action": state.get("planned_action")
    })

    if approval["approved"]:
        # 执行操作
        return {"result": "操作已执行"}
    else:
        return {"result": "操作已取消"}

# 编译时加入 checkpointer
checkpointer = MemorySaver()
app = graph.compile(
    checkpointer=checkpointer,
    interrupt_before=["risky_action_node"]  # 到这个节点前暂停
)

# 第一次运行:会在 risky_action_node 前暂停
thread_id = {"configurable": {"thread_id": "task-001"}}
result = app.invoke(initial_state, config=thread_id)
# result 里包含待确认的信息

# 人工审批后,恢复执行
resume_result = app.invoke(
    {"approved": True},
    config=thread_id
)

这个模式对需要"让人类保持控制"的 Agent 系统非常关键。Agent 发现要做一个高风险动作(比如发邮件、修改数据库),可以先暂停,展示给用户确认,而不是直接执行。

手写 vs LangChain vs LangGraph 对比

场景建议选择
学习阶段,搞清楚 Tool Calling 怎么工作手写
快速搭 RAG 原型,用标准 RetrieverLangChain
做多步 Agent,需要条件分支和状态管理LangGraph
Agent 需要暂停、等待人工审批、恢复执行LangGraph
线上系统对可维护性和依赖稳定性要求高手写 + 适当借用

不存在"LangGraph 比手写版更好"这个说法。LangGraph 的优势是在图结构清晰、需要 checkpoint 和 Human-in-the-Loop 的场景。如果你的 Agent 是一个直接跑到底的简单循环,手写版更透明,出了问题更好查。

LangGraph 和 LangChain 的关系

LangGraph 是 LangChain 生态里的一个独立包(langgraph),但不依赖 LangChain 就能用。两者的关系是:

  • LangChain 提供了模型封装、Prompt Template、Memory、Retriever 等"积木"
  • LangGraph 提供了编排这些积木的"图结构框架"
  • 你可以单独用 LangGraph + 原生 OpenAI SDK,不用 LangChain 那一层

实际项目里比较常见的组合:用 LangGraph 做流程编排,用 LangChain 的 Retriever 做检索,模型调用直接用各家官方 SDK。每层选最熟悉的工具。

和 Agent 基础原理的关系

Agent 基础原理里的 Plan → Act → Observe 循环,在 LangGraph 里的对应关系:

  • Plan 阶段:模型决定下一步的逻辑,封装成一个节点
  • Act 阶段:工具执行节点
  • Observe 阶段:处理工具结果的节点,根据结果决定走哪条边
  • 终止条件conditional_edges 里包含 END 分支

LangGraph 没有改变 Agent 的本质逻辑,只是把这个逻辑用图的方式表达出来,让分支、循环和中断变得更显式、更可测试。

如果你已经理解了手写 Agent Loop 的工作方式,看 LangGraph 的图定义会很自然——它其实就是把你脑子里已经有的状态机,用代码显式地画了出来。


进一步了解 Agent 的推理模式,可以继续阅读 CoT 与 ReAct;如果你想深入理解 LangGraph 支持的多 Agent 架构,可以参考 多 Agent 协调

面向开发者的 AI 实战路线——Vibe Coding 与 AI 应用开发