编程边界突破:当AI能听懂你的需求时…
前沿
大模型如同人类大脑,擅长理解与决策,却需要‘肢体’来执行行动。LangChain4j的Tools机制,正是为AI打造的‘智能四肢’,将语言指令转化为实际解决方案。
大模型的不足
大模型的答案本质是概率预测,而非实时检索。时间敏感问题(如‘今天日期’)可能出错,因为它的‘知识库’尚未包含此时此刻的信息。问它‘今天几号?’,它只能推测,因为它还没‘经历’今天。",或者当前所在地都一无所知
一句话 大模型的训练数据是静态的,无法获取最新信息。
public static void main(String[] args) {String apiKey = "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";StreamingChatLanguageModel model = OpenAiStreamingChatModel.builder().apiKey(apiKey).modelName("gpt-4o-mini").httpClientBuilder(new SpringRestClientBuilder()).build();model.chat("我这是哪里,今天几月几号,天气怎么样", new StreamingChatResponseHandler() {@Overridepublic void onPartialResponse(String s) {System.out.print(s);}@Overridepublic void onCompleteResponse(ChatResponse chatResponse) {System.out.println("\n----------------全部完成输出如下------------------------");System.out.print(chatResponse.aiMessage().text());}@Overridepublic void onError(Throwable throwable) {System.out.print(throwable.getMessage());}});try {TimeUnit.SECONDS.sleep(60);} catch (InterruptedException e) {e.printStackTrace();}}
执行结果如下:
抱歉,我无法实时获取位置信息、日期或天气情况。你可以通过手机或电脑上的天气应用、搜索引擎或地图服务来获取这些信息。如果你需要了解某个特定地方的天气或其他信息,请告诉我,我会尽力提供相关的建议或信息。
多执行几次,每次执行结果很有可能不一样,所以如果要求大模型处理实时的问题,它就无能为力了。
因此,我们扩展一下,出现这种情况的原因是ChatGPT是基于历史数据来进行预测的,它没办法拿到当前最新的数据,比如说时间、地方,从而限制了它的进一步使用,那么LangChain4j的Tools机制就能够帮助大模型来获取当前最新的数据,从而解决上述时间相关的问题。
ToolSpecification
首先需要定义一个工具,其实就是一个方法,用来返回当前日期,当前城市,当前日期和城市的实时天气,并且通过@Tool注解来描述该工具,从而使得大模型在需要获取当前时间时能够调用该工具方法得到当前时间:
static class ToolsContext{@Tool("获取当前日期")public static String dateUtil(){System.out.println("获取当前日期");return LocalDateTime.now().toString();}@Tool("获取当前城市")public static String currLocation() throws IOException {System.out.println("============获取当前城市");String publicIP = IPUtils.getPublicIP();String result= Objects.requireNonNull(getCityFromIP(publicIP)).get("city").getAsString();System.out.println("城市信息:"+result);return result;}@Tool("获取当前位置经纬度")public static String currLatAndLon() throws IOException {System.out.println("获取经纬度");String publicIP = IPUtils.getPublicIP();JsonObject obj = getCityFromIP(publicIP);assert obj != null;return obj.get("lat").getAsString()+","+obj.get("lon").getAsString();}@Tool("根据当前城市信息获取当前城市编号")public static String currCityNo(String cityInfo) throws Exception {JsonArray location = WeatherUtils.getCityData(cityInfo).get("location").getAsJsonArray();String result= location.get(0).getAsJsonObject().get("id").toString().replace("\"","");System.out.println("获取城市编号:"+result);return result;}@Tool("根据城市编号获取当前的天气")public static String currentWeather(String no) throws Exception{System.out.println("当前城市编号:"+no);String result = Objects.requireNonNull(WeatherUtils.getCurrWeatherByLocation(no)).get("now").toString();System.out.println("当地天气:"+result);result +="""返回参数说明obsTime 数据观测时间temp 温度,默认单位:摄氏度feelsLike 体感温度,默认单位:摄氏度icon 天气状况的图标代码,另请参考天气图标项目text 天气状况的文字描述,包括阴晴雨雪等天气状态的描述wind360 风向360角度windDir 风向windScale 风力等级windSpeed 风速,公里/小时humidity 相对湿度,百分比数值precip 过去1小时降水量,默认单位:毫米pressure 大气压强,默认单位:百帕vis 能见度,默认单位:公里cloud 云量,百分比数值""";return result;}}
然后将工具方法转成ToolSpecification对象,并传递给大模型:
注 无论 deepseek 还是openai 都是可以的 代码不用修改 ,除了模型名和baseUrl 按照不同模型配置 其它不动
package com.example;import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.agent.tool.ToolSpecifications;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.http.client.spring.restclient.SpringRestClientBuilder;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.service.AiServices;import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;import static com.example.IPLocation.getCityFromIP;
import static dev.langchain4j.model.openai.OpenAiChatModelName.*;public class ToolsDemo1 {static class ToolsContext{@Tool("获取当前日期")public static String dateUtil(){System.out.println("获取当前日期");return LocalDateTime.now().toString();}@Tool("获取当前城市")public static String currLocation() throws IOException {System.out.println("============获取当前城市");String publicIP = IPUtils.getPublicIP();String result= Objects.requireNonNull(getCityFromIP(publicIP)).get("city").getAsString();System.out.println("城市信息:"+result);return result;}@Tool("获取当前位置经纬度")public static String currLatAndLon() throws IOException {System.out.println("获取经纬度");String publicIP = IPUtils.getPublicIP();JsonObject obj = getCityFromIP(publicIP);assert obj != null;return obj.get("lat").getAsString()+","+obj.get("lon").getAsString();}@Tool("根据当前城市信息获取当前城市编号")public static String currCityNo(String cityInfo) throws Exception {JsonArray location = WeatherUtils.getCityData(cityInfo).get("location").getAsJsonArray();String result= location.get(0).getAsJsonObject().get("id").toString().replace("\"","");System.out.println("获取城市编号:"+result);return result;}@Tool("根据城市编号获取当前的天气")public static String currentWeather(String no) throws Exception{System.out.println("当前城市编号:"+no);String result = Objects.requireNonNull(WeatherUtils.getCurrWeatherByLocation(no)).get("now").toString();System.out.println("当地天气:"+result);result +="""返回参数说明obsTime 数据观测时间temp 温度,默认单位:摄氏度feelsLike 体感温度,默认单位:摄氏度icon 天气状况的图标代码,另请参考天气图标项目text 天气状况的文字描述,包括阴晴雨雪等天气状态的描述wind360 风向360角度windDir 风向windScale 风力等级windSpeed 风速,公里/小时humidity 相对湿度,百分比数值precip 过去1小时降水量,默认单位:毫米pressure 大气压强,默认单位:百帕vis 能见度,默认单位:公里cloud 云量,百分比数值""";return result;}}interface Assistant {String chat(String userMessage);}public static void main(String[] args) throws NoSuchMethodException {String apiKey = System.getenv("DEEPSEEK_API_KEY");ChatLanguageModel model = OpenAiChatModel.builder().apiKey(apiKey).baseUrl("https://api.deepseek.com/v1").modelName("deepseek-chat").httpClientBuilder(new SpringRestClientBuilder()).strictTools(true) // https://docs.langchain4j.dev/integrations/language-models/open-ai#structured-outputs-for-tools.build();Assistant assistant = AiServices.builder(Assistant.class).chatLanguageModel(model).tools(new ToolsContext()).chatMemory(MessageWindowChatMemory.withMaxMessages(10)).build();String question = "今年几月几号,我所在的城市是?? 天气如何?";String answer = assistant.chat(question);System.out.println(answer);}}
运行结果:
dev.langchain4j.service.tool.DefaultToolExecutor.execute()
DEBUG: About to execute ToolExecutionRequest { id = "call_0_0f705d5c-5859-4aac-bc21-2e199bd534e0", name = "dateUtil", arguments = "{}" } for memoryId default
获取当前日期
2025-06-05 11:01:04 [main] dev.langchain4j.service.tool.DefaultToolExecutor.execute()
DEBUG: Tool execution result: 2025-06-05T11:01:04.489845700
2025-06-05 11:01:04 [main] dev.langchain4j.service.tool.DefaultToolExecutor.execute()
DEBUG: About to execute ToolExecutionRequest { id = "call_1_1803c476-9972-4549-9525-603e683cddcf", name = "currLocation", arguments = "{}" } for memoryId default
============获取当前城市
{"status":"success","country":"China","countryCode":"CN","region":"CQ","regionName":"Chongqing","city":"Chongqing","zip":"","lat":29.5689,"lon":106.5577,"timezone":"Asia/Shanghai","isp":"China Mobile","org":"China Mobile Communications Corporation","as":"AS9808 China Mobile Communications Group Co., Ltd.","query":"183.226.61.121"}
城市信息:Chongqing
2025-06-05 11:01:05 [main] dev.langchain4j.service.tool.DefaultToolExecutor.execute()
DEBUG: Tool execution result: Chongqing
2025-06-05 11:01:11 [main] io.micrometer.observation.SimpleObservation$SimpleScope.close()
TRACE: NoOp observation used with SimpleScope
2025-06-05 11:01:11 [main] dev.langchain4j.service.tool.DefaultToolExecutor.execute()
DEBUG: About to execute ToolExecutionRequest { id = "call_0_087d4e0d-38d2-4687-8698-b6a3dc58746e", name = "currCityNo", arguments = "{"cityInfo":"Chongqing"}" } for memoryId default
https://hu3dn53293.re.qweatherapi.com/geo/v2/city/lookup?number=1&location=Chongqing
{"code":"200","location":[{"name":"重庆","id":"101040100","lat":"29.56376","lon":"106.55046","adm2":"重庆","adm1":"重庆市","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"11","fxLink":"https://www.qweather.com/weather/chongqing-101040100.html"}],"refer":{"sources":["QWeather"],"license":["QWeather Developers License"]}}
获取城市编号:101040100
2025-06-05 11:01:11 [main] dev.langchain4j.service.tool.DefaultToolExecutor.execute()
DEBUG: Tool execution result: 101040100
2025-06-05 11:01:16 [main] io.micrometer.observation.SimpleObservation$SimpleScope.close()
TRACE: NoOp observation used with SimpleScope
2025-06-05 11:01:16 [main] dev.langchain4j.service.tool.DefaultToolExecutor.execute()
DEBUG: About to execute ToolExecutionRequest { id = "call_0_ffb7eee3-3222-4d81-90c4-1acddb9e95ec", name = "currentWeather", arguments = "{"no":"101040100"}" } for memoryId default
当前城市编号:101040100
https://hu3dn53293.re.qweatherapi.com/v7/weather/now?location=101040100
当地天气:{"obsTime":"2025-06-05T10:56+08:00","temp":"30","feelsLike":"31","icon":"101","text":"多云","wind360":"315","windDir":"西北风","windScale":"3","windSpeed":"12","humidity":"58","precip":"0.0","pressure":"976","vis":"11","cloud":"91","dew":"19"}
2025-06-05 11:01:16 [main] dev.langchain4j.service.tool.DefaultToolExecutor.execute()
DEBUG: Tool execution result: {"obsTime":"2025-06-05T10:56+08:00","temp":"30","feelsLike":"31","icon":"101","text":"多云","wind360":"315","windDir":"西北风","windScale":"3","windSpeed":"12","humidity":"58","precip":"0.0","pressure":"976","vis":"11","cloud":"91","dew":"19"}返回参数说明obsTime 数据观测时间
temp 温度,默认单位:摄氏度
feelsLike 体感温度,默认单位:摄氏度
icon 天气状况的图标代码,另请参考天气图标项目
text 天气状况的文字描述,包括阴晴雨雪等天气状态的描述
wind360 风向360角度
windDir 风向
windScale 风力等级
windSpeed 风速,公里/小时
humidity 相对湿度,百分比数值
precip 过去1小时降水量,默认单位:毫米
pressure 大气压强,默认单位:百帕
vis 能见度,默认单位:公里
cloud 云量,百分比数值2025-06-05 11:01:25 [main] io.micrometer.observation.SimpleObservation$SimpleScope.close()
TRACE: NoOp observation used with SimpleScope
今天是2025年6月5日,您所在的城市是重庆。当前天气情况如下:
- **天气状况**:多云
- **温度**:30°C
- **体感温度**:31°C
- **风向**:西北风
- **风力等级**:3级
- **风速**:12公里/小时
- **相对湿度**:58%
- **降水量**:0.0毫米
- **大气压强**:976百帕
- **能见度**:11公里
- **云量**:91%数据观测时间为今天上午10:56。Process finished with exit code 0
所以,一个ToolSpecification对象就代表一个工具,当用户把要问题UserMessage和工具ToolSpecification一起传递给大模型,大模型就知道要结合工具描述来解决用户的问题,此时大模型响应的AiMessage不再是一串文本,而是:
2025-06-05 11:13:36 [main] dev.langchain4j.http.client.log.HttpRequestLogger.log()
DEBUG: HTTP request:
- method: POST
- url: https://api.deepseek.com/v1/chat/completions
- headers: [Authorization: Beare...5f], [User-Agent: langchain4j-openai], [Content-Type: application/json]
- body: {"model" : "deepseek-chat","messages" : [ {"role" : "user","content" : "今年几月几号,我所在的城市是?? 天气如何?"} ],"stream" : false,"tools" : [ {"type" : "function","function" : {"name" : "currLatAndLon","description" : "获取当前位置经纬度","strict" : true,"parameters" : {"type" : "object","properties" : { },"required" : [ ],"additionalProperties" : false}}}, {"type" : "function","function" : {"name" : "currLocation","description" : "获取当前城市","strict" : true,"parameters" : {"type" : "object","properties" : { },"required" : [ ],"additionalProperties" : false}}}, {"type" : "function","function" : {"name" : "dateUtil","description" : "获取当前日期","strict" : true,"parameters" : {"type" : "object","properties" : { },"required" : [ ],"additionalProperties" : false}}}, {"type" : "function","function" : {"name" : "currCityNo","description" : "根据当前城市信息获取当前城市编号","strict" : true,"parameters" : {"type" : "object","properties" : {"cityInfo" : {"type" : "string"}},"required" : [ "cityInfo" ],"additionalProperties" : false}}}, {"type" : "function","function" : {"name" : "currentWeather","description" : "根据城市编号获取当前的天气","strict" : true,"parameters" : {"type" : "object","properties" : {"no" : {"type" : "string"}},"required" : [ "no" ],"additionalProperties" : false}}} ]
}
tools,表示一个工具链执行请求,表示大模型在解决问题时,需要调用工具来解决用户的问题,由于我们可能传了多个工具给大模型,所以tools是一个List,表示为了解决用户的问题需要调用哪些工具。
所以,我们在得到了tool后,就需要取执行对应的工具方法了,其中function的name属性就是方法名,parameters就表示要传递给方法的参数值
源码分析
当使用了tools的时候,在代理对象的invoke()方法中,以下代码会去调用大模型的底层API:
ChatRequestParameters parameters = ChatRequestParameters.builder().toolSpecifications(toolExecutionContext.toolSpecifications()).responseFormat(responseFormat).build();ChatRequest chatRequest = ChatRequest.builder().messages(messages).parameters(parameters).build();
ChatResponse chatResponse = context.chatModel.chat(chatRequest);
这里tools执行了两次 第一次执行后会返回我们AI会话里面直接用到的tool请求参数,但是未返回结果 第二次执行会执行tool并返回结果 同时里面关联的其他tool也会被执行返回结果,代码如下:
//执行chat但是这时候工具并未执行 但是结果要给到下面ChatResponse chatResponse = context.chatModel.chat(chatRequest);verifyModerationIfNeeded(moderationFuture);ToolExecutionResult toolExecutionResult = context.toolService.executeInferenceAndToolsLoop(//chatResponse,parameters,messages,context.chatModel,chatMemory,memoryId,toolExecutionContext.toolExecutors());chatResponse = toolExecutionResult.chatResponse();
依次为:用户的问题、第一次工具执行请求和结果、第二次工具执行请求和结果
package dev.langchain4j.service.tool;import static dev.langchain4j.agent.tool.ToolSpecifications.toolSpecificationFrom;
import static dev.langchain4j.internal.Exceptions.runtime;
import static dev.langchain4j.service.IllegalConfigurationException.illegalConfiguration;import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolExecutionRequest;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.ToolExecutionResultMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.model.chat.request.ChatRequestParameters;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.output.TokenUsage;
import dev.langchain4j.service.IllegalConfigurationException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;/*** 工具服务类,用于管理和执行AI工具*/
public class ToolService {// 工具规格列表private final List<ToolSpecification> toolSpecifications = new ArrayList<>();// 工具执行器映射表(工具名称 -> 执行器)private final Map<String, ToolExecutor> toolExecutors = new HashMap<>();// 工具提供者private ToolProvider toolProvider;// 最大连续工具调用次数private int maxSequentialToolsInvocations = 100;// 工具幻觉策略(当AI请求不存在的工具时的处理策略)private Function<ToolExecutionRequest, ToolExecutionResultMessage> toolHallucinationStrategy =HallucinatedToolNameStrategy.THROW_EXCEPTION;/*** 设置工具幻觉策略*/public void hallucinatedToolNameStrategy(Function<ToolExecutionRequest, ToolExecutionResultMessage> toolHallucinationStrategy) {this.toolHallucinationStrategy = toolHallucinationStrategy;}/*** 设置工具提供者*/public void toolProvider(ToolProvider toolProvider) {this.toolProvider = toolProvider;}/*** 添加工具集合*/public void tools(Map<ToolSpecification, ToolExecutor> tools) {tools.forEach((toolSpecification, toolExecutor) -> {toolSpecifications.add(toolSpecification);toolExecutors.put(toolSpecification.name(), toolExecutor);});}/*** 从带有@Tool注解的对象中添加工具*/public void tools(Collection<Object> objectsWithTools) {for (Object objectWithTool : objectsWithTools) {if (objectWithTool instanceof Class) {throw illegalConfiguration("Tool '%s' must be an object, not a class", objectWithTool);}// 扫描对象中的所有方法,查找带有@Tool注解的方法for (Method method : objectWithTool.getClass().getDeclaredMethods()) {if (method.isAnnotationPresent(Tool.class)) {ToolSpecification toolSpecification = toolSpecificationFrom(method);if (toolExecutors.containsKey(toolSpecification.name())) {throw new IllegalConfigurationException("Duplicated definition for tool: " + toolSpecification.name());}// 为每个工具方法创建执行器toolExecutors.put(toolSpecification.name(), new DefaultToolExecutor(objectWithTool, method));toolSpecifications.add(toolSpecificationFrom(method));}}}}/*** 设置最大连续工具调用次数*/public void maxSequentialToolsInvocations(int maxSequentialToolsInvocations) {this.maxSequentialToolsInvocations = maxSequentialToolsInvocations;}/*** 创建工具执行上下文* @param memoryId 记忆ID* @param userMessage 用户消息* @return 工具执行上下文*/public ToolExecutionContext executionContext(Object memoryId, UserMessage userMessage) {if (this.toolProvider == null) {return this.toolSpecifications.isEmpty() ?new ToolExecutionContext(null, null) :new ToolExecutionContext(this.toolSpecifications, this.toolExecutors);}// 合并默认工具和动态提供的工具List<ToolSpecification> toolsSpecs = new ArrayList<>(this.toolSpecifications);Map<String, ToolExecutor> toolExecs = new HashMap<>(this.toolExecutors);ToolProviderRequest toolProviderRequest = new ToolProviderRequest(memoryId, userMessage);ToolProviderResult toolProviderResult = toolProvider.provideTools(toolProviderRequest);if (toolProviderResult != null) {for (Map.Entry<ToolSpecification, ToolExecutor> entry :toolProviderResult.tools().entrySet()) {if (toolExecs.putIfAbsent(entry.getKey().name(), entry.getValue()) == null) {toolsSpecs.add(entry.getKey());} else {throw new IllegalConfigurationException("Duplicated definition for tool: " + entry.getKey().name());}}}return new ToolExecutionContext(toolsSpecs, toolExecs);}/*** 执行推理和工具调用的循环* @param chatResponse 初始聊天响应* @param parameters 聊天请求参数* @param messages 消息列表* @param chatModel 聊天模型* @param chatMemory 聊天记忆* @param memoryId 记忆ID* @param toolExecutors 工具执行器映射* @return 工具执行结果*/public ToolExecutionResult executeInferenceAndToolsLoop(ChatResponse chatResponse,ChatRequestParameters parameters,List<ChatMessage> messages,ChatLanguageModel chatModel,ChatMemory chatMemory,Object memoryId,Map<String, ToolExecutor> toolExecutors) {// 累计token使用量TokenUsage tokenUsageAccumulator = chatResponse.metadata().tokenUsage();int executionsLeft = maxSequentialToolsInvocations;List<ToolExecution> toolExecutions = new ArrayList<>();// 工具调用循环while (true) {// 检查是否超过最大调用次数if (executionsLeft-- == 0) {throw runtime("Something is wrong, exceeded %s sequential tool executions", maxSequentialToolsInvocations);}AiMessage aiMessage = chatResponse.aiMessage();// 将AI响应添加到记忆或消息列表if (chatMemory != null) {chatMemory.add(aiMessage);} else {messages = new ArrayList<>(messages);messages.add(aiMessage);}// 如果没有工具调用请求,则退出循环if (!aiMessage.hasToolExecutionRequests()) {break;}// 处理每个工具调用请求for (ToolExecutionRequest toolExecutionRequest : aiMessage.toolExecutionRequests()) {ToolExecutor toolExecutor = toolExecutors.get(toolExecutionRequest.name());// 执行工具或应用幻觉策略ToolExecutionResultMessage toolExecutionResultMessage = toolExecutor == null? applyToolHallucinationStrategy(toolExecutionRequest): ToolExecutionResultMessage.from(toolExecutionRequest, toolExecutor.execute(toolExecutionRequest, memoryId));// 记录工具执行情况toolExecutions.add(ToolExecution.builder().request(toolExecutionRequest).result(toolExecutionResultMessage.text()).build());// 将工具执行结果添加到记忆或消息列表if (chatMemory != null) {chatMemory.add(toolExecutionResultMessage);} else {messages.add(toolExecutionResultMessage);}}// 如果需要,从记忆获取最新消息if (chatMemory != null) {messages = chatMemory.messages();}// 准备下一次聊天请求ChatRequest chatRequest = ChatRequest.builder().messages(messages).parameters(parameters).build();// 获取新的聊天响应chatResponse = chatModel.chat(chatRequest);// 累计token使用量tokenUsageAccumulator = TokenUsage.sum(tokenUsageAccumulator, chatResponse.metadata().tokenUsage());}return new ToolExecutionResult(chatResponse, toolExecutions, tokenUsageAccumulator);}/*** 应用工具幻觉策略*/public ToolExecutionResultMessage applyToolHallucinationStrategy(ToolExecutionRequest toolExecutionRequest) {return toolHallucinationStrategy.apply(toolExecutionRequest);}// 以下为getter方法public List<ToolSpecification> toolSpecifications() {return toolSpecifications;}public Map<String, ToolExecutor> toolExecutors() {return toolExecutors;}public ToolProvider toolProvider() {return toolProvider;}
}
关键代码
通过这个Demo,我们发现,我们可以利用自然语言来整合各项系统功能,这将是一种新的编程模式:自然语言编程
小结:通过Tools机制可以通过自然语言整合大模型和系统内部功能,使得大模型这个智能大脑拥有了灵活的四肢,从而可以处理更复杂的场景,同时也感受到了自然语言编程离我们越来越近了