AI-Chain

Eino:把 Go 的型別、串流與工作流組合成可控的 LLM Agent 應用框架

CloudWeGo Eino 是以 Go 打造的 AI 應用開發框架,將模型、提示詞、RAG 元件、工具、Chain、Graph、串流與 callbacks 組合成可測試、可觀測的 LLM Agent 工作流。本文從原始碼結構出發,說明它適合的工程場景、導入順序與安全邊界。

分享:
Eino:把 Go 的型別、串流與工作流組合成可控的 LLM Agent 應用框架

Eino:把 Go 的型別、串流與工作流組合成可控的 LLM Agent 應用框架

當 LLM 應用從「呼叫一次模型」走向檢索、工具調用、結構化輸出、多人協作與可恢復流程時,真正困難的通常不是再包一層 API,而是讓每一個步驟都能被組合、觀測、測試與維護。CloudWeGo Eino 正是針對這個工程問題而來的 Go AI 應用開發框架:它把模型、提示詞、文件處理、向量檢索、工具和工作流放在同一套可組合的抽象之下,再利用 Go 的型別系統與並行能力,把原型逐步推向可運行的服務。

本文不把 Eino 宣稱成「自動解決所有 Agent 問題」的魔法工具,而是從原始碼與官方文件能確認的能力出發,拆解它適合處理什麼、如何組成一條可測試的 LLM pipeline,以及導入時應該保留哪些邊界。文中版本與數據以 2026 年 9 月 8 日查證結果為準。

先看查證結果:這不是教學清單,而是可執行的框架

本次查證的專案是 cloudwego/eino,GitHub 顯示超過 1 萬顆星,最近一次推送在 2026 年 9 月,符合「超過 5,000 顆星且近 180 天仍有更新」的篩選條件。儲存庫主要語言是 Go,模組路徑是 github.com/cloudwego/eino,根目錄包含 adk、compose、components 與 callbacks 等實作目錄;這些都指向可匯入、可執行與可測試的框架程式碼,而不是資源彙整或單純學習材料。

我也以 Notion 資料庫的 GitHub URL 欄位對 https://github.com/cloudwego/eino 做 exact match 查詢,未發現既有頁面,因此不會改寫或覆蓋已收錄的專案。需要注意的是,GitHub 星數、推送時間與 alpha 版本都會變動;讀者若要在生產環境採用,仍應鎖定實際依賴版本並重新閱讀相容性說明。

Eino 的核心思路:先定義可組合的步驟,再決定流程形狀

LLM 應用常被畫成一條直線:輸入提示詞、呼叫模型、輸出答案。但真實系統比較像一張圖。問題可能先經過分類,再決定是否檢索;檢索結果要被重排或壓縮;模型可能提出工具呼叫;工具結果又回到模型;最後還要把輸出轉成 API 能接受的結構。若每一段都使用不同的資料型別與錯誤處理方式,程式很快會變成大量膠水碼。

Eino 的做法是把常見 AI 元件與流程控制分開。components 提供模型、prompt、document、embedding、indexer、retriever、tool 等元件邊界;compose 則提供 Chain、Graph、DAG、分支、平行與欄位映射等組合能力。這個分層很重要:模型供應商可以替換,流程圖可以改寫,而應用程式的業務邏輯不必和某一個 SDK 的請求格式綁死。

在更高階的 Agent 開發上,儲存庫另有 adk 目錄,並包含 agent、tool、handler、flow 與 callback 相關程式。這表示 Eino 不只處理單次 completion,也把 Agent 的狀態轉移、工具交互與事件處理視為可測試的程式結構。它的價值不是「替你決定 Agent 要做什麼」,而是把決策流程放進一個能被檢視的執行模型。

從 Chain 開始:把最小可行流程變成可替換元件

最簡單的 Eino 應用,可以先從單一模型步驟開始,再逐步插入 prompt、解析器或檢索器。概念上的流程如下:

使用者問題 → Prompt Template → Chat Model → 結構化輸出或文字回應

這條路徑看似普通,但抽象化之後有兩個工程收益。第一,步驟的輸入與輸出可以在編譯期或組合階段被檢查,較早發現「上一個節點產生的型別不是下一個節點需要的型別」。第二,模型實作不必散落在業務程式各處;你可以把模型當成元件注入,讓測試時替換成 deterministic fake model,或在不同環境切換供應商。

當流程有明確的線性順序時,Chain 是合理的起點。不要一開始就把所有東西畫成複雜 Graph:先讓輸入、提示詞、模型輸出與錯誤路徑能被單獨測試,等需求真的出現分支、平行或循環,再把流程提升為圖。這是使用框架時比 API 呼叫本身更重要的設計習慣。

Graph 與 DAG:讓分支、平行和依賴關係可見

當應用需要「先判斷意圖,再走不同處理器」,或需要同時查詢多個資料來源,線性 Chain 就不夠了。Eino 的 compose 目錄包含 Graph、DAG、Branch、Parallel 以及 checkpoint 相關程式,適合表達這些依賴關係。

例如,一個問答服務可以拆成:

  1. 先對問題做路由,判斷是知識庫問題、工具操作,還是一般對話。
  2. 知識庫分支執行 embedding、retriever 與 context 組裝。
  3. 工具分支驗證工具參數,再呼叫外部服務。
  4. 兩個分支都回到共同的回答節點,並產生可驗證的輸出。

把這些步驟寫成圖的好處,是依賴關係不再只存在於巢狀 callback 裡。團隊可以針對節點測試,也可以針對整張圖測試;當某個模型或 retriever 變慢時,還能以節點為單位觀察,而不是只看到整個 HTTP request 的總耗時。

平行流程尤其適合多路檢索或多個獨立評估器,但不能把「可以同時執行」誤解成「一定應該同時執行」。外部 API 的 rate limit、資料一致性、成本與錯誤聚合方式都要先定義。框架可以幫你表達平行結構,卻不會替你做服務等級與成本決策。

串流不是裝飾:回應體驗與資源生命週期

聊天介面通常希望模型逐步輸出 token,而不是等待完整答案才回傳。Eino 的模型與組合抽象涵蓋 stream 相關測試和處理路徑,因此可以把串流視為流程的一級資料,而不是在最外層另外打補丁。

串流設計需要同時考量三件事。第一是取消:使用者關閉頁面時,HTTP request 的 context 是否能一路傳到模型與工具,避免後端繼續消耗資源。第二是錯誤:模型可能在串流中途失敗,API 層必須定義已送出的片段如何處理,以及客戶端如何知道回應沒有完成。第三是聚合:若中間經過工具呼叫或多個節點,哪些事件要直接顯示,哪些事件只進觀測系統,必須有清楚的協定。

這也是 Go 框架的實務切入點。Go 的 context、goroutine 與 channel 能自然地表達取消和串流,但「能寫出並行程式」不等於「並行程式會正確結束」。導入 Eino 時,應該把 cancel、timeout、背壓和 channel 關閉列為測試案例,而不是等壓力測試才發現 goroutine 泄漏。

RAG 與工具調用:把資料邊界放在元件層

Eino 將 document、embedding、indexer 與 retriever 列為獨立 components,這讓 RAG pipeline 可以拆成可替換的幾段:文件載入與切分、向量化、索引、查詢、結果組裝,最後才交給模型生成。這種拆分能降低供應商鎖定,也讓團隊能針對檢索品質做離線評估,而不是把所有問題都歸咎於 prompt。

實務上,RAG 最容易被忽略的是資料邊界。文件切分器不應該默默丟失來源資訊;retriever 回傳的片段要保留文件 ID、權限範圍與時間戳;組裝 context 時要限制長度,並對來自文件的內容做資料隔離。模型看見的文字不等於可信指令,尤其當文件可能包含「請忽略系統規則」之類的內容時,應把它當作待分析資料,而不是讓它改變 Agent 的控制流程。

工具也應遵循同樣原則。工具 schema 應該描述輸入型別與必要欄位,執行前做權限、範圍與速率檢查;工具輸出回到模型前,則要區分資料與控制訊息。Eino 可以提供 tool 元件與 Agent 組合的結構,但真正的安全邊界仍要由應用層建立,包括 allowlist、審計記錄、敏感欄位遮罩與人工核准。

Callback 與觀測:不要只記錄最後一句答案

只記錄 prompt 和 final answer,通常不足以排查 LLM 應用問題。一次失敗可能來自路由錯誤、retriever 找不到文件、工具超時、模型重試,或串流在最後一段被中斷。Eino 儲存庫包含 callbacks 目錄與相關 handler、aspect 測試,提供在流程事件周邊掛接觀測邏輯的方向。

建議至少記錄以下欄位:流程或節點名稱、trace ID、模型與版本、輸入輸出 token 或估算量、每個外部呼叫的耗時、重試次數、錯誤類型,以及是否發生 fallback。日誌內容則應避開 API key、完整個資與不必要的文件正文。若要保存 prompt 或 tool argument,應先定義保存期限與遮罩規則。

Callback 的另一個價值是把可觀測性和流程本身解耦。產品團隊可以增加 metrics,安全團隊可以加入敏感操作告警,測試環境可以收集節點事件,而不必在每一個元件中重複修改相同的 logging 程式。這種解耦只有在事件名稱、錯誤語意和上下文傳遞保持穩定時才成立,因此仍需要把 callback contract 當成公共介面管理。

一個務實的導入順序

如果要用 Eino 建立 Go 的 LLM 服務,可以採取以下順序,而不是先追求最複雜的 Agent:

  1. 鎖定依賴和模型邊界。 使用 go.mod 管理版本,建立一個能以假模型執行的最小流程;先驗證輸入輸出與錯誤契約。
  2. 加入一個真實元件。 例如只接一個 Chat Model 或 retriever,將 timeout、重試、取消與成本記錄補齊。
  3. 把提示詞和解析器獨立出來。 不讓業務邏輯依賴模型回傳的偶然文字,對結構化輸出做 schema 驗證。
  4. 再導入工具或 RAG。 每個工具都先有權限與輸入驗證;每個檢索結果都保留來源,並建立基本的 precision、recall 或人工抽樣評估。
  5. 最後才使用 Graph、平行和 checkpoint。 只有當流程的分支、恢復或並行需求已經清楚,才增加圖的複雜度;每增加一個節點,就增加相應的單元和整合測試。

這個順序能把框架的能力轉成可控制的風險。否則很容易得到一個 demo:它可以回答問題,卻無法解釋為什麼走了某個分支、為什麼花了這麼多錢,也無法在外部服務失敗時安全地恢復。

適合誰,以及不適合什麼情境

Eino 適合已經選擇 Go,並希望把 LLM、RAG、工具與工作流納入同一個服務工程體系的團隊。若現有系統需要高並行、低延遲、明確的 context cancellation,或團隊希望以編譯器和測試協助維護流程,它值得進行小規模技術驗證。

它不一定是所有人的第一選擇。若團隊只需要一個很薄的模型代理,直接使用供應商 SDK 可能更簡單;若團隊的主要資產是 Python 資料科學工具,則應先比較跨語言邊界和生態系成本;若產品仍沒有穩定的任務定義、評估集和安全規則,換框架通常不會自動改善結果。Eino 解決的是組合與工程化問題,不是模型能力、資料品質或產品策略問題。

結語:框架的價值在於讓複雜度可見

從 GitHub 儲存庫的結構來看,Eino 的定位很清楚:以 Go 為基礎,把 AI 元件、流程組合、Agent 工具互動、callback 和測試放進一個可演進的框架。它最值得注意的不是某一個單獨 API,而是鼓勵開發者把 LLM 應用當成有輸入輸出契約、取消語意、錯誤路徑和觀測事件的軟體系統。

對 AI Chain 讀者而言,這提供一個很實際的判斷角度:當需求還只是「呼叫模型並顯示答案」時,保持簡單;當需求開始出現多步驟、工具、檢索、平行和恢復時,再用 Eino 的 Chain、Graph、components 與 callbacks 把複雜度顯式化。框架不會替你做架構決策,但它能讓決策留下可測試、可觀測、可替換的程式邊界。

參考與查證來源

查證提醒:本文的星數、最近更新時間與版本資訊是執行當日從 GitHub API 讀取的快照;文章中的架構描述以儲存庫當時的公開程式碼與文件為依據,實際採用前請重新確認版本與 API。