Spring AI 系列之三十八 - Spring AI Alibaba-Tool Calling

之前做个几个大模型的应用,都是使用Python语言,后来有一个项目使用了Java,并使用了Spring AI框架。随着Spring AI不断地完善,最近它发布了1.0正式版,意味着它已经能很好的作为企业级生产环境的使用。对于Java开发者来说真是一个福音,其功能已经能满足基于大模型开发企业级应用。借着这次机会,给大家分享一下Spring AI框架。

注意由于框架不同版本改造会有些使用的不同,因此本次系列中使用基本框架是 Spring AI-1.0.0,JDK版本使用的是19,Spring-AI-Alibaba-1.0.0.3-SNAPSHOT
代码参考: https://github.com/forever1986/springai-study

在《Spring AI 系列之六 - 工具调用》中讲了Spring AI的工具集成,但是Spring AI只是提供的工具的集成框架,对于现有工具几乎没有。不过好在Spring AI Alibaba弥补了这一部分的空缺,在Spring AI Alibaba中,对于工具集成也已经形成了一个较好的生态。这一章将讲一下Spring AI Alibaba的工具集成。

1 Tool Calling

1.1 Tool Calling集成

虽然现在已经有了MCP,但是工具的调用对于大模型来说还是非常重要的。Spring AI Alibaba 社区提供了很多 Tool Calling 扩展实现,方便开发者通过声明的方式直接开启插件,避免重复开发的麻烦。
以下是截止到目前为止实现的一些解析插件(版本号截止到目前为止,亲测有效):

工具说明工具名称配置前缀及说明Maven依赖版本
阿里云机器翻译aliTranslateServicespring.ai.alibaba.toolcalling.alitranslate
enabled:设置为true时启动插件。
access-key-id:服务的AccessKeyId,若不提供则读取系统环境变量ALITRANSLATE_ACCESS_KEY_ID的值。
secret-key:服务的SecretKey,若不提供则读取系统环境变量ALITRANSLATE_ACCESS_KEY_SECRET的值。
spring-ai-alibaba-starter-tool-calling-alitranslate1.0.0.3-SNAPSHOT
高德地图获取城市天气gaoDeGetAddressWeatherspring.ai.alibaba.toolcalling.amap
enabled:设置为true时启动插件。
api-key:高德地图服务的ApiKey,若不提供则读取系统环境变量GAODE_AMAP_API_KEY的值。
spring-ai-alibaba-starter-tool-calling-amap1.0.0.3-SNAPSHOT
百度地图baiduMapGetAddressInformation:获取地址详细信息
baiDuMapGetAddressWeatherInformation:获取城市天气
spring.ai.alibaba.toolcalling.baidu.map
enabled:设置为true时启动插件。
api-key:百度地图服务的ApiKey,若不提供则读取系统环境变量BAIDU_MAP_API_KEY的值。
spring-ai-alibaba-starter-tool-calling-baidumap1.0.0.3-SNAPSHOT
百度搜索baiduSearchspring.ai.alibaba.toolcalling.baidu.search
enabled:设置为true时启动插件。
spring-ai-alibaba-starter-tool-calling-baidusearch1.0.0.3-SNAPSHOT
百度翻译baiduTranslatespring.ai.alibaba.toolcalling.baidu.translate
enabled:设置为true时启动插件。
secret-key:百度翻译服务的SecretKey,若不提供则读取系统环境变量BAIDU_TRANSLATE_SECRET_KEY的值。
app-id:百度翻译服务的AppId,若不提供则读取系统环境变量BAIDU_TRANSLATE_APP_ID的值。
spring-ai-alibaba-starter-tool-calling-baidutranslate1.0.0.3-SNAPSHOT
必应搜索bingSearchspring.ai.alibaba.toolcalling.bingsearch
enabled:设置为true时启动插件。
token:必应服务的Token,若不提供则读取系统环境变量BING_SEARCH_TOKEN的值。
spring-ai-alibaba-starter-tool-calling-bingsearch1.0.0.2
钉钉群发消息dingTalkGroupSendMessageByCustomRobotspring.ai.alibaba.toolcalling.dingtalk enabled:设置为true时启动插件。
custom-robot-access-token:自定义机器人的AccessToken,必须提供。
custom-robot-signature:自定义机器人的Signature,必须提供。
spring-ai-alibaba-starter-tool-calling-dingtalk1.0.0.3-SNAPSHOT
DuckDuckGo 查询最近新闻duckDuckGoQueryNewsspring.ai.alibaba.toolcalling.duckduckgo
enabled:设置为true时启动插件。
api-key:Serpapi服务的ApiKey,若不提供则读取系统环境变量SERPAPI_KEY的值。
spring-ai-alibaba-starter-tool-calling-duckduckgo1.0.0.3-SNAPSHOT
GitHub Tool KitsgetIssue :获取 GitHub 某个仓库的 Issue 信息
createPullRequest :在 GitHub 某个仓库创建 PR
SearchRepository :查询 GitHub 某个名称的仓库信息
spring.ai.alibaba.toolcalling.githubtoolkit enabled:设置为true时启动插件。
token:GitHub的Token,若不提供则读取系统环境变量GITHUB_TOKEN。
owner:要查询的仓库所有者,必须设置。
repository:要查询的仓库名称,必须设置。
pring-ai-alibaba-starter-tool-calling-githubtoolkit1.0.0.3-SNAPSHOT
谷歌翻译googleTranslatespring.ai.alibaba.toolcalling.googletranslate enabled:设置为true时启动插件。
api-key:谷歌翻译的ApiKey,若不提供则读取系统环境变量GOOGLE_TRANSLATE_APIKEY。
spring-ai-alibaba-starter-tool-calling-googletranslate1.0.0.3-SNAPSHOT
JSON 处理工具jsonInsertPropertyFieldFunction:给一个 JSON 对象添加字段值。
jsonParsePropertyFunction:获取 JSON 对象某个字段的值。
jsonRemovePropertyFieldFunction:删除 JSON 对象某个字段。
jsonReplacePropertyFiledValueFunction: 替换 JSON 对象某个字段的值。
spring.ai.alibaba.toolcalling.jsonprocessor
enabled:设置为true时启动插件。
spring-ai-alibaba-starter-tool-calling-jsonprocessor1.0.0.3-SNAPSHOT
快递100查询快递信息queryTrackspring.ai.alibaba.toolcalling.kuaidi100
enabled:设置为true时启动插件。
api-key:快递100的ApiKey,若不提供则读取系统环境变量KUAIDI100_KEY的值。
app-id:快递100的AppId,若不提供则读取系统环境变量KUAIDI100_CUSTOMER的值。
spring-ai-alibaba-starter-tool-calling-kuaidi1001.0.0.3-SNAPSHOT
飞书文档larksuiteCreateDocFunction:创建文档
larksuiteChatFunction:发送聊天消息
larksuiteCreateSheetFunction:创建工作表
spring.ai.alibaba.toolcalling.larksuite
enabled:设置为true时启动插件。
app-id:飞书的AppId,必须提供。
app-secret:飞书的AppSecret,必须提供。
spring-ai-alibaba-starter-tool-calling-larksuite1.0.0.3-SNAPSHOT
微软翻译microSoftTranslateFunctionspring.ai.alibaba.toolcalling.microsofttranslate enabled:设置为true时启动插件。
api-key:微软翻译的ApiKey,若不提供则读取系统环境变量MICROSOFT_TRANSLATE_API_KEY的值。
region:为请求头Ocp-Apim-Subscription-Region的值,必须提供。
spring-ai-alibaba-starter-tool-calling-microsofttranslate1.0.0.3-SNAPSHOT
正则表达式查询regexFindAllspring.ai.alibaba.toolcalling.regex
enabled:设置为true时启动插件。
spring-ai-alibaba-starter-tool-calling-regex1.0.0.3-SNAPSHOT
敏感信息过滤sensitiveFilterspring.ai.alibaba.toolcalling.sensitivefilter
enabled:设置为true时启动插件。
replacement:用来替换敏感信息的字符串,默认为"***"。
filterPhoneNumber:是否过滤电话号码,默认为true。
filterIdCard:是否过滤 ID 卡号,默认为true。
filterBankCard:是否过滤银行卡号,默认为true。
filterEmail:是否过滤邮箱地址,默认为true。
spring-ai-alibaba-starter-tool-calling-sensitivefilter1.0.0.3-SNAPSHOT
Serpai 查询serpApiSearchspring.ai.alibaba.toolcalling.serpapi
enabled:设置为true时启动插件。
api-key:Serpapi服务的ApiKey,若不提供则读取系统环境变量SERPAPI_KEY的值。
engine:选择使用的搜索引擎,必填。
spring-ai-alibaba-starter-tool-calling-serpapi
新浪新闻getSinaNewsspring.ai.alibaba.toolcalling.sinanews
enabled:设置为true时启动插件。
spring-ai-alibaba-starter-tool-calling-sinanews1.0.0.3-SNAPSHOT
Tavily SearchtavilySearchspring.ai.alibaba.toolcalling.tavilysearch
enabled:设置为true时启动插件。
api-key:Tavily Search 的ApiKey,若不提供则读取系统环境变量TAVILY_SEARCH_API_KEY的值。
spring-ai-alibaba-starter-tool-calling-tavilysearch
获取某个时区时间getCityTimeFunctionspring.ai.alibaba.toolcalling.time
enabled:设置为true时启动插件。
spring-ai-alibaba-starter-tool-calling-time1.0.0.3-SNAPSHOT
今日头条getToutiaoNewsspring.ai.alibaba.toolcalling.toutiaonews
enabled:设置为true时启动插件。
spring-ai-alibaba-starter-tool-calling-toutiaonews1.0.0.3-SNAPSHOT
Weather Api 获取城市天气getWeatherServicespring.ai.alibaba.toolcalling.weather
enabled:设置为true时启动插件。
api-key:服务的ApiKey,若不提供则读取系统环境变量WEATHER_API_KEY的值。
spring-ai-alibaba-starter-tool-calling-weather1.0.0.3-SNAPSHOT
有道翻译youdaoTranslatespring.ai.alibaba.toolcalling.youdaotranslate
enabled:设置为true时启动插件。
secret-key:有道翻译的AppSecret,若不提供则读取系统环境变量YOUDAO_APP_SECRET的值。
app-id:有道翻译的AppId,若不提供则读取系统环境变量YOUDAO_APP_ID的值。
spring-ai-alibaba-starter-tool-calling-youdaotranslate1.0.0.3-SNAPSHOT
语雀createYuqueDoc:创建语雀文档。
createYuqueBook:创建语雀Book知识库。
updateDocService:更新语雀文档。
deleteDocService:删除语雀文档。
spring.ai.alibaba.toolcalling.yuque
enabled:设置为true时启动插件。
token,语雀的Token,必须设置。
spring-ai-alibaba-starter-tool-calling-yuque1.0.0.3-SNAPSHOT

1.2 示例演示

代码参考lesson29子模块

示例说明:通过引入百度搜索(baiduSearch)工具,实现在线查询功能,(注意:这里使用的是智谱的大模型,非阿里大模型

1)在lesson29子模块的pom中引入:

<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter-tool-calling-baidusearch</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-zhipuai</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2)新建application.properties配置文件

# 聊天模型
spring.ai.zhipuai.api-key=你的智谱API KEY
spring.ai.zhipuai.chat.options.model=GLM-4-Flash-250414
spring.ai.zhipuai.chat.options.temperature=0.7

# 百度配置
spring.ai.alibaba.toolcalling.baidu.search.enabled=true

3)创建BaiduSearchController演示类

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BaiduSearchController {

    private ChatClient chatClient;

    public BaiduSearchController(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder
                .defaultToolNames("baiduSearch")
                .build();
    }

    /**
     * @param message 问题
     */
    @GetMapping("/ai/baidu")
    public String baidu(@RequestParam(value = "message", defaultValue = "从百度搜索中查找北京天气?", required = true) String message) {
        return this.chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

4)创建Lesson29Application 启动类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Lesson29Application {

    public static void main(String[] args) {
        SpringApplication.run(Lesson29Application.class, args);
    }

}

5)演示效果

http://localhost:8080/ai/baidu

在这里插入图片描述

结语:本章讲解了Spring AI Alibaba的Tool Calling的生态,可以看出在Spring AI的基础上,Spring AI Alibaba扩展了很多插件,这样也是丰富了Spring AI的生态,对于java用户来说是一个很好的福音。

Spring AI系列上一章:《Spring AI 系列之三十七 - Spring AI Alibaba-DocumentReader

Spring AI系列下一章:《Spring AI 系列之三十九 - Spring AI Alibaba-集成百炼知识库

<think>嗯,用户问的是为什么在Spring AI的Ollama Starter 1.0.0-M6版本加上Qwen2.5-7B模型后,添加了工具调用tool calling)功能后,流式输出就不工作了。我需要先理解这个问题的大致背景。 首先,Spring AISpring生态系统中的一个项目,可能用于集成AI模型到应用中。Ollama应该是一个支持本地运行大模型的工具,比如像Llama这样的模型。用户用的版本是M6,可能还在开发阶段,所以可能存在一些不稳定因素。 用户提到的Qwen2.5-7B是通义千问的一个7B参数的模型,可能通过Ollama来部署。然后他们添加了工具调用功能,之后流式输出失效了。工具调用通常指的是让模型能够调用外部工具或API,比如函数调用,这在OpenAI的API中有类似功能。可能Spring AI的Ollama模块支持这样的功能。 接下来,流式输出通常是指数据分块传输,逐步返回结果,而不是一次性返回所有内容。当用户启用工具调用后,流式输出停止工作,可能是因为工具调用和流式处理在实现上有冲突。 我需要考虑可能的原因。首先,是否工具调用和流式输出在Ollama或Spring AI的当前版本中不兼容?比如,当模型被配置为使用工具调用时,是否必须等待完整的响应才能解析工具调用的参数,从而无法流式传输?或者可能是Spring AI在处理工具调用时,强制使用了同步请求,而禁用了流式传输? 另外,可能涉及到模型本身的问题。Qwen2.5-7B在处理工具调用时,是否必须以非流式的方式响应?或者Ollama在启用某些功能时,是否关闭了流式传输的支持? 还有可能是Spring AI的库在处理工具调用时,没有正确传递流式参数,或者在处理响应时,即使请求是流式的,但工具调用的解析逻辑需要完整的响应体,导致无法流式输出。 另一个角度是配置问题。用户可能在添加工具调用时,修改了某些配置,比如关闭了流式选项,或者触发了某种默认行为的变化。比如,工具调用可能默认要求同步处理,因此Spring AI内部可能切换到了非流式请求。 也可能是一个Bug。因为用户使用的是M6版本,属于里程碑版本,可能存在未解决的缺陷。在GitHub的issue中,可能已经有类似的问题报告,或者需要用户检查日志、文档来确认。 可能的解决步骤包括:检查Ollama和Spring AI的文档,确认工具调用是否支持流式;查看是否需要在请求中显式启用流式;查看日志是否有错误信息;尝试在工具调用的情况下手动启用流式参数;或者联系社区看是否有已知问题。 总结可能的原因:1. 工具调用和流式处理在实现上的不兼容;2. 配置错误或默认行为变更;3. 库或模型的Bug。</think>在 Spring AI 的 `spring-ai-ollama-spring-boot-starter`(1.0.0-M6)中,结合 Qwen2.5-7B 模型添加 Tool Calling 功能后流式输出失效的问题,通常与以下原因相关: --- ### **1. Tool Calling 与流式响应的机制冲突** - **Tool Calling 的实现逻辑**: 当模型启用 Tool Calling工具调用)时,模型需要生成结构化响应(如 JSON 格式的函数参数),而流式输出(逐块返回结果)可能无法保证结构化数据的完整性。Ollama 或 Spring AI 可能在检测到 Tool Calling 需求时,**强制切换为同步请求**,以确保返回的数据能被正确解析。 - **Qwen2.5-7B 的限制**: 某些模型在输出结构化内容(如 JSON)时,可能无法支持分块流式传输,必须一次性生成完整结果。Qwen2.5-7B 可能在 Tool Calling 模式下默认关闭了流式能力。 --- ### **2. Spring AI 的实现限制** - **当前版本的兼容性**: `1.0.0-M6` 是里程碑版本,可能存在未完善的特性。Spring AITool Calling 的支持可能尚未完全适配流式场景,代码逻辑可能强制使用非流式请求(如底层调用 Ollama API 时未传递 `stream: true` 参数)。 - **响应解析逻辑冲突**: Spring AI 在解析 Tool Calling 的响应时,可能需要完整的响应体来提取结构化数据(如函数名称、参数),而流式处理的分块响应可能导致解析失败,因此框架可能自动禁用流式。 --- ### **3. 配置或代码问题** - **显式关闭流式**: 添加 Tool Calling 时,可能无意中覆盖了流式配置(例如,在 `OllamaApi` 或 `ChatClient` 的设置中,`stream` 参数被设为 `false`)。 - **依赖版本冲突**: Ollama 或 Spring AI 的依赖版本不兼容(例如,低版本 Ollama 服务端对 Tool Calling 的流式支持存在缺陷)。 --- ### **排查与解决方法** 1. **检查文档与版本**: - 确认 Ollama 服务端版本是否支持 Tool Calling 的流式输出。 - 查看 Spring AI 官方文档或 GitHub Issue,确认是否为已知限制(例如 [Spring AI #1234](https://github.com/spring-projects/spring-ai/issues))。 2. **调试请求参数**: 在代码中手动设置流式参数,确保请求明确启用流式: ```java OllamaOptions options = OllamaOptions.create() .withStream(true); // 强制启用流式 ``` 3. **日志分析**: 启用 Spring AI 的调试日志,观察 Ollama 请求的实际参数和响应格式,确认是否因 Tool Calling 导致请求从 `stream: true` 变为 `stream: false`。 4. **简化场景测试**: - 在不启用 Tool Calling 时,验证流式是否正常工作。 - 使用其他模型(如 Llama3)测试相同场景,确认是否为 Qwen2.5-7B 的特定问题。 5. **临时解决方案**: 如果流式是必需功能,暂时回退到非 Tool Calling 实现,或等待 Spring AI 的后续版本修复。 --- ### **总结** 根本原因可能是 Spring AITool Calling 场景下强制禁用了流式,或 Qwen2.5-7B 模型的结构化输出与流式传输不兼容。建议优先通过日志验证请求参数,并关注 Spring AI 的版本更新(如升级到更新的里程碑版本)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linmoo1986

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值