游乐游手机版
首页/AI教程/文章详情

LangGraph思维模型与第一个图:跨平台爆款图文Agent第1篇

时间:2026-06-18 16:02
LangGraph是一个通过有向图结构替代线性链条和if else条件判断来编排Agent工作流的框架。其核心要素包括状态、节点和边,利用StateGraph组织,经compile编译验证后调用invoke执行,并支持Mermaid图形可视化,从而高效实现循环、分支等复杂流程。

第1章:图的力量——LangGraph 思维模型与首个图实战

本章学习目标

读完本章,你将发现——构建AI Agent工作流完全无需依赖繁复的if/else堆砌。你将收获以下核心能力:

图的力量——LangGraph 思维模型与第一个图 — LangGraph 实战——构建跨平台爆款图文 Agent 第1篇

  • 能清晰阐述“AI Agent为何必须采用图结构而非线性链条”
  • 能够独立定义一个StateGraph,编写多个节点函数,使用边将它们串联起来
  • 能够编译(compile)该图,并通过invoke调用它获取最终结果
  • 还能借助Mermaid图将图结构可视化,一目了然地展示设计

知识讲解

从一个生活实例切入

想象你走进一家快递分拣中心。

包裹从卡车上卸下,它的旅程是这样的:

包裹到达 → 扫码分类 → 按地区分拣 → 装车 → 出发

每个环节相当于一个分拣站,站点之间由传送带连接。包裹在每个站点被处理完毕,身上的标签信息就会更新——例如从“未分类”变为“华东区”——随后顺着传送带滑向下一个站点。

关键之处在于:有些包裹的下一站并非固定不变。若标签显示“易碎品”,传送带便将其分流至“易碎品专用通道”;若是“加急件”,则直接跳转至“优先装车站”。这个决策是在运行过程中根据标签内容动态做出的,而非事先硬性规定。

LangGraph将这种“图”模型映射到代码中:

快递中心LangGraph说明
包裹上的标签State(状态)记录当前所有信息,在节点间流转
分拣站Node(节点)一个Python函数,读取标签、执行处理、更新标签
传送带Edge(边)连接两个节点,决定数据流向
整个分拣系统StateGraph将所有节点和边组织在一起的容器
启动前的线路检查compile()验证图结构:无死循环、无断头路
把包裹放入系统invoke()传入初始数据,启动执行

想一想:如果包裹的下一站完全由当前标签内容决定(比如“易碎品走专用通道”),这对应于LangGraph中的哪个概念?答案稍后揭晓。

工作原理

为什么线性链条不够用?

假设你正在用代码编写一个简单的“内容分析助手”。没有LangGraph时,你很可能写出这样的流程:

def analyze_content(url: str) -> str:
    raw = fetch_content(url)        # 1. 抓取内容
    cleaned = clean_html(raw)       # 2. 清洗HTML
    summary = summarize(cleaned)    # 3. 生成摘要
    return summary

这是一个纯粹的线性流程——水管式,必须执行完第1步才能到第2步,再到第3步。对于简单的ETL任务,这种方式确实够用。

但若增加一个需求:当摘要质量不足时需要重新生成,线性代码立刻变得别扭:

def analyze_content(url: str) -> str:
    raw = fetch_content(url)
    cleaned = clean_html(raw)
    summary = summarize(cleaned)
    if quality_score(summary) < 0.7:
        # 不满意?
        summary = summarize(cleaned)   # 再来一次
    if quality_score(summary) < 0.7:
        # 还不满意?
        summary = summarize(cleaned)   # 第三次...
    return summary

问题显而易见:你不得不使用if嵌套来模拟循环,代码可读性急剧下降。而实际场景中,“不满意就重试”可能需要重复3次、5次,甚至需要人工介入——用线性代码硬写这种逻辑,很快就会变得杂乱无章。

更糟糕的是:如果需求变为“抓取完成后,根据内容类型走不同分支——视频内容走视频分析流程,图文内容走图文分析流程”,嵌套的if会迅速失控。

这正是LangGraph要解决的痛点:让你用“图”的方式描述复杂工作流——包含循环、分支、并行——而不是依靠if/else硬编码。

StateGraph是如何工作的?

LangGraph的核心模型极为简洁,仅包含三个要素:

  1. State(状态)——一个数据结构,所有节点共享。每个节点可以读取它,并通过返回部分更新来修改它。它就像一个背包,在工作流的各个阶段之间传递。
  2. Node(节点)——一个Python函数,签名是(state: State) -> dict。它接收当前完整状态,返回一个部分更新字典——只包含你想修改的字段。LangGraph自动将返回值合并到状态中。
  3. Edge(边)——决定“从A节点之后去哪里”。固定边(add_edge)意味着总是从A走到B;条件边(add_conditional_edges)意味着根据状态内容动态选择下一站。

一个最小的LangGraph程序如下所示:

START → node_a → node_b → END

用“启动→处理→汇总→结束”来理解:

  • 传入初始数据给START
  • node_a进行第一轮处理
  • node_b进行第二轮处理
  • END结束

思考一下:上面的图是否存在循环?没有——它只是一个顺序流程。那么什么时候会出现循环?当某个条件边的返回值指向了前面的节点时,就形成了循环。例如“质量检查不通过→回到生成节点”——这正是第2章要深入探讨的内容。

执行流程:invoke到底做了什么?

当你调用graph.invoke(initial_state)时,LangGraph内部发生以下步骤:

  1. START出发,找到第一条边连接的目标节点
  2. 执行该节点的函数,传入当前状态
  3. 将该函数的返回值(一个dict)合并到状态中
  4. 根据边的定义,找到下一个节点
  5. 重复步骤2-4,直到到达END
  6. 返回最终状态

每一步都是确定性的——相同的输入、相同的图,必然产生相同的输出。这种确定性对于调试和测试至关重要。

代码实战

环境准备

开始之前,请在终端中安装LangGraph:

pip install -U langgraph

基础版:最简两节点图

我们从整个教程中最简单的图开始——两个节点,一条边,没有任何分支。

打开编辑器,新建文件chapter01_hello_graph.py

"""第1章 基础演示:最简两节点LangGraph
LocalTrend项目起点——一个能跑通的空骨架
"""
from typing import TypedDict
from langgraph.graph import StateGraph, START, END

# ============================================================
# Step 1: 定义State(图的状态数据结构)
# ============================================================
class LocalTrendState(TypedDict):
    """LocalTrend项目的全局状态。
    所有节点共享这个结构,每个节点只返回自己需要更新的字段。
    """
    raw_content: str   # 原始内容(模拟抓取结果)
    summary: str       # 分析摘要

# ============================================================
# Step 2: 定义Node函数(图的处理单元)
# ============================================================
def fetch_content(state: LocalTrendState) -> dict:
    """模拟从平台抓取内容。
    接收当前状态,返回一个部分更新dict。
    """
    print("[fetch_content] 正在抓取内容...")
    # 实际项目中这里会调用requests.get()或网页抓取工具
    # 本章先用模拟数据建立图的结构直觉
    return {"raw_content": "LangGraph 是构建 AI Agent 的强大框架,它用图来编排复杂工作流。"}

def generate_summary(state: LocalTrendState) -> dict:
    """对抓取到的内容生成摘要。"""
    print(f"[generate_summary] 正在分析内容: {state['raw_content'][:30]}...")
    content = state["raw_content"]
    # 实际项目中这里会调用LLM,第2章会讲
    summary = f"分析结果:这篇内容的核心主题是'{content[:20]}'"
    return {"summary": summary}

# ============================================================
# Step 3: 构建StateGraph,添加节点和边
# ============================================================
def build_graph() -> StateGraph:
    """构建LocalTrend的最简图骨架。"""
    # 创建图容器,指定状态类型
    builder = StateGraph(LocalTrendState)

    # 添加节点:给每个函数起一个名字
    builder.add_node("fetch_content", fetch_content)
    builder.add_node("generate_summary", generate_summary)

    # 添加边:定义执行顺序
    # START → fetch_content → generate_summary → END
    builder.add_edge(START, "fetch_content")
    builder.add_edge("fetch_content", "generate_summary")
    builder.add_edge("generate_summary", END)

    # 编译:验证图结构并返回可执行对象
    return builder.compile()

# ============================================================
# Step 4: 运行
# ============================================================
if __name__ == "__main__":
    graph = build_graph()

    # invoke() 接收初始状态,返回最终状态
    # 注意:raw_content 和 summary 都传空字符串作为初始值
    result = graph.invoke({"raw_content": "", "summary": ""})

    print("\n=== 最终状态 ===")
    print(f"raw_content: {result['raw_content']}")
    print(f"summary: {result['summary']}")

在你的终端中执行以下命令:

python chapter01_hello_graph.py

你应该会看到类似这样的输出:

[fetch_content] 正在抓取内容...
[generate_summary] 正在分析内容: LangGraph 是构建 AI Agent 的强大框架...
=== 最终状态 ===
raw_content: LangGraph 是构建 AI Agent 的强大框架,它用图来编排复杂工作流。
summary: 分析结果:这篇内容的核心主题是'LangGraph 是构建 AI Age'

逐行解析

class LocalTrendState(TypedDict)

这就是我们的“包裹标签”。TypedDict是Python标准库提供的一种类型提示方式——它定义了字典应该包含哪些键、每个键是什么类型。LangGraph利用它来确保节点之间传递的数据结构保持一致。

注意,我们只定义了两个字段:raw_contentsummary。State应尽量精简——字段过多意味着每个节点都需要理解更多上下文,增加认知负担。随着教程的深入,我们会逐步为State添加新字段。

def fetch_content(state) -> dict

这是第一个节点。其签名至关重要:接收完整的State,返回一个dict。返回的dict仅包含你想更新的字段——无需返回整个State。LangGraph会自动将你返回的{"raw_content": "..."}合并到全局状态中。

builder = StateGraph(LocalTrendState)

创建图容器。这一行告诉LangGraph:“我要构建一个图,其状态结构是LocalTrendState。”此后所有节点的读写都会参照这个结构。

builder.add_node("fetch_content", fetch_content)

将函数注册为节点,节点名称为"fetch_content"。节点名称很重要——后续添加边、定义条件路由时都要使用该名称来引用。名称可以任意取,但建议与函数名保持一致以降低理解成本。

builder.add_edge(START, "fetch_content")

START是LangGraph内置的特殊常量,代表图的入口。这条边表示“图的执行从fetch_content节点开始”。如果忘记添加此边,编译时会报错——LangGraph不知道从哪里启动执行。

builder.add_edge("generate_summary", END)

END同样是内置常量。连接到END的节点执行完后,图即结束。

builder.compile()

这一行完成多项工作:检查所有边连接的目标节点是否存在、检查是否存在不可达节点、检查循环是否合理。如果图结构存在问题,它会在此处抛出明确错误,而非等到运行时报错。编译通过=图结构正确。

graph.invoke({"raw_content": "", "summary": ""})

invoke()是启动图执行的方法。传入的字典必须是完整的初始State——所有TypedDict定义的字段都要提供。执行完毕后,invoke()返回最终状态的完整字典。

可视化你的图

LangGraph内置了生成Mermaid图的能力。在chapter01_hello_graph.pyif __name__ == "__main__":块中,graph = build_graph()之后加入以下代码:

# 生成Mermaid图并保存
mermaid_code = graph.get_graph().draw_mermaid()
with open("chapter01_graph.md", "w", encoding="utf-8") as f:
    f.write(mermaid_code)
print("图已保存到 chapter01_graph.md")

这段代码会将图的Mermaid描述保存到Markdown文件中。在VS Code中安装“Markdown Preview Mermaid Support”插件后,即可直接预览图形。你应该能看到:

START → fetch_content → generate_summary → END

养成习惯:每次修改图结构后,先将其画出来看一眼——很多问题肉眼就能发现。

扩展版:增加预处理节点

上述基础版仅包含一个“抓取→生成摘要”流程。但实际项目中,抓取到的内容通常需要先进行清洗——去除HTML标签、截断过长文本、处理乱码等。

接下来,我们为LocalTrend添加一个清洗节点,同时演示多节点串行:

"""第1章 扩展演示:三节点串行处理流水线
在基础版上增加一个内容清洗节点,展示多节点图的构建模式
"""
from typing import TypedDict
from langgraph.graph import StateGraph, START, END

class LocalTrendState(TypedDict):
    raw_content: str
    cleaned_content: str   # ? 新增:清洗后的内容
    summary: str

def fetch_content(state: LocalTrendState) -> dict:
    """模拟抓取——返回含HTML标签的原始内容"""
    print("[fetch_content] 正在抓取...")
    return {"raw_content": "

LangGraph教程

这是一个很棒的框架。

"} def clean_content(state: LocalTrendState) -> dict: """清洗内容:去除HTML标签。""" raw = state["raw_content"] print(f"[clean_content] 清洗中... 原始长度: {len(raw)} 字符") # 简易HTML去标签——实际项目建议用BeautifulSoup import re cleaned = re.sub(r"<[^>]+>", "", raw).strip() print(f"[clean_content] 清洗后长度: {len(cleaned)} 字符") return {"cleaned_content": cleaned} def generate_summary(state: LocalTrendState) -> dict: """基于清洗后的内容生成摘要""" # 优先用清洗后的内容 content = state.get("cleaned_content") or state["raw_content"] print(f"[generate_summary] 分析内容: {content[:40]}...") return {"summary": f"摘要:{content[:50]}..."} def build_graph() -> StateGraph: builder = StateGraph(LocalTrendState) builder.add_node("fetch_content", fetch_content) builder.add_node("clean_content", clean_content) builder.add_node("generate_summary", generate_summary) # 三节点串行流水线 builder.add_edge(START, "fetch_content") builder.add_edge("fetch_content", "clean_content") builder.add_edge("clean_content", "generate_summary") builder.add_edge("generate_summary", END) return builder.compile() if __name__ == "__main__": graph = build_graph() result = graph.invoke({ "raw_content": "", "cleaned_content": "", "summary": "", }) print(f"\n=== 最终状态 ===") print(f"raw: {result['raw_content'][:60]}...") print(f"cleaned: {result['cleaned_content']}") print(f"summary: {result['summary']}")

运行后你会看到三个节点按顺序执行。关键观察:clean_content读取了fetch_content写入的raw_content,而generate_summary读取了clean_content写入的cleaned_content。这就是图的威力——节点之间通过State传递数据,每个节点只关心自己的输入和输出,无需知晓上下游的细节。

本章小结

  1. LangGraph将复杂工作流建模为图——节点执行处理,边控制流向,State在它们之间传递数据。
  2. State是以TypedDict定义的数据结构,所有节点共享。节点通过返回dict(而非直接修改state)来更新它。
  3. StateGraph是图容器;add_node注册节点函数;add_edge定义固定流向。
  4. STARTEND是内置常量,标记图的入口和出口。忘记START边会导致图无法启动。
  5. compile()验证图结构,invoke()同步执行图。先编译后执行——编译通过表示结构正确。
  6. 每个节点只返回自己修改的字段——LangGraph自动将部分更新合并到全局State。
  7. get_graph().draw_mermaid()可以可视化图结构——养成“画出来看看”的习惯。

关键术语

术语释义
StateGraphLangGraph的核心类,用于定义、构建、编译一个有向图工作流
State图中所有节点共享的数据结构(TypedDict / Pydantic),在节点间流转
Node(节点)一个(state) -> dict签名的Python函数,读取State并返回部分更新
Edge(边)定义节点之间的流向,固定边(add_edge)总是从A到B
START内置常量,标记图的入口。必须有一条边从START出发
END内置常量,标记图的出口。到达END的边意味着执行结束
compile()验证图结构(边连通性、节点存在性)并返回可执行Runable
invoke()传入初始State同步执行图,返回最终State
来源:https://juejin.cn/post/7651495364991074342
上一篇Codex新手入门教程普通人也能快速上手的AI编程助手 下一篇AI辅助编程从代码生成到实际落地的思考
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
RAG四标融合企业知识资产体系四库协同GEO优化实践
AI教程 · 2026-07-01

RAG四标融合企业知识资产体系四库协同GEO优化实践

生成式AI正在彻底改写信息检索的底层逻辑。传统SEO依赖关键词堆砌和外链建设的策略,在大模型的内容采信规则下已经基本失效。取而代之的,是生成式引擎优化(GEO)。它不再关注外链数量,而是重点衡量你的知识是否结构化、证据链是否坚实、信源是否可靠——这些维度才是RAG(检索增强生成)架构真正看重的核心指

一个普通上班人分享WorkBuddy使用心得与真实体验
AI教程 · 2026-07-01

一个普通上班人分享WorkBuddy使用心得与真实体验

前言 最近我开始使用WorkBuddy——这是腾讯推出的一款AI办公工作台。差不多用了一周时间,趁印象还新鲜,把真实的使用感受记录下来,给还在犹豫的朋友做个参考。不吹不黑,只说实际体验。 初印象:不只是聊天机器人 之前用过不少AI工具,大多数就是个对话框,你问它答,答完就结束了。WorkBuddy不

AI幻觉变真功能实战教程:App Inventor 2视频录制拓展一周开发实录
AI教程 · 2026-07-01

AI幻觉变真功能实战教程:App Inventor 2视频录制拓展一周开发实录

先讲一个颇具戏剧性的开端。 这件事的开端颇显荒诞——有用户前来咨询,称AI Pro版的介绍中提到我们有一款“视频录制拓展”。团队全体成员都感到困惑,翻遍产品列表,发现根本不存在该组件。AI那种“一本正经胡说八道”的能力,这次确实让我们陷入尴尬。 按常理,此事到此便可结束——一句“抱歉,暂时没有这个拓

别再混淆OLAP和SQL-on-Hadoop两者查询本质不同
AI教程 · 2026-07-01

别再混淆OLAP和SQL-on-Hadoop两者查询本质不同

OLAP和SQL-on-Hadoop虽都使用SQL查询数据,但本质不同。SQL-on-Hadoop负责海量数据批量计算与ETL,查询速度秒级至分钟级;OLAP通过预聚合实现毫秒级多维分析,适合BI报表。两者在数据平台分工协作,前者是后厨加工,后者是前台快速服务。

GEO优化深度解析:AI偏好FAQ还是长文内容?
AI教程 · 2026-07-01

GEO优化深度解析:AI偏好FAQ还是长文内容?

在GEO优化中,AI对内容形式无统一偏好:FAQ在简单查询中引用率41%,长文在复杂查询中达58%。内容应基于用户意图选择形式,FAQ适配简单事实类问题,长文建立主题权威,两者互补而非替代。