Langgraph State TypedDict 类型和dict类型

状态类型 dict vs TypedDict


builder = StateGraph( xx ) 是 LangGraph 中初始化状态图的代码,其核心作用是 定义一个动态状态(State)的结构。以下是详细解析:

1. 如state_schema 为 dict 的含义

  • 状态类型dict 表示状态(State)是一个 普通的 Python 字典,而非严格类型定义的 TypedDict
  • 动态性:状态可以包含任意字段(如 xy 等),无需预定义结构,字段在运行时动态添加。

2. 对比 TypedDict 方案

之前的代码(使用 TypedDict

class OverallState(TypedDict):
    question: str
    answer: str

builder = StateGraph(OverallState)
  • 严格类型:状态字段需提前声明(如 questionanswer)。
  • 类型安全:节点函数返回值必须匹配 TypedDict 的字段定义,否则会触发类型检查错误。

当前代码(使用 dict

builder = StateGraph(dict)
  • 完全动态:状态可以是任意字典,字段无需提前声明。
  • 灵活性:节点函数可以返回任意字段(如 xy),LangGraph 会自动合并到状态中。

3. 何时选择 dict vs TypedDict

场景 dict TypedDict
开发阶段 快速原型 正式项目
状态复杂度 简单(字段少且动态) 复杂(字段多且固定)
团队协作 个人开发 多人协作(需明确接口)
错误检查 运行时可能报错(如 KeyError 编码时类型检查(提前发现问题)

总结

  • 核心作用StateGraph(dict) 表示状态是一个动态字典,字段无需预定义。
  • 优势:灵活快速,适合简单或动态场景。
  • 劣势:缺乏类型安全和文档支持,需谨慎处理字段访问。

建议在复杂项目中使用 TypedDict,而在快速验证逻辑时使用 dict

例子1 : node1 输入的结果通过node2翻译。 使用TypedDict 作为类型

设计要点: 在节点里面操作的变量必须在模式里面定义。

FAQ

1 llm_node 函数,return llm_answer 属于InputState还是OuputState ?
在用户的代码中,InputState被扩展为包含llm_answer,这是一个Optional字段。这意味着在初始输入时,llm_answer可能不存在,但llm_node执行后会添加它。因此,llm_answer实际上是中间状态的一部分,属于OverallState,而不是单纯的InputState或OutputState。
可能用户混淆了TypedDict的继承与实际状态流转。OverallState合并了Input和Output,所以所有可能的字段都应该在其中定义。但用户可能认为InputState和OutputState是独立的,而实际上在状态流转中,所有的中间变量都存储在OverallState里。

from langgraph.graph import StateGraph
from typing_extensions import TypedDict
from langgraph.graph import START, END
from typing_extensions import TypedDict, Optional


# 定义输入的模式
class InputState(TypedDict):
    question: str
    llm_answer: Optional[str]  # 表示 answer 可以是 str 类型,也可以是 None


# 定义输出的模式
class OutputState(TypedDict):
    answer: str

# 将 InputState 和 OutputState 这两个 TypedDict 类型合并成一个更全面的字典类型。
class OverallState(InputState, OutputState):
    pass


from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

import getpass
import os

def create_llm() -> ChatOpenAI:
    """创建并返回配置好的大模型实例"""
    return ChatOpenAI(
        api_key=os.getenv("DASHSCOPE_API_KEY") or "your_api_key_here",
        base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
        model="qwen2.5-math-72b-instruct",

    )


def llm_node(state: InputState):
    messages = [
        ("system", "你是一位乐于助人的智能小助理",),
        ("human", state["question"])
    ]

    llm = create_llm()
    response = llm.invoke(messages)

    # 自定义变量 llm_answer, 该变量需要在 模式里面定义
    return {"llm_answer": response.content}


def action_node(state: InputState):
    messages = [
        ("system", "无论你接收到什么语言的文本,请翻译成英语",),
        ("human", state["llm_answer"])
    ]

    llm = create_llm()

    response = llm.invoke(messages)

    return {"answer": response.content}


# 明确指定它的输入和输出数据的结构或模式
builder = StateGraph(OverallState, input=InputState, output=OutputState)

# 添加节点
builder.add_node("llm_node", llm_node)
builder.add_node("action_node", action_node)


# 添加边
builder.add_edge(START, "llm_node")
builder.add_edge("llm_node", "action_node")

builder.add_edge("action_node", END)

# 编译图
graph = builder.compile()


final_answer = graph.invoke({"question":"你好,请你详细的介绍一下你自己"})

print(final_answer["answer"])

例子2 : 使用dict作为state类型

from langgraph.graph import StateGraph

# 构建图
builder = StateGraph(dict)
print("builder.schema",builder.schema)

def addition(state):
    print(state)
    return {"x": state["x"] + 1}

def subtraction(state):
    print(state)
    return {"y": state["x"] - 2}

from langgraph.graph import START, END


# 向图中添加两个节点
builder.add_node("addition", addition)
builder.add_node("subtraction", subtraction)

# 构建节点之间的边
builder.add_edge(START, "addition")
builder.add_edge("addition", "subtraction")
builder.add_edge("subtraction", END)
print("builder.edges=",builder.edges)
graph = builder.compile()
# 定义一个初始化的状态
initial_state = {"x":10}

graph.invoke(initial_state)

from IPython.display import Image, display

display(Image(graph.get_graph(xray=True).draw_mermaid_png()))

参考资料

https://www.bilibili.com/video/BV1XmoKYWEaU?buvid=XY794497F40D7190397F2DB552749EB743FAC&from_spmid=main.my-history.0.0&is_story_h5=false&mid=w29dlCSuM4lPthGu19G2hA%3D%3D&plat_id=116&share_from=ugc&share_medium=android&share_plat=android&share_session_id=92aef98e-b415-4c8b-972b-cab5239051c3&share_source=WEIXIN&share_tag=s_i&spmid=united.player-video-detail.0.0&timestamp=1749123457&unique_k=wtxmozp&up_id=1621571159&vd_source=70438ef17a4595bc040495393207971e&spm_id_from=333.788.videopod.episodes&p=10

posted @ 2025-04-05 15:48  向着朝阳  阅读(158)  评论(0)    收藏  举报