时间:2025-11-03 11:44
人气:
作者:admin
大家好,我是王中阳,见字如面,感谢阅读!
最近我们团队在疯狂的研究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是CloudWeGo生态下的AI应用开发框架,旨在降低大模型应用开发门槛。它提供了统一的接口抽象,支持多模型集成(如OpenAI、Anthropic等),内置流式响应、提示词模板等核心功能,让开发者可以专注于业务逻辑而非底层交互细节。
相较于传统开发方式,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鉴权、请求构造等底层逻辑。
在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}"),
)
}
这个模板包含三个关键部分:
{role})和回答风格({style})通过模板参数化,可以灵活调整AI的行为和对话内容,而无需修改模板结构,比以往更加灵活。
同样在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会自动处理模板渲染,生成符合大模型要求的消息格式。
在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)
}
整个流程非常清晰:
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面试官智能体项目时原有繁琐的流失输出得到了更简洁的优化,而且输出效果更好,而且还有多种实时流选择。
通过这个简单的Demo,我们可以感受到Eino框架的几个核心优势:
MessagesPlaceholder轻松维护对话历史,无需手动拼接消息列表Eino框架为大模型应用开发提供了一套高效、简洁的解决方案。通过本文的Demo,我仅用几十行代码就实现了一个具备流式响应、上下文管理功能的AI对话应用,比我们智能体项目原有的流式响应、上下文管理功能代码优化的更简洁高效,使用起来的感觉不亚于隔壁的SpringAI。
我之前在使用GoZero去写这个项目的时候感觉真的很繁琐,而现在Eino可以显著降低开发成本,让我的精力集中在业务逻辑和用户体验上。而且eino也提供了开箱即用的多agent编排模式使用也简单,我在优化我们训练营智能体项目agent的时候也方便许多,而且工具的调用也更加灵活。
如果你也在开发大模型应用,不妨试试CloudWeGo Eino,体验GO在Ai智能体领域的新方式。 (注:Demo基于Eino v0.5.11版本开发,实际使用时请参考官方最新文档)
也正因为如此,所以,我们决定使用Eino重构优化【AI智能面试官项目】,下面是关于这个项目的介绍:


我们的项目功能:
交互流程与状态管理
接收客户端 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 向量实现对话上下文关联、连续性维护及知识库检索
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),无需额外环境配置
对AI应用的开发感兴趣,欢迎关注我的账号,私信AI开发,我邀你进交流群。