大家好,我是王中陽,見字如面,感謝閲讀!
最近我們團隊在瘋狂的研究AI。期間不僅做了幾個還不錯的項目,也踩坑不少。下面我就分享一下,過去用GoZero開發了怎樣一個AI應用,以及為什麼現在要用字節的Eino重構和優化。
我們過去基於gozero實現AI面試官智能體項目,一方面搞定了從0到1開發AI智能體應用,各種造輪子;另一方面,模擬面試,也是我粉絲股東們很迫切的需求。
之所以使用GoZero,是因為我在社區裏看到了對MCP的支持,過去也用gozero開發了不少項目,本着快速跑通的原則,我們團隊花了不到一個月就搞定全流程了,具體功能,大家可以看文章最後的介紹哈。
大家點擊這個鏈接可以體驗:核心功能全部搞定,細節還在持續優化中,歡迎大家提bug和建議哈。(目前服務器配置不高,token也有限,如果不可用,可以微信私信我:wangzhongyang1993,我再進行充值,哈哈)
但是,我們發現想進一步做性能和效果的優化,還是有些吃力,或者説有點摸不着頭腦,不想一直自己造輪子,於是開始各種調研和對比,最終,我們把目光聚焦到了CloudWeGo開源的Eino框架。
畢竟我們團隊絕大多數同學是gopher,字節在go生態中的地位我就不必多説了:
現在字節跳動旗下CloudWeGo開源的Eino框架可以説Langchain的平替,提供了一套簡單易用卻功能強大的解決方案,最近在看到這個框架的時候真的感覺的像是用到SpringAI框架真的很方便(我也是老Java了哈哈),我最近在優化的AI面試官智能體項目也通過這個框架變得更加簡潔,功能更加強大。
我這次將結合開源文檔和實際開發的Demo,給大家分享一下Eino框架的使用方法和核心優勢,同時下一期內容給大家演示最重要的Agent領域的表現。
什麼是Eino框架?
Eino是CloudWeGo生態下的AI應用開發框架,旨在降低大模型應用開發門檻。它提供了統一的接口抽象,支持多模型集成(如OpenAI、Anthropic等),內置流式響應、提示詞模板等核心功能,讓開發者可以專注於業務邏輯而非底層交互細節。
相較於傳統開發方式,Eino的優勢在於:
- 簡化大模型API調用流程,無需重複封裝HTTP請求
- 內置流式響應處理,輕鬆實現實時對話體驗
- 強大的提示詞模板系統,便於管理複雜對話邏輯
- 完善的上下文管理,輕鬆維護對話歷史
- 兼容主流大模型,切換模型無需大幅修改代碼
- 靈活強大的編排能力:覆蓋從簡單到複雜的全場景
實戰:用Eino構建對話應用
接下來我通過一個完整的Demo,看看如何用Eino快速開發一個AI對話應用。
項目結構
我的Demo項目結構非常簡潔:
ai-eino-agent/
├── chatApp/
│ ├── main.go // 程序入口
│ └── chat/
│ └── chatTemplate.go // 對話模板定義
├── go.mod // 依賴管理
└── go.sum
核心依賴配置
在go.mod中,我們主要依賴了Eino核心包和OpenAI擴展組件:
require (
github.com/cloudwego/eino v0.5.11
github.com/cloudwego/eino-ext/components/model/openai v0.1.2
// 其他依賴...
)
通過這些依賴,我們可以直接使用Eino封裝好的OpenAI接口,無需自己處理API鑑權、請求構造等底層邏輯。
1. 定義對話模板
在chatTemplate.go中,我們使用Eino的prompt包創建對話模板:
func creatTemplate() prompt.ChatTemplate {
// 創建模版,使用Fstring格式
return prompt.FromMessages(schema.FString,
// 系統提示詞,定義AI角色和語氣
schema.SystemMessage("你是一個{role},你需要用{style}的語氣回答問題,你的目標是解答程序員的面試問題"),
// 插入對話歷史
schema.MessagesPlaceholder("chat_history", true),
// 用户消息模板
schema.UserMessage("問題:{question}"),
)
}
這個模板包含三個關鍵部分:
- 系統提示詞:定義AI的角色(
{role})和回答風格({style}) - 對話歷史佔位符:用於插入之前的對話內容
- 用户問題佔位符:接收當前用户輸入
通過模板參數化,可以靈活調整AI的行為和對話內容,而無需修改模板結構,比以往更加靈活。
2. 初始化對話內容
同樣在chatTemplate.go中,我們實現了MessagesTemplate()函數來初始化對話內容:
func MessagesTemplate() []*schema.Message {
template := creatTemplate()
// 填充模板參數
messages, err := template.Format(context.Background(), map[string]any{
"role": "經驗豐富的大廠開發面試專家",
"style": "温和且專業",
"question": "你好,什麼是go語言",
"chat_history": []*schema.Message{
schema.UserMessage("你好"),
schema.AssistantMessage("嘿!我是你的程序員面試助手...", nil),
// 更多歷史消息...
},
})
if err != nil {
log.Fatalf("format template failed: %v", err)
}
return messages
}
這裏我們為模板填充了具體參數,包括AI角色定義、對話歷史和當前問題。Eino會自動處理模板渲染,生成符合大模型要求的消息格式。
3. 主程序邏輯
在main.go中,我們實現了完整的對話流程:
func main() {
ctx := context.Background()
// 創建消息
fmt.Printf("===create messages===\n")
message := chat.MessagesTemplate()
// 創建LLM實例
fmt.Printf("===create llm===\n")
model := chat.CreatOpenAiChatModel(ctx)
// 流式獲取並輸出結果
fmt.Printf("===llm stream ===\n")
streamResult := chat.Stream(ctx, model, message)
chat.ReportSteam(streamResult)
}
整個流程非常清晰:
- 初始化上下文
- 創建消息列表(基於之前定義的模板)
- 初始化OpenAI模型客户端
- 發起流式對話請求並處理響應
4. 流式響應處理
Eino的流式響應處理非常優雅,我們不需要手動處理WebSocket或長輪詢,只需調用Stream()方法即可獲得一個流式結果通道,然後通過ReportSteam()函數實時輸出結果:
func ReportSteam(sr *schema.StreamReader[*schema.Message]) {
defer sr.Close()
for {
message, err := sr.Recv()
if err == io.EOF {
return
}
if err != nil {
log.Fatalf("recv message failed: %v", err)
}
content := message.Content
fmt.Printf(content)
}
}
func Stream(ctx context.Context, llm model.ToolCallingChatModel, in []*schema.Message) *schema.StreamReader[*schema.Message] {
result, err := llm.Stream(ctx, in)
if err != nil {
log.Fatalf("llm generate failed: %v", err)
}
return result
}
這種處理方式讓我們輕鬆實現類似ChatGPT的打字機效果,大幅提升用户體驗,我在優化Ai面試官智能體項目時原有繁瑣的流失輸出得到了更簡潔的優化,而且輸出效果更好,而且還有多種實時流選擇。
Eino框架的核心優勢
通過這個簡單的Demo,我們可以感受到Eino框架的幾個核心優勢:
- 簡化開發流程:封裝了大模型調用的底層細節,開發者無需關注API請求格式、鑑權等問題
- 強大的模板系統:通過結構化的提示詞模板,輕鬆管理複雜對話邏輯,提高prompt的可維護性
- 原生支持流式響應:內置流式處理機制,幾行代碼即可實現實時對話效果
- 靈活的上下文管理:通過
MessagesPlaceholder輕鬆維護對話歷史,無需手動拼接消息列表 - 多模型兼容:通過統一接口抽象,切換不同大模型時只需修改模型初始化部分
不僅如此!
Eino框架為大模型應用開發提供了一套高效、簡潔的解決方案。通過本文的Demo,我僅用幾十行代碼就實現了一個具備流式響應、上下文管理功能的AI對話應用,比我們智能體項目原有的流式響應、上下文管理功能代碼優化的更簡潔高效,使用起來的感覺不亞於隔壁的SpringAI。
我之前在使用GoZero去寫這個項目的時候感覺真的很繁瑣,而現在Eino可以顯著降低開發成本,讓我的精力集中在業務邏輯和用户體驗上。而且eino也提供了開箱即用的多agent編排模式使用也簡單,我在優化我們訓練營智能體項目agent的時候也方便許多,而且工具的調用也更加靈活。
如果你也在開發大模型應用,不妨試試CloudWeGo Eino,體驗GO在Ai智能體領域的新方式。 (注:Demo基於Eino v0.5.11版本開發,實際使用時請參考官方最新文檔)
重構優化
也正因為如此,所以,我們決定使用Eino重構優化【AI智能面試官項目】,下面是關於這個項目的介紹:
體驗地址:http://aigo.dayu.club/#/
我們的項目功能:
-
交互流程與狀態管理
- 接收客户端 Post 請求(含用户輸入 / 操作指令 / 文件上傳)
- 通過 SSE 流式實時輸出 AI 面試問題 / 反饋
- 利用 Redis 狀態機(SessionID:State)管理面試流程,AI 能主動引導話題,推進面試目標
- 維持請求 - 響應鏈路的低延遲交互
-
多輪對話與知識庫管理
- 基於 pgvector 擴展的
vector_store表存儲對話數據及知識庫內容(含 id/chat\_id(or doc\_id)/role/content/embedding/created\_at 字段) - 支持單條消息/知識存儲與歷史對話/知識批量查詢(通過 chat\_id/doc\_id 關聯)
- 依託 embedding 向量實現對話上下文關聯、連續性維護及知識庫檢索
- 基於 pgvector 擴展的
-
PDF 處理與知識庫構建
- 通過 MCP 服務(gRPC)接收並解析客户端上傳的 PDF 文件,轉換為文字內容並生成向量
- 提供獨立 POST 接口,支持上傳 PDF 文件至 RAG 本地知識庫(存儲原始文本及向量至 pgvector)
- 在 SSE 聊天交互中,自動將知識庫檢索結果與當前解析文本(如有)拼接至上下文,作為 AI 生成響應的參考依據
-
RAG 本地知識庫集成
- 支持構建本地知識庫(通過專用接口上傳 PDF 向量化存儲)
- 基於用户輸入、對話歷史及知識庫內容,實時檢索(向量相似度)知識庫中相關內容輔助生成回覆,提升 AI 響應的專業性與針對性
-
智能體調度與部署
- 基於 Redis 狀態機實現 AI 智能體的目標導向行為,動態調整面試流程
- 採用 容器化部署:通過
Dockerfile構建鏡像,docker-compose.yml編排服務(API, MCP-gRPC, PostgreSQL-pgvector, Redis, etcd),init.sql初始化數據庫表結構及擴展 - 實現一鍵啓動:本地安裝 Docker 後,執行
docker-compose up即可啓動全套服務(API、MCP、DB、Redis、etcd),無需額外環境配置
優化重構核心思路
- 核心框架從gozero--->字節生態的Enio
- 向量數據庫從pgvector--->milvus
- 實現多Agent調用
歡迎提寶貴建議
- 更多的優化細節和建議,歡迎大家在評論區討論,我們也想基於大家迫切的需求,以及想學的功能點知識點做優化,更好的反哺社區。
對AI應用的開發感興趣,歡迎關注我的賬號,或者微信我:wangzhongyang1993,備註AI開發,我邀你進交流羣。