周三下午,財(cái)務(wù)部的Lisa收到一封郵件——某筆采購(gòu)需要她審批。她點(diǎn)開(kāi)附件里的Excel表格,發(fā)現(xiàn)版本號(hào)已經(jīng)亂成"最終版_真的最終版_5月修訂"。上周的審批記錄在哪?不知道。誰(shuí)改的預(yù)算數(shù)字?找不到。如果審計(jì)明天來(lái)查,她只能回復(fù):"我再問(wèn)問(wèn)。"
這不是某個(gè)公司的特例。大多數(shù)企業(yè)的審批流程根本不是"系統(tǒng)",而是郵件串、轉(zhuǎn)發(fā)鏈和隨時(shí)可能崩潰的共享表格。當(dāng)流程跨部門(mén)時(shí),問(wèn)題更糟:采購(gòu)要查供應(yīng)商、財(cái)務(wù)要核預(yù)算、法務(wù)要審合同,每一步都在不同系統(tǒng)里,沒(méi)有共享狀態(tài)。第三步卡住了?從頭再來(lái)。
![]()
技術(shù)層面的核心問(wèn)題是:沒(méi)有持久化、結(jié)構(gòu)化的工作流狀態(tài)。郵件里的流程無(wú)法暫停、無(wú)法審計(jì)、崩潰后無(wú)法恢復(fù)。一位開(kāi)發(fā)者用LangGraph、FastAPI和SQLite搭建了解決方案,本文是他的實(shí)現(xiàn)思路。
![]()
核心需求很明確:工作流必須在人工決策點(diǎn)暫停,并在精確位置恢復(fù)——哪怕服務(wù)器中間重啟過(guò)。LangGraph的StateGraph恰好滿足這一點(diǎn)。它將工作流結(jié)構(gòu)(節(jié)點(diǎn)和邊)與工作流狀態(tài)(類(lèi)型化的字典數(shù)據(jù))分離,每一步轉(zhuǎn)換都自動(dòng)保存檢查點(diǎn)。
兩個(gè)關(guān)鍵原語(yǔ)讓這套方案落地:
interrupt_before:編譯圖時(shí)可指定在哪些節(jié)點(diǎn)前中斷。到達(dá)這些節(jié)點(diǎn)時(shí),圖暫停、狀態(tài)持久化到檢查點(diǎn),控制權(quán)交回調(diào)用方。用相同線程ID再次調(diào)用時(shí),從斷點(diǎn)精確恢復(fù)。
![]()
AsyncSqliteSaver:持久化檢查點(diǎn)后端,將圖狀態(tài)寫(xiě)入SQLite。與默認(rèn)的MemorySaver(進(jìn)程本地存儲(chǔ))不同,它在服務(wù)器重啟后仍然存活,任何有正確連接字符串的進(jìn)程都能讀取。
這套"檢查點(diǎn)模式"解決了一個(gè)常見(jiàn)陷阱:假設(shè)進(jìn)程內(nèi)存是持久的。實(shí)際上,每次服務(wù)器重啟、每次部署、每次崩潰,都會(huì)靜默殺死所有進(jìn)行中的工作流。唯一的修復(fù)方案是:每一步轉(zhuǎn)換都寫(xiě)持久存儲(chǔ),而非僅在結(jié)束時(shí)保存。
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.