大語言模型應用開發框架 —— Eino 正式開源!
作者|Eino 項目組
今天,經過字節跳動內部半年多的使用和迭代,基於 Golang 的大模型應用綜合開發框架 —— Eino,已在 CloudWeGo 正式開源啦!
Eino 基於明確的 “組件” 定義,提供強大的流程“編排”,覆蓋開發全流程,旨在幫助開發者以最快的速度實現最有深度的大模型應用。
你是否曾有這種感受:想要爲自己的應用添加大模型的能力,但面對這個較新的領域,不知如何入手;想持續的站在研究的最前沿,應用最新的業界成果,但使用的應用開發框架卻已經數月沒有更新;想看懂項目裏的用 Python 寫的代碼,想確定一個變量或者參數的類型,需要反覆查看上下文確認;不確定模型生成的效果是否足夠好,想用又不太敢用;在調試、追蹤、評測等開發之外的必要環節,還需要額外探索學習其他配套的工具。如果是,歡迎瞭解和嘗試 Eino,因爲 Eino 作爲旨在覆蓋 devops 全流程的大模型應用開發框架,具有如下特點:
-
內核穩定,API 簡單易懂,有明確的上手路徑,平滑的學習曲線。
-
極致的擴展性,研發工作高度活躍,長期可持續。
-
基於強類型語言 Golang,代碼能看懂,易維護,高可靠。
-
背靠字節跳動核心業務線的充分實踐經驗。
-
提供開箱即用的配套工具。
Eino 已成爲字節跳動內部大模型應用的首選全代碼開發框架,已有包括豆包、抖音、釦子等多條業務線、數百個服務接入使用。
項目地址:
https://github.com/cloudwego/eino
https://github.com/cloudwego/eino-ext
未來,我們將以 Eino 開源庫爲核心代碼倉庫,堅持內外用一套代碼,與社區共建最優秀的大模型應用開發框架。
0****1
快速認識 Eino
Eino 是覆蓋 devops 全流程的大模型應用開發框架,從最佳實踐樣例的 Eino Examples,到各環節的工具鏈,都是 Eino 的領域:
Composition of Eino Framework from a devops perspective
那麼 Eino 具體能做什麼?首先,Eino 由一個個大模型領域的 “組件” 組成,比如最核心的是與大模型交互的 Chat Model:
model, _ := ark.NewChatModel(ctx, config) // 創建一個豆包大模型
message, _ := model.Generate(ctx, []*Message{
SystemMessage("you are a helpful assistant."),
UserMessage("what does the future AI App look like?")}
像上面這樣一個個的直接使用組件,當然沒問題,Eino 提供了大量有用的組件實現供選擇。但是,大模型應用有它們自身的特點和規律,比如:
-
核心是大模型,業務邏輯圍繞 “如何給大模型充分、有效的上下文” 以及“如何讓大模型的輸出可靠的影響環境”,核心的組件類型、數據類型和交互模式是可以枚舉的,整體可以由有向圖來描述。
-
大模型輸出的特點是流式輸出,意味着模型的下游都需要有效的處理流式數據,包括流的實時處理、流的複製、多個流的合併、單個流的拼接等。
-
以有向圖爲基礎,衍生出併發處理、扇入扇出、通用橫切面、option 分配等一系列子問題。
Eino 的編排能力,是上述通用問題的充分解決方案。
以 ReAct Agent 爲例:一個 ChatModel(大模型),“綁定” 了 Tool(工具),接收輸入的 Message,由 ChatModel 自主判斷是否調用 Tool 或輸出最終結果。Tool 執行結果會再次成爲給到 ChatModel 的 Message,並作爲下一輪自主判斷的上下文。
上述基於 ChatModel 進行自主決策和選路的 ReAct Agent,便是基於 Eino 的 組件 和 Graph 編排 來實現, 代碼清晰簡潔,可與流程圖清晰對應。
-
代碼實現詳見:「flow/agent/react 」的實現
-
ReAct Agent 用戶手冊詳見:「react_agent_manual」
「flow/agent/react」https://github.com/cloudwego/eino/blob/main/flow/agent/react/react.go
「react_agent_manual」https://www.cloudwego.io/zh/docs/eino/core_modules/flow_integration_components/react_agent_manual/
在 Eino 中,這是幾十行代碼的圖編排:
// 構建一個 ReAct Agent,編譯爲一個輸入爲 []*Message,輸出爲 *Message 的 Runnable
// 創建包含 state 的 Graph,用戶存儲請求維度的 Message 上下文
graph = NewGraph[[]*Message, *Message](
WithGenLocalState(func(ctx context.Context) *state {
return &state{Messages: make([]*Message, 0, config.MaxStep+1)}
}))
// 將一個輪次中的上下文和響應,存儲到 Graph 的臨時狀態中
modelPreHandle = func(ctx context.Context, input []*Message, state *state) ([]*Message, error) {
state.Messages = append(state.Messages, input...)
return state.Messages, nil
}
_ = graph.AddChatModelNode(nodeKeyModel, chatModel, WithStatePreHandler(modelPreHandle))
_ = graph.AddEdge(START, nodeKeyModel)
_ = graph.AddToolsNode(nodeKeyTools, toolsNode)
// chatModel 的輸出可能是多個 Message 的流
// 這個 StreamGraphBranch 根據流的首個包即可完成判斷,降低延遲
modelPostBranch = NewStreamGraphBranch(
func(_ context.Context, sr *schema.StreamReader[*Message]) (endNode string, err error) {
defer sr.Close()
if msg, err := sr.Recv(); err != nil {
return "", err
} else if len(msg.ToolCalls) == 0 {
return END, nil
}
return nodeKeyTools, nil
}, map[string]bool{nodeKeyTools: true, END: true})
_ = graph.AddBranch(nodeKeyModel, modelPostBranch)
// toolsNode 執行結果反饋給 chatModel
_ = graph.AddEdge(nodeKeyTools, nodeKeyModel)
// 編譯 Graph:類型檢查、callback 注入、自動流式轉換、生成執行器
agent, _ := graph.Compile(ctx, WithMaxRunSteps(config.MaxStep))
在上面這幾十行代碼的背後,Eino 自動做了一些事情:
-
類型檢查,在 compile 時確保相鄰的節點的類型對齊。
-
流式封裝,編譯出的 Runnable 既可以 Invoke 調用,也可以 Stream 調用,無論內部的 Tool 是否支持流。
-
併發管理,對 state 這個公共狀態的讀寫是併發安全的。
-
橫切面注入,如果某個組件(比如一個 tool)沒有實現 callbacks 注入,則 Eino 自動注入。
-
Option 分配,編譯出的 Runnable 可以靈活接收並把 option 分配給指定的節點。
02
Eino 的獨特優勢
基於大語言模型的軟件應用正處於快速發展階段,新技術、新思路、新實踐不斷湧現,我們作爲應用開發者,一方面需要高效、可靠的把業界共識的最佳實踐應用起來,另一方面需要不斷學習和提升認知,從而能夠整體理解這個新領域的可能性。因此,一個優秀的大模型應用開發框架,既需要封裝領域內 “不變” 的通用核心要素,又需要基於最新進展敏捷的橫向和縱向擴展。
另一方面,目前較爲主流的框架如 LangChain,LlamaIndex 等,都基於 Python,雖然能借助 Python 較爲豐富的生態快速實現多樣的功能,但是同時也繼承了 Python 作爲動態語言所帶來的 “弱類型檢驗” 和“長期維護成本高”等問題。在大模型應用快速進入大規模線上運行階段的當下,基於 Golang 這一強類型語言而實現的高可靠性和高可維護性,逐漸具有更大的價值。
基於大模型的應用開發是相對較新的領域,有時需要摸着石頭過河,靠實踐來檢驗認知。依託字節跳動高頻應用豆包、抖音等的多樣場景、快速迭代和海量反饋,Eino 在實踐驅動設計方面有獨特的優勢。
最後,生產級的框架需要面對真實、複雜的業務場景,因此,除了直觀易用的 API 設計之外,提供有針對性設計的開發工具可以有效的幫助開發者理解和應對複雜性、加速開發過程。
內核穩定
我們認爲,存在一個常見的組件列表,共同構成了大模型應用的常見組成部分。每類組件作爲一個 interface,有完善、穩定的定義:具體的輸入輸出類型,明確的運行時 option,以及明確的流處理範式。
在明確的組件定義基礎之上,我們認爲,大模型應用開發存在通用的基座性質的能力,包括但不限於:處理模型輸出的流式編程能力;支持橫切面功能以及透出組件內部狀態的 Callback 能力;組件具體實現超出組件 interface 定義範圍的 option 擴展能力。
在組件定義和通用基座能力的基礎上,我們認爲,大模型應用開發存在相對固定的數據流轉和流程編排範式:以 ChatModel(大模型)爲核心,通過 ChatTemplate 注入用戶輸入和系統 prompt,通過 Retriever、Document Loader & Transformer 等注入上下文,經過 ChatModel 生成,輸出 Tool Call 並執行,或輸出最終結果。基於此,Eino 提供了上述組件的不同編排範式:Chain,鏈式有向無環圖;Graph,有向圖或有向無環圖;Workflow,有字段映射能力的有向無環圖。
上述設計和功能共同構成了 Eino 的穩定內核:
敏捷擴展
每類組件都可以橫向擴展出不同的實現,比如 ChatModel 組件可以有 OpenAI、Gemini、Claude 等不同的實現等。這些具體的實現,在實現組件 interface 從而可作爲組件參與編排的基礎上,可以實現和持續擴展自身的特殊功能。
當實際業務場景中,出現需要進入編排但是不對應任何組件定義的功能時,Eino 支持將自定義 function 聲明爲 Lambda 類型。Lambda 有用戶聲明的輸入輸出以及 option 類型,可支持全部的流處理範式,具備完整的 Callback 能力,在編排視角等價於官方組件。
在大模型應用開發領域,存在並且持續會湧現多個組件的特定編排範式,這些範式封裝了驗證有效的研究成果或實踐經驗,比如 ReAct Agent,Host Multi-Agent 等。這些開箱即用的封裝,濃縮了大模型應用開發領域的最佳實踐,會隨着我們認知的提升持續縱向擴展。
在組件和圖執行過程中,開發者可以在固定的時機嵌入自定義的回調邏輯,用於注入橫切面功能。
綜上所述,Eino 框架具備充分的可擴展性:
高可靠易維護
基於 Golang 寫 Eino 代碼時,開發者可以充分利用 Golang 的強類型特性,爲所有的組件、Lambda、編排產物等聲明具體類型。這像是爲代碼繪製了一幅精確的地圖,開發者可以沿着清晰的路徑進行維護和擴展,即使在項目規模不斷擴大、功能持續迭代的情況下,依然能夠保有較高的可維護性。
同時,Eino 編排能力也充分利用了強類型系統的編譯時校驗能力,儘可能將類型匹配問題暴露的時機提前到 graph 的編譯時,而不是 graph 的運行時。儘早並明確的暴露類型匹配問題,有助於開發者迅速定位和修復,減少因類型錯誤在運行時引發的難以排查的故障和性能問題。
另一方面,Eino 遵循模塊化設計,核心庫以及各組件實現是單獨的 go module,每個 go module 做到依賴最小化。同時,API 設計以 “精簡”、"直觀" 和“同構性” 爲原則,輔以由淺入深的全面文檔,儘可能讓學習曲線更平滑。最重要的是,Eino 採用清晰的分層設計,每層職責明確、功能內聚,在提升維護性的同時能更好的保證穩定性。
Eino 框架結構圖:
實踐驅動
Eino 框架的設計開發過程,紮根於 “滿足真實需求” 與 “實踐驅動設計” 這兩大基石之上。功能的演進過程與字節跳動各業務線的接入過程緊密結合,始終傾聽開發者的聲音,並通過實際使用效果來檢驗設計的合理性。比如我們收到來自抖音的 “希望能夠以字段爲粒度在圖中映射和傳遞數據” 的需求,以此爲基礎設計了 Workflow;傾聽來自豆包的使用痛點,增強作爲模型輸入輸出類型的 Message 結構體。在未來的開源生態共建過程中,我們會繼續堅持上述原則,滿足更廣大的用戶和開發者的真實需求,並在更大的範圍內認真實踐和精進。
工具生態
鏈路追蹤、調試、可視化,是編排引擎的三個重要輔助工具。Eino 內置了 tracing callback,並與 Langfuse 平臺做了集成。同時提供了 IDE 插件,可以在寫代碼的過程中隨時可視化查看編排出的 graph,並進行調試運行,甚至可以通過 UI 拖拽的方式快速構建 graph 並導出爲 Eino 代碼。
03
快速上手
針對 Eino 的學習和使用,我們提供了完善的 Eino 用戶手冊,幫助大家快速理解 Eino 中的概念,掌握基於 Eino 開發設計 AI 應用的技能,趕快通過「Eino: 快速開始」嘗試使用吧~
如有任何問題,可通過下方的飛書羣或者「Eino Issues」和我們溝通、反饋~
「Eino: 快速開始」https://www.cloudwego.io/zh/docs/eino/quick_start/
「Eino Issues」https://github.com/cloudwego/eino/issues
項目地址:
https://github.com/cloudwego/eino
https://github.com/cloudwego/eino-ext
項目官網:https://www.cloudwego.io
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/bdG1dor3HG9lr5OrpeOTCA