spring-ai-alibaba 1.0.0.2 学习(十)——各种工具调用方式对比
接触过FunctionCallback、ToolCallback、MCP、spring-ai-alibaba的starter-tool-calling包,spring-ai-alibaba的Agent,有没有感觉眼花缭乱?
我们来一起梳理下他们之间到底有什么关系
Spring-ai相关功能
FunctionCallback和ToolCallback
首先是FunctionCallback和ToolCallback概念,这两个都是spring-ai中的概念,FunctionCallback是正式版本之前的名称,从1.0.0版本开始就已经改名为ToolCallback了。ChatClient中也移除了defaultFunctions和functions方法
| 名称 | 来源 | 版本 |
| FunctionCallback | spring-ai | 1.0.0之前(不含) |
| ToolCallback | spring-ai | 1.0.0之后(含) |
FunctionToolCallback和MethodToolCallback
FunctionToolCallback和MethodToolCallback都是ToolCallback接口的实现类,注意这里FunctionToolCallback中间多了个Tool,和前文的FunctionCallback并不是同一个概念。
| 名称 | FunctionToolCallback | MethodToolCallback |
| 来源 | sping-ai | spring-ai |
| 接口 | ToolCallback | ToolCallback |
| 应用对象 | 实现了Function接口的类 | 方法 |
| 编程式 | 使用FunctionToolCallback.builder |
使用反射获取方法Method后, 使用MethodToolCallback.builder |
| 声明式 |
使用@Bean注解到装配方法上, 使用ChatClient的toolNames方法 |
使用@Tool注解到方法上, 使用ChatClient的tools方法 |
FunctionToolCallback和MethodToolCallback都有编程式使用方式和声明式使用方式,但过程中使用的类和注解不同。应用对象分别是实现了Function接口的类和方法。
ToolCallback和MCP
ToolCallback和MCP都是对工具的调用,他们之间有区别也有联系。
先来说一下联系,MCP集成进spring-ai框架时,使用的其实就是ToolCallback接口。
以同步模式为例,MCP Client获取到远程的tools信息后,就会将其封装为ToolCallback的实现类SyncMcpToolCallback。使用时将SyncMcpToolCallbackProvider传入ChatClient的toolCallbacks方法即可。
换句话说,MCP底层虽然与传统的ToolCallback(FunctionToolCallback和MethodToolCallback)不同,但是spring-ai框架将其抽象成了ToolCallback的另一种实现。
区别主要在于调用时的入参格式Schema,ToolCallback模式入参格式是静态的,如果要修改则需要修改代码重新部署,而MCP则是动态获取Schema。
| ToolCallback | MCP | |
| 接口 | ToolCallback | ToolCallback |
| 实现类 |
FunctionToolCallback MethodToolCallback |
SyncMcpToolCallback AsyncMcpToolCallback |
| 工具位置 | 一般是本地 | 远程 |
| Schema | 静态 | 动态 |
spring-ai-alibaba相关功能
前面是spring-ai相关的能力,接下来我们来看一下spring-ai-alibaba扩展出来的tool-calling包和Agent接口。
tool-calling包和MCP
tool-calling和MCP都能调用远程的工具,但是调用方式不同
以前调用远程工具,如高德地图,首先需要学习api文档,然后编写api调用代码,比如请求对象封装,url调用等
tool-calling包:实际上就是spring-ai-alibaba帮你按照上述方式完成了对api的调用,查看其jar包能看到底层封装请求对象和对不同url的调用,实际角色只有调用方和被调用方2者
MCP:而mcp不同,mcp中角色包括调用方,中转方,被调用方3者,中转方即mcp server
mcp server提供两个工具接口,tool/list和tool/call,list可以查看该server有哪些工具可用,以及其入参格式,call方法则可以对某个工具进行调用。相当于是提供api文档和提供统一调用接口。
此时调用方不需要再学习api文档,每次启动时访问mcp server的tool/list接口获取接口名称和格式,然后调用时通过mcp server 的call方法调用即可。
两者实现方式也略有区别:
tool-calling是使用FunctionToolCallback的声明式使用方式,实现Function接口,然后通过toolNames方法注册。
而且tool-calling的Schema是定义在tool-calling包中,要修改只能升级tool-calling包。
| tool-calling | MCP | |
| 实现原理 | 基于FunctionToolCallback的声明式 | 基于ToolCallback但自行实现 |
| 工具位置 | 远程 | 远程 |
| 工具实现 | jar包 | 远程MCP Server |
| Schema | 静态 | 动态 |
| 调用方式 | 直接 | mcp server 转发 |
| 角色 | 调用方及被调用方 | 调用方、中转、被调用方 |
Agent和其他
前面的各种工具调用方式都是在本地给大模型增加各种外挂,无论是ToolCallback还是MCP,最终对工具进行调用的都是本地,大模型返回的结果中说需要调用xxx工具,本地进行调用后,将调用结果传递给大模型,然后大模型进行输出。
然而Agent智能体是大模型自带外挂,对工具的调用也不需要再经过本地,发送请求后,大模型直接对工具进行调用,然后返回结果。(ps:在智能体内部其实仍然是请求大模型->返回结果说需要调用xxx工具->智能体调用工具->调用结果传递给大模型->大模型输出的过程)
换一个视角,A服务访问大模型,并使用ToolCallback或MCP对工具进行了调用,然后将整个功能封装为一个接口对外提供服务
那么此时在另一个服务B眼中,A服务就是一个智能体,B服务只需要调用A服务,那么A服务就会访问大模型,调用工具,返回结果
| Agent | 其他 | |
| 发送请求次数 | 1次 | 2次 |
| 工具调用方 | 智能体 | 本地 |
| 是否能对工具执行结果进行优化 | 不可以 | 可以 |
更多推荐



所有评论(0)