大家好,我是王中阳,见字如面,感谢阅读!

最近我们团队在疯狂的研究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框架?

EinoCloudWeGo生态下的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中,我们使用Einoprompt包创建对话模板

    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)
    }

整个流程非常清晰:

  1. 初始化上下文
  2. 创建消息列表(基于之前定义的模板)
  3. 初始化OpenAI模型客户端
  4. 发起流式对话请求并处理响应

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框架的几个核心优势:

  1. 简化开发流程:封装了大模型调用的底层细节,开发者无需关注API请求格式鉴权等问题
  2. 强大的模板系统:通过结构化的提示词模板,轻松管理复杂对话逻辑,提高prompt的可维护性
  3. 原生支持流式响应:内置流式处理机制,几行代码即可实现实时对话效果
  4. 灵活的上下文管理:通过MessagesPlaceholder轻松维护对话历史,无需手动拼接消息列表
  5. 多模型兼容:通过统一接口抽象,切换不同大模型时只需修改模型初始化部分

不仅如此!

Eino框架为大模型应用开发提供了一套高效、简洁的解决方案。通过本文的Demo,我仅用几十行代码就实现了一个具备流式响应上下文管理功能的AI对话应用,比我们智能体项目原有的流式响应上下文管理功能代码优化的更简洁高效,使用起来的感觉不亚于隔壁的SpringAI

我之前在使用GoZero去写这个项目的时候感觉真的很繁琐,而现在Eino可以显著降低开发成本,让我的精力集中在业务逻辑用户体验上。而且eino也提供了开箱即用的多agent编排模式使用也简单,我在优化我们训练营智能体项目agent的时候也方便许多,而且工具的调用也更加灵活。

如果你也在开发大模型应用,不妨试试CloudWeGo Eino,体验GO在Ai智能体领域的新方式。 (注:Demo基于Eino v0.5.11版本开发,实际使用时请参考官方最新文档)

重构优化

也正因为如此,所以,我们决定使用Eino重构优化【AI智能面试官项目】,下面是关于这个项目的介绍:

体验地址:http://aigo.dayu.club/#/

我们的项目功能:

  1. 交互流程与状态管理

    • 接收客户端 Post 请求(含用户输入 / 操作指令 / 文件上传)

    • 通过 SSE 流式实时输出 AI 面试问题 / 反馈

    • 利用 Redis 状态机(SessionID:State)管理面试流程,AI 能主动引导话题,推进面试目标

    • 维持请求 - 响应链路的低延迟交互

  2. 多轮对话与知识库管理

    • 基于 pgvector 扩展的 vector_store 表存储对话数据及知识库内容(含 id/chat_id(or doc_id)/role/content/embedding/created_at 字段)

    • 支持单条消息/知识存储与历史对话/知识批量查询(通过 chat_id/doc_id 关联)

    • 依托 embedding 向量实现对话上下文关联连续性维护知识库检索

  3. PDF 处理与知识库构建

    • 通过 MCP 服务(gRPC)接收并解析客户端上传的 PDF 文件,转换为文字内容并生成向量

    • 提供独立 POST 接口,支持上传 PDF 文件至 RAG 本地知识库(存储原始文本及向量至 pgvector)

    • 在 SSE 聊天交互中,自动将知识库检索结果与当前解析文本(如有)拼接至上下文,作为 AI 生成响应的参考依据

  4. RAG 本地知识库集成

    • 支持构建本地知识库(通过专用接口上传 PDF 向量化存储)

    • 基于用户输入、对话历史及知识库内容,实时检索(向量相似度)知识库中相关内容辅助生成回复,提升 AI 响应的专业性与针对性

  5. 智能体调度与部署

    • 基于 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应用的开发感兴趣,欢迎关注我的账号,备注AI开发,我邀你进交流群。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐