LangGraph学习笔记四(Node和Edge)

一.Node基础笔记

1.给节点添加retry_policy和cache_policy

python 复制代码
from functools import partial
from typing import TypedDict

from langgraph.graph import StateGraph, START, END
from langgraph.types import RetryPolicy
from requests import RequestException, Timeout
from langgraph.types import CachePolicy

# 定义状态
class GraphState(TypedDict):
    process_data: dict # 默认更新策略


# 定义一个节点,入参为state
def input_node(state: GraphState) -> GraphState:
    print(f'input_node收到的初始值:{state}')
    return {"process_data": {"input": "input_value"}}

# 定义带参数的node节点
def process_node(state: dict, param1: int, param2: str) -> dict:
    print("-"*100)
    print(state, param1, param2)
    print("-"*100)
    return {"process_data": {"process": "process_value"}}


# 重试策略,add_node方法时可选
retry_policy = RetryPolicy(
    max_attempts=3,                       # 最大重试次数
    initial_interval=1,                   # 初始间隔
    jitter=True,                          # 抖动(添加随机性避免重试风暴)
    backoff_factor=2,                     # 退避乘数(每次重试间隔时间的增长倍数)
    retry_on=[RequestException, Timeout]  # 只重试这些异常
)



stateGraph = StateGraph(GraphState)
# 添加inpu节点
stateGraph.add_node("input", input_node)
# 给process_node节点绑定参数
process_with_params = partial(process_node, param1=100, param2="test")
# 添加带参数的node节点
stateGraph.add_node(
    node="process",
    action= process_with_params,
    retry_policy=retry_policy,
    cache_policy= CachePolicy(ttl=8))

# 定义节点之间的执行顺序 edges
# 设置节点间的依赖关系,形成执行流程图
stateGraph.add_edge(START, "input")
stateGraph.add_edge("input", "process")
stateGraph.add_edge("process", END)

# 编译图构建器生成计算图
graph = stateGraph.compile()


# # 打印图的边和节点信息
print(stateGraph.edges)
print(stateGraph.nodes)
# 打印图的可视化结构
print(graph.get_graph().print_ascii())

print()

# 定义一个初始状态字典,包含键值对"x": 5
initial_state={"process_data": 5}
# 调用graph对象的invoke方法,传入初始状态,执行图计算流程
result= graph.invoke(initial_state)
print(f"最后的结果是:{result}")

二.Edge基础笔记

1.普通边

python 复制代码
"""
LangGraph普通边演示

普通边是直接连接两个节点的边,表示无条件地从一个节点跳转到另一个节点。
"""

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


# 定义状态
class AtguiguState(TypedDict):
    value: int
    step: str


# 定义节点函数
def node_a(state: AtguiguState) -> dict:
    """节点A"""
    print("执行节点A")
    return {"value": state["value"] + 1, "step": "A执行完毕"}


def node_b(state: AtguiguState) -> dict:
    """节点B"""
    print("执行节点B")
    return {"value": state["value"] * 2, "step": "B执行完毕"}


def node_c(state: AtguiguState) -> dict:
    """节点C"""
    print("执行节点C")
    return {"value": state["value"] - 1, "step": "C执行完毕"}


def main():
    """演示普通边"""
    print("=== 普通边演示 ===")

    # 创建图
    builder = StateGraph(AtguiguState)

    # 添加节点
    builder.add_node("node_a", node_a)
    builder.add_node("node_b", node_b)
    builder.add_node("node_c", node_c)

    # 添加普通边
    builder.add_edge(START, "node_a")  # 从开始到A
    builder.add_edge("node_a", "node_b")  # 从A到B
    builder.add_edge("node_b", "node_c")  # 从B到C
    builder.add_edge("node_c", END)  # 从C到结束

    # 编译图
    app = builder.compile()

    # 执行图
    result = app.invoke({"value": 1})
    print(f"执行结果: {result}\n")
    # 打印图的边和节点信息
    print(builder.edges)
    #print(builder.nodes)
    # 打印图的ascii可视化结构
    print(app.get_graph().print_ascii())
    print("=================================")
    print()
    # 打印图的可视化结构,生成更加美观的Mermaid 代码,通过processon 编辑器查看
    print(app.get_graph().draw_mermaid())


if __name__ == "__main__":
    main()

执行结果:

2.条件边

python 复制代码
"""
LangGraph 条件边
分支流程控制语句分支路由(Router → Weather / Chat)
使用langgraph构建了一个状态图,根据输入数值的奇偶性执行不同节点。
check_x接收并传递状态,
is_even判断奇偶,
handle_even和handle_odd分别处理偶数和奇数情况,最终输出结果。
"""

from typing import Optional
from langgraph.constants import START, END
from langgraph.graph import StateGraph
from loguru import logger
from pydantic import BaseModel


class MyState(BaseModel):
    """
    定义状态模型,用于在图节点之间传递数据
    Attributes:
        x (int): 输入的整数
        result (Optional[str]): 处理结果,可为"even"或"odd"
    """
    x: int
    result: Optional[str] = None

# 检查输入状态的节点函数
def check_x(state: MyState) -> MyState:
    """
    检查输入状态的节点函数
    Args:
        state (MyState): 包含输入数据的状态对象
    Returns:
        MyState: 返回原始状态对象,未做修改
    """
    logger.info(f"[check_x] Received state: {state}")
    return state

# 判断状态中x值是否为偶数的条件函数
def is_even(state: MyState) -> bool:
    """
    判断状态中x值是否为偶数的条件函数
    Args:
        state (MyState): 包含待判断数值的状态对象
    Returns:
        bool: 如果x是偶数返回True,否则返回False
    """
    logger.info(f"[is_even] :{state.x % 2 == 0} ")
    return state.x % 2 == 0

# 处理偶数情况的节点函数
def handle_even(state: MyState) -> MyState:
    """
    处理偶数情况的节点函数
    Args:
        state (MyState): 包含偶数输入的状态对象
    Returns:
        MyState: 返回更新后的状态对象,result设置为"even"
    """
    logger.info("[handle_even] x 是偶数")
    return MyState(x=state.x, result="even")

#处理奇数情况的节点函数
def handle_odd(state: MyState) -> MyState:
    """
    处理奇数情况的节点函数
    Args:
        state (MyState): 包含奇数输入的状态对象
    Returns:
        MyState: 返回更新后的状态对象,result设置为"odd"
    """
    logger.info("[handle_odd] x 是奇数")
    return MyState(x=state.x, result="odd")

builder = StateGraph(MyState)
# 添加节点
builder.add_node("check_x", check_x)
builder.add_node("handle_even", handle_even)
builder.add_node("handle_odd", handle_odd)


# 添加条件边,根据is_even函数的返回值决定流向哪个节点
builder.add_conditional_edges("check_x", is_even, {
    True: "handle_even",
    False: "handle_odd"
})

# 添加起始边,从START节点流向check_x节点
builder.add_edge(START, "check_x")

# 添加结束边,从处理节点流向END节点
builder.add_edge("handle_even", END)
builder.add_edge("handle_odd", END)

# 编译图结构
graph = builder.compile()

# 打印图的可视化结构
print(graph.get_graph().print_ascii())

# 测试用例:输入偶数4
logger.info("输入 x=4(偶数)")
graph.invoke(MyState(x=3))

# # 测试用例:输入奇数3
# logger.info("输入 x=3(奇数)")
# graph.invoke(MyState(x=3))

执行结果:

3.多个条件边

python 复制代码
from langgraph.graph import StateGraph, START, END
from typing import TypedDict, List, Annotated


# 定义状态
class AtguiguState(TypedDict):
    x: int

def addition1(state):
    """
    执行加法运算的节点函数
    参数:
        state (dict): 包含输入数据的状态字典,必须包含键"x"
    返回:
        dict: 返回更新后的状态字典,其中"x"的值增加1
    """
    print(f'加法节点addition1收到的初始值:{state}')
    return {"x": state["x"] + 1}

def addition2(state):
    print(f'加法节点addition2收到的初始值:{state}')
    return {"x": state["x"] + 2}

def addition3(state):
    print(f'加法节点addition3收到的初始值:{state}')
    return {"x": state["x"] + 3}

def route_by_sentiment(state: AtguiguState) -> str:
    # 路由逻辑...返回最终的条件
    flag = state["x"]
    if flag == 1:
        return "condition_1"
    elif flag == 2:
        return "condition_2"
    else:
        return "condition_3"

graph = StateGraph(AtguiguState)
graph.add_node("node1", addition1)
graph.add_node("node2", addition2)
graph.add_node("node3", addition3)
# 添加路由函数,参数:当前节点,路由函数,路由函数返回的条件与node的映射
graph.add_conditional_edges(
    source=START,
    path= route_by_sentiment,
    path_map={
        "condition_1": "node1",
        "condition_2": "node2",
        "condition_3": "node3"
    }
)

# 所有处理节点都连接到END
graph.add_edge("node1", END)
graph.add_edge("node2", END)
graph.add_edge("node3", END)
app = graph.compile()
# 定义一个初始状态字典,包含键值对"x": 具体数字
initial_state ={"x": 3}
# 调用graph对象的invoke方法,传入初始状态,执行图计算流程
result= app.invoke(initial_state)
print(f"最后的结果是:{result}")



# 打印图的边和节点信息
#print(graph.edges)
#print(graph.nodes)
# 打印图的ascii可视化结构
print(app.get_graph().print_ascii())
print("=================================")
print()
# 打印图的可视化结构,生成更加美观的Mermaid 代码,通过processon 编辑器查看
print(app.get_graph().draw_mermaid())

执行结果:

相关推荐
ZengLiangYi12 小时前
Prompt 工程:让 LLM 输出结构化 JSON
前端·javascript·后端
何乐乐12 小时前
【Taro 5.0 技术与实践】 - 高性能 iOS 渲染层与 TaroUI 跨端框架介绍
android·前端·ios
猩球中的木子12 小时前
什么是DNS解析
前端·vue.js·面试
Ticnix12 小时前
从零封装 Ollama AI 服务:TypeScript 流式对话工具开发
前端·ollama
ZengLiangYi12 小时前
MCP 协议从零实现:手写最简 MCP Server
前端·javascript·后端
罗超驿12 小时前
2.HTML表格详解:标签、属性与单元格合并实战
前端·html
李子琪。13 小时前
Web 漏洞实战全解析:CSRF 攻击原理、Token 防御机制与实验验证(上)
前端·网络·经验分享·csrf
小救星小杜、13 小时前
new Router base的作用
前端·javascript·vue.js
程序二次开发13 小时前
wordpress 文章页,文章分类,单页,woocommerc 产品页,分类页添加.html后缀
大数据·前端·html·php