Eino:概览
简介
Eino(发音类似 “I know”,寓意为“我知道”) 是一个用 Golang 构建的终极 LLM 应用开发框架。它从 LangChain、LlamaIndex 等优秀开源框架中汲取灵感,同时结合前沿研究成果和真实业务场景,致力于构建一个更符合 Golang 编程风格的 LLM 应用开发框架,强调简单性、可扩展性、可靠性和高效性。
Eino 提供的能力包括:
- 精心设计的 组件(component) 抽象及实现,可以方便地复用和组合,用于构建 LLM 应用;
- 强大的 编排(composition) 框架,帮你完成类型检查、流式处理、并发管理、切面注入、参数配置等复杂任务;
- 简洁清晰的 API,设计关注点就是简单易懂;
- 不断增长的最佳实践集合,打包为 flows(流程) 和 examples(示例);
- 一整套实用工具,覆盖从可视化开发与调试,到在线追踪与评估的整个开发周期。
借助以上能力和工具,Eino 可以在 LLM 应用的各个阶段实现标准化、简化操作并提升效率:
快速上手
直接使用一个组件:
model, _ := openai.NewChatModel(ctx, config) // 创建一个可调用的 LLM 实例
message, _ := model.Generate(ctx, []*Message{
SystemMessage("you are a helpful assistant."),
UserMessage("what does the future AI App look like?")})
当然可以这么用,Eino 提供了大量开箱即用的组件。不过更推荐你用编排(orchestration)方式,理由有三:
- 编排能封装 LLM 应用中常见的模式;
- 编排解决了流式响应处理这一大难题;
- 编排自动处理类型安全、并发控制、切面注入和参数赋值。
Eino 提供了三套编排 API:
API | 特点与用法 |
---|---|
Chain | 简单的链式有向图,只能向前执行 |
Graph | 支持有环或无环的有向图,功能强大、灵活 |
Workflow | 无环图,支持结构体字段级别的数据映射 |
让我们来构建一个简单的 Chain:一个 ChatTemplate 接一个 ChatModel。
chain, err := NewChain[map[string]any, *Message]().
AppendChatTemplate(prompt).
AppendChatModel(model).
Compile(ctx)
if err != nil {
return err
}
out, err := chain.Invoke(ctx, map[string]any{"query": "what's your name?"})
接下来我们构建一个 Graph:使用 ChatModel 生成工具调用,再用 ToolsNode 执行工具调用:
graph := NewGraph[map[string]any, *schema.Message]()
_ = graph.AddChatTemplateNode("node_template", chatTpl)
_ = graph.AddChatModelNode("node_model", chatModel)
_ = graph.AddToolsNode("node_tools", toolsNode)
_ = graph.AddLambdaNode("node_converter", takeOne)
_ = graph.AddEdge(START, "node_template")
_ = graph.AddEdge("node_template", "node_model")
_ = graph.AddBranch("node_model", branch)
_ = graph.AddEdge("node_tools", "node_converter")
_ = graph.AddEdge("node_converter", END)
compiledGraph, err := graph.Compile(ctx)
if err != nil {
return err
}
out, err := compiledGraph.Invoke(ctx, map[string]any{"query": "Beijing's weather this weekend"})
接下来构建一个支持字段级数据映射的 Workflow:
wf := NewWorkflow[[]*Message, *Message]()
wf.AddChatModelNode("model", model).AddInput(START)
wf.AddLambdaNode("l1", lambda1).AddInput(NewMapping("model").From("Content").To("Input"))
wf.AddLambdaNode("l2", lambda2).AddInput(NewMapping("model").From("Role").To("Role"))
wf.AddLambdaNode("l3", lambda3).AddInput(
NewMapping("l1").From("Output").To("Query"),
NewMapping("l2").From("Output").To("MetaData"),
)
wf.AddEnd([]*Mapping{NewMapping("node_l3")})
runnable, _ := wf.Compile(ctx)
runnable.Invoke(ctx, []*Message{UserMessage("kick start this workflow!")})
现在来创建一个 ReAct agent:一个 ChatModel 与 Tools 绑定。它接收消息后,判断是直接输出答案还是调用工具,工具执行结果会变成下一轮的上下文。
Eino 已在 flow
包中实现了完整的 ReAct agent,可查看代码:flow/agent/react
Eino 背后自动处理了这些关键功能:
- 类型检查:编译时保证输入输出类型匹配;
- 流式处理:将多段消息拼接成流传递给 ChatModel 或 ToolsNode,并复制到回调处理器;
- 状态管理:保证共享状态的读写安全;
- 切面注入(Aspect Injection):在 ChatModel 执行前后自动注入回调;
- 参数赋值:参数可全局设定、针对组件类型或指定节点设定。
比如可以加上回调函数:
handler := NewHandlerBuilder().
OnStartFn(func(ctx context.Context, info *RunInfo, input CallbackInput) context.Context {
log.Infof("onStart, runInfo: %v, input: %v", info, input)
return ctx
}).
OnEndFn(func(ctx context.Context, info *RunInfo, output CallbackOutput) context.Context {
log.Infof("onEnd, runInfo: %v, out: %v", info, output)
return ctx
}).
Build()
compiledGraph.Invoke(ctx, input, WithCallbacks(handler))
或者给不同节点指定参数:
// 所有节点
compiledGraph.Invoke(ctx, input, WithCallbacks(handler))
// 仅作用于 ChatModel 节点
compiledGraph.Invoke(ctx, input, WithChatModelOption(WithTemperature(0.5)))
// 指定某个节点 node_1
compiledGraph.Invoke(ctx, input, WithCallbacks(handler).DesignateNode("node_1"))
主要特性
✅ 丰富的组件体系
封装了常见能力为 组件抽象(component abstraction),每种抽象都有多个可直接使用的 组件实现(implementation):
- 例如 ChatModel、Tool、PromptTemplate、Retriever、Document Loader、Lambda 等;
- 每种组件类型都有明确的输入输出类型、参数类型、流式处理机制;
- 抽象即编排的单位,组件实现可嵌套复杂业务逻辑;
例如:React Agent、MultiQueryRetriever、Host MultiAgent 等;
- 虽然内部复杂,但对外接口保持统一,如 MultiQueryRetriever 可以在任何接受 Retriever 的场景中使用。
⚙️ 强大的编排能力(Graph / Chain / Workflow)
- 数据从 Retriever / Document Loaders / Prompt Template → ChatModel → Tools → 最终输出;
- 组件实例是图节点,边表示数据流;
支持复杂业务逻辑编排:
- 类型检查、流处理、并发管理、切面注入、参数赋值;
- 运行时分支、全局状态读写、字段级映射等。
🌊 完整的流式处理机制
- ChatModel 在生成消息时是流式输出,因此流处理对于编排尤为关键;
Eino 自动处理如下场景:
- 拼接流:下游只接受非流输入时会自动拼接;
- 转为流:上游非流数据自动转为流;
- 合并流:多个流合并成一个下游输入;
- 复制流:将流分发给多个下游节点或回调;
- 编排元素如 分支(branch) 或 StateHandler 同样支持流处理;
- 用户无需关心组件是否支持流,Eino 会自动转换;
- 编译后的 Graph 支持四种流式调用模式:
调用模式 | 说明 |
---|---|
Invoke | 输入输出都是非流数据 |
Stream | 输入非流,输出为 StreamReader[O] |
Collect | 输入为 StreamReader[I],输出为非流数据 |
Transform | 输入为 StreamReader[I],输出为 StreamReader[O] |
🔧 可扩展的切面机制(Callbacks)
- 处理日志、链路追踪、监控等横切逻辑;
- 支持五种回调:OnStart, OnEnd, OnError, OnStartWithStreamInput, OnEndWithStreamOutput;
- 自定义回调只需注册即可自动调用;
- 甚至可以给原本不支持回调的组件注入切面。
Eino 框架结构
- Eino:包含类型定义、流处理机制、组件抽象、编排逻辑、切面机制等;
- EinoExt:组件实现、回调实现、工具库(如评估器、提示词优化器)等;
- Eino Devops:可视化开发与调试工具;
- EinoExamples:示例应用与最佳实践集合。
详细说明见:Eino 框架结构
使用文档
想学习和使用 Eino?我们提供了完整的用户手册,帮助你快速掌握概念和实践技能:
📘 Eino 使用手册 🚀 Eino 快速入门 📚 完整 API 文档
依赖要求
- Go 1.18 及以上版本;
- Eino 依赖 kin-openapi 提供的 OpenAPI JSONSchema 实现;
- 为保持 Go 1.18 兼容性,已将其版本固定为 v0.118.0。
安全问题报告
如果你发现了潜在的安全问题,请通过 安全中心 或 漏洞报告邮箱 向 ByteDance 安全团队反馈。
请 不要 通过 GitHub 公共 issue 报告安全漏洞。