LangGraph(一):入門從0到1(零基礎)

文章目錄

  • 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 配置入口。角色…