一句話理解

LangGraph 用有向圖(狀態機)描述 AI 工作流,支援條件分支、迴圈、多 Agent 協作,比普通 Chain 更適合複雜任務。


什麼時候用 LangGraph?

需求用什麼
固定 A→B→C 流程LangChain-基礎Chain
AI 自主決定工具LangChain-Agent
需要條件分支(if/else)LangGraph
需要迴圈(反覆修正)LangGraph
多個 Agent 協作LangGraph

安裝

pip install langgraph

核心概念

State(狀態)   ← 整個流程共享的資料結構
Node(節點)    ← 每個步驟的函式
Edge(邊)      ← 節點之間的連接
Conditional Edge ← 根據 State 決定走哪條路

基本範例:客服分流

from langgraph.graph import StateGraph, END
from typing import TypedDict, Literal
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
 
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
 
# 1. 定義 State
class SupportState(TypedDict):
    question: str
    category: str  # "technical" | "billing" | "general"
    answer: str
 
# 2. 定義 Node 函式(每個接收 state,回傳更新)
def classify(state: SupportState) -> SupportState:
    """判斷問題類型"""
    response = llm.invoke([
        HumanMessage(content=f"""
        判斷以下問題屬於哪個類別,只回答一個詞:technical / billing / general
        問題:{state['question']}
        """)
    ])
    return {"category": response.content.strip()}
 
def handle_technical(state: SupportState) -> SupportState:
    response = llm.invoke([HumanMessage(content=f"作為技術支援,回答:{state['question']}")])
    return {"answer": response.content}
 
def handle_billing(state: SupportState) -> SupportState:
    response = llm.invoke([HumanMessage(content=f"作為帳務部門,回答:{state['question']}")])
    return {"answer": response.content}
 
def handle_general(state: SupportState) -> SupportState:
    response = llm.invoke([HumanMessage(content=f"作為客服,回答:{state['question']}")])
    return {"answer": response.content}
 
# 3. 條件函式(決定走哪個分支)
def route(state: SupportState) -> Literal["technical", "billing", "general"]:
    return state["category"]
 
# 4. 建立圖
graph = StateGraph(SupportState)
graph.add_node("classify", classify)
graph.add_node("technical", handle_technical)
graph.add_node("billing", handle_billing)
graph.add_node("general", handle_general)
 
# 5. 加邊
graph.set_entry_point("classify")
graph.add_conditional_edges("classify", route, {
    "technical": "technical",
    "billing": "billing",
    "general": "general"
})
graph.add_edge("technical", END)
graph.add_edge("billing", END)
graph.add_edge("general", END)
 
# 6. 編譯並執行
app = graph.compile()
result = app.invoke({"question": "我的帳單怎麼算的?", "category": "", "answer": ""})
print(result["answer"])

ReAct Agent 用 LangGraph 實作

from langgraph.prebuilt import create_react_agent
 
agent = create_react_agent(
    model=llm,
    tools=[search_tool, calculator_tool],
)
 
result = agent.invoke({"messages": [HumanMessage(content="台北今天天氣如何?")]})
print(result["messages"][-1].content)

Human-in-the-Loop(中途讓人類審核)

from langgraph.checkpoint.memory import MemorySaver
 
checkpointer = MemorySaver()
app = graph.compile(
    checkpointer=checkpointer,
    interrupt_before=["execute_action"]  # 執行前暫停等人確認
)
 
config = {"configurable": {"thread_id": "task_001"}}
# 執行到 interrupt_before 的節點就暫停
result = app.invoke(initial_state, config=config)
 
# 人類審核後繼續
app.invoke(None, config=config)

圖的視覺化

# 印出 ASCII 圖
print(app.get_graph().draw_ascii())
 
# 產生 PNG(需安裝 graphviz)
from IPython.display import Image
Image(app.get_graph().draw_mermaid_png())

LangGraph vs Agent 比較

面向LangGraph一般 Agent
流程控制明確定義圖結構LLM 自主決定
除錯難度容易(每個 node 獨立)難(LLM 決策不透明)
條件分支✅ 原生支援❌ 需技巧實作
迴圈✅ 原生支援❌ 靠 max_iterations
多 Agent✅ 原生支援❌ 需自己管
學習曲線較高較低

相關筆記