第十六篇:Eino入门——核心组件总览与场景选型总结

2026-04-26 36 0

到本篇为止,我们已经完成Eino基础消息协议、Prompt模板、工具调用全链路组件的学习。在进入Compose编排体系学习之前,我们需要对前面学习过的全部核心对象做系统性梳理:明确每个组件的定位、职责、边界、适用与不适用场景,厘清易混淆API之间的本质差异,消除概念歧义。

核心原则:Eino采用分层设计,数据层只负责存储数据,组件层实现原子能力,编排层负责流程调度,Agent层交由模型驱动决策,观测层负责链路可观测。每个组件只承担自己边界内的职责,组件之间通过标准结构体解耦,可以自由组合,也可以单独使用。

一、分层架构总览

Eino整体分为5个层级,层级自上而下抽象程度逐步提高;高层组件底层会复用下层的原子组件,开发者可以按需选择使用任意层级,不是必须使用高层封装。

层级模块核心职责特征
数据层schema包系列结构体定义标准化数据模型:消息、工具元信息、Token统计、多模态结构纯数据结构体,无任何业务执行逻辑,全框架统一数据契约
组件层ChatModel、ChatTemplate、InvokableTool、Retriever实现独立原子能力,每个组件只完成单一职责无内置循环、无流程调度,输入输出都是schema标准类型,可独立单元测试
编排层compose包:ToolsNodeChainGraphStreamReader实现确定性业务流程编排,分支、串行、并行调度流程由开发者代码定义,不由大模型决策
Agent层adk包:ChatModelAgentRunnerAgentTool实现模型驱动的ReAct智能体循环,由模型决定下一步动作内置循环逻辑,模型自主决策是否调用工具、调用哪些工具
观测层Callback、AgentEvent、StreamReader链路埋点、事件输出、流式数据消费只读观测为主,部分Handler允许拦截修改请求/响应

重要提示:高层组件是对底层组件的组合封装,不是替代。例如ChatModelAgent内部复用ChatModelcompose.ToolsNode,开发者完全可以不使用Agent,手动组合底层组件实现相同业务。

二、核心对象职责对照表

1)schema 数据层(仅数据,无逻辑)

对象类型核心职责关键边界说明
schema.Message结构体统一对话消息载体,支持system/user/assistant/tool四种角色;支持文本、多模态、工具调用、元数据只存消息数据,本身不会做渲染、不会调用模型
schema.ToolInfo结构体工具元数据(工具说明书):工具名称、描述、入参JSON‑Schema约束仅用于给LLM读取的静态描述,不包含任何执行逻辑,不能直接运行工具
schema.ToolCall结构体模型输出的工具调用指令,存放工具名、调用ID、JSON参数由assistant消息携带,是模型推理产出,不是开发者手动定义的工具

2)组件层(原子能力组件)

对象包路径核心职责关键边界说明
prompt.ChatTemplategithub.com/cloudwego/eino/components/promptPrompt模板引擎,支持FString/GoTemplate/Jinja2;支持MessagesPlaceholder历史消息占位;将变量渲染为[]*schema.Message只负责消息渲染,不调用大模型
model.BaseChatModelgithub.com/cloudwego/eino/components/model基础聊天模型,提供Generate同步、Stream流式接口,输入输出为[]*schema.Message单次请求,没有循环,不会自动执行工具
model.ToolCallingChatModelmodel包继承BaseChatModel,新增WithTools([]tool.BaseTool)方法WithTools仅提取内部ToolInfo提交给模型;仅告知模型工具列表,框架不会自动执行任何工具,ToolCall需要业务侧处理
tool.InvokableToolgithub.com/cloudwego/eino/components/tool可执行工具接口;组合ToolInfo元信息 + Go业务执行函数;提供Info()获取说明书、Execute()执行工具拥有元信息同时具备执行能力;可通过utils.InferTool / utils.NewTool构造

 

3)编排层(开发者定义确定流程)

对象包路径核心职责关键边界说明
compose.ToolsNodegithub.com/cloudwego/eino/compose工具调用调度节点;接收携带ToolCall的*schema.Message,完成工具匹配、参数解析、串行/并行执行,输出[]*schema.Message(Tool角色消息)单次执行,内部没有ReAct循环,不会主动调用LLM;只处理输入消息内的ToolCall
compose.Chain / compose.Graphcompose包通用工作流编排,串联各个节点,支持条件分支、并行、错误处理全部流程由开发者定义,模型不能改变流转路径

4)Agent层(模型驱动,内置ReAct循环)

对象包路径核心职责关键边界说明
adk.ChatModelAgentgithub.com/cloudwego/eino/adk实现标准ReAct Reason‑Action‑Observation循环;内部组合ToolCallingChatModel + compose.ToolsNode;对外暴露Run()同步、StreamRun()流式接口内置迭代循环,配置MaxIterations防止死循环;模型自主判断是否产生ToolCall
adk.Runneradk包Agent运行时载体,消费Agent事件,管理执行上下文,支持事件回调用于运行Agent,做事件订阅、上层封装
adk.AgentTooladk包将一个ChatModelAgent包装成为tool.BaseTool,实现子Agent嵌套调用让Agent可以作为工具被另外一个Agent调用

三、高频易混淆概念辨析(消除歧义)

1. ToolInfo VS InvokableTool

  • ToolInfo纯静态元数据,JSON Schema描述,给LLM阅读,无执行函数;
  • InvokableTool:接口,= ToolInfo + 业务执行函数;既可以拿到工具说明书给模型,又可以调用Execute()执行业务逻辑。

易错点:不要把ToolInfo直接当做可执行工具传入ToolsNode,ToolsNode接收的是tool.BaseTool(即InvokableTool)。

2. ToolCallingChatModel.WithTools() VS ChatModelAgentConfig.ToolsConfig

  1. 1. WithTools([]tool.BaseTool)
    • • 行为:提取每个工具内部的ToolInfo,把工具描述提交给大模型;
    • • 边界:仅此而已。模型返回ToolCall之后,框架不会自动执行,必须业务代码接收ToolCall,手动送入ToolsNode处理;
    • • 使用场景:底层手动实现ReAct循环场景。
  2. 2. ChatModelAgentConfig.ToolsConfig compose.ToolsNodeConfig
    • • 行为:不仅把工具元信息提交模型,Agent内部实例化ToolsNode;当模型输出ToolCall,Agent内部自动调用ToolsNode执行工具、回填消息上下文;
    • • 使用场景:直接使用高层Agent,完整ReAct由框架接管。

3. 手动手写ReAct循环 VS ChatModelAgent

手写ReAct(底层原生组合)
开发者自己编写for循环:调用ChatModel → 判断是否存在ToolCall → 调用ToolsNode执行工具 → 手动append回填Message → 循环直到无ToolCall或者达到最大迭代次数。

  • • 优点:100%可控,每一步业务代码都可以介入修改;
  • • 缺点:重复样板代码,需要自己处理迭代上限、错误处理、上下文维护、事件埋点。

ChatModelAgent(高层封装)
内部已经实现上述整套for循环逻辑,对外只暴露Run() / StreamRun()

  • • 优点:消除样板代码,内置迭代保护、事件体系、错误处理;
  • • 缺点:流程被封装,部分高度定制场景需要使用Handler做拦截扩展。

本质:Agent没有魔法,只是底层组件的标准化封装,底层完全等价手写ReAct。

4. 编排层ToolsNode VS Agent层ChatModelAgent

  • compose.ToolsNode:编排节点,只有工具执行能力,没有LLM调用、没有循环,输入一条assistant消息,输出工具结果消息;可以单独在Graph/Chain中作为普通节点使用。
  • ChatModelAgent:内部包含ToolsNode,并且叠加LLM循环驱动。

5. 编排层(Chain/Graph) VS Agent

  • compose编排(Chain/Graph):人定流程:所有分支、步骤、执行顺序写死在代码;模型只作为其中一个节点,不能改变整体流转路径。适合确定性业务流水线。
  • ChatModelAgent:模型定流程:下一步做什么由大模型推理结果决定,适合开放、不确定的业务。

四、业务场景选型指南

✅ 适合使用 ChatModelAgent

  1. 1. 用户输入开放,后续业务路径无法在开发期预先确定
  2. 2. 需要ReAct模式,由模型自主选择调用哪些工具、调用顺序;
  3. 3. 需要多轮思考‑工具调用迭代,不想手写ReAct样板循环;
  4. 4. 子任务不确定,需要根据工具返回结果动态调整后续任务。

核心判断:下一步动作交给大模型决策

❌ 不建议使用 ChatModelAgent

  1. 1. 业务流程完全确定:步骤、顺序、分支全部开发期已知(文档解析、数据转换、固定数据流水线);优先选择compose.Graph / compose.Chain确定性编排;
  2. 2. 高吞吐、强性能约束,不能接受多轮LLM调用带来的Token开销与时延;
  3. 3. 强合规强确定性场景,不允许模型自由决策,所有执行步骤必须由代码控制;
  4. 4. 仅简单的单次模型调用,不需要任何工具调用。

✅ 适合直接使用底层组件(ChatModel + ToolsNode,手写ReAct)

  1. 1. 需要深度干预ReAct每一步,需要在每一轮思考/工具执行前后做高度定制化逻辑;
  2. 2. 需要自定义循环终止条件,不满足Agent内置终止逻辑;
  3. 3. 做二次封装,自研内部Agent框架。

✅ 适合直接使用 ToolsNode(不搭配Agent)

  1. 1. 在compose Graph/Chain编排中作为独立节点;上游已经产出携带ToolCall的Message,只需要执行工具拿到结果;
  2. 2. 自定义ReAct循环,负责工具调度环节。

五、两套完整实现路径对照(工具调用)

路径一:底层原生手动组合(无Agent)

1. ChatTemplate渲染得到 []*schema.Message
2. ToolCallingChatModel.WithTools() 传入工具,提交ToolInfo给模型
3. for循环(业务手写)
    3‑1 ChatModel.Generate() 获取assistant消息(可能携带ToolCall)
    3‑2 判断消息是否包含ToolCall
    3‑3 有ToolCall:调用 compose.ToolsNode.Invoke() 执行工具,拿到工具结果消息
    3‑4 手动append回填消息切片
    3‑5 判断迭代次数,达到上限退出循环
4. 返回最终assistant消息

路径二:高层Agent封装(adk.ChatModelAgent)

1. ChatTemplate渲染得到 []*schema.Message
2. 构造ChatModelAgentConfig,填入Model、ToolsConfig、MaxIterations
3. agent.Run(ctx, messages)
4. 内部自动执行整套ReAct循环,业务直接拿到最终assistant消息

六、课程整体知识链路回顾

  1. 1. schema.Message:统一消息数据契约,承载system/user/assistant/tool各类对话内容,支持多模态、工具调用元数据;
  2. 2. ChatTemplate:Prompt模板渲染,变量替换、MessagesPlaceholder历史消息占位,输出标准化消息切片;
  3. 3. ChatModel / ToolCallingChatModel:原子模型调用组件,单次同步/流式请求;WithTools仅向模型投递工具元信息;
  4. 4. schema.ToolInfo:工具静态说明书,提供给LLM理解工具能力与参数约束;
  5. 5. InvokableTool:Go业务函数封装,绑定ToolInfo与执行逻辑;
  6. 6. compose.ToolsNode:编排层工具调度节点;接收ToolCall消息,完成工具匹配、串行/并行执行,输出ToolMessage;无循环,单次执行;
  7. 7. ChatModelAgent:Agent高层组件,内部组合ChatModel + ToolsNode,内置标准ReAct循环;模型自主决策工具调用,对外只需要调用Run()获取最终结果。

重要:上层Agent不是黑盒魔法,全部能力都可以由底层组件手动组合实现。

七、开发实践建议

  1. 1. 优先从原子组件理解:遇到问题优先分清当前对象属于哪一层,明确组件的输入输出与边界,不要混淆“数据描述”和“可执行逻辑”;
  2. 2. 不要无脑全部上Agent:优先评估业务流程是否确定;确定流程用compose编排,不确定、开放任务才选用Agent
  3. 3. 调试工具调用:优先确认ToolInfo是否正确,其次确认InvokableTool可单独执行,再测试ToolsNode,最后再接入Agent;分层排查问题;
  4. 4. Agent不等于万能:Agent带来灵活性的同时,引入Token开销、时延、模型不确定性,生产环境必须配置MaxIterations,避免无限迭代;
  5. 5. ToolsNode可以独立使用,Graph编排场景经常直接作为节点使用,不是只能搭配Agent。

相关文章

第十五篇:Eino ChatModelAgent 模型自己决定是否调用工具
第十四篇:Eino ToolsNode 工具调用执行器
第十三篇:InvokableTool-把Go函数包装成模型可调用的工具
第十二篇:Eino ToolInfo工具-给模型看的说明书
第十一篇:Eino Message与Prompt上下文编排
第十篇:Eino ChatModel:将大模型调用抽象成可复用组件

发布评论