從 Redux 到 LangGraph:狀態管理的進化與未來

許恆修 | Heng-Shiou Sheu
10 min readAug 9, 2024

在軟體開發的世界中,狀態管理一直是一個至關重要的課題。隨著應用程序的複雜性增加,如何有效地管理和維護應用程序的狀態成為了許多開發者面臨的挑戰。本文將深入探討 Redux 這一傳統狀態管理框架的核心理念,並進一步探討 LangGraph,對比這兩者的設計思想與應用場景,並探討未來可能的發展方向。

1.1 Redux Pattern 是什麼?

在我們開始展開這個議題之前,我們需要先回答 Redux Pattern 是什麼?

redux.html

Redux Pattern 是一個用於 JavaScript 應用的可預測狀態容器,主要用於管理複雜的應用狀態。它的核心思想是將整個應用的狀態存儲在一個中央位置,稱為 store。

當中使用 Action, Reduce, Store 來表達網站中狀態轉換機制,如果要動用網站以外的狀態則會使用 side effect 來執行。

1.1.1 Redux 當中三個原則

  1. Single Source Of Truth:整個應用的狀態存儲在一個對象樹中,並且這個對象樹只存在於唯一的 store 中。
  2. Immutable State:改變狀態的唯一方法是觸發一個 action,action 是一個描述發生什麼的普通對象。
  3. Pure function:為了描述 action 如何改變狀態樹,你需要編寫 reducers。

這三個原則共同確保了 Redux 應用的狀態變化是可預測和可追蹤的,從而簡化了複雜應用的狀態管理。

1.1.2 Redux 簡易範例

以下是 Redux 中的一個簡單計數器範例,展示了 Redux 如何通過 action 和 reducer 管理應用狀態:

// 1. 定義初始狀態
const initialState = { count: 0 };

// 2. 定義 action 類型
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';

// 3. 定義 action creators
const increment = () => ({ type: INCREMENT });
const decrement = () => ({ type: DECREMENT });

// 4. 定義 reducer
function counterReducer(state = initialState, action) {
switch (action.type) {
case INCREMENT:
return { ...state, count: state.count + 1 };
case DECREMENT:
return { ...state, count: state.count - 1 };
default:
return state;
}
}

// 5. 創建 store
import { createStore } from 'redux';
const store = createStore(counterReducer);

// 6. 訂閱狀態變化
store.subscribe(() => console.log(store.getState()));

// 7. 派發 action
store.dispatch(increment()); // 輸出: { count: 1 }
store.dispatch(increment()); // 輸出: { count: 2 }
store.dispatch(decrement()); // 輸出: { count: 1 }

展示了 Redux 的核心運作原理:
1. 我們定義了初始狀態。
2. 定義了 action 類型,這些是描述狀態變化的唯一方式。
3. 創建了 action creators,這些函數返回 action 對象。
4. 定義了 reducer,它是一個純函數,根據當前狀態和接收到的 action 返回新的狀態。
5. 使用 reducer 創建了 store,它是整個應用狀態的容器。
6. 訂閱了 store 的變化,每次狀態更新時都會觸發回調。
7. 通過 dispatch 方法派發 action,觸發狀態更新。

官方網站也有互動版本,會更有感覺

https://redux.js.org/introduction/examples

想要了解更多可以參考之前的狀態機分享文章

1.1.3 Redux 狀態管理的反思

從狀態機理論的角度來看,Redux 實現了一個確定性有限狀態機(Deterministic Finite State Machine, DFA)的形式化模型。這一模型使得 Redux 能夠以數學上嚴謹的方式來處理應用的狀態變化,從而確保應用的狀態變化是可預測和可追蹤的。

更多資源可以參考這系列影片:https://www.youtube.com/watch?v=40i4PKpM0cI&t=69s&pp=ygUDREZB

2.1 LangGraph 狀態管理機制:從 Redux 到 AI 應用

在現代軟體開發中,狀態管理一直是一個關鍵議題。隨著人工智能(AI)應用的興起,這個問題在複雜性和重要性上都有了新的維度。將介紹 LangGraph 的狀態管理機制,並通過與 Redux 的對比,幫助讀者更好地理解其工作原理。

2.1 狀態管理的核心元素

在深入探討 LangGraph 之前,讓我們先回顧一下 Redux 狀態管理的關鍵元素。以下是簡化後的核心概念:

  1. 狀態存儲 (Store): 統一存放應用程序的狀態
  2. 行為 (Action): 描述狀態變化的事件
  3. 狀態轉換 (Reducer): 處理狀態轉換的邏輯
  4. 副作用 (Side Effect): 需要額外機制處理的操作,如API調用

這些概念在不同的狀態管理框架中可能有不同的實現方式,但核心思想是一致的。

2.1.1 LangGraph 狀態管理機制:自定義 State

在 LangGraph 中,狀態存儲通過自定義的 State 類來實現。這個類通常繼承自 BaseModel,並定義了應用程序需要追踪的各種狀態。

from pydantic import BaseModel, Field
from typing import List, Optional

# 定義狀態
class OverallState(BaseModel):
topic: str
current_step: str
generated_content: str
# 構建狀態圖
graph = StateGraph(OverallState)

這個例子定義了一個用於生成和選擇笑話的應用狀態。StateGraph 使用這個自定義的 OverallState 來管理整個應用的狀態。

2.1.2 LangGraph 中的 Action:Prompt

在 LangGraph 中,行為主要通過 Prompt(提示語) 來表示。Prompt 的內容根據當前的狀態動態生成,確保 AI 模型獲得正確的上下文和指令。

initial_state = {"article_state": "The Pope will visit Spain today"}
result = app.invoke(initial_state)

2.1.3 LangGraph 中 reducer: Node

LangGraph 中的狀態轉換邏輯主要在 Node (節點) 中實現。每個 Node 代表一個狀態,並定義了如何處理進入該狀態的邏輯

# 定義節點
def generate_story(state: ConversationState) -> ConversationState:
prompt = PromptTemplate(
template="為主題 '{topic}' 創作一個短故事。當前需求:{current_step}",
input_variables=["topic", "current_step"]
)
response = ai_model(prompt.format(topic=state.topic, current_step=state.current_step))
state.generated_content = response
state.current_step = "審核"
return state

2.1.4 LangGraph 中 Side Effect: Tools

在 LangGraph 中,副作用主要通過自定義的 Tools 來處理。這些 Tools 可以執行外部操作,如資料庫查詢或 API 調用。

class JokeRatingTool(BaseTool):
name = "joke_rater"
description = "Rate a joke based on its quality"

def _run(self, joke: str) -> float:
# 實現評分邏輯,可能涉及 API 調用或複雜計算
return external_rating_service.rate_joke(joke)

2.1.5 Redux vs LangGraph: 對比分析

將兩者比較圖統整在表格中,方便對應

主要區別:

  1. 狀態結構: Redux 使用單一的 JavaScript 對象作為狀態樹,而 LangGraph 使用 Pydantic 模型,提供了更強的類型檢查和數據驗證。
  2. 行為觸發: Redux 通過 dispatch 函數顯式地觸發 action,而 LangGraph 的狀態轉換是通過圖的邊隱式定義的。
  3. 轉換邏輯: Redux 使用純函數 reducer 來處理狀態轉換,LangGraph 則使用可能包含副作用的節點函數。
  4. 副作用處理: Redux 需要額外的中間件(如 Redux-Thunk)來處理副作用,而 LangGraph 將副作用直接集成到其工具系統中。
  5. 應用場景: Redux 主要用於 Web 前端開發,而 LangGraph 專注於 AI 和自然語言處理任務。

碎碎念時間

這算是一篇嘗試用第一性原理讓多數接觸過狀態管理機制的人引發聯想,或許在日後使用 LangGraph 設計上提供點方向。全文概念不一定完全對應,但可以從 LangGraph 底層實作嘗試找出點對應。想法上可能都對得起來,但實作上還是比較多困難,畢竟 LangGraph 還是滿心的才 v0.2 版本,很多東西不成熟。

期待有更好的工具更好的腳踏車可以載著意念前行。

結論與重點整理

在傳統的 Web 開發中,Redux 提供了一個強大且可預測的狀態管理框架,為前端開發者解決了許多複雜的狀態管理問題。然而,隨著人工智能的發展,LangGraph 應運而生,為 AI 應用提供了一個更加靈活且功能強大的機制。

反思問題:

  1. 在AI驅動的應用中,傳統的狀態管理方法還夠用嗎?
  2. LangGraph的方法如何影響我們設計和實現AI系統的方式?
  3. 未來的狀態管理框架會如何演進以適應更複雜的AI任務?

--

--

許恆修 | Heng-Shiou Sheu
許恆修 | Heng-Shiou Sheu

Written by 許恆修 | Heng-Shiou Sheu

AI研究員 @喬泰科技,軟體工程師@微光國際,業界講師 @FCU 創能學院,Co-Founder @圖靈文本。專注將科技應用於改善生活中,持續性分享軟體架構設計、前沿人工智慧研究、公司治理等觀念。整合科技、人文思維於一體。聯絡 📪 hengshiousheu@gmail.com

No responses yet