什麼是 LangGraph?
LangGraph 是一個專門為 LLM 應用設計的工作流編排框架。它的核心理念是:
- 將複雜任務拆分為狀態和轉換
- 管理狀態之間的流轉邏輯
- 處理任務執行過程中的各種異常情況
想象一下購物過程:瀏覽商品 → 加入購物車 → 結算 → 支付,LangGraph 就是幫助我們管理這種流程的工具。
核心概念解析
1. 狀態(State)
狀態就像是任務執行過程中的"檢查點":
from typing import TypedDict, List
class ShoppingState(TypedDict):
# 當前狀態
current_step: str
# 購物車商品
cart_items: List[str]
# 總金額
total_amount: float
# 使用者輸入
user_input: str
class ShoppingGraph(StateGraph):
def __init__(self):
super().__init__()
# 定義狀態
self.add_node("browse", self.browse_products)
self.add_node("add_to_cart", self.add_to_cart)
self.add_node("checkout", self.checkout)
self.add_node("payment", self.payment)
2. 狀態轉換(Transition)
狀態轉換定義了任務流程的"路線圖":
class ShoppingController:
def define_transitions(self):
# 新增狀態轉換規則
self.graph.add_edge("browse", "add_to_cart")
self.graph.add_edge("add_to_cart", "browse")
self.graph.add_edge("add_to_cart", "checkout")
self.graph.add_edge("checkout", "payment")
def should_move_to_cart(self, state: ShoppingState) -> bool:
"""判斷是否應該轉換到購物車狀態"""
return "add to cart" in state["user_input"].lower()
3. 狀態持久化
為了保證系統的可靠性,我們需要持久化狀態資訊:
class StateManager:
def __init__(self):
self.redis_client = redis.Redis()
def save_state(self, session_id: str, state: dict):
"""儲存狀態到 Redis"""
self.redis_client.set(
f"shopping_state:{session_id}",
json.dumps(state),
ex=3600 # 1小時過期
)
def load_state(self, session_id: str) -> dict:
"""從 Redis 載入狀態"""
state_data = self.redis_client.get(f"shopping_state:{session_id}")
return json.loads(state_data) if state_data else None
4. 錯誤恢復機制
任何步驟都可能出錯,我們需要優雅地處理這些情況:
class ErrorHandler:
def __init__(self):
self.max_retries = 3
async def with_retry(self, func, state: dict):
"""帶重試機制的函式執行"""
retries = 0
while retries < self.max_retries:
try:
return await func(state)
except Exception as e:
retries += 1
if retries == self.max_retries:
return self.handle_final_error(e, state)
await self.handle_retry(e, state, retries)
def handle_final_error(self, error, state: dict):
"""處理最終錯誤"""
# 儲存錯誤狀態
state["error"] = str(error)
# 回退到上一個穩定狀態
return self.rollback_to_last_stable_state(state)
實戰案例:智慧客服系統
讓我們看一個實際的例子 - 智慧客服系統:
from langgraph.graph import StateGraph, State
class CustomerServiceState(TypedDict):
conversation_history: List[str]
current_intent: str
user_info: dict
resolved: bool
class CustomerServiceGraph(StateGraph):
def __init__(self):
super().__init__()
# 初始化狀態
self.add_node("greeting", self.greet_customer)
self.add_node("understand_intent", self.analyze_intent)
self.add_node("handle_query", self.process_query)
self.add_node("confirm_resolution", self.check_resolution)
async def greet_customer(self, state: State):
"""歡迎客戶"""
response = await self.llm.generate(
prompt=f"""
歷史對話:{state['conversation_history']}
任務:生成合適的歡迎語
要求:
1. 保持專業友好
2. 如果是老客戶,表示認出了他們
3. 詢問如何幫助
"""
)
state['conversation_history'].append(f"Assistant: {response}")
return state
async def analyze_intent(self, state: State):
"""理解使用者意圖"""
response = await self.llm.generate(
prompt=f"""
歷史對話:{state['conversation_history']}
任務:分析使用者意圖
輸出格式:
{
"intent": "退款/諮詢/投訴/其他",
"confidence": 0.95,
"details": "具體描述"
}
"""
)
state['current_intent'] = json.loads(response)
return state
使用方法
# 初始化系統
graph = CustomerServiceGraph()
state_manager = StateManager()
error_handler = ErrorHandler()
async def handle_customer_query(user_id: str, message: str):
# 載入或建立狀態
state = state_manager.load_state(user_id) or {
"conversation_history": [],
"current_intent": None,
"user_info": {},
"resolved": False
}
# 新增使用者訊息
state["conversation_history"].append(f"User: {message}")
# 執行狀態機流程
try:
result = await graph.run(state)
# 儲存狀態
state_manager.save_state(user_id, result)
return result["conversation_history"][-1]
except Exception as e:
return await error_handler.with_retry(
graph.run,
state
)
最佳實踐
-
狀態設計原則
- 保持狀態簡單清晰
- 只儲存必要資訊
- 考慮序列化需求
-
轉換邏輯最佳化
- 使用條件轉換
- 避免死迴圈
- 設定最大步驟數
-
錯誤處理策略
- 實現優雅降級
- 記錄詳細日誌
- 提供回滾機制
-
效能最佳化
- 使用非同步操作
- 實現狀態快取
- 控制狀態大小
常見陷阱和解決方案
-
狀態爆炸
- 問題:狀態數量過多導致維護困難
- 解決:合併相似狀態,使用狀態組合而不是建立新狀態
-
死鎖情況
- 問題:狀態轉換迴圈導致任務卡住
- 解決:新增超時機制和強制退出條件
-
狀態一致性
- 問題:分散式環境下狀態不一致
- 解決:使用分散式鎖和事務機制
總結
LangGraph 狀態機為複雜 AI Agent 任務流程管理提供了一個強大的解決方案:
- 清晰的任務流程管理
- 可靠的狀態持久化
- 完善的錯誤處理
- 靈活的擴充套件能力