开启左侧

【LangGraph】langgraph.prebuilt.InjectedState 类:工具函数中注入状态图的当前状态

[复制链接]
AI小编 发表于 昨天 09:31 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
作者:彬彬侠
langgraph.prebuilt.InjectedState 是 LangGraph 库中 langgraph.prebuilt 模块的一个特殊类型注解,继承自 InjectedToolArg,用于在工具函数中注入 LangGraph 状态图的当前状态。它允许工具在运行时访问状态(如对话历史或用户上下文),同时隐藏该参数,使语言模型(LLM)无法生成或修改状态,从而提高安全性和开发效率。以下是对 InjectedState 类的有序、清晰介绍,基于提供的参考信息和 LangGraph 文档。

1. 定义与功能

1.1 类定义

InjectedState 是一个类型注解类,定义如下:
  1. from langgraph.prebuilt import InjectedState
  2. classInjectedState(InjectedToolArg):"""
  3.     用于工具参数的注解,表示该参数将注入状态图的当前状态。
  4.     参数:
  5.         field: 可选,指定状态中要注入的特定键。如果为 None,则注入整个状态。
  6.     示例:
  7.         @tool
  8.         def state_tool(x: int, state: Annotated[dict, InjectedState]) -> str:
  9.             '''处理状态的工具。'''
  10.             if len(state["messages"]) > 2:
  11.                 return state["foo"] + str(x)
  12.             else:
  13.                 return "消息不足"
  14.     """def__init__(self, field: Optional[str]=None)->None:
  15.         self.field = field
复制代码
    继承:继承自 InjectedToolArg,表明它是工具参数注入机制的一部分。作用:标记工具函数中的参数,指示 LangGraph 在运行时注入状态图的状态。
  • 关键特性
      隐藏参数:使用 InjectedState 注解的参数不会出现在工具的模式(schema)中,LLM 无法生成该参数的值。自动注入:当工具通过 ToolNode 执行时,LangGraph 自动将状态(或指定字段)注入到参数中。

1.2 核心功能

    状态注入:将状态图的当前状态(或其某个字段)传递给工具函数,供工具使用。模式隔离:隐藏状态参数,防止 LLM 尝试生成或修改状态,确保安全和正确性。灵活性:支持注入整个状态(field=None)或特定字段(field="key"),适应不同场景。与 ToolNode 集成:与 ToolNode 配合使用,自动处理工具调用和状态注入。
1.3 使用场景

    状态依赖工具:工具需要访问状态(如对话历史、用户信息)以执行上下文相关的操作。多轮对话:在聊天机器人中,工具需要引用对话历史或用户上下文。安全敏感场景:状态包含敏感数据(如用户 ID),不应暴露给 LLM。复杂工作流:工具需要状态中的中间结果或共享变量来完成任务。

2. 参数与用法

2.1 参数


  • field
      类型:Optional[str]默认值:None
    • 描述:
        如果为 None,注入整个状态对象(通常是字典或自定义状态类)。如果指定为字符串(如 "foo"),仅注入状态中对应键的值。

    • 示例:
        InjectedState():注入整个状态,如 {"messages": [...], "foo": "bar"}。InjectedState("foo"):仅注入 state["foo"],如 "bar"。


2.2 用法

InjectedState 通常与 typing_extensions.Annotated 一起使用,注解工具函数的参数。以下是基本用法:
    定义工具
    使用 @tool 装饰器创建工具,参数中添加 InjectedState 注解。
    集成到状态图
    使用 ToolNode 处理工具调用,LangGraph 自动注入状态。
    运行工作流
    通过状态图的 invoke 或 stream 方法执行,工具接收注入的状态。

3. 实现原理

3.1 状态注入机制

    注解识别:LangGraph 的运行时(通过 ToolNode)识别工具函数中带有 InjectedState 注解的参数。
  • 状态提取
      如果 field=None,将整个状态对象(通常是字典或 Pydantic 模型)传递给工具。如果 field 指定为键(如 "foo"),从状态中提取对应值。
    参数注入:在工具调用时,运行时将状态(或字段值)注入到工具的参数中,绕过 LLM 的生成过程。模式隐藏:InjectedState 参数被从工具的模式中移除,LLM 只看到其他暴露的参数(如 x: int)。
3.2 与 ToolNode 的协作

    ToolNode 是 LangGraph 的工具执行节点,负责解析 AIMessage 中的工具调用(tool_calls)。当工具包含 InjectedState 参数,ToolNode 在调用工具前自动注入状态,确保工具接收正确的上下文。注入过程对开发者透明,简化了状态管理。
3.3 状态格式

    状态通常是字典(如 {"messages": [...], "foo": "bar"})或自定义 TypedDict。工具通过标准字典操作(如 state["key"])或属性访问(如果状态是 Pydantic 模型)获取数据。

4. 使用示例

以下是一个完整的示例,展示如何使用 InjectedState 在状态图中注入状态到工具。
4.1 示例代码
  1. from typing import List
  2. from typing_extensions import Annotated, TypedDict
  3. from langchain_core.messages import BaseMessage, AIMessage
  4. from langchain_core.tools import tool
  5. from langgraph.prebuilt import InjectedState, ToolNode
  6. # 定义状态classAgentState(TypedDict):
  7.     messages: List[BaseMessage]
  8.     foo:str# 定义工具 1:访问整个状态@tooldefstate_tool(x:int, state: Annotated[dict, InjectedState])->str:"""根据状态中的消息数量处理输入。"""iflen(state["messages"])>2:return state["foo"]+str(x)else:return"消息不足"# 定义工具 2:访问特定字段@tooldeffoo_tool(x:int, foo: Annotated[str, InjectedState("foo")])->str:"""处理状态中的 foo 字段。"""return foo +str(x +1)# 创建 ToolNode
  9. tools =[state_tool, foo_tool]
  10. node = ToolNode(tools)# 定义状态和工具调用
  11. tool_call1 ={"name":"state_tool","args":{"x":1},"id":"1","type":"tool_call"}
  12. tool_call2 ={"name":"foo_tool","args":{"x":1},"id":"2","type":"tool_call"}
  13. state ={"messages":[AIMessage("", tool_calls=[tool_call1, tool_call2])],"foo":"bar"}# 执行工具节点
  14. result = node.invoke(state)for msg in result["messages"]:print(f"{msg.__class__.__name__}: {msg.content}")
复制代码
4.2 输出示例
  1. ToolMessage: 消息不足
  2. ToolMessage: bar2
复制代码
4.3 代码解析

    状态:AgentState 定义了状态结构,包含 messages 和 foo 字段。
  • 工具
      state_tool:使用 InjectedState 注入整个状态,检查 messages 长度并操作 foo。foo_tool:使用 InjectedState("foo") 注入 state["foo"],直接操作该字段。

  • 工具调用
      tool_call1 调用 state_tool,传入 x=1,注入整个状态。由于 messages 长度为 1,返回“消息不足”。tool_call2 调用 foo_tool,传入 x=1,注入 foo="bar",返回 bar2。
    ToolNode:处理工具调用,自动注入状态并生成 ToolMessage。
4.4 集成到状态图

以下是将上述工具集成到完整状态图的示例:
  1. from langgraph.graph import StateGraph, END
  2. from langchain_openai import ChatOpenAI
  3. from langchain_core.prompts import ChatPromptTemplate
  4. # 定义 Agent 节点defagent(state: AgentState)-> AgentState:
  5.     prompt = ChatPromptTemplate.from_template("根据输入调用工具:{input}")
  6.     llm = ChatOpenAI(model="gpt-3.5-turbo").bind_tools(tools)
  7.     message = llm.invoke(state["messages"][-1].content)
  8.     state["messages"].append(message)return state
  9. # 构建状态图
  10. workflow = StateGraph(AgentState)
  11. workflow.add_node("agent", agent)
  12. workflow.add_node("tools", node)
  13. workflow.add_edge("tools","agent")
  14. workflow.add_conditional_edges("agent",lambda state:"tools"if state["messages"][-1].tool_calls else END)
  15. workflow.set_entry_point("agent")# 编译并运行
  16. graph = workflow.compile()
  17. initial_state ={"messages":[HumanMessage(content="处理数字 1")],"foo":"bar"}
  18. result = graph.invoke(initial_state)
复制代码

5. 使用场景

InjectedState 适用于以下场景:
    上下文相关工具:工具需要访问对话历史、用户信息或其他状态数据,例如个性化响应。敏感数据处理:状态包含敏感信息(如用户 ID、会话令牌),不应暴露给 LLM。多轮对话:在聊天机器人中,工具需要引用历史消息或上下文。复杂工作流:工具需要访问共享状态变量以协调多步骤任务。
示例场景
    聊天机器人:工具根据用户 ID 从状态中获取用户偏好,提供定制化回答。自动化工作流:工具根据状态中的中间结果决定操作,例如数据处理后更新状态。

6. 注意事项

    状态格式
      确保状态包含工具期望的键(如 foo),否则可能引发 KeyError。如果使用 field,验证状态中存在该键。
    工具模式
      InjectedState 参数不出现在工具模式中,LLM 只生成其他参数。确保工具的非注入参数有清晰的类型注解,便于 LLM 生成。
    性能
      注入整个状态可能增加内存开销,对于大型状态,优先使用 field 指定字段。使用异步工具调用(ToolNode 支持 ainvoke)优化性能。
    调试
      启用 debug=True 查看状态注入日志。使用 graph.get_graph().to_dot() 可视化状态图,验证工具节点行为。
    版本兼容性
      InjectedState 是较新的功能(截至 2025 年 5 月,LangGraph 0.3+ 支持)。检查 LangGraph 文档 确认版本支持。


7. 与其他注解的对比

注解用途是否暴露给 LLM示例场景
InjectedState注入整个状态或指定字段工具访问对话历史或用户上下文
InjectedToolArg注入运行时参数(如特定值)注入动态用户 ID 或会话令牌
RunnableConfig注入运行时配置(如执行设置)传递执行超时或元数据
InjectedStore注入 LangGraph 存储对象工具访问持久化存储数据
InjectedState 专注于状态注入,适合需要完整上下文的工具,而 InjectedToolArg 更适合单一值注入。

8. 总结

langgraph.prebuilt.InjectedState 是一个强大的类型注解,用于在 LangGraph 工具中注入状态图的状态。它通过隐藏状态参数,防止 LLM 生成敏感数据,同时允许工具访问上下文,实现安全、高效的上下文相关操作。支持注入整个状态或指定字段,与 ToolNode 无缝集成,适用于聊天机器人、自动化工作流等场景。通过清晰的注解和自动注入机制,它简化了状态管理,提升了开发效率。

原文地址:https://blog.csdn.net/u013172930/article/details/148011556
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题
阅读排行更多+

Powered by Discuz! X3.4© 2001-2013 Discuz Team.( 京ICP备17022993号-3 )