你的AI助手是个"工具囤积狂"吗?
想象一下这个场景:你让AI助手帮你查个天气,结果它带着50个工具箱出门了------有修电脑的、做饭的、修车的、甚至还有做核酸的工具!这就像你只想拧个螺丝,却背着整个五金店出门一样荒谬。
更要命的是,每次它出门前都要把所有工具的说明书读一遍,光是翻说明书就花了你55000个令牌的费用。而你只是想知道明天要不要带伞啊!
这就是现在AI工具调用的真实写照。今天我们就来聊聊Spring AI是如何治好AI的"工具选择困难症"的。
当前AI工具调用的"灾难现场"
让我们先看看传统的AI工具调用是怎么工作的:

图1:传统工具调用的"带着大炮打蚊子"现场
问题一:上下文膨胀症
就像有个同事开会前要把所有可能用到的文件都打印出来,即使只讨论一个议题。AI也是这样,它要把所有工具的定义都加载到上下文里,哪怕你只是想查个天气。
问题二:选择困难症
当AI面对30+个名字相似的工具时,就像你在超市面对50种洗发水一样懵逼。getWeather()、getCurrentWeather()、fetchWeatherData()...天哪,它们看起来都能查天气!
问题三:钱包出血症
每次调用都为用不到的工具定义买单,就像点外卖必须把整个菜单都买下来,即使你只想要一碗面。
Spring AI的"按需点菜"解决方案
Spring AI引入了一个叫"工具搜索工具"的聪明做法,就像给AI配了个智能管家:

图2:Spring AI的"按需点菜"工具发现流程
这个过程就像这样:
- AI: "老板,我要查天气的工具"
- 工具搜索工具 : "稍等,我给您找找...找到了,这个
weather工具应该合您意" - AI: "完美!就用它了"
而不是传统的:
- AI: "老板,这里有修电脑、做饭、修车、查天气、做核酸...50个工具,我该用哪个?"
- 大脑: "崩溃..."
真实场景:上海穿搭助手
让我们看个具体例子。假设你要开发一个AI穿搭助手:
typescript
@SpringBootApplication
public class StyleAdvisorApp {
@Bean
CommandLineRunner demo(ChatClient.Builder builder, ToolSearcher toolSearcher) {
return args -> {
// 这里注册了100多个工具,但AI一开始看不到!
var advisor = ToolSearchToolCallAdvisor.builder()
.toolSearcher(toolSearcher)
.build();
ChatClient chatClient = builder
.defaultTools(new StyleTools()) // 偷偷注册100+工具
.defaultAdvisors(advisor) // 启动"智能管家"模式
.build();
var answer = chatClient.prompt("""
帮我规划今天在上海的穿搭建议,
顺便推荐几家现在还开门的服装店。
""").call().content();
System.out.println(answer);
};
}
static class StyleTools {
@Tool(description = "获取指定位置和时间的天气")
public String weather(String location, String time) {
// 就像问天气预报员
return "阳光明媚,15°C,适合轻薄外套";
}
@Tool(description = "获取指定位置和时间营业的服装店")
public List<String> clothingStores(String location, String time) {
// 就像问本地向导
return Arrays.asList("H&M", "Zara", "Uniqlo");
}
@Tool(description = "获取指定位置的当前时间")
public String currentTime(String location) {
// 就像看手表
return "2025-12-08T11:30";
}
// ...还有其他97个工具
}
}
AI的聪明工作流程
- 用户: "帮我规划上海穿搭"
- AI : "我需要时间工具" → 发现并获取
currentTime - AI : "知道时间了,现在需要天气工具" → 发现并获取
weather - AI : "有了天气,需要找服装店" → 发现并获取
clothingStores - AI: "完美!基于15°C的阳光天气,推荐轻薄外套,附近的H&M、Zara都在营业"
整个过程AI只"看到"了3个真正需要的工具,而不是全部100个!
性能数据:省钱效果有多惊人?
我们来看看实际测试数据(虽然作者很诚实地说这是初步测试,但数据还是很有说服力的):
Lucene搜索策略结果
| AI模型 | 传统方式令牌数 | Spring AI方式 | 节省比例 |
|---|---|---|---|
| Gemini | 5,375 | 2,165 | 60% 💰 |
| OpenAI | 7,175 | 4,706 | 34% 💰 |
| Anthropic | 17,342 | 6,273 | 64% 💰 |
这些数字意味着什么?
- Gemini用户: 原来花100块,现在只花40块,省了一顿火锅钱
- OpenAI用户: 原来花100块,现在花66块,省了一杯奶茶钱
- Anthropic用户: 原来花100块,现在只花36块,这简直是半价优惠券啊!
为什么能省这么多?
就像点外卖一样:
传统方式:
- 必须把整个菜单都买下来(所有工具定义)
- 即使你只要一碗面
Spring AI方式:
- 服务员问你想要什么(工具搜索)
- 只为你点的菜付费(按需加载工具)
三种搜索策略:总有一款适合你
Spring AI提供了三种工具搜索策略,就像三种不同的图书馆管理员:
1. 语义搜索(VectorToolSearcher)
这个管理员很聪明,你说"我想要做饭相关的",他会给你找到炒菜、烘焙、调料等所有相关工具。
适合场景: 自然语言描述,模糊查找
arduino
// 用户说:我想处理图片
// 它会找到:resizeImage, cropImage, filterImage 等
2. 关键词搜索(LuceneToolSearcher)
这个管理员比较直接,你说"weather",他就找所有包含"weather"的工具。
适合场景: 精确匹配,已知工具名
arduino
// 用户说:weather
// 它会找到:getWeather, getCurrentWeather, fetchWeatherData 等
3. 正则表达式搜索(RegexToolSearcher)
这个管理员是个技术宅,懂各种模式匹配。
适合场景: 工具命名有规律
arduino
// 模式:get_*_data
// 它会找到:get_weather_data, get_user_data, get_stock_data 等
什么时候该用Spring AI的工具搜索?
适合使用的情况(推荐指数⭐⭐⭐⭐⭐)
就像以下情况,你绝对需要这个功能:
-
工具超市症候群: 系统里有20+个工具
- 就像你的工具箱里有20把不同的螺丝刀
-
令牌烧钱症: 工具定义超过5000个令牌
- 就像每次出门都要背着百科全书
-
MCP多服务器环境: 连接多个MCP服务器
- 就像同时在淘宝、京东、拼多多开店
-
工具选择困难症: AI老是选错工具
- 就像老是拿菜刀去削铅笔
不适合使用的情况(传统方式更好)
-
极简工具库: 少于20个工具
- 就像你只有一把瑞士军刀,直接用就好
-
高频全能工具: 每次对话都要用所有工具
- 就像厨师每道菜都要用遍所有调料
-
超紧凑定义: 工具定义都很简短
- 就像说明书只有一句话
快速上手:5分钟搞定配置
想试试这个省钱神器?来,5分钟搞定:
1. 添加依赖(就像装插件)
xml
<dependency>
<groupId>org.springaicommunity</groupId>
<artifactId>tool-search-tool</artifactId>
<version>1.0.1</version>
</dependency>
<!-- 选择一个搜索策略,我推荐Lucene -->
<dependency>
<groupId>org.springaicommunity</groupId>
<artifactId>tool-searcher-lucene</artifactId>
<version>1.0.1</version>
</dependency>
2. 配置工具搜索(就像雇个管家)
kotlin
@Configuration
public class AIConfig {
@Bean
public ToolSearchToolCallAdvisor toolSearchAdvisor(ToolSearcher searcher) {
return ToolSearchToolCallAdvisor.builder()
.toolSearcher(searcher)
.maxResults(5) // 最多返回5个工具,防止选择困难症复发
.build();
}
}
3. 使用(就像平常一样聊天)
ini
// AI会自动按需发现工具,你什么都不用管!
var response = chatClient.prompt("帮我查查明天北京的天气").call().content();
就这么简单!AI会自动变聪明,账单会自动变小。
实际应用:为什么Java开发者需要关心这个?
你可能会问:"我就是个Java后端开发,为什么要关心AI的工具调用?"
现实场景:智能客服系统
假设你在开发一个电商的智能客服系统:
less
@Service
public class CustomerServiceAI {
// 你的系统需要这些能力
@Tool("查询订单状态") public OrderStatus getOrderStatus(String orderId) {...}
@Tool("查询物流信息") public ShippingInfo getShippingInfo(String trackingId) {...}
@Tool("处理退款申请") public RefundResult processRefund(String orderId) {...}
@Tool("查询商品信息") public ProductInfo getProductInfo(String productId) {...}
@Tool("查询用户信息") public UserInfo getUserInfo(String userId) {...}
@Tool("发送邮件通知") public void sendEmail(String to, String subject) {...}
@Tool("查询库存") public int getInventory(String productId) {...}
@Tool("查询优惠券") public List<Coupon> getCoupons(String userId) {...}
@Tool("计算运费") public BigDecimal calculateShipping(String address) {...}
@Tool("查询售后政策") public String getReturnPolicy() {...}
// ... 还有40个工具
}
传统方式的问题:
- 用户问:"我的订单什么时候到?"
- AI接收到50个工具定义(包括很多不相关的)
- 令牌费用爆炸,响应速度慢
Spring AI工具搜索的优势:
- AI只获取
getOrderStatus和getShippingInfo相关工具 - 令牌使用量减少60%
- 响应更快,用户更满意
- 运营成本大幅下降
为什么Java开发者要学这个?
- 成本控制: 在AI应用中,令牌就是真金白银
- 性能优化: 更少的上下文意味着更快的响应
- 系统扩展性: 可以轻松添加更多工具而不影响性能
- 用户体验: 更准确的工具选择意味着更好的服务质量
注意事项:不是万能药
虽然Spring AI的工具搜索很棒,但也有一些需要注意的地方:
老模型可能"学不会"
就像教你爷爷用智能手机一样,有些老版本的AI模型可能搞不定这套流程。这时候你可能需要:
- 添加更详细的提示信息
- 换个搜索策略试试
- 或者配合"AI判官"模式来确保效果
更多请求 vs 更少令牌
这是个经典的时间换空间的问题:
- 传统方式:3-4次请求,但每次都很"重"
- 工具搜索:4-5次请求,但每次都很"轻"
就像快递一样,你是愿意一次搬个大箱子,还是分几次搬小包裹?
未来展望:这只是开始
Spring AI团队正在考虑把这个功能加入核心框架,这意味着:
- 更好的集成: 不需要额外依赖
- 更多策略: 可能会有更智能的搜索算法
- 更强兼容性: 支持更多AI模型
同时,他们还在研究:
- 预选工具顾问: 在AI调用前就选好工具
- AI判官模式: 确保选择的工具真正解决了问题
总结:AI工具管理的"断舍离"哲学
Spring AI的工具搜索模式本质上就是AI版的"断舍离":
- 断: 断掉不必要的工具定义传输
- 舍: 舍弃"全家桶"式的工具加载
- 离: 远离令牌浪费和选择困难
它告诉我们一个道理:有时候,少即是多。
当你的AI助手不再是个"工具囤积狂",而是个"按需专家"时,你会发现:
- 账单变小了
- 响应变快了
- 准确性提高了
- 开发效率up了
所以,如果你正在开发AI应用,特别是需要大量工具集成的场景,不妨试试Spring AI的工具搜索模式。
让AI学会"断舍离",让你的钱包松口气!
想了解更多Spring AI的黑科技?关注我们的Java技术分享,每周为你带来最实用的开发技巧!