LangGraph中结点并行执行

LangGraph节点并行执行解析

基本概念

LangGraph 支持节点的并行执行 这种并行化可以通过扇出(fan-out)和扇入(fan-in)机制实现,利用标准边或条件边(conditionalEdges)来完成 。框架原生支持并行执行可以显著提升基于图的工作流的性能

LangGraph 的状态图执行模型中有一个“超级步”(superstep)的概念。当一个节点有多个出边(无论是普通边还是条件边返回了多个目标节点名)时,所有这些目标节点会在下一个“超级步”中被并行执行 。同一层级的节点会并行执行,但它们的执行顺序是不确定的 。这意味着,只要节点之间没有依赖关系(例如,一个节点的输出不能作为另一个并行节点的输入),它们就可以同时运行。

案例

from typing import TypedDict, Annotated, List
import operator
from langgraph.graph import StateGraph, END
import time
import asyncio # 用于模拟异步操作

# 定义状态。使用列表来收集并行节点的结果。
class AgentState(TypedDict):
    query: str # 用户的原始查询
    parallel_results: Annotated[List[str], operator.add] # 用于累积并行节点的输出

# 模拟两个并行执行的工具节点
async def tool_weather(state: AgentState):
    """模拟调用天气API"""
    await asyncio.sleep(5) # 模拟网络延迟
    result = f"Weather info for '{
     
     state['query']}': Sunny, 25°C"
    print(f"Executed tool_weather: {
     
     result}"
基于大模型智能体Agent的LangGraph入门与实战课程目标:本课程旨在为LangGraph的初学者提供深入的理论知识和实践技能,使其能够独立构建和部署基于LangGraph的应用程序。课程形式:理论讲解 + 实战演练第1课 LangGraph基础架构与环境配置-LangGraph的概念解析第2课 LangGraph基础架构与环境配置-LangGraph的环境搭建与依赖管理第3课 LangGraph的基础原理与应用入门-构建基本聊天机器人及使用工具增强第4课 LangGraph的基础原理与应用入门-内存管理、人在回路、状态更新第5课 LangGraph高级图控制技术-并行节点扇出和扇入、增加额外步骤、条件分支第6课 LangGraph高级图控制技术-稳定排序、Map-Reduce并行执行、图递归控制第7课 LangGraph持久化机制与状态管理-线程级持久化、子图持久化、跨线程持久化第8课 LangGraph Human-in-the-loop-断点设置、动态设置断点、编辑更新状态第9课 LangGraph Human-in-the-loop-等待用户输入、时间旅行、工具评审第10课 LangGraph在具有长期记忆的有状态Agent中的应用-长期记忆及短期记忆、过滤信息、删掉信息第11课 LangGraph在具有长期记忆的有状态Agent中的应用-摘要总结、跨线程持久化、代理语义搜索第12课 LangGraph工具集成与调用-直接调用ToolNode、大模型使用工具第13课 LangGraph工具集成与调用-工具调用报错处理、运行时值传递给工具、注入参数第14课 LangGraph工具集成与调用-配置传入工具、从工具更新图状态、管理大量工具第15课 LangGraph子图设计与实现-添加及使用子图、父图及子图状态管理第16课 LangGraph子图设计与实现-子图状态的查看与更新、子图输入输出的转换与处理第17课 LangGraph项目实战演练-多智能体系统主管委托各个代理第18课 LangGraph课程复习与答疑 自我反思案例及论文案例讲解
### 带头结点的链栈 Push 操作实现 在带有头结点的链栈中,Push 操作的核心思想是通过头插法将新节点插入到头结点之后。这种方法能够保证每次插入操作的时间复杂度为 O(1),并且实现栈的后进先出(LIFO)特性。 以下是带头结点链栈 Push 操作的具体实现方法和代码示例: #### 1. 新节点的创建 首先需要为新节点分配内存,并初始化其数据域和指针域。这一步确保了新节点能够正确存储数据并链接到链表中。 ```c LinkList p = (LinkList)malloc(sizeof(LNode)); // 创建新节点并分配内存 p->data = e; // 将传入的数据赋值给新节点的数据域 p->next = NULL; // 初始化新节点的指针域为 NULL ``` #### 2. 插入新节点 接下来,将新节点插入到头结点之后。具体步骤包括: - 将新节点的 `next` 指针指向当前头结点的 `next` 节点。 - 更新头结点的 `next` 指针,使其指向新节点。 以下是完整的 Push 操作代码实现: ```c Status Push(LinkList L, ElemType e) { LinkList p = (LinkList)malloc(sizeof(LNode)); // 分配新节点内存 if (p == NULL) return ERROR; // 如果内存分配失败,返回错误 p->data = e; // 设置新节点的数据域 p->next = L->next; // 将新节点的 next 指针指向当前头结点的下一个节点 L->next = p; // 更新头结点的 next 指针,使其指向新节点 return OK; // 返回成功状态 } ``` #### 3. 代码解析 - **内存分配**:通过 `malloc` 函数为新节点分配内存[^1]。 - **数据赋值**:将传入的元素值 `e` 赋值给新节点的数据域 `data`[^2]。 - **指针调整**:新节点的 `next` 指针指向当前头结点的 `next` 节点,然后更新头结点的 `next` 指针指向新节点[^3]。 #### 4. 注意事项 - 确保在调用 `malloc` 时检查内存分配是否成功。如果内存分配失败,函数应返回 `ERROR`[^5]。 - 头结点本身不存储实际数据,仅作为辅助节点使用,因此其 `next` 指针始终指向栈顶节点[^4]。 ### 示例运行 假设初始链栈为空,头结点的 `next` 指针为 `NULL`。依次执行以下操作: - `Push(L, 1)`:新节点 `1` 被插入到头结点之后,链表结构为 `Head -> 1 -> NULL`。 - `Push(L, 2)`:新节点 `2` 被插入到头结点之后,链表结构为 `Head -> 2 -> 1 -> NULL`。 - `Push(L, 3)`:新节点 `3` 被插入到头结点之后,链表结构为 `Head -> 3 -> 2 -> 1 -> NULL`。 最终链表的顺序反映了栈的后进先出特性。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值