首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >langchain源码分析:langgraph

langchain源码分析:langgraph

作者头像
golangLeetcode
发布2026-03-18 18:15:12
发布2026-03-18 18:15:12
1640
举报

LangGraph 是一款基于图结构的工作流编排框架,专为构建复杂多Agent协作系统而设计,支持循环流程、状态持久化和动态任务编排‌,广泛应用于客服流程管理、实时研究助手等场景。‌‌‌‌

‌图结构模型‌

  • 节点(Node)‌:包含Agent节点(调用AI模型)、工具节点(执行API或数据库操作)和终止节点;‌
  • 边(Edge)‌:定义状态流转路径,支持条件跳转(如用户投诉转人工审核)和并行处理;‌
  • 状态(State)‌:贯穿流程的动态数据结构,记录交互数据和上下文信息‌‌1‌动态编排机制‌。

下面我们结合例子分析下它的源码

代码语言:javascript
复制
代码语言:javascript
复制
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import MessagesState
import sys
import os
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, base_dir)
from init.openai import LLM
llm = LLM()

# 创建graph
graph_builder = StateGraph(MessagesState)

# 创建节点函数
def chatbot(state: MessagesState):
    return {"messages": [llm.invoke(state["messages"])]}

# 添加节点,命名为chatbot
graph_builder.add_node("chatbot", chatbot)

# 添加起始边
graph_builder.add_edge(START, "chatbot")

# 添加结束边
graph_builder.add_edge("chatbot", END)

# 代码编译为图
graph = graph_builder.compile()

# 生成图的流程图片,写到当前目录下
qa_async_png = graph.get_graph().draw_mermaid_png()
with open("chatbot.png", "wb") as f:
    f.write(qa_async_png)

# 流式调用大模型
for event in graph.stream({"messages": [{"role": "user", "content": "中国最好的大学是哪所?"}]}):
    for value in event.values():
        print("Assistant:", value["messages"][-1].content)

首先创建了一个graph,它的类型是MessagesState

代码语言:javascript
复制
graph_builder = StateGraph(MessagesState)

然后向图中添加节点

代码语言:javascript
复制
graph_builder.add_node("chatbot", chatbot)

然后添加起始边和结束边

代码语言:javascript
复制
# 添加起始边
graph_builder.add_edge(START, "chatbot")
# 添加结束边
graph_builder.add_edge("chatbot", END)

这是其中一种方式,如果不指定特殊的START和END,就需要指定起始节点。

然后把代码编译为图

代码语言:javascript
复制
graph = graph_builder.compile()

也可以生成图片

代码语言:javascript
复制
qa_async_png = graph.get_graph().draw_mermaid_png()

最后我们调用流式大模型使用我们的graph。

其实调用大模型只是节点的一个动作而已,我们也可以不调用大模型,下面介绍一个复杂的langgraph例子

代码语言:javascript
复制
代码语言:javascript
复制
# 创建一个状态图
from langgraph.graph import StateGraph
from typing import TypedDict, List, Optional,Dict, Any
class PizzaState(TypedDict):
    order_id: str
    size: str
    flour_type: str
    sauce: str
    extra_cheese: bool
    toppings: List[str]
    dough_ready: Optional[bool]  # 后续步骤中添加的字段
    # 其他字段...
# 使用类型化状态创建图
pizza_workflow = StateGraph(PizzaState) # 不能用下面的原始Dict初始化,否则报错不能画图
# pizza_workflow = StateGraph(Dict[str, Any])  # 创建基于字典的状态图
# 接下来我们会向这个图中添加节点和边
def prepare_dough(state: Dict[str, Any]) -> Dict[str, Any]:
    """准备面团节点"""
    # 输入状态可能包含面粉类型、水量等信息
    print(f"正在准备 {state.get('flour_type', '普通')} 面粉的面团")

    # 处理后更新状态
    state["dough_ready"] = True
    state["dough_size"] = state.get("size", "中号")

    return state  # 返回更新后的状态
# 在图中添加这个节点
pizza_workflow.add_node("prepare_dough", prepare_dough)
def add_sauce(state: Dict[str, Any]) -> Dict[str, Any]:
    """添加酱料节点"""
    # 输入状态可能包含酱料类型、水量等信息
    print(f"正在添加 {state.get('sauce', '无')} 酱料")
    # 处理后更新状态
    state["sauce_added"] = True
    state["sauce_type"] = state.get("sauce", "无")
    return state  # 返回更新后的状态
# 在图中添加这个节点
pizza_workflow.add_node("add_sauce", add_sauce)
def add_cheese(state: Dict[str, Any]) -> Dict[str, Any]:
    """添加奶酪节点"""
    # 输入状态可能包含奶酪类型、水量等信息
    print(f"正在添加 {state.get('cheese_type', '无')} 奶酪")    
    # 处理后更新状态
    state["cheese_added"] = True
    state["cheese_type"] = state.get("cheese_type", "无")
    return state  # 返回更新后的状态
# 在图中添加这个节点
pizza_workflow.add_node("add_cheese", add_cheese)
# 标准边:定义固定的执行路径
pizza_workflow.add_edge("prepare_dough", "add_sauce")  # 准备面团后添加酱料
pizza_workflow.add_edge("add_sauce", "add_cheese")     # 添加酱料后撒奶酪
pizza_workflow.set_entry_point("prepare_dough")
def extra_cheese_node(state: Dict[str, Any]) -> Dict[str, Any]:
    """额外奶酪节点"""
    # 输入状态可能包含额外奶酪类型、水量等信息
    print(f"正在添加 {state.get('extra_cheese_type', '无')} 额外奶酪")    
    # 处理后更新状态
    state["extra_cheese_added"] = True
    state["extra_cheese_type"] = state.get("extra_cheese_type", "无")
    return state  # 返回更新后的状态
# 在图中添加额外奶酪节点
pizza_workflow.add_node("extra_cheese_node", extra_cheese_node)
def baking_node(state: Dict[str, Any]) -> Dict[str, Any]:
    """烘烤节点"""
    # 处理后更新状态
    state["baking_time"] = "12分钟"
    state["pizza_ready"] = True
    state["quality_check"] = "passed"
    return state  # 返回更新后的状态
    # 在图中添加烘烤节点
pizza_workflow.add_node("baking_node", baking_node)
# 条件边:根据状态决定下一步
def check_cheese_preference(state: Dict[str, Any]) -> str:
    """检查奶酪偏好,决定下一步"""
    if state.get("extra_cheese", False):
        return "add_extra_cheese"  # 如果客户要求额外奶酪,走这条路径
    return "regular_baking"        # 否则直接烘烤
# 添加条件边,根据函数返回值决定下一步
pizza_workflow.add_conditional_edges(
    "add_cheese",                 # 从这个节点出发
    check_cheese_preference,      # 使用这个函数判断
    {
        "add_extra_cheese": "extra_cheese_node",  # 返回值与下一个节点的映射
        "regular_baking": "baking_node"
    }
)
# 初始状态:客户订单信息
initial_state = {
    "order_id": "12345",
    "size": "大号",
    "flour_type": "全麦",
    "sauce": "番茄",
    "extra_cheese": True,
    "toppings": ["蘑菇", "橄榄", "青椒"]
}
# 编译工作流
compiled_workflow = pizza_workflow.compile()
# qa_async_png = compiled_workflow.get_graph().draw_mermaid_png()
graph = compiled_workflow.get_graph()
if hasattr(graph, 'draw_mermaid_png'):
    qa_async_png = graph.draw_mermaid_png()
with open("edg.png", "wb") as f:
    f.write(qa_async_png)
# 执行工作流,传入初始状态
final_state = compiled_workflow.invoke(initial_state)
# 最终状态会包含整个过程中添加的所有信息
print(final_state)
# 可能输出: {'order_id': '12345', 'size': '大号', ..., 'dough_ready': True, 
#           'sauce_added': True, 'cheese_type': '马苏里拉', 'baking_time': '12分钟',
#           'pizza_ready': True, 'quality_check': 'passed'}

生成的图片如下

也就是说,如果你不嫌麻烦,你也可以用langchain来画流程图

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档