当前位置: 首页 > news >正文

源码分析Eino框架工具调用--创建篇

Eino框架中通过tool node这个官方的组件给模型加上了手脚,工具有多种创建方式,本文不讨论如何创建tool而是聚焦于调用工具过程的底层实现,关于工具的其他内容可以参考这里创建tool
调用一个工具需要这些东西:名称,描述,参数说明以及实现(本地or mcp)
先看tool node的创建,总的来说创建节点的过程分为以下几步

  1. info方法检测
  2. invoke && stream方法实现,二选一即可
  3. 打包原信息,和运行时有关
  4. 打包具体的实现了runnable这个interface的struct,至此通过下面的函数实现了所有工具以来信息的
// NewToolNode creates a new ToolsNode.
// e.g.
//
//	conf := &ToolsNodeConfig{
//		Tools: []tool.BaseTool{invokableTool1, streamableTool2},
//	}
//	toolsNode, err := NewToolNode(ctx, conf)
func NewToolNode(ctx context.Context, conf *ToolsNodeConfig) (*ToolsNode, error) {tuple, err := convTools(ctx, conf.Tools)if err != nil {return nil, err}return &ToolsNode{tuple:                tuple,unknownToolHandler:   conf.UnknownToolsHandler,executeSequentially:  conf.ExecuteSequentially,toolArgumentsHandler: conf.ToolArgumentsHandler,}, nil
}

最后的ToolNode结构其实是这样的

type ToolsNode struct {tuple                *toolsTuple // 核心结构unknownToolHandler   func(ctx context.Context, name, input string) (string, error) // 当模型调用了不存在的func时触发这个handler,若没有指定会直接报错executeSequentially  bool // 多个工具的调用顺序是穿行还是并行toolArgumentsHandler func(ctx context.Context, name, input string) (string, error) // 处理入参的handler
}
/* 
这个是toolNode的核心结构,可以看到indexes是map其他的都是切片,这点是为了根据被调用工具的名字快速找到index后去meta和rps中找到需要的其他数据
meta存储一些元信息
rps是工具执行的关键,实现了eino框架的invoke或者是stream
*/
type toolsTuple struct {indexes map[string]int meta    []*executorMetarps     []*runnablePacker[string, string, tool.Option]
}

我们这里重点关注一下tuple的创建过程,以invoke调用进行说明,创建tuple的源码如下

func convTools(ctx context.Context, tools []tool.BaseTool) (*toolsTuple, error) {ret := &toolsTuple{indexes: make(map[string]int),meta:    make([]*executorMeta, len(tools)),rps:     make([]*runnablePacker[string, string, tool.Option], len(tools)),}for idx, bt := range tools {// 检测是否实现了info方法tl, err := bt.Info(ctx)if err != nil {return nil, fmt.Errorf("(NewToolNode) failed to get tool info at idx= %d: %w", idx, err)}toolName := tl.Namevar (st tool.StreamableToolit tool.InvokableToolinvokable  func(ctx context.Context, argumentsInJSON string, opts ...tool.Option) (string, error)streamable func(ctx context.Context, argumentsInJSON string, opts ...tool.Option) (*schema.StreamReader[string], error)ok   boolmeta *executorMeta)if st, ok = bt.(tool.StreamableTool); ok {streamable = st.StreamableRun}if it, ok = bt.(tool.InvokableTool); ok {invokable = it.InvokableRun}// 工具只有invoke和stream两种调用方式,如果这两个方法都没实现会直接error,同时进行了流的转换,因为eino框架默认支持了流的拼接if st == nil && it == nil {return nil, fmt.Errorf("tool %s is not invokable or streamable", toolName)}// 设置上面所说的meta信息if st != nil {meta = parseExecutorInfoFromComponent(components.ComponentOfTool, st)} else {meta = parseExecutorInfoFromComponent(components.ComponentOfTool, it)}ret.indexes[toolName] = idxret.meta[idx] = meta// 这个packer通过源码可以看到是包装出一个struct实现了runnable这个interface,也就是说我们最终调用工具的时候,其实是通过这个interface的具体实现来的ret.rps[idx] = newRunnablePacker(invokable, streamable,nil, nil, !meta.isComponentCallbackEnabled)}return ret, nil
}func parseExecutorInfoFromComponent(c component, executor any) *executorMeta {componentImplType, ok := components.GetType(executor)if !ok {componentImplType = generic.ParseTypeName(reflect.ValueOf(executor))}return &executorMeta{component:                  c,isComponentCallbackEnabled: components.IsCallbacksEnabled(executor),componentImplType:          componentImplType,}
}
http://www.lryc.cn/news/617259.html

相关文章:

  • 瑞芯微rk3588:yolov8-obb训练实战笔记
  • 云原生环境 Prometheus 企业级监控实战
  • 容器 K8S Docker Kata 学习(一)
  • k8s的calico是什么作用,举例一下
  • 【软考中级网络工程师】知识点之 UDP 协议:网络通信中的高效轻骑兵
  • k8s PV和PVC开始总结
  • AI时代基于云原生的 CI/CD 基础设施 Tekton
  • RabbitMQ 声明队列和交换机详解
  • HTTPS 协议原理 ——4种方案
  • HTTPS的应用层协议
  • 2024年ESWA SCI1区TOP,自适应种群分配和变异选择差分进化算法iDE-APAMS,深度解析+性能实测
  • 在 ASP.NET 项目中用 C# 生成二维码
  • 为 Promethus 配置https访问
  • 无人机航拍数据集|第12期 无人机停车场车辆计数目标检测YOLO数据集1568张yolov11/yolov8/yolov5可训练
  • FP32、BF16、FP16三种方式比较
  • 计算机视觉CS231n学习(7)
  • 《范仲淹传》读书笔记与摘要
  • MySQL数据库简介
  • MySQL-日志
  • Vue 3 快速入门 第六章
  • Linux操作系统从入门到实战(十九)进程状态
  • JS-第二十三天-正则
  • 大数据量下分页查询性能优化实践(SpringBoot+MyBatis-Plus)
  • 集成电路学习:什么是URDF Model统一机器人描述格式模型
  • ZeroNews:如何构建安全(无需 V*N!)的工业物联网连接
  • 大模型落地:AI 技术重构工作与行业的底层逻辑
  • Salesforce案例:零售企业会员积分体系
  • 【软考架构】需求工程中,系统分析与设计的结构化方法
  • [Shell编程] Shell 编程之免交互
  • C语言模拟 MCU 上电后程序的执行顺序 + 回调函数机制 + 程序计数器(PC)和堆栈的作用