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

网站管理助手操作搜索引擎推广一般包括哪些

网站管理助手操作,搜索引擎推广一般包括哪些,南宁网站建设公,做教程网站资源放哪里1、基于spring-ai 1.0.0 和spring-ai-alibaba 1.0.0.2 概述 “工具调用(Tool Calling)”或“函数调用”允许大型语言模型(LLM)在必要时调用一个或多个可用的工具,这些工具通常由开发者定义。工具可以是任何东西&#…

1、基于spring-ai 1.0.0 和spring-ai-alibaba 1.0.0.2

概述

“工具调用(Tool Calling)”或“函数调用”允许大型语言模型(LLM)在必要时调用一个或多个可用的工具,这些工具通常由开发者定义。工具可以是任何东西:网页搜索、对外部 API 的调用,或特定代码的执行等。LLM 本身不能实际调用工具;相反,它们会在响应中表达调用特定工具的意图(而不是以纯文本回应)。然后,应用程序应该执行这个工具,并报告工具执行的结果给模型。当 LLM 可以访问工具时,它可以在合适的情况下决定调用其中一个工具,这是一个非常强大的功能。

工具调用定义

Spring AI 支持两种工具调用的定义:方法工具 和 函数工具。接下来将以“获取当前时间工具”为例,简单介绍这两种工具定义方法。

方法工具

Spring AI 可以定义类的某个方法为工具,在方法上标记 @Tool 注解,在参数上标记 @ToolParam 注解。例如:

/** Copyright 2024-2025 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.cloud.ai.toolcall.component;import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;public class TimeTools {/*** Spring AI 可以定义类的某个方法为工具,在方法上标记 @Tool 注解,* 在参数上标记 @ToolParam 注解** @param timeZoneId* @return*/@Tool(description = "Get the time of a specified city.")public String getCityTime(@ToolParam(description = "Time zone id, such as Asia/Shanghai")String timeZoneId) {
//        当前方法工具不支持以下类型的参数和返回类型:
//
//        Optional
//        异步类型(CompletableFuture、Future)
//        响应式类型(Flow、Mono、Flux)
//        函数类型(Function、Supplier、Consumer)ZoneId zid = ZoneId.of(timeZoneId);ZonedDateTime zonedDateTime = ZonedDateTime.now(zid);DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");return zonedDateTime.format(formatter);}
}

在调用 ChatClient 时,通过 .tools() 方法传递工具对象,或者在实例化 ChatClient 对象的时候通过 .defalutTools() 方法传递工具对象:

String response = chatClient.prompt("获取北京时间").tools(new TimeTools()).call().content();

实例化工具

/** Copyright 2024-2025 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.cloud.ai.toolcall.config;import com.alibaba.cloud.ai.toolcall.component.AddressInformationTools;
import com.alibaba.cloud.ai.toolcall.component.TimeTools;
import com.alibaba.cloud.ai.toolcalling.baidumap.BaiduMapSearchInfoService;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ToolCallAutoConfiguration {@Beanpublic TimeTools timeTools() {return new TimeTools();}@Beanpublic AddressInformationTools addressInformationTools(BaiduMapSearchInfoService service) {return new AddressInformationTools(service);}@Beanpublic ChatClient chatClient(ChatModel chatModel) {return ChatClient.builder(chatModel).defaultAdvisors(new SimpleLoggerAdvisor()).build();}}

请求controller

/** Copyright 2024-2025 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.cloud.ai.toolcall.controller;import com.alibaba.cloud.ai.toolcall.component.TimeTools;
import com.alibaba.cloud.ai.toolcall.component.TimeToolsMethodToolCallBack;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.ai.tool.method.MethodToolCallback;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.lang.reflect.Method;@RestController
public class TimeController {private final ChatClient dashScopeChatClient;private final TimeTools timeTools;public TimeController(ChatClient chatClient, TimeTools timeTools) {this.dashScopeChatClient = chatClient;this.timeTools = timeTools;}/*** No Tool*/@GetMapping("/time/chat")public String simpleChat(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {return dashScopeChatClient.prompt(query).call().content();}/*** Methods as Tools*/@GetMapping("/time/chat-tool-method")public String chatWithTimeFunction(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        在调用 ChatClient 时,通过 .tools() 方法传递工具对象
//        ,或者在实例化 ChatClient 对象的时候通过 .defalutTools() 方法传递工具对象:return dashScopeChatClient.prompt(query).tools(timeTools).call().content();}/*** Methods as Tools*/@GetMapping("/time/timeToolsMethodToolCallBack")public String timeToolsMethodToolCallBack(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {
//        通过 MethodToolCallBack.Builder 定义方法工具:String inputSchema = """{"$schema" : "https://json-schema.org/draft/2020-12/schema","type" : "object","properties" : {"zoneId" : {"type" : "string","description" : "Time zone id, such as Asia/Shanghai"}},"required" : [ "zoneId" ],"additionalProperties" : false}""";Method method = ReflectionUtils.findMethod(TimeToolsMethodToolCallBack.class, "getTimeByZoneId", String.class);if (method == null) {throw new RuntimeException("Method not found");}MethodToolCallback toolCallback = MethodToolCallback.builder().toolDefinition(ToolDefinition.builder().description("Get time by zone id").name("getTimeByZoneId").inputSchema(inputSchema).build()).toolMethod(method).toolObject(new TimeToolsMethodToolCallBack()).build();
//        可以使用 JsonSchemaGenerator.generateForMethodInput(method) 方法获取 Input Schema。
//        但如果原方法的参数没有 @ToolParam 或者 @JsonPropertyDescription 注解,则会缺失参数的 description 字段,
//        因此建议可以用该方法生成一个模板,然后填充参数的 description 字段。
//
//        在调用 ChatClient 时,通过.toolCallbacks() 传递 MethodToolCallBack 对象,
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 方法传递工具对象:return dashScopeChatClient.prompt(query).toolCallbacks(toolCallback).call().content();}}

如果要使用之前编写好的类的方法,不想修改源代码,可以使用 MethodToolCallBack 定义方法工具。

比如,现在有这样的一个类:

package com.alibaba.cloud.ai.toolcall.component;import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;/*** 如果要使用之前编写好的类的方法,不想修改源代码,* 可以使用 MethodToolCallBack 定义方法工具。** 比如,现在有这样的一个类*/
public class TimeToolsMethodToolCallBack {public String getTimeByZoneId(String zoneId) {
//        当前方法工具不支持以下类型的参数和返回类型:
//
//        Optional
//        异步类型(CompletableFuture、Future)
//        响应式类型(Flow、Mono、Flux)
//        函数类型(Function、Supplier、Consumer)ZoneId zid = ZoneId.of(zoneId);ZonedDateTime zonedDateTime = ZonedDateTime.now(zid);DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");return zonedDateTime.format(formatter);}
}

通过 MethodToolCallBack.Builder 定义方法工具:

    String inputSchema = """{"$schema" : "https://json-schema.org/draft/2020-12/schema","type" : "object","properties" : {"zoneId" : {"type" : "string","description" : "Time zone id, such as Asia/Shanghai"}},"required" : [ "zoneId" ],"additionalProperties" : false}""";Method method = ReflectionUtils.findMethod(TimeToolsMethodToolCallBack.class, "getTimeByZoneId", String.class);if (method == null) {throw new RuntimeException("Method not found");}MethodToolCallback toolCallback = MethodToolCallback.builder().toolDefinition(ToolDefinition.builder().description("Get time by zone id").name("getTimeByZoneId").inputSchema(inputSchema).build()).toolMethod(method).toolObject(new TimeToolsMethodToolCallBack()).build();

可以使用 JsonSchemaGenerator.generateForMethodInput(method) 方法获取 Input Schema。但如果原方法的参数没有 @ToolParam 或者 @JsonPropertyDescription 注解,则会缺失参数的 description 字段,因此建议可以用该方法生成一个模板,然后填充参数的 description 字段。

在调用 ChatClient 时,通过.toolCallbacks() 传递 MethodToolCallBack 对象,或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 方法传递工具对象:

String response = chatClient.prompt("获取北京时间").toolCallbacks(toolCallback).call().content();

函数工具

开发者可以把任意实现 Function 接口的对象,定义为 Bean ,并通过 .toolNames() 或 .defaultToolNames() 传递给 ChatClient 对象。

例如有这么一个实现了Function 接口的类:

package com.alibaba.cloud.ai.toolcall.function;import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.function.Function;public class TimeFunction implementsFunction<TimeFunction.Request, TimeFunction.Response> {@JsonClassDescription("Request to get time by zone id")public record Request(@JsonProperty(required = true, value = "zoneId")@JsonPropertyDescription("Time zone id, such as Asia/Shanghai") String zoneId) {}@JsonClassDescription("Response to get time by zone id")public record Response(@JsonPropertyDescription("time") String time) {}@Overridepublic Response apply(Request request) {ZoneId zid = ZoneId.of(request.zoneId());ZonedDateTime zonedDateTime = ZonedDateTime.now(zid);DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");return new Response(zonedDateTime.format(formatter));}
}

将该类的对象定义为 Bean:

package com.alibaba.cloud.ai.toolcall.config;import com.alibaba.cloud.ai.toolcall.function.TimeFunction;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;@Configuration
public class TimeFunctionAutoConfiguration {@Bean@Description("Get time by zone id")public TimeFunction getTimeByZoneId() {return new TimeFunction();}
}

在调用 ChatClient 时,通过.toolNames() 传递函数工具的 Bean 名称,或者在实例化 ChatClient 对象的时候通过 .defalutToolNames() 方法传递函数工具:

String response = chatClient.prompt("获取北京时间").toolNames("getTimeByZoneId").call().content();

controller代码

/** Copyright 2024-2025 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.cloud.ai.toolcall.controller;import com.alibaba.cloud.ai.toolcall.component.TimeTools;
import com.alibaba.cloud.ai.toolcall.component.TimeToolsMethodToolCallBack;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.ai.tool.method.MethodToolCallback;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.lang.reflect.Method;@RestController
public class TimeController {private final ChatClient dashScopeChatClient;private final TimeTools timeTools;public TimeController(ChatClient chatClient, TimeTools timeTools) {this.dashScopeChatClient = chatClient;this.timeTools = timeTools;}/*** No Tool*/@GetMapping("/time/chat")public String simpleChat(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {return dashScopeChatClient.prompt(query).call().content();}/*** Methods as Tools*/@GetMapping("/time/chat-tool-method")public String chatWithTimeFunction(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        在调用 ChatClient 时,通过 .tools() 方法传递工具对象
//        ,或者在实例化 ChatClient 对象的时候通过 .defalutTools() 方法传递工具对象:return dashScopeChatClient.prompt(query).tools(timeTools).call().content();}/*** Methods as Tools*/@GetMapping("/time/timeToolsMethodToolCallBack")public String timeToolsMethodToolCallBack(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {
//        通过 MethodToolCallBack.Builder 定义方法工具:String inputSchema = """{"$schema" : "https://json-schema.org/draft/2020-12/schema","type" : "object","properties" : {"zoneId" : {"type" : "string","description" : "Time zone id, such as Asia/Shanghai"}},"required" : [ "zoneId" ],"additionalProperties" : false}""";Method method = ReflectionUtils.findMethod(TimeToolsMethodToolCallBack.class, "getTimeByZoneId", String.class);if (method == null) {throw new RuntimeException("Method not found");}MethodToolCallback toolCallback = MethodToolCallback.builder().toolDefinition(ToolDefinition.builder().description("Get time by zone id").name("getTimeByZoneId").inputSchema(inputSchema).build()).toolMethod(method).toolObject(new TimeToolsMethodToolCallBack()).build();
//        可以使用 JsonSchemaGenerator.generateForMethodInput(method) 方法获取 Input Schema。
//        但如果原方法的参数没有 @ToolParam 或者 @JsonPropertyDescription 注解,则会缺失参数的 description 字段,
//        因此建议可以用该方法生成一个模板,然后填充参数的 description 字段。
//
//        在调用 ChatClient 时,通过.toolCallbacks() 传递 MethodToolCallBack 对象,
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 方法传递工具对象:return dashScopeChatClient.prompt(query).toolCallbacks(toolCallback).call().content();}@GetMapping("/time/function")public String function(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        在调用 ChatClient 时,通过.toolNames() 传递函数工具的 Bean 名称,
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolNames() 方法传递函数工具:return dashScopeChatClient.prompt(query).toolNames("getTimeByZoneId").call().content();}}

开发者也可以不用定义 Bean,直接定义 FunctionToolCallBack 对象,在调用 ChatClient 时通过 .toolCallBacks() 或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 传递 FunctionToolCallBack 对象:

示例如下 TimeFunction2 

package com.alibaba.cloud.ai.toolcall.function;import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.function.Function;public class TimeFunction2 implementsFunction<TimeFunction2.Request, TimeFunction2.Response> {@JsonClassDescription("Request to get time by zone id")public record Request(@JsonProperty(required = true, value = "zoneId")@JsonPropertyDescription("Time zone id, such as Asia/Shanghai") String zoneId) {}@JsonClassDescription("Response to get time by zone id")public record Response(@JsonPropertyDescription("time") String time) {}@Overridepublic Response apply(Request request) {ZoneId zid = ZoneId.of(request.zoneId());ZonedDateTime zonedDateTime = ZonedDateTime.now(zid);DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");return new Response(zonedDateTime.format(formatter));}
}

    @GetMapping("/time/function2")public String function2(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        开发者也可以不用定义 Bean,直接定义 FunctionToolCallBack 对象,在调用 ChatClient 时通过 .toolCallBacks() 
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 传递 FunctionToolCallBack 对象:String response = dashScopeChatClient.prompt(query).toolCallbacks(FunctionToolCallback.builder("getTimeByZoneId", new TimeFunction2()).description("Get time by zone id").inputType(TimeFunction2.Request.class).build()).call().content();return response;}

请求controller

/** Copyright 2024-2025 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.cloud.ai.toolcall.controller;import com.alibaba.cloud.ai.toolcall.component.TimeTools;
import com.alibaba.cloud.ai.toolcall.component.TimeToolsMethodToolCallBack;
import com.alibaba.cloud.ai.toolcall.function.TimeFunction2;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.ai.tool.method.MethodToolCallback;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.lang.reflect.Method;@RestController
public class TimeController {private final ChatClient dashScopeChatClient;private final TimeTools timeTools;public TimeController(ChatClient chatClient, TimeTools timeTools) {this.dashScopeChatClient = chatClient;this.timeTools = timeTools;}/*** No Tool*/@GetMapping("/time/chat")public String simpleChat(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {return dashScopeChatClient.prompt(query).call().content();}/*** Methods as Tools*/@GetMapping("/time/chat-tool-method")public String chatWithTimeFunction(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        在调用 ChatClient 时,通过 .tools() 方法传递工具对象
//        ,或者在实例化 ChatClient 对象的时候通过 .defalutTools() 方法传递工具对象:return dashScopeChatClient.prompt(query).tools(timeTools).call().content();}/*** Methods as Tools*/@GetMapping("/time/timeToolsMethodToolCallBack")public String timeToolsMethodToolCallBack(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {
//        通过 MethodToolCallBack.Builder 定义方法工具:String inputSchema = """{"$schema" : "https://json-schema.org/draft/2020-12/schema","type" : "object","properties" : {"zoneId" : {"type" : "string","description" : "Time zone id, such as Asia/Shanghai"}},"required" : [ "zoneId" ],"additionalProperties" : false}""";Method method = ReflectionUtils.findMethod(TimeToolsMethodToolCallBack.class, "getTimeByZoneId", String.class);if (method == null) {throw new RuntimeException("Method not found");}MethodToolCallback toolCallback = MethodToolCallback.builder().toolDefinition(ToolDefinition.builder().description("Get time by zone id").name("getTimeByZoneId").inputSchema(inputSchema).build()).toolMethod(method).toolObject(new TimeToolsMethodToolCallBack()).build();
//        可以使用 JsonSchemaGenerator.generateForMethodInput(method) 方法获取 Input Schema。
//        但如果原方法的参数没有 @ToolParam 或者 @JsonPropertyDescription 注解,则会缺失参数的 description 字段,
//        因此建议可以用该方法生成一个模板,然后填充参数的 description 字段。
//
//        在调用 ChatClient 时,通过.toolCallbacks() 传递 MethodToolCallBack 对象,
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 方法传递工具对象:return dashScopeChatClient.prompt(query).toolCallbacks(toolCallback).call().content();}@GetMapping("/time/function")public String function(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        在调用 ChatClient 时,通过.toolNames() 传递函数工具的 Bean 名称,
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolNames() 方法传递函数工具:return dashScopeChatClient.prompt(query).toolNames("getTimeByZoneId").call().content();}@GetMapping("/time/function2")public String function2(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        开发者也可以不用定义 Bean,直接定义 FunctionToolCallBack 对象,在调用 ChatClient 时通过 .toolCallBacks()
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 传递 FunctionToolCallBack 对象:String response = dashScopeChatClient.prompt(query).toolCallbacks(FunctionToolCallback.builder("getTimeByZoneId", new TimeFunction2()).description("Get time by zone id").inputType(TimeFunction2.Request.class).build()).call().content();return response;}}

pom

<?xml version="1.0" encoding="UTF-8"?><!--Copyright 2023-2024 the original author or authors.Licensed under the Apache License, Version 2.0 (the "License");you may not use this file except in compliance with the License.You may obtain a copy of the License athttps://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.
--><project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://maven.apache.org/POM/4.0.0"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-examples</artifactId><version>${revision}</version><relativePath>../pom.xml</relativePath></parent><version>${revision}</version><artifactId>spring-ai-alibaba-tool-calling-demo</artifactId><description>Spring AI Alibaba Tool Calling Example</description><name>Spring AI Alibaba Tool Calling Examples</name><properties><junit-jupiter.version>5.10.0</junit-jupiter.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-dashscope</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-tool-calling-baidutranslate</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-tool-calling-weather</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-tool-calling-baidumap</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-tool-calling-time</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-tool-calling-githubtoolkit</artifactId></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>${junit-jupiter.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-deploy-plugin</artifactId><version>${maven-deploy-plugin.version}</version><configuration><skip>true</skip></configuration></plugin></plugins></build></project>

工具上下文

Spring AI 支持通过 ToolContext API 向工具传递额外的上下文信息。该特性允许提供补充数据,比如用户身份信息。这些数据将与 AI 模型传递的工具参数结合使用。

public class UserInfoTools {@Tool(description = "get current user name")public String getUserName(ToolContext context) {String userId = context.getContext().get("userId").toString();if (!StringUtils.hasText(userId)) {return "null";}// 模拟数据return userId + "user";}
}

在调用 ChatClient 时,通过 .toolContext() 方法传递工具上下文:

String response = chatClient.prompt("获取我的用户名").tools(new UserInfoTools()).toolContext(Map.of("userId", "12345")).call().content();

controller

/** Copyright 2024-2025 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.cloud.ai.toolcall.controller;import com.alibaba.cloud.ai.toolcall.component.TimeTools;
import com.alibaba.cloud.ai.toolcall.component.TimeToolsMethodToolCallBack;
import com.alibaba.cloud.ai.toolcall.component.UserInfoTools;
import com.alibaba.cloud.ai.toolcall.function.TimeFunction2;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.ai.tool.method.MethodToolCallback;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.lang.reflect.Method;
import java.util.Map;@RestController
public class TimeController {private final ChatClient dashScopeChatClient;private final TimeTools timeTools;public TimeController(ChatClient chatClient, TimeTools timeTools) {this.dashScopeChatClient = chatClient;this.timeTools = timeTools;}/*** No Tool*/@GetMapping("/time/chat")public String simpleChat(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {return dashScopeChatClient.prompt(query).call().content();}/*** Methods as Tools*/@GetMapping("/time/chat-tool-method")public String chatWithTimeFunction(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        在调用 ChatClient 时,通过 .tools() 方法传递工具对象
//        ,或者在实例化 ChatClient 对象的时候通过 .defalutTools() 方法传递工具对象:return dashScopeChatClient.prompt(query).tools(timeTools).call().content();}/*** Methods as Tools*/@GetMapping("/time/timeToolsMethodToolCallBack")public String timeToolsMethodToolCallBack(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {
//        通过 MethodToolCallBack.Builder 定义方法工具:String inputSchema = """{"$schema" : "https://json-schema.org/draft/2020-12/schema","type" : "object","properties" : {"zoneId" : {"type" : "string","description" : "Time zone id, such as Asia/Shanghai"}},"required" : [ "zoneId" ],"additionalProperties" : false}""";Method method = ReflectionUtils.findMethod(TimeToolsMethodToolCallBack.class, "getTimeByZoneId", String.class);if (method == null) {throw new RuntimeException("Method not found");}MethodToolCallback toolCallback = MethodToolCallback.builder().toolDefinition(ToolDefinition.builder().description("Get time by zone id").name("getTimeByZoneId").inputSchema(inputSchema).build()).toolMethod(method).toolObject(new TimeToolsMethodToolCallBack()).build();
//        可以使用 JsonSchemaGenerator.generateForMethodInput(method) 方法获取 Input Schema。
//        但如果原方法的参数没有 @ToolParam 或者 @JsonPropertyDescription 注解,则会缺失参数的 description 字段,
//        因此建议可以用该方法生成一个模板,然后填充参数的 description 字段。
//
//        在调用 ChatClient 时,通过.toolCallbacks() 传递 MethodToolCallBack 对象,
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 方法传递工具对象:return dashScopeChatClient.prompt(query).toolCallbacks(toolCallback).call().content();}@GetMapping("/time/function")public String function(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        在调用 ChatClient 时,通过.toolNames() 传递函数工具的 Bean 名称,
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolNames() 方法传递函数工具:return dashScopeChatClient.prompt(query).toolNames("getTimeByZoneId").call().content();}@GetMapping("/time/function2")public String function2(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        开发者也可以不用定义 Bean,直接定义 FunctionToolCallBack 对象,在调用 ChatClient 时通过 .toolCallBacks()
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 传递 FunctionToolCallBack 对象:String response = dashScopeChatClient.prompt(query).toolCallbacks(FunctionToolCallback.builder("getTimeByZoneId", new TimeFunction2()).description("Get time by zone id").inputType(TimeFunction2.Request.class).build()).call().content();return response;}@GetMapping("/time/user")public String user() {String response = dashScopeChatClient.prompt("获取我的用户名").tools(new UserInfoTools()).toolContext(Map.of("userId", "12345")).call().content();return response;}}

工具调用直接返回

默认情况下,工具调用的返回值会再次回传到 AI 模型进一步处理。但在一些场景中需要将结果直接返回给调用方而非模型,比如数据搜索。

定义方法工具时,可以通过 @Tool 注解的 returnDirect 参数置 true 来启动直接返回;定义方法工具和函数工具时需要通过 ToolMetadata 对象传递到 MethodToolCallBack.Builder 和 FunctionToolCallBack.Builder中。

以工具调用定义中的 TimeFunction 为例,演示代码:

String response = chatClient.prompt("获取北京时间").toolCallbacks(FunctionToolCallback.builder("getTimeByZoneId", new TimeFunction()).toolMetadata(ToolMetadata.builder().returnDirect(true).build()).description("Get time by zone id").inputType(TimeFunction.Request.class).build()).call().content();

调用这段代码将直接返回 TimeFunction 返回的JSON对象,而不再经过大模型加工处理。

controller代码

/** Copyright 2024-2025 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.cloud.ai.toolcall.controller;import com.alibaba.cloud.ai.toolcall.component.TimeTools;
import com.alibaba.cloud.ai.toolcall.component.TimeToolsMethodToolCallBack;
import com.alibaba.cloud.ai.toolcall.component.UserInfoTools;
import com.alibaba.cloud.ai.toolcall.function.TimeFunction;
import com.alibaba.cloud.ai.toolcall.function.TimeFunction2;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.ai.tool.metadata.ToolMetadata;
import org.springframework.ai.tool.method.MethodToolCallback;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.lang.reflect.Method;
import java.util.Map;@RestController
public class TimeController {private final ChatClient dashScopeChatClient;private final TimeTools timeTools;public TimeController(ChatClient chatClient, TimeTools timeTools) {this.dashScopeChatClient = chatClient;this.timeTools = timeTools;}/*** No Tool*/@GetMapping("/time/chat")public String simpleChat(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {return dashScopeChatClient.prompt(query).call().content();}/*** Methods as Tools*/@GetMapping("/time/chat-tool-method")public String chatWithTimeFunction(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        在调用 ChatClient 时,通过 .tools() 方法传递工具对象
//        ,或者在实例化 ChatClient 对象的时候通过 .defalutTools() 方法传递工具对象:return dashScopeChatClient.prompt(query).tools(timeTools).call().content();}/*** Methods as Tools*/@GetMapping("/time/timeToolsMethodToolCallBack")public String timeToolsMethodToolCallBack(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {
//        通过 MethodToolCallBack.Builder 定义方法工具:String inputSchema = """{"$schema" : "https://json-schema.org/draft/2020-12/schema","type" : "object","properties" : {"zoneId" : {"type" : "string","description" : "Time zone id, such as Asia/Shanghai"}},"required" : [ "zoneId" ],"additionalProperties" : false}""";Method method = ReflectionUtils.findMethod(TimeToolsMethodToolCallBack.class, "getTimeByZoneId", String.class);if (method == null) {throw new RuntimeException("Method not found");}MethodToolCallback toolCallback = MethodToolCallback.builder().toolDefinition(ToolDefinition.builder().description("Get time by zone id").name("getTimeByZoneId").inputSchema(inputSchema).build()).toolMethod(method).toolObject(new TimeToolsMethodToolCallBack()).build();
//        可以使用 JsonSchemaGenerator.generateForMethodInput(method) 方法获取 Input Schema。
//        但如果原方法的参数没有 @ToolParam 或者 @JsonPropertyDescription 注解,则会缺失参数的 description 字段,
//        因此建议可以用该方法生成一个模板,然后填充参数的 description 字段。
//
//        在调用 ChatClient 时,通过.toolCallbacks() 传递 MethodToolCallBack 对象,
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 方法传递工具对象:return dashScopeChatClient.prompt(query).toolCallbacks(toolCallback).call().content();}@GetMapping("/time/function")public String function(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        在调用 ChatClient 时,通过.toolNames() 传递函数工具的 Bean 名称,
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolNames() 方法传递函数工具:return dashScopeChatClient.prompt(query).toolNames("getTimeByZoneId").call().content();}@GetMapping("/time/function2")public String function2(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {//        开发者也可以不用定义 Bean,直接定义 FunctionToolCallBack 对象,在调用 ChatClient 时通过 .toolCallBacks()
//        或者在实例化 ChatClient 对象的时候通过 .defalutToolCallBacks() 传递 FunctionToolCallBack 对象:String response = dashScopeChatClient.prompt(query).toolCallbacks(FunctionToolCallback.builder("getTimeByZoneId", new TimeFunction2()).description("Get time by zone id").inputType(TimeFunction2.Request.class).build()).call().content();return response;}@GetMapping("/time/user")public String user() {String response = dashScopeChatClient.prompt("获取我的用户名").tools(new UserInfoTools()).toolContext(Map.of("userId", "12345")).call().content();return response;}@GetMapping("/time/function3")public String function3() {String response = dashScopeChatClient.prompt("获取北京时间").toolCallbacks(FunctionToolCallback.builder("getTimeByZoneId", new TimeFunction()).toolMetadata(ToolMetadata.builder().returnDirect(true).build()).description("Get time by zone id").inputType(TimeFunction.Request.class).build()).call().content();return response;}}

 

http://www.dtcms.com/wzjs/402530.html

相关文章:

  • 做视频网站 投入国际新闻网站
  • 网站开发公司云鲸互创怎么联系网站收录批量查询
  • 有哪个理财网站是专门做汽车抵押的淘宝seo排名优化软件
  • 蓝色系网站全自动引流推广软件免费
  • 做网站需要哪类商标搜索引擎优化工具有哪些
  • 成都网站海口网站建设百度搜索引擎优化的养成良好心态
  • 服务器与网站安徽做网站公司哪家好
  • 北京seo推广公司网站seo在线诊断分析
  • 南昌建设局网站查询塔吊证外链信息
  • 南昌做建网站的搜索引擎优化排名案例
  • 做便民工具网站如何在google上免费推广
  • 微信小程序可以做电影网站吗三只松鼠营销策划书
  • wordpress电影资讯wp博客seo插件
  • 网络宣传网站建设建站迅雷磁力链bt磁力天堂下载
  • 网站建设 更新 维护知名做网站的公司
  • 做网站属于什么专业国际新闻最新消息10条
  • 公司注册地址可以是家庭地址吗系统优化大师免费版
  • 无锡短视频seoseo教程seo教程
  • 安徽餐饮网站建设漳州网络推广
  • 做美食的视频网站怎么提高百度关键词排名
  • 网站制作3种csswindows7优化大师
  • 台州公司网站建设公司想建个网站怎么弄
  • 邯郸网站制作个人网站做成app
  • 东莞东城区疫情最新消息seo指导
  • 做水晶接单在哪个网站接软文标题
  • 广州网站建设讯度下载app到手机上并安装
  • 做简易动画的网站域名注册查询入口
  • 专门做杂志的网站百度官网认证申请
  • 有哪些网站可以做海报设计知乎安徽网站建设优化推广
  • 建设企业网站新闻开发的意义百度如何优化排名靠前