文章目录

  • LangGraph入门从0到1
    • 0️⃣ 安装 & 确认环境
    • 1️⃣ 把 LangGraph 想象成「自动化的做菜流水线」
    • 2️⃣ 最小可运行例子:一句话复读机
    • 3️⃣ 加一个小节点:把用户输入变大写
    • 4️⃣ 条件边:如果用户说 quit 就结束,否则复读
    • 5️⃣ 加内存:让机器人记住「总共复读过几次」
    • 6️⃣ 真实 LLM 节点:让 GPT 来回答
    • 7️⃣ 把节点拆文件:项目怎么组织
    • 8️⃣ 一张图总结所有概念

LangGraph入门从0到1

下面用「小白视角」带你从零到一拆解 LangGraph:
我会把官方那套黑话翻译成“大白话 + 生活例子”,每句话都配可运行的极短代码,复制即见效果。整篇不需要任何 LangChain 基础,只要会 Python print 就行。

0️⃣ 安装 & 确认环境

我这里使用的是uv来管理的项目以及包的安装,你们可以使用pip进行依赖导入。

uv add langgraph langchain_openai

1️⃣ 把 LangGraph 想象成「自动化的做菜流水线」

官方词大白话厨房例子
Graph(图)一张流程图做菜步骤图:切菜→炒菜→装盘
Node(节点)流程图里的一个小步骤“切菜”动作
Edge(边)箭头,决定下一步去哪切完菜后“箭头”指向炒锅
State(状态)一块共享砧板,所有人都能放/拿食材砧板上现有:切好的洋葱、生牛肉
Checkpointer照相机,随时给砧板拍照存档,断电也能恢复每做完一步拍照,厨房停电后来电继续

2️⃣ 最小可运行例子:一句话复读机

功能:用户说什么,机器人就复读什么。
先别看复杂代码,先跑起来!

# 文件:repeat_bot.py
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END# 1. 定义“砧板”上有什么
class State(TypedDict):user_text: str   # 用户说的话bot_text: str    # 机器人回答# 2. 定义节点:复读机节点
def repeat_node(state: State):return {"bot_text": f"复读:{state['user_text']}"}# 3. 搭流程图
builder = StateGraph(State)
builder.add_node("repeat", repeat_node)   # 把节点叫“repeat”
builder.add_edge(START, "repeat")         # 从起点→repeat
builder.add_edge("repeat", END)           # repeat→终点# 4. 生成可执行对象
graph = builder.compile()# 5. 运行!
result = graph.invoke({"user_text": "你好 LangGraph"})
print(result["bot_text"])

运行:

# 输出:复读:你好 LangGraph

恭喜!你已经跑完第一个 LangGraph。

在 LangGraph 里:

  • END 是一个内置常量,代表整张流程图的“厨房大门”——也就是终点,那么START也就是起点
  • 只要箭头指向 END,整个图就会立即停在这一步,不再继续。

3️⃣ 加一个小节点:把用户输入变大写

现在流程图是:START → upper → repeat → END
(upper 节点负责变大写,repeat 节点负责复读)

# 文件:repeat_bot.py
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END# 1. 定义“砧板”上有什么
class State(TypedDict):user_text: str   # 用户说的话bot_text: str    # 机器人回答# 2. 定义节点:复读机节点
def repeat_node(state: State):return {"bot_text": f"复读:{state['user_text']}"}def upper_node(state: State):return {"user_text": state["user_text"].upper()}builder = StateGraph(State)
builder.add_node("upper", upper_node)builder.add_node("repeat", repeat_node)builder.add_edge(START, "upper")
builder.add_edge("upper", "repeat")
builder.add_edge("repeat", END)graph = builder.compile()
print(graph.invoke({"user_text": "hello"})["bot_text"])
# 输出:复读:HELLO
# 5. 运行!
result = graph.invoke({"user_text": "你好 LangGraph"})
print(result["bot_text"])

就这么简单,两个节点串起来了。

4️⃣ 条件边:如果用户说 quit 就结束,否则复读

条件边 = 带“红绿灯”的箭头,红灯停(END),绿灯继续(upper)。

from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END# 1. 定义“砧板”上有什么
class State(TypedDict):user_text: str   # 用户说的话bot_text: str    # 机器人回答# 2. 定义节点:复读机节点
def repeat_node(state: State):return {"bot_text": f"复读:{state['user_text']}"}def should_continue(state: State) -> str:if state["user_text"].strip().lower() == "quit":return "end_chat"return "go_repeat"def upper_node(state: State):return {"user_text": state["user_text"].upper()}builder = StateGraph(State)
builder.add_node("repeat", repeat_node)
builder.add_node("upper", upper_node)
builder.add_edge(START, "repeat")
# 条件边:repeat 之后听红绿灯
builder.add_conditional_edges("repeat",should_continue,{"go_repeat": "upper","end_chat": END})
builder.add_edge("upper",END)
graph = builder.compile()# 测试
print(graph.invoke({"user_text": "upper"})["user_text"])
print(graph.invoke({"user_text": "quit"})["user_text"])

运行:

#输出
UPPER
quit

那么到这里就有一点问题了,这个add_conditional_edges{"go_repeat": "upper","end_chat": END}明明就是一个字典,该怎么理解呢?

可以这么理解:
should_continue 只负责**“举箭头牌子”,它返回的字符串必须是字典的某一把钥匙**;
字典 {"go_repeat": "repeat", "end_chat": END} 是**“钥匙→真正目的地”**的对照表。
LangGraph 内部做两步:

  1. 先调用 should_continue(state) 拿到一把钥匙(例如 "go_repeat")。
  2. 再用这把钥匙去对照表里找:
    "go_repeat" 对应 "upper" → 就把箭头画向名叫 "upper" 的节点;
    如果拿到 "end_chat" → 对应 END → 画向终点。

所以字典不是should_continue 用的,而是给 LangGraph 自己“查地图”用的。

5️⃣ 加内存:让机器人记住「总共复读过几次」

(引入真正的 LangGraph State 累加用法)

from typing import Annotated
import operator
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, ENDclass State(TypedDict):user_text: strbot_text: strcount: Annotated[int, operator.add]  # 每次节点返回 +1 就自动累加def repeat_node(state: State):return {"bot_text": f"复读{state['count']+1}次:{state['user_text']}","count": 1}  # 只要写增量
def should_continue(state: State) -> str:if state["user_text"].strip().lower() == "quit":return "end_chat"return "go_repeat"builder = StateGraph(State)
builder.add_node("repeat", repeat_node)
builder.add_edge(START, "repeat")
builder.add_conditional_edges("repeat", should_continue,{"go_repeat": END, "end_chat": END})# 加照相机(内存)版本
from langgraph.checkpoint.memory import MemorySaver
graph_with_memory = builder.compile(checkpointer=MemorySaver())config = {"configurable": {"thread_id": "user007"}}
# 第一次
print(graph_with_memory.invoke({"user_text": "hi", "count": 0}, config)["bot_text"])
# 第二次
print(graph_with_memory.invoke({"user_text": "hi", "count": 0}, config)["bot_text"])

输出:

复读1次:hi
复读2次:hi

注意:我这里不管需不需要重复我都选择了END因为,你箭头若还是指向了repeat就会成一个死循环,为了程序能运行,所以我设置成了END。还有第二次我们没给 count=2,而是 count=0,但 LangGraph 自动帮我们加到了 2。这就是 Annotated[..., operator.add] 的魔法。

6️⃣ 真实 LLM 节点:让 GPT 来回答

我们现在引入LLM让我们的ai来回答我们的问题:

from typing_extensions import TypedDict
from typing import Annotated
import operator
class State(TypedDict):user_text: strbot_text: strcount: Annotated[int, operator.add]from langchain_openai import ChatOpenAIllm = ChatOpenAI(openai_api_key="*************",base_url="https://api.siliconflow.cn/v1",model="Qwen/Qwen2.5-7B-Instruct"
)def llm_node(state: State) -> State:ai = llm.invoke([{"role": "user", "content": state["user_text"]}])# print(ai.content)return {"bot_text": ai.content, "count": 1,"user_text":"quit"}from langgraph.graph import StateGraph, START, ENDdef should_continue(state: State):return "end" if state["user_text"].strip().lower() == "quit" else "again"builder = StateGraph(State)
builder.add_node("chat", llm_node)
builder.add_edge(START, "chat")
builder.add_conditional_edges("chat", should_continue,{"again": "chat", "end": END})
graph = builder.compile()result = graph.invoke({"user_text": "给我讲个笑话", "count": 0})
print(result["bot_text"])

你看我直接返回了一个{"bot_text": ai.content, "count": 1,"user_text":"quit"},我直接返回的是这两个的值,那为什么循环还是结束了?之后的判断边它怎么知道"user_text":"quit"了。

用幼儿园砧板比喻:

  • 你(节点)从砧板拿走一张旧纸条,读完随手 丢回一张新纸条
  • 新纸条上写了哪些字段,LangGraph 就 照着名字往砧板上“贴”
    • 名字已存在 → 直接盖掉旧值
    • 名字不存在 → 自动贴一张新纸条
  • 也就是你返回的东西都会留在砧板上

所以

return {"bot_text": ai.content, "count": 1, "user_text": "quit"}
  • bot_text 旧值被覆盖
  • count 旧值被 +1 覆盖(前面用了 Annotated[int, operator.add] 会再叠一次)
  • user_text 旧值被强行改成 "quit",下次节点拿到就是 "quit"

一句话:返回的字典就是“增量补丁”,State 里没有的 key 就新增,有的 key 就原地更新。

7️⃣ 把节点拆文件:项目怎么组织

我们在创建项目的时候方便管理,最好是模块来写代码管理代码就比如如下方式:

my_bot/
├─ state.py # 只放 State TypedDict
├─ nodes.py # 所有节点函数
├─ graph.py # 搭图、compile
└─ main.py # 运行入口

8️⃣ 一张图总结所有概念

在这里插入图片描述

所有节点共享同一块砧板(State),LangGraph 帮你端菜、拍照、指路。

你已经完成 0→1 通关!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/95643.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/95643.shtml
英文地址,请注明出处:http://en.pswp.cn/web/95643.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习数据结构(16)快速排序

快速排序的基本思想:快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该基准值将待排序集合分割成两子序列,左子序列中所有元素均小于基准值&am…

uni-app iOS 上架常见问题与解决方案,实战经验全解析

uni-app 让开发者能够“一套代码,多端运行”,极大降低了开发成本。 但当应用进入 iOS 上架阶段 时,不少团队发现流程并没有想象中那么顺利:证书问题、打包失败、上传出错、审核被拒……这些都可能让项目卡壳。 本文结合实际案例&a…

洗衣机的智能升级集成方案WT2606B屏幕驱动+AI语音控制

2025,洗衣机市场正从功能满足转向体验升级,企业正面临哪些转型难点?一文为您解读洗衣机行业智能化升级之路。传统洗衣机就像是一个"沉默的工人",只能通过简单的LED指示灯告诉你它在工作,却无法让你真正了解它在干嘛。用…

机器学习进阶,梯度提升机(GBM)与XGBoost

梯度提升机(Gradient Boosting Machine, GBM),特别是其现代高效实现——XGBoost。这是继随机森林后自然进阶的方向,也是当前结构化数据竞赛和工业界应用中最强大、最受欢迎的算法之一。为什么推荐XGBoost? 与随机森林互…

【ARMv7】开篇:掌握ARMv7架构Soc开发技能

本专栏,开始与大家共同总结使用ARMv7系列CPU的Soc开发技能。大概汇总了一下,后面再逐步完善下面的思维导图。简单说说:与通用的ARMv7-A/R相比,以STM32F为代表的ARMv7-M架构有以下关键区别和重点:无MMU,有MP…

【学术会议论文投稿】JavaScript在数据可视化领域的探索与实践

【ACM出版 | EI快检索 | 高录用】2024年智能医疗与可穿戴智能设备国际学术会议(SHWID 2024)_艾思科蓝_学术一站式服务平台 更多学术会议请看 学术会议-学术交流征稿-学术会议在线-艾思科蓝 目录 引言 JavaScript可视化库概览 D3.js基础入门 1. 引入…

CSS基础学习步骤

好的,这是一份为零基础初学者量身定制的 **CSS 学习基础详细步骤**。我们将从最根本的概念开始,通过一步一步的实践,带你稳稳地入门。 第一步:建立核心认知 - CSS 是做什么的? 1. 理解角色: HTML&…

MTK Linux DRM分析(三十七)- MTK phy-mtk-hdmi.c 和 phy-mtk-hdmi-mt8173.c

一、简介 HDMI PHY驱动 HDMI 的物理层接口主要就是 HDMI Type-A 接口(19 pin),除此之外还有 Type-B、Type-C(Mini HDMI)、Type-D(Micro HDMI)、Type-E(车载专用)。 1. HDMI Type-A(常见 19-pin 标准接口) HDMI Type-A Connector Pinout ========================…

【人工智能学习之MMdeploy部署踩坑总结】

【人工智能学习之MMdeploy部署踩坑总结】报错1:TRTNet: device must be a GPU!报错2:Failed to create Net backend: tensorrt报错3:Failed to load library libonnxruntime_providers_shared.so1. 确认库文件是否存在2. 重新安装 ONNX Runti…

力扣516 代码随想录Day16 第一题

找二叉树左下角的值class Solution { public:int maxd0;int result;void traversal(TreeNode* root,int depth){if(root->leftNULL&&root->rightNULL){if(depth>maxd){maxddepth;resultroot->val;}}if(root->left){depth;traversal(root->left,depth…

网格图--Day07--网格图DFS--LCP 63. 弹珠游戏,305. 岛屿数量 II,2061. 扫地机器人清扫过的空间个数,489. 扫地机器人,2852. 所有单元格的远离程度之和

网格图–Day07–网格图DFS–LCP 63. 弹珠游戏,305. 岛屿数量 II,2061. 扫地机器人清扫过的空间个数,489. 扫地机器人,2852. 所有单元格的远离程度之和 今天要训练的题目类型是:【网格图DFS】,题单来自灵茶山…

多功能修改电脑机器码序列号工具 绿色版

多功能修改电脑机器码序列号工具 绿色版电脑机器码序列号修改软件是一款非常使用的数据化虚拟修改工具。机器码修改软件可以虚拟的定制您电脑上的硬件信息,软件不会对您的电脑造成伤害。软件不需要您有专业的知识,就可以模拟一份硬件信息。机器码修改软…

React Hooks深度解析:useState、useEffect及自定义Hook最佳实践

React Hooks自16.8版本引入以来,彻底改变了我们编写React组件的方式。它们让函数组件拥有了状态管理和生命周期方法的能力,使代码更加简洁、可复用且易于测试。本文将深入探讨三个最重要的Hooks:useState、useEffect,以及如何创建…

期权平仓后权利金去哪了?

本文主要介绍期权平仓后权利金去哪了?期权平仓后权利金的去向需结合交易角色(买方/卖方)、平仓方式及市场价格变动综合分析,具体可拆解为以下逻辑链条。期权平仓后权利金去哪了?1. 买方平仓:权利金的“差价…

2025国赛C题题目及最新思路公布!

C 题 NIPT 的时点选择与胎儿的异常判 问题 1 试分析胎儿 Y 染色体浓度与孕妇的孕周数和 BMI 等指标的相关特性,给出相应的关系模 型,并检验其显著性。 思路1:针对附件中孕妇的 NIPT 数据,首先对数据进行预处理,并对多…

NLP技术爬取

“NLP技术爬取”这个词组并不指代一种单独的爬虫技术,而是指将自然语言处理(NLP)技术应用于网络爬虫的各个环节,以解决传统爬虫难以处理的问题,并从中挖掘出更深层次的价值。简单来说,它不是指“用NLP去爬”…

让录音变得清晰的软件:语音降噪AI模型与工具推荐

在数字内容创作日益普及的今天,无论是播客、线上课程、视频口播,还是远程会议,清晰的录音质量都是提升内容专业度和观众体验的关键因素之一。然而,由于环境噪音、设备限制等因素,录音中常常夹杂各种干扰声音。本文将介…

大话 IOT 技术(1) -- 架构篇

文章目录前言抛出问题现有条件初步设想HTTP 与 MQTT中间的服务端完整的链路测试的虚拟设备实现后话当你迷茫的时候,请点击 物联网目录大纲 快速查看前面的技术文章,相信你总能找到前行的方向 前言 Internet of Things (IoT) 就是物联网,万物…

【wpf】WPF 自定义控件绑定数据对象的最佳实践

WPF 自定义控件绑定数据对象的最佳实践:以 ImageView 为例 在 WPF 中开发自定义控件时,如何优雅地绑定数据对象,是一个经常遇到的问题。最近在实现一个自定义的 ImageView 控件时,我遇到了一个典型场景: 控件内部需要使…

[Dify 专栏] 如何通过 Prompt 在 Dify 中模拟 Persona:即便没有专属配置,也能让 AI 扮演角色

在 AI 应用开发中,“Persona(角色扮演)”常被视为塑造 AI 个性与专业边界的重要手段。然而,许多开发者在使用 Dify 时会疑惑:为什么我在 Chat 应用 / Agent 应用 / Workflow 里都找不到所谓的 Persona 配置项? 答案是:Dify 平台目前并没有内建的 Persona 配置入口。角色…