Go + Eino 实现生产级 Multi-Agent:我们是怎么设计「面试吧」的?

45 阅读4分钟

本文介绍「面试吧」(Interview Agent)的 Multi-Agent 架构设计思路。面试吧是一个已上线的企业级 AI 模拟面试平台,基于字节跳动开源的 Eino 框架构建,完整技术栈:Go + Eino + Milvus + Hertz + Thrift。在线体验:interviewbar.xyz/

image.png


为什么选 Eino,而不是 LangChain?

做 AI Agent 项目,第一个问题是框架选型。

市面上最主流的是 LangChain,但它是 Python 生态的。对于 Go 后端工程师来说,用 Python 写 Agent 意味着:

  • 引入一套完全不同的工程体系
  • 高并发场景下性能天花板明显
  • 和现有 Go 服务的集成成本高

字节跳动开源的 Eino 是专门为 Go 设计的 Agent 框架,核心是 Graph 编排模型:把 Agent 的执行流程抽象成有向图,节点是 Component(LLM、Tool、Retriever 等),边是数据流。

这个设计的好处是:复杂的多智能体协作流程,可以用图来清晰表达,而不是一堆嵌套的函数调用。


面试吧的 Multi-Agent 设计

面试吧的核心场景是:用户上传简历,AI 面试官根据简历和岗位要求进行多轮专业提问,最后生成评估报告。

这个场景天然适合 Multi-Agent:不同技术领域的面试,需要不同的「专家」来主导。

我们设计了两类 Agent:

专项面试官(Specialized Agent)

每个技术领域一个独立 Agent,目前覆盖:Go、Java、MySQL、Redis、算法等 5+ 个方向。

agent/interview/specialized/
├── go_interviewer.go
├── java_interviewer.go
├── mysql_interviewer.go
├── redis_interviewer.go
└── algorithm_interviewer.go

每个专项 Agent 有自己的 System Prompt,定义了该领域的考察重点、提问风格、难度梯度。

专项 Agent 的提问不是随机生成的,而是通过 RAG 从 Milvus 知识库里检索对应领域的高质量题目,再结合用户简历内容进行个性化提问。

综合面试官(General Agent)

基于 ReAct 范式实现,负责:

  • 综合评估候选人的整体能力
  • 跨领域的系统设计题
  • 根据简历内容追问项目经验

ReAct 的核心是「思考 → 行动 → 观察」的循环,让 Agent 能够根据用户的回答动态调整下一个问题,而不是按固定脚本走。


RAG 的接入方式:Tool Use

面试吧的 RAG 不是独立模块,而是以 Tool 的形式接入 Agent。

Agent 在需要检索知识时,主动调用检索 Tool,Tool 返回结果后,Agent 基于检索内容生成回答。

// tool/get_resume_info_tool.go
type RetrieveInput struct {
    Query      string `json:"query"`
    Domain     string `json:"domain"`     // go / java / mysql / redis
    Category   string `json:"category"`   // algorithm / system / project
    TopK       int    `json:"top_k"`
}

检索层用的是 Milvus 的混合检索:向量相似度 + 标量字段过滤

纯向量检索的问题是:语义相近但领域不同的内容会混在一起。加上 domaincategory 的标量过滤后,Go 并发题只会从 Go 知识库里检索,不会和 MySQL 锁的内容混淆。


异步架构:为什么要用消息队列

AI 推理是耗时操作,一次面试评估报告的生成可能需要 10-30 秒。

如果同步等待,用户体验很差,服务的并发能力也会被拖垮。

我们的方案是:手写基于 Redis 的消息队列,将评估报告生成任务异步化。

用户提交面试结束
    → 写入 Redis Queue
    → 立即返回「生成中」
    → Consumer 异步消费,调用 LLM 生成报告
    → 报告生成后推送给前端(SSE)

SSE(Server-Sent Events)负责流式推送,让报告内容像打字机一样逐字出现,而不是等全部生成完再一次性返回。


工程化:IDL 驱动开发

面试吧的前后端协作用的是 Thrift IDL 驱动开发

先定义 .thrift 文件,用 hz 工具自动生成路由、Handler 骨架、请求/响应结构体,前后端都基于同一份 IDL 对齐接口契约。

好处是:接口变更时,改 IDL 重新生成,不会出现前后端字段对不上的问题。

// idl/interview.thrift
service InterviewService {
    StartInterviewResp StartInterview(1: StartInterviewReq req)
    SubmitAnswerResp   SubmitAnswer(1: SubmitAnswerReq req)
    GetReportResp      GetReport(1: GetReportReq req)
}

整体架构总结

用户请求
    → Hertz 网关(JWT 鉴权 / CORS / Recovery)
    → Handler(Thrift IDL 生成)
    → Service 层
        ├── 简历解析 Agent(Eino + PDF 解析)
        ├── 专项面试 Agent × N(Eino Graph + RAG Tool)
        └── 综合面试 Agent(Eino ReAct)
    → Milvus(向量检索)
    → Redis Queue(异步任务)
    → SSE 流式响应

这套架构的核心设计原则:

  • Agent 无状态:每个 Agent 只负责自己领域,通过 Tool 获取外部知识
  • 降级优先:Milvus 故障时自动回退纯 LLM,不中断主流程
  • 异步解耦:耗时任务全部走消息队列,保证接口响应时间

最后

面试吧目前已上线,可以直接体验:interviewbar.xyz/

这个项目也是我们出版的 Go + AI 实战课程的核心项目,完整源码 + 视频教程 + 文档教程,已完成。

并且我们已签约人民邮电出版社,书稿已完成,坐等出版社印刷出版。

感兴趣的同学可以加我微信了解:wangzhongyang1993

标签:#Go #Eino #RAG #MultiAgent #Milvus #AI应用开发 #字节跳动