LangGraph官方文档笔记——5.自定义状态


到目前为止,我们依赖一个包含一个条目(消息列表)的简单状态。虽然这个简单状态可以走得很远,但如果您想定义复杂的行为而不依赖于消息列表,您可以向状态添加额外的字段。

参考文档

官方文档参考

实践自定义状态

1.将键添加到状态中

在这里,我们将演示一个新场景,其中聊天机器人使用其搜索工具查找特定信息,并将其转发给人工进行审查。让聊天机器人研究一个实体的生日。我们将向状态添加namebirthday

from typing import Annotated

from typing_extensions import TypedDict

from langgraph.graph.message import add_messages


class State(TypedDict):
    messages: Annotated[list, add_messages]
    name: str
    birthday: str

2.在工具内部更新状态

我们将在 human_assistance 工具内部填充状态键。这允许人工在信息存储到状态之前对其进行审查。我们将再次使用 Command,这次是从我们的工具内部发出状态更新。

# 导入所需模块和类型
from langchain_core.messages import ToolMessage  # 工具调用结果消息类型
from langchain_core.tools import InjectedToolCallId, tool  # 工具调用ID注入标记和工具装饰器
from langgraph.types import Command, interrupt  # 状态更新命令和人工干预中断函数


@tool
def human_assistance(
    name: str, birthday: str, 
    tool_call_id: Annotated[str, InjectedToolCallId]
) -> str:
    """请求人工协助验证和修正信息"""
    
    # 触发人工干预流程,传递待验证的姓名和生日信息
    human_response = interrupt(
        {
            "question": "Is this correct?",  # 询问信息是否正确
            "name": name,                    # 待验证姓名
            "birthday": birthday,            # 待验证生日
        },
    )
    
    # 处理人工反馈结果
    if human_response.get("correct", "").lower().startswith("y"):
        # 信息正确时,直接使用原始数据
        verified_name = name
        verified_birthday = birthday
        response = "Correct"  # 标记信息正确
    else:
        # 信息错误时,获取人工修正后的数据
        verified_name = human_response.get("name", name)
        verified_birthday = human_response.get("birthday", birthday)
        response = f"Made a correction: {human_response}"  # 记录修正内容
    
    # 构造状态更新数据
    state_update = {
        "name": verified_name,            # 验证后的姓名
        "birthday": verified_birthday,    # 验证后的生日
        "messages": [ToolMessage(         # 封装工具调用结果消息
            response, 
            tool_call_id=tool_call_id      # 关联工具调用ID
        )],
    }
    
    # 返回状态更新命令,通知系统更新对话状态
    return Command(update=state_update)

3. 提示聊天机器人

图的其余部分保持不变。

import os
# from langchain.chat_models import init_chat_model
from langchain_openai import ChatOpenAI
from langchain_tavily import TavilySearch

from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode, tools_condition

#环境变量设置,替换为你的API KEY
os.environ['TAVILY_API_KEY'] = 'TAVILY_API_KEY'
os.environ['ARK_API_KEY'] = 'API_KEY'

tool = TavilySearch(max_results=2)
tools = [tool, human_assistance]
llm = ChatOpenAI(
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    api_key=os.environ.get('ARK_API_KEY'),  
    model="doubao-1-5-pro-32k-250115"  # 根据实际模型名称修改
)
llm_with_tools = llm.bind_tools(tools)


def chatbot(state: State):
    message = llm_with_tools.invoke(state["messages"])
    assert len(message.tool_calls) <= 1
    return {"messages": [message]}


graph_builder = StateGraph(State)
graph_builder.add_node("chatbot", chatbot)

tool_node = ToolNode(tools=tools)
graph_builder.add_node("tools", tool_node)

graph_builder.add_conditional_edges(
    "chatbot",
    tools_condition,
)
graph_builder.add_edge("tools", "chatbot")
graph_builder.add_edge(START, "chatbot")

memory = MemorySaver()
graph = graph_builder.compile(checkpointer=memory)

提示聊天机器人查找 LangGraph 库的“生日”(即发布时间),并在获取所需信息后引导聊天机器人使用 human_assistance 工具。通过在工具的参数中设置 name 和 birthday,你强制聊天机器人为这些字段生成建议。

user_input = (
    "Can you look up when LangGraph was released? "
    "When you have the answer, use the human_assistance tool for review."
)
config = {"configurable": {"thread_id": "1"}}

events = graph.stream(
    {"messages": [{"role": "user", "content": user_input}]},
    config,
    stream_mode="values",
)
for event in events:
    if "messages" in event:
        event["messages"][-1].pretty_print()

返回结果:

================================ Human Message =================================

Can you look up when LangGraph was released? When you have the answer, use the human_assistance tool for review.
================================== Ai Message ==================================

First, use the tavily_search tool to find out when LangGraph was released. Then, use the human_assistance tool to review the obtained information.
Tool Calls:
  tavily_search (call_llt1sw4ifqhu46h92z6jc6o7)
 Call ID: call_llt1sw4ifqhu46h92z6jc6o7
  Args:
    query: When was LangGraph released?
    include_domains: None
    exclude_domains: None
    search_depth: None
    include_images: None
    time_range: None
    topic: None
================================= Tool Message =================================
Name: tavily_search

{"query": "When was LangGraph released?", "follow_up_questions": null, "answer": null, "images": [], "results": [{"title": "LangGraph 0.3 Release: Prebuilt Agents - blog.langchain.dev", "url": "https://blog.langchain.dev/langgraph-0-3-release-prebuilt-agents/", "content": "LangGraph 0.3 Release: Prebuilt Agents LangGraph 0.3 Release: Prebuilt Agents Over the past year, we’ve invested heavily in making LangGraph the go-to framework for building AI agents. Up to this point, we’ve had one higher level abstraction and it’s lived in the main langgraph package. We are also introducing a new set of prebuilt agents built on top of LangGraph, in both Python and JavaScript. LangGraph Supervisor: for getting started with a supervisor multi-agent architecture LangGraph Swarm: for getting started with a swarm multi-agent architecture We hope that this will foster a large collection of prebuilt agents built by the community. We hope the same will happen with LangGraph prebuilt agents.", "score": 0.27467275, "raw_content": null}, {"title": "Releases · langchain-ai/langgraph - GitHub", "url": "https://github.com/langchain-ai/langgraph/releases", "content": "Releases · langchain-ai/langgraph · GitHub *   GitHub Copilot Write better code with AI *   GitHub Advanced Security Find and fix vulnerabilities Search code, repositories, users, issues, pull requests... *   update dockerfile generation logic, fix pip removal in wolfi *   Remove dict subclasses used for values/updates stream chunks (#4816) *   Merge branch 'langchain-ai:main' into fix-examples-link-readme Changes since prebuilt==0.2.1 *   Add message state test *   prebuilts hitl: fix branching logic + add structural snapshot tests (#4767) *   sqlite: Add test for search with list filters (#4747) Changes since prebuilt==0.2.0 Changes since prebuilt==0.1.8 *   prebuilts hitl: fix branching logic + add structural snapshot tests (#4767) *   sqlite: Add test for search with list filters (#4747) *   prebuilt: remove state_modifier (#4439) *   fixing prebuilt tests", "score": 0.16426189, "raw_content": null}], "response_time": 1.8}
================================== Ai Message ==================================

The search results did not directly indicate the release time of LangGraph. However, the information can be further verified by human assistance.
Tool Calls:
  human_assistance (call_mbmtx7ovld4qgf4uty079oz6)
 Call ID: call_mbmtx7ovld4qgf4uty079oz6
  Args:
    name: LangGraph
    birthday: The release time could not be found in the search results.

我们再次触发了 human_assistance 工具中的 interrupt。在这种情况下,聊天机器人未能识别正确的日期,所以我们可以协助它:

human_command = Command(
    resume={
        "name": "LangGraph",
        "birthday": "Jan 17, 2024",
    },
)

events = graph.stream(human_command, config, stream_mode="values")
for event in events:
    if "messages" in event:
        event["messages"][-1].pretty_print()

返回结果:

================================== Ai Message ==================================

The search results did not directly indicate the release time of LangGraph. However, the information can be further verified by human assistance.
Tool Calls:
  human_assistance (call_mbmtx7ovld4qgf4uty079oz6)
 Call ID: call_mbmtx7ovld4qgf4uty079oz6
  Args:
    name: LangGraph
    birthday: The release time could not be found in the search results.
================================= Tool Message =================================
Name: human_assistance

Made a correction: {'name': 'LangGraph', 'birthday': 'Jan 17, 2024'}
================================== Ai Message ==================================

The release time of LangGraph, as corrected by human assistance, is January 17, 2024.

请注意,这些字段现在已反映在状态中:

snapshot = graph.get_state(config)

{k: v for k, v in snapshot.values.items() if k in ("name", "birthday")}

返回结果:

{'name': 'LangGraph', 'birthday': 'Jan 17, 2024'}

这使得下游节点(例如进一步处理或存储信息的节点)可以轻松访问这些信息。

手动更新状态

LangGraph 对应用程序状态提供了高度控制。例如,在任何时候(包括中断时),我们可以直接使用graph.update_state手动覆盖一个键。

graph.update_state(config, {"name": "LangGraph (library)"})

返回结果:

{'configurable': {'thread_id': '1',
  'checkpoint_ns': '',
  'checkpoint_id': '1f045d6d-9738-6a69-8006-0c42ead9b2f2'}}

如果我们调用 graph.get_state,可以看到新值已反映出来:

snapshot = graph.get_state(config)

{k: v for k, v in snapshot.values.items() if k in ("name", "birthday")}

返回结果:

{'name': 'LangGraph (library)', 'birthday': 'Jan 17, 2024'}

恭喜!您已向状态添加了自定义键,以便实现更复杂的工作流,并学习了如何从工具内部生成状态更新。

posted @ 2025-06-12 09:27  Filament  阅读(278)  评论(0)    收藏  举报
返回顶端