到目前为止,我们依赖一个包含一个条目(消息列表)的简单状态。虽然这个简单状态可以走得很远,但如果您想定义复杂的行为而不依赖于消息列表,您可以向状态添加额外的字段。
参考文档
实践自定义状态
1.将键添加到状态中
在这里,我们将演示一个新场景,其中聊天机器人使用其搜索工具查找特定信息,并将其转发给人工进行审查。让聊天机器人研究一个实体的生日。我们将向状态添加name
和birthday
键
from typing import Annotatedfrom typing_extensions import TypedDictfrom langgraph.graph.message import add_messagesclass 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 # 状态更新命令和人工干预中断函数@tooldef 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_modelfrom langchain_openai import ChatOpenAIfrom langchain_tavily import TavilySearchfrom langgraph.checkpoint.memory import MemorySaverfrom langgraph.graph import StateGraph, START, ENDfrom langgraph.prebuilt import ToolNode, tools_condition#环境变量设置,替换为你的API KEYos.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_assistanceMade 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'}
恭喜! 您已向状态添加了自定义键,以便实现更复杂的工作流,并学习了如何从工具内部生成状态更新。
原文地址:https://www.cnblogs.com/LiShengTrip/p/18924971