7.3 LangGraph中TypedDict与BaseModel的共通与嵌套

LangGraph智能体设计模式与多智能体开发(人工智能技术丛书)【行情 报价 价格 评测】-京东

王晓华LangGraph开发入门书《LangGraph智能体设计模式与多智能体开发》全文试读~_langgraph智能体设计模式与多智能体开发 pdf 下载-CSDN博客

目录

[7.3.1 LangGraph中TypedDict与BaseModel的共通](#7.3.1 LangGraph中TypedDict与BaseModel的共通)

[7.3.2 LangGraph中状态空间进阶:多类型数据嵌套](#7.3.2 LangGraph中状态空间进阶:多类型数据嵌套)


我们在上一节完成了多工具智能体的演示,通过设置一个用于传输状态的状态空间AgentState,我们可以完成工具的调用与状态更新。在定义上,相对于前期使用的BaseModel,这里我们使用了一种新的数据结构TypedDict。

数据结构的精准定义是LangGraph流程稳定运行的基石,TypedDict与BaseModel作为该领域的核心工具,其应用逻辑直接影响开发效率与数据可靠性。深入厘清二者的特性不仅是类型规范的基础,更能为多组件协同提供清晰指引。

在LangGraph开发中,TypedDict与BaseModel是定义数据结构的常用工具,二者均服务于类型规范与代码可读性,但在设计理念、功能边界和适用场景上存在显著差异。理解这些差异是实现LangGraph流程高效开发、数据可靠流转的关键------TypedDict聚焦于"类型提示",是Python原生的轻量级解决方案;BaseModel则依托Pydantic生态,提供"强数据校验与处理"能力。本文将从核心定位、功能特性、LangGraph适配场景三个维度展开分析,并结合实例说明二者的具体应用。

7.3.1 LangGraph中TypedDict与BaseModel的共通

在LangGraph的开发体系中,TypedDict(Python原生类型工具)与BaseModel(Pydantic核心类)是两类高频用于数据结构定义的工具。尽管二者的设计定位、功能强度存在差异,但核心共通点始终围绕为LangGraph 流程中的数据流转提供明确的类型约束展开------目的都是为了解决原生字典/数据对象在节点间传递时"类型不明确、结构无规范"的问题,既是静态类型提示的核心载体,也共同服务于 LangGraph 数据流转的可维护性与可读性提升。

  1. TypedDict:Python原生的"类型标注工具"

TypedDict是Python 3.8 及以上版本纳入标准库的类型工具(Python 3.10+可直接从typing_extensions导入),其核心价值是为原生字典赋予静态类型提示能力:它不创建新的数据类型,仅在开发阶段通过mypy、PyCharm 内置检查器等工具,强制规范字典的键名、键值类型,运行时几乎无额外性能损耗。

在LangGraph中,TypedDict的核心作用是"勾勒数据轮廓"------用于定义流程节点输入/输出的字典结构,明确节点间传递的字典必须包含哪些键、对应值的类型是什么。这是它与BaseModel的核心共通点之一:以类型约束为核心,让 LangGraph节点间的数据流转有明确的结构预期。

  1. BaseModel:Pydantic的"强类型数据契约"

BaseModel是Pydantic 库(LangGraph的核心依赖)的核心基类,主打"强类型数据模型"构建。它完全继承了 TypedDict "静态类型提示"的核心能力(核心共通点),并进一步在运行时实现了数据校验、自动类型转换、默认值填充、错误提示等增强功能,本质是为数据定义"不可违反的契约"。

在LangGraph中,BaseModel与TypedDict的另一核心共通点是:均服务于节点间数据流转的规范性;区别仅在于 BaseModel 更适用于需要数据可靠性保障的场景(如接收外部 API 输入、处理工具返回结果、定义核心业务数据结构),而TypedDict更轻量,仅聚焦于类型提示层面的约束。

核心共通点:

  • 类型约束目标一致:均为LangGraph 流程中的状态/节点数据提供明确的类型规则,解决原生字典"类型模糊"的问题。
  • 静态类型提示能力:均可被代码编辑器、类型检查工具识别,开发阶段提供类型补全、错误提示,减少类型相关 bug。
  • 适配 LangGraph 场景:均可作为LangGraph StateGraph的状态类型,直接定义节点间传递的数据结构,贴合 LangGraph的数据流设计逻辑。

下面根据LangGraph 最典型的"状态定义 +节点处理"场景,展示两者的共通点。

  1. 用TypedDict定义LangGraph状态(轻量类型约束)

from typing import TypedDict, Optional

from pydantic import BaseModel, ValidationError

from langgraph.graph import StateGraph, END

定义节点间传递的字典结构(核心:类型约束,与BaseModel共通)

class GraphStateTypedDict(TypedDict):

user_query: str # 必选字段,字符串类型

tool_result: Optionalstr # 可选字段,字符串类型

is_finished: bool = False # 3.10+支持默认值(类型约束延伸)

定义LangGraph节点:严格遵循TypedDict的类型约束处理数据

def process_query_typed(state: GraphStateTypedDict) -> GraphStateTypedDict:

开发阶段:若误写键名/类型,PyCharm/mypy会即时提示(静态类型提示能力)

state"tool_result" = f"处理查询:{state'user_query'}"

state"is_finished" = True

return state

构建LangGraph流程(TypedDict直接作为状态类型,适配LangGraph)

graph_typed = StateGraph(GraphStateTypedDict).add_node("process", process_query_typed).set_entry_point("process").add_edge("process", END).compile()

运行流程(验证类型约束:开发阶段错误会被提示,运行时无校验)

valid_input = {"user_query": "LangGraph使用教程", "is_finished": False}

result_typed = graph_typed.invoke(valid_input)

print("TypedDict流程结果:", result_typed)

这段代码首先导入了 TypedDict、BaseModel等核心依赖,接着定义了 GraphStateTypedDict 这个 TypedDict类,为LangGraph节点间传递的字典数据设定明确的类型约束,其中包含必选的字符串类型 user_query 字段、可选的字符串类型 tool_result 字段,以及带默认值的布尔类型 is_finished 字段,这是它与BaseModel实现类型约束的共通点。

process_query_typed节点函数,参数和返回值均严格遵循该TypedDict的类型规范,函数内为tool_result赋值并将is_finished标记为True,开发阶段若误写键名或类型,PyCharm、mypy等工具会实时提示,体现了静态类型提示能力。接着基于该TypedDict构建StateGraph流程,依次添加处理节点、设置流程入口点和结束边并编译,说明TypedDict可直接适配LangGraph的状态类型设计。最后传入符合类型约束的合法输入运行流程,输出处理结果,整个过程验证了TypedDict仅在开发阶段提供类型约束提示,运行时无额外校验的特性,核心是通过轻量的类型约束规范LangGraph节点间的数据流。

  1. 用BaseModel定义相同状态(强类型约束 + 运行时校验)

from typing import TypedDict, Optional

from pydantic import BaseModel, ValidationError

from langgraph.graph import StateGraph, END

定义强类型数据模型(核心:继承TypedDict的类型约束能力,新增运行时校验)

class GraphStateBaseModel(BaseModel):

user_query: str # 必选字段,字符串类型(与TypedDict共通)

tool_result: Optionalstr = None # 可选字段+默认值

is_finished: bool = False

自定义校验规则(BaseModel增强能力,TypedDict无)

def validate_query_length(self):

if len(self.user_query) > 100:

raise ValueError("用户查询长度不能超过100字符")

定义LangGraph节点:遵循类型约束,且可触发运行时校验

def process_query_model(state: GraphStateBaseModel) -> GraphStateBaseModel:

运行时校验(BaseModel增强能力,TypedDict无)

state.validate_query_length()

#类型约束逻辑与TypedDict一致(核心共通点)

state.tool_result = f"处理查询:{state.user_query}"

state.is_finished = True

return state

构建LangGraph流程(BaseModel同样适配StateGraph,与TypedDict共通)

graph_model = StateGraph(GraphStateBaseModel).add_node("process", process_query_model).set_entry_point("process").add_edge("process", END).compile()

运行流程:触发BaseModel的运行时类型校验

try:

合法输入(类型约束符合要求)

valid_input_model = {"user_query": "LangGraph使用教程"}

result_model = graph_model.invoke(valid_input_model)

print("BaseModel流程结果:", result_model)

非法输入(长度超限,触发运行时校验错误)

invalid_input_model = {"user_query": "a" * 101, "is_finished": False}

graph_model.invoke(invalid_input_model)

except ValidationError as e:

print("BaseModel运行时校验错误:", e.errors())

这段代码先基于Pydantic的BaseModel定义GraphStateBaseModel数据模型,其中user_query等字段的类型约束与TypedDict保持共通,同时新增自定义的validate_query_length方法,用于校验user_query长度不超过100字符,这是BaseModel独有的运行时校验能力。接着定义process_query_model节点函数,参数和返回值均遵循该BaseModel的类型规范,函数内先触发自定义校验,再完成tool_result赋值和is_finished状态更新,类型约束逻辑与TypedDict一致,体现核心共通点。随后基于该BaseModel构建 LangGraph的StateGraph流程,添加处理节点、设置入口点和结束边并编译,说明BaseModel同样适配LangGraph的状态类型设计,与TypedDict的适配性共通。最后通过try-except块运行流程:先传入仅含合法user_query的输入,流程正常执行并输出结果。

再传入user_query长度超限的非法输入,触发BaseModel的运行时校验,抛出ValidationError异常并捕获输出错误信息,完整展现BaseModel在类型约束基础上,新增运行时校验的核心特性。

通过代码演示,我们也可以清晰看到:TypedDict与BaseModel在LangGraph中都以类型约束为核心使命,无论是定义状态结构还是适配StateGraph流程,都能为节点间数据流转提供明确规范,开发阶段的静态类型提示能力也让代码更易维护。

但二者的定位差异同样显著------TypedDict作为Python原生工具,以"轻量无侵入"为优势,仅聚焦开发阶段的类型提示,运行时不产生额外开销,适合数据结构简单、无需严格校验的场景;而BaseModel依托Pydantic的强大能力,在继承类型约束核心功能的基础上,通过运行时数据校验、自动转换等特性构建"数据契约",能有效保障外部输入、工具返回等关键数据的可靠性,更适合对数据质量要求高的业务场景。

简言之,两者并非替代关系,而是LangGraph开发中适配不同需求的互补工具,开发者可根据是否需要运行时校验、数据复杂度等因素灵活选择,核心都是通过明确的类型规则提升LangGraph流程的稳定性与可读性。

7.3.2 LangGraph中状态空间进阶:多类型数据嵌套

LangGraph的状态空间(State Space)是流程数据流转的"中枢",承载着各节点的输入输出、流程进度与核心业务信息。在处理复杂任务(如多步骤计划执行、多维度信息整合)时,单一扁平的键值对结构难以满足数据组织需求,此时数据嵌套成为关键解决方案。通过多类型的嵌套定义,可将分散的关联数据封装为层级清晰的结构化模型,让状态空间既具备强类型校验能力,又能精准映射实际业务逻辑。

LangGraph的状态空间本质是"全流程共享的数据容器",节点通过读取或修改状态空间数据实现协同。当业务场景涉及"聚合型数据"(如包含多个子项的计划、关联多类信息的任务)时,扁平结构会导致状态键名冗余(如step_1_action、step_2_action)、数据关联性弱化,而数据嵌套通过"父模型包含子模型"的层级结构,可将关联数据聚合封装,让状态空间的组织逻辑与业务逻辑保持一致。

下面代码中,作者通过TypedDict实现的Step与Plan类,正是数据嵌套的基础实践------Step模型定义"单个步骤"的原子结构,Plan模型通过嵌套Step列表,形成"完整计划"的聚合结构,而对于WorkflowState我们使用BaseModel进行结构定义,从而为LangGraph状态空间提供高可读性、高可维护的数据载体。

1. 原子模型:TypedDict(仅类型标注,需通过字典索引访问)

class Step(TypedDict):

step: int

action: str

status: Literal"pending", "executing", "completed", "failed"

2.聚合模型:TypedDict(字典类型,需通过键索引访问)

class Plan(TypedDict):

plan_id: str

goal: str

steps: ListStep

create_time: str

3. LangGraph状态模型(Pydantic BaseModel,兼容字典类型的plan字段)

class WorkflowState(BaseModel):

current_node: str = Field(description="工作流当前执行的节点名称")

user_query: str = Field(description="用户输入的原始查询语句")

plan: OptionalPlan = Field(default=None, description="嵌套的计划数据(字典类型)")

error_info: Optionalstr = Field(default=None, description="错误信息")

这段代码首先通过Python原生的TypedDict定义了两层结构化的数据类型,用于规范计划相关的数据格式:

  • Step作为原子级别的数据模型,仅做静态类型标注,限定了单个步骤必须包含整数类型的步骤序号、字符串类型的执行动作,以及仅能取特定枚举值的执行状态,运行时本质仍是原生字典,需通过键索引而非属性访问。
  • Plan则作为聚合级模型,同样基于 TypedDict设计,整合了计划唯一标识、核心目标、Step类型的步骤列表和创建时间字段,将多个原子步骤组合成完整的计划结构,这种设计仅在开发阶段提供类型提示,无运行时校验能力,需要手动确保所有键值都完整传入。

在此基础上,代码基于 Pydantic的BaseModel把WorkflowState定义为LangGraph 工作流的核心状态载体,它承接了前面TypedDict定义的计划数据结构,同时补充了工作流运行所需的核心字段。current_node记录当前执行的节点名称,user_query 存储触发工作流的原始用户查询;plan字段标注为可选的Plan类型且默认值为None,适配计划尚未生成的场景;error_info则用于记录执行过程中的错误信息。

WorkflowState借助BaseModel的特性,为工作流状态提供了运行时的数据校验能力;Field 函数不仅补充了字段描述,还为可选字段设置了合理默认值,既兼容了TypedDict类型的plan字典,又保障了整个工作流状态数据的规范性和可维护性。

完整代码如下所示:

from langgraph.graph import StateGraph, END

from pydantic import BaseModel, Field

from typing import List, Literal, Optional, TypedDict

1. 原子模型:TypedDict(仅类型标注,需通过字典索引访问)

class Step(TypedDict):

step: int

action: str

status: Literal"pending", "executing", "completed", "failed"

2.聚合模型:TypedDict(字典类型,需通过键索引访问)

class Plan(TypedDict):

plan_id: str

goal: str

steps: ListStep

create_time: str

3. LangGraph状态模型(Pydantic BaseModel,兼容字典类型的plan字段)

class WorkflowState(BaseModel):

current_node: str = Field(description="工作流当前执行的节点名称")

user_query: str = Field(description="用户输入的原始查询语句")

plan: OptionalPlan = Field(default=None, description="嵌套的计划数据(字典类型)")

error_info: Optionalstr = Field(default=None, description="错误信息")

#节点1:生成计划(手动传入所有TypedDict键,返回状态对象)

def generate_plan(state: WorkflowState) -> WorkflowState:

手动为每个Step字典传入所有键(TypedDict无默认值)

steps = [

Step(step=1, action=f"分析用户需求:{state.user_query}", status="pending"),

Step(step=2, action="收集该需求相关的资料信息", status="pending"),

Step(step=3, action="制定具体的落地实施方案", status="pending"),

Step(step=4, action="审核并优化方案内容", status="pending"),

Step(step=5, action="敲定最终计划并输出结果", status="pending"),

]

构建Plan字典(传入所有必填键)

plan = Plan(

plan_id="plan_20251125_001",

goal=f"响应用户查询:{state.user_query}",

steps=steps,

create_time="2025-11-25"

)

更新状态对象(plan是字典类型)

state.plan = plan

state.current_node = "plan_executor"

return state

#节点2:执行计划并更新步骤状态(字典索引访问,而非点访问)

def execute_plan(state: WorkflowState) -> WorkflowState:

"""执行已生成的计划,更新已完成步骤的状态"""

if not state.plan: # state.plan是字典,None表示未生成

state.error_info = "计划尚未生成"

state.current_node = "error_handler"

return state

关键修正:字典用\[\]访问键,而非.属性

模拟执行前2步,更新status为completed

for i in range(2):

state.plan"steps"i"status" = "completed"

第3步更新为executing

state.plan"steps"2"status" = "executing"

state.current_node = "status_updater"

state.error_info = None

return state

#节点3:输出计划执行状态(字典索引访问步骤信息)

def update_status(state: WorkflowState) -> WorkflowState:

"""输出计划当前的执行状态信息"""

if not state.plan:

state.error_info = "计划尚未生成"

state.current_node = "error_handler"

return state

关键修正:遍历字典列表,用\[\]访问step/status/action键

step_status = [

f"步骤 {step'step'}:{step'status'} - {step'action'}"

for step in state.plan"steps"

]

print("当前计划执行状态:\n" + "\n".join(step_status))

state.current_node = "end"

return state

构建LangGraph工作流

graph = StateGraph(WorkflowState)

graph.add_node("plan_generator", generate_plan)

graph.add_node("plan_executor", execute_plan)

graph.add_node("status_updater", update_status)

错误处理节点:返回完整的WorkflowState对象

graph.add_node("error_handler", lambda state: WorkflowState(

current_node="end",

user_query=state.user_query,

plan=state.plan,

error_info=state.error_info

))

#设置流程流转规则

graph.set_entry_point("plan_generator")

graph.add_edge("plan_generator", "plan_executor")

graph.add_edge("plan_executor", "status_updater")

graph.add_edge("status_updater", END)

graph.add_edge("error_handler", END)

编译流程

app = graph.compile()

模拟运行流程

if name == "main":

初始化状态

initial_state = WorkflowState(

current_node="plan_generator",

user_query="为初学者制定一份LangGraph学习计划"

)

执行流程(返回字典类型)

final_state_dict = app.invoke(initial_state)

转换回WorkflowState对象

final_state = WorkflowState(**final_state_dict)

打印最终计划数据(字典类型,直接输出)

print("\n最终计划数据:\n", final_state.plan)

输出结果如下所示:

当前计划执行状态:

步骤 1:completed - 分析用户需求:为初学者制定一份LangGraph学习计划

步骤 2:completed - 收集该需求相关的资料信息

步骤 3:executing - 制定具体的落地实施方案

步骤 4:pending - 审核并优化方案内容

步骤 5:pending - 敲定最终计划并输出结果

最终计划数据:

{'plan_id': 'plan_20251125_001', 'goal': '响应用户查询:为初学者制定一份LangGraph学习计划', 'steps': {'step': 1, 'action': '分析用户需求:为初学者制定一份LangGraph学习计划', 'status': 'completed'}, {'step': 2, 'action': '收集该需求相关的资料信息', 'status': 'completed'}, {'step': 3, 'action': '制定具体的落地实施方案', 'status': 'executing'}, {'step': 4, 'action': '审核并优化方案内容', 'status': 'pending'}, {'step': 5, 'action': '敲定最终计划并输出结果', 'status': 'pending'}, 'create_time': '2025-11-25'}

我们运行该代码后,从结果可以看到,会先输出计划的实时执行状态,再打印格式化的最终计划数据(包含所有步骤的序号、动作、状态等嵌套信息),直观体现 LangGraph中嵌套 Pydantic 模型的状态管理方式。

LangGraph中状态空间的数据嵌套,本质是通过框架的层级定义,将业务逻辑映射为结构化的数据模型,其核心价值在于:以类型安全为基础,提升复杂状态的组织效率、操作便捷性与可维护性。参考代码中的Step与Plan模型是嵌套设计的起点,通过扩展集成到WorkflowState状态空间后,可适配从简单计划管理到复杂多步骤流程的各类场景。

在实际开发中,需结合业务复杂度设计嵌套层级,平衡灵活性与简洁性------通过原子模型拆分、聚合模型整合、状态模型集成的"三步走"策略,即可充分发挥数据嵌套在LangGraph流程中的优势,构建高效、可靠的结构化工作流。

相关推荐
旖旎夜光1 小时前
【LangChain实战】LangChain 学习笔记(一):从定义大模型到工具调用
人工智能·笔记·python·学习·langchain
月华路1 小时前
《模型不玄学》第16章 概率校准
人工智能·深度学习·机器学习
艾莉丝努力练剑2 小时前
【AI大模型接入SDK】ChatGPT API
网络·c++·人工智能·websocket·网络协议·学习·chatgpt
枫叶林FYL3 小时前
【群体智能集群控制工程实践】第8章 无人机蜂群测试与部署
人工智能·无人机
2601_949950636 小时前
练题簿,把培训从“走过场”变成“真落地”
人工智能·学习·小程序·刷题·小程序推荐
诸神缄默不语8 小时前
备战 AI 出海 DAY 0:海外数据采集
大数据·人工智能
Ysn07199 小时前
YOLO-Master工程:experts.py 专家结构详解与目标检测专家设计启发
人工智能·yolo·目标检测
BingoGo9 小时前
使用 GPT-6 Astra 模型 请立刻更新你的 Skill 与提示词
人工智能
香菜+9 小时前
端侧视频分析 · 架构笔记
人工智能