LangGraph 入门到精通0x02:Graph 其他基础能力

前言

前面 逐个学习了 LangGraph 的一些基础能力:Reducers、Send、Interrupt、Command。今天继续看 LangGraph 的其他基础能力。

checkpoint

Checkpoints 是 LangGraph 在图执行过程中,在每个超级步骤(Super-step)结束时自动创建的状态快照。每个Checkpoint都是一个 StateSnapshot 对象。 values: 当前所有状态通道的具体数据(如图中的foo、bar字段值)

  • next: 下一个要执行的节点名称(为空表示执行结束)

  • config: 关联的配置,包含唯一标识符thread_id和checkpoint_id

  • metadata: 元数据,如执行来源、修改记录、步骤编号

  • created_at/ parent_config: 创建时间和父检查点配置(用于构建执行链路)

Checkpointer是负责保存和管理这些快照的工具。LangGraph提供了多种实现:

  • InMemorySaver: 内存存储,适用于开发和测试
  • SqliteSaver: SQLite 文件存储,适用于小型生产或本地开发
  • PostgresSaver: PostgreSQL 存储,适用于生产环境,支持并发

几个常用的方法:

  • get_state:获取当前快照
  • get_state_history:读取所有快照:包括图每一步的执行情况

记忆绑定

要想让 graph 带快照功能,必须在 graph 编译的时候带上 checkpointer 参数。

Python 复制代码
# 内存记忆器:保存每一步执行状态,支持回溯
checkpointer = InMemorySaver()
# 编译并绑定记忆
graph = workflow.compile(checkpointer=checkpointer)

会话标识

会话ID:区分不同对话/执行上下文

Python 复制代码
config = {"configurable": {"thread_id": "thread-1"}}

快照获取

Python 复制代码
# 获取快照
snapshot = graph.get_state(config)

# 获取全部历史快照
history = list(graph.get_state_history(config))

图调用

graph 本身并不存储快照,只负责处理流程。快照存储是和 CheckPointer 绑定的。所以在 graph 调用时要传入 config。内部原理是:

  1. graph 根据 config 里的 thread_idcheckpoint 绑定

  2. 获取 snapshot 时,graph 再根据 thread_id 去 checkpoint 取数据

ini 复制代码
# 执行图
result = graph.invoke(initial_state, config)

Context Memory

像之前 LangChain 的 ChatModel 都会接受 Message 对象列表作为输入。这些消息以各种形式出现(HumanMessage或 AIMessage)。在 LangGraph 中的 State 同样可以模拟实现类似 BaseMessage 的功能。

自动合并消息的 State

Python 复制代码
class ChatState(TypedDict):
    # messages 自动合并消息的历史记录
    # Annotated:附加信息
    # Sequence:有序列表
    messages: Annotated[Sequence[BaseMessage], operator.add]

用户输入

Python 复制代码
def handle_user_input(state: ChatState):
    """
    处理用户输入节点(增强健壮性)
    """
    try:
        user_input = input("\n用户输入(输入'Q'结束): ").strip()
        if user_input.lower() == "Q":
            logger.info(f"正在结束对话...")
            return END
        # 保留历史记录并追加新消息
        return {"messages": [HumanMessage(content=user_input)]}
    except Exception :
        return END

AI 回复

Python 复制代码
def generate_ai_response(state: ChatState):
    """
    生成AI响应节点(增加错误处理)
    """
    try:
        # 使用最近6条消息保持上下文连贯性
        recent_history = state["messages"][-6:]
        """做个摘要"""
        response = model.invoke(recent_history)
        return {"messages": [response]}
    except Exception as e:
        error_msg = f"系统暂时无法响应,请稍后再试(错误代码:{str(e)[:30]})"
        return {"messages": [AIMessage(content=error_msg)]}

节点注册

  • RunnableLambda: 可不写,add_node 内部会自动包装成 RunnableLambda
Python 复制代码
# 节点注册
# RunnableLambda 可不写,add_node 内部会自动包装成 RunnableLambda
builder.add_node("user_input", handle_user_input)
builder.add_node("ai_response", RunnableLambda(generate_ai_response))

对话循环

Python 复制代码
while True:
    try:
        # 执行对话流程
        result = conversation.invoke(state)
        if result is None or "messages" not in result:
            break
        # 提取最新交互记录
        new_messages = result["messages"][len(state["messages"]):]
        # 打印AI响应
        for msg in new_messages:
            if isinstance(msg, AIMessage):
                logger.info(f"\n【AI响应】\n{msg.content}\n")
        # 更新对话状态
        state = result
        # 检查退出条件
        if any(isinstance(m, HumanMessage) and m.content.lower() == "退出" for m in state["messages"]):
            break
    except Exception as e:
        logger.info(f"\n系统异常:{str(e)}")
        break

Subgraphs

Subgraphs 就是子图。就好比我们开发语言的父类/子类关系,LangGraph 允许将复杂的工作流分解为更小、更易管理的子图。然后将这些子图作为 Node 添加到主图中。LangGraph 提供了两种不同模式的子图:

  • 共享模式 :父图和子图有共享的状态键
    • 共享的状态键(如foo)会自动在父图和子图间同步,子图可以直接读写这些共享状态。就好比父类的 public 变量。
  • 不同状态模式 :父图和子图状态结构完全不同
    • 这种模式下需要在父图节点中进行"输入映射→子图调用→输出映射"的手动转换

共享状态模式:

Python 复制代码
class SharedParentState(TypedDict):
    text: str  # 父图与子图共享的键
    result: str  # 父图私有键(可选)


class SharedSubgraphState(TypedDict):
    text: str  # 与父图共享的键(必须同名)
    processed: str  # 子图私有键(仅子图可见)
    

def subgraph_node(state: SharedSubgraphState) -> SharedSubgraphState:
    """子图节点:将共享键"text"转大写,存到私有键"processed"""
    return {
        "text": state["text"].upper(),  # 修改共享键(自动同步到父图)
        "processed": f"Processed: {state['text'].upper()}"  # 子图私有数据
    }
    

def parent_node(state: SharedParentState) -> SharedParentState:
    """父图节点:直接调用子图(共享键自动传递)"""
    return state  # 子图会修改"text"键,父图后续可直接用

不同状态模式,和共享状态不同,这里需要在父图节点中进行"输入映射→子图调用→输出映射"的手动转换。

  • subgraph_input = {"task": state["user_query"]}: 子图输入映射
  • compiled_different_subgraph.invoke(subgraph_input):子图调用
  • { "answer": subgraph_output["result"], "user_query": state["user_query"] # 保留父图原始输入 }:输出映射
Python 复制代码
def parent_wrapper_node(state: DifferentParentState) -> DifferentParentState:
    """
    父图包装节点:【核心:手动状态映射】
    因为父子图状态完全独立,必须手动:
    1. 父图状态 → 子图输入
    2. 调用子图
    3. 子图输出 → 父图状态
    """
    # ---------------------- 输入映射 ----------------------
    # 父图键:user_query → 子图键:task
    subgraph_input = {"task": state["user_query"]}

    # ---------------------- 调用独立子图 ----------------------
    # 子图与父图状态隔离,不会互相污染
    subgraph_output = compiled_different_subgraph.invoke(subgraph_input)

    # ---------------------- 输出映射 ----------------------
    # 子图键:result → 父图键:answer
    return {
        "answer": subgraph_output["result"],
        "user_query": state["user_query"]  # 保留父图原始输入
    }

根据主图的输入映射 {"task": state["user_query"]},子图在 state 里操作主图传递的 task 字段。

Python 复制代码
def different_subgraph_node(state: DifferentSubgraphState) -> DifferentSubgraphState:
    # 处理逻辑:给 task 增加子图前缀
    return {"result": f"[Subgraph] Processed: {state['task']}"}

visualization

我们可以将编译后的 LangGraph 整体流程绘制成一张流程图。

Python 复制代码
graph.get_graph().draw_mermaid_png(output_file_path=save_file_path)

源码

github

相关推荐
colinCao2 小时前
SDD 规范驱动开发:用自然语言重塑全栈开发流程 从需求描述到前后端交付,AI 仅用 60 分钟完成全栈开发。这不是科幻,这是 SDD(Specificatio
ai编程·全栈
chaors2 小时前
LangGraph 入门到精通0x01:Graph 通讯机制
langchain·llm·agent
阿荻在肝了2 小时前
Agent实践三:基于Chroma的RAG检索
python·学习·agent
是Dream呀2 小时前
Gemma-4-31B-it到底强在哪:从 vLLM 启动到 OpenCode 接入,我把整条链路跑通了
人工智能·llm
Cachel wood2 小时前
Macbook M4 pro本地部署大模型|Ollama+Gemma4/Qwen3.5
人工智能·python·自动化·llm·qwen·ollama·gemma4
小陈同学呦2 小时前
AI 时代的代码焦虑与破局之道
ai编程
得物技术3 小时前
立正请站好:一个组件复用 Skill 的工程化实践|得物技术
前端·架构·ai编程
Joy-word3 小时前
手机上的全能智能体,Auto小二正式开源
ai·agent·手机智能体·autoglm·养虾
三寸3373 小时前
2026 最新 Codex 如何使用指南:ChatGPT 订阅、CLI 安装、App 登录全流程
ai·chatgpt·ai编程