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

网站建设的要素菜鸟教程网站开发

网站建设的要素,菜鸟教程网站开发,cms做企业网站建站系统,windows优化大师官方对于一些LLM来说除了可以生成文本外,还可以触发操作。 有一个概念叫“工具/函数调用”。它允许LLM在必要的时候调用一个或多个可用的工具,这些工具一般是针对业务由开发人员来定义的。 这里说的工具可以是任何东西。如:网络搜索、外部API的…

对于一些LLM来说除了可以生成文本外,还可以触发操作。

有一个概念叫“工具/函数调用”。它允许LLM在必要的时候调用一个或多个可用的工具,这些工具一般是针对业务由开发人员来定义的。

这里说的工具可以是任何东西。如:网络搜索、外部API的调用或特定代码的执行......LLM不能自己调用这些工具。然而它们在响应中表达了调用特定工具的意图,作为开发人员应该使用提供的参数来执行这个工具,并报告出这个执行的结果。

两个抽象层次

对于工具的使用,LangChain4j提供了两个层次的抽象

  • 低级别的,使用ChatLanguageModel和ToolSpecification的api
  • 高级别的,使用AiServece和@Tool注解的java方法

低级别的

对于它可以使用ChatLanguageModel的generate(List<ChatMessage),List<ToolSpecification>)方法。StreamingChatLangugageModel也有类似的方法。

ToolSpecification对象中包含了关于工具的所有信息,这些信息包含:

  • name:工具的名称
  • description:工具的描述
  • parameters:工具的参数

注意:要尽可能详细地提供工具的信息,清晰的名字、全面的描述及每个参数的描述等

我们定义一个工具的类

public class WeatherTools {@Tool("根据给出的城市,获取天气信息")String getWeather(// 这里的@P()注解,用在工具的参数上用来说明参数的@P("用来指定要获取天气的城市") String city) {return "[" +  city + "],天气信息: 晴,12~19℃,北风2级 ";}
}

这里的方法使用@Tool注解标注,其中提供的信息是对这个工具的说明

在Controller类中我们在进行具体聊天时去执行工具获取对应的信息

@Slf4j
@RestController
@RequestMapping("/tools")
public class ToolsController {@Resourceprivate StreamingChatLanguageModel streamingChatLanguageModel;@Resourceprivate ChatLanguageModel chatLanguageModel;@GetMapping(path = "/chat", produces = "text/plain;charset=UTF-8")public Flux<String> weather(@RequestParam("message") String message) {// 创建工具/*ToolSpecification weatherTool = ToolSpecification.builder().name("getWeather").description("获取天气信息").parameters(JsonObjectSchema.builder().addStringProperty("city", "城市").required("city").build()).build();*/List<ToolSpecification> toolSpecifications = ToolSpecifications.toolSpecificationsFrom(WeatherTools.class);Response<AiMessage> generate = chatLanguageModel.generate(List.of(UserMessage.from(message)), toolSpecifications);WeatherTools wt = new WeatherTools();List<ChatMessage> messages = new ArrayList<>();generate.content().toolExecutionRequests().forEach(toolExecutionRequest -> {System.out.println(toolExecutionRequest.name());System.out.println(toolExecutionRequest.arguments());// 手动调用工具String toolExecutorResponse = new DefaultToolExecutor(wt, toolExecutionRequest).execute(toolExecutionRequest, null);ToolExecutionResultMessage toolExecutionResultMessage = ToolExecutionResultMessage.from(toolExecutionRequest, toolExecutorResponse);messages.add(UserMessage.from(message)); // UserMessagemessages.add(generate.content()); // AIMessagemessages.add(toolExecutionResultMessage); // ToolExecutionResultMessage});return Flux.create(slink -> {streamingChatLanguageModel.generate(messages, toolSpecifications, new StreamingResponseHandler<AiMessage>() {@Overridepublic void onNext(String token) {slink.next(token);}@Overridepublic void onError(Throwable error) {slink.error(error);}@Overridepublic void onComplete(Response<AiMessage> response) {slink.complete();}});});}
}

多这里我们可以看到,chatLanguageModel.generate()方法调用时传入了用户的消息,同时把封装消息的toolSpecifications传入进去了,它返回的结果当中.toolExceutionRequests()可以取到对工具调用的意图,这个时候根据ai的意图我们要手动去调用工具,最终把用户消息,ai返回消息,工具调用产生的消息一并封装为消息列表给到ai进行处理,这里ai根据这此信息来给用户最终的回复。

高级别的

从上面的代码看我们使用低级别的去处理工具调用还是非常麻烦的,为了降低这个复杂度,可以使用AiService。

首先,我们把WeatherTools这个类加上@Component,方便后续的注入使用

@Component
public class WeatherTools {@Tool("根据给出的城市,获取天气信息")String getWeather(// 这里的@P()注解,用在工具的参数上用来说明参数的@P("用来指定要获取天气的城市") String city) {return "[" +  city + "],天气信息: 晴,12~19℃,北风2级 ";}
}

新增一个AiService的接口

public interface ToolService {Flux<String> weather(String message);
}

新增配置类来配置AiService的代理Bean

@Configuration
public class ToolServiceConfig {@Resourceprivate StreamingChatLanguageModel streamingChatLanguageModel;@Resourceprivate WeatherTools weatherTools;@Beanpublic ToolService toolService() {return AiServices.builder(ToolService.class).streamingChatLanguageModel(streamingChatLanguageModel).tools(weatherTools).build();}
}

这里可以看到与普通的AiService没有太多区别,无非是在Builder的时候使用了.tools()把工具类对象传了进来

接下来Controller当中就可以直接使用这个AiService的代理对象了

@Resource
private ToolService toolService;@GetMapping(path = "/chat2", produces = "text/plain;charset=UTF-8")
public Flux<String> weather2(@RequestParam("message") String message) {Flux<String> weather = toolService.weather(message);return weather;
}
工具方法的限制

工具方法就是指带@Tool注解的方法

  • 它可以是静态的或者非静态的
  • 任何的可见性都可以(公共的、私有的...)
工具方法的参数

带@Tool注解的方法可以接收任意数量的各种类型的参数

  • 基本类型:int,double...
  • 对象类型:String,Integer,Double...
  • 自定义的pojo,并且可以是嵌套的pojo
  • 枚举
  • List,Set,其中列表中的元素是上述元素中的一种
  • Map<K,V>:需要在参数说明中使用@P注解主动指定K和V的类型

工具方法也可以是没有参数的

默认的情况下,所有的方法都被认为是强制的必须的,如果要把其中某个参数指定为可选的则必须使用@P(required=false)来指定

对于递归的参数,如:List<Person>子字段的Person类,当前只有OpenAI支持

工具方法的返回值

带@Tool注解的方法可以返回任何类型,甚至是返回void,如果工具方法返回void,方法执行成功则会把"Success"字符串发送给LLM

如果工具方法返回的是String类型,则返回值会按原样发送给LLM,不会进行任何转换

对于其它的返回类型,返回值在发送给LLM之前会被转为JSON字符串

异常处理

如果带@Tool注解的方法执行过程中抛出异常,则异常消息(e.getMessage())会作为工具执行结果发送给LLM,如果LLM认为有必要则允许它纠正错误并重试。

@Tool

任何带有@Tool注解的并在构建AiService期间显示指定的Java方法都可以由LLM执行。

新增一个工具类其中指定的一批数学计算相关的工具

@Component
public class Calculator {@Tooldouble add(double a, double b) {return a + b;}@Tooldouble subtract(double a, double b) {return a - b;}@Tooldouble multiply(double a, double b) {return a * b;}@Tooldouble divide(double a, double b) {return a / b;}@Tooldouble squareRoot(double x) {return Math.sqrt(x);}
}

在AiService接口中新增方法

Flux<String> claculator(String message);

在配置Bean的配置类当中,注入数学工具类对象,并把这个对象放到.tools()当中

@Resource
private Calculator calculator;@Bean
public ToolService toolService() {return AiServices.builder(ToolService.class).streamingChatLanguageModel(streamingChatLanguageModel).tools(weatherTools,calculator).build();
}

在Controller当中直接使用

@GetMapping(path = "/chat3", produces = "text/plain;charset=UTF-8")
public Flux<String> Calculator(@RequestParam("message") String message) {Flux<String> result = toolService.claculator(message);return result;
}

此时我们使用下面的对话访问:

http://localhost:8080/tools/chat3?message=872346平方根是多少?

ai的回答结果是:872346的平方根是大约933.995

@Tool注解有两个属性

  • name:用来指定工具的名称,如果不指定那么名称就默认是方法的名称
  • value:指定对工具的描述

根据工具的不同,就算是没有任何描述,LLM也是可以很好地理解它,比如:add(a,b)这个明显就是做加法处理,但通常来说最好是加上清晰有意义的名称和描述。这样的话LLM就会有更多的信息来决定是否调用这个工具,以及如何去调用。

@P

可以使用@P来注释方法的参数

@P有两个属性

  • value:描述参数的信息,这是强制性的属性
  • required:指定参数是否必需,默认是true,这个属性是可选配置
@Description

类和字段的描述可以用@Description注解来指定

这个注解可以用于类也可以用于字段,用来作为辅助的描述信息

@ToolMemoryId

如果我们的AiService接口方法上有一个用@MemoryId标注的参数,可以用@ToolMemoryId标注@Tool方法的参数。在提供给AiService方法的值会自动传给@Tool方法,这样可以对于多个用户和/或者是每个用户有多个聊天记忆在@Tool方法中要以进行区分。

访问已执行的工具

如果希望在调用AiService期间已执行的工具,可以通过在Result类中包装返回类型来实现

我们再定义一个工具类

@Component
public class Calculator2 {@Tooldouble add(double a, double b) {return a + b;}@Tooldouble subtract(double a, double b) {return a - b;}@Tooldouble multiply(double a, double b) {return a * b;}@Tooldouble divide(double a, double b) {return a / b;}@Tooldouble squareRoot(double x) {return Math.sqrt(x);}
}

对于AiService接口中我们再定义一个方法让其返回的是Result<String>

Result<String> chat(String message);

配置类中配置AiService的Bean

@Resource
private Calculator2 calculator2;@Resource
private ChatLanguageModel chatLanguageModel;@Bean("chatService")
public ToolService chatService() {return AiServices.builder(ToolService.class).chatLanguageModel(chatLanguageModel).tools(calculator2).build();
}

controller中我们可以获取到调用AiService方法后执行的工具

@Resource(name = "chatService")
private ToolService chatService;@GetMapping(path = "/chat4")
public String chat(@RequestParam("message") String message) {Result<String> result = chatService.chat(message);// 获取到所有已执行的工具List<ToolExecution> toolExecutions = result.toolExecutions();log.info("toolExecutions:{}", toolExecutions);return result.content();
}

如果是在streaming模式下,要获取到执行的工具,可以上AiService中的方法返回TokenStream

TokenStream chat2(String message);

对于AiService的构造Bean中只是把chatLanguageModel改为了streamingChatLanguageModel()

@Bean("streamingService")
public ToolService toolService() {return AiServices.builder(ToolService.class).streamingChatLanguageModel(streamingChatLanguageModel).tools(weatherTools,calculator).build();
}

在controller当中通过如下操作可以获取聊天中执行的过的工具

@GetMapping(path = "/chat5", produces = "text/plain;charset=UTF-8")
public Flux<String> chat2(@RequestParam("message") String message) {TokenStream result = toolService.chat2(message);return Flux.create(slink -> {result.onNext(slink::next).onToolExecuted(toolExecution -> {log.info("toolExecution:{}", toolExecution);}).onComplete(response -> slink.complete())   // 注意这里的写法.onError(slink::error)  // 必须要实现.start();});
}
以编程的方法指定工具

在使用AiService的时候也可以通过编程的方式来配置工具,这个配置可以从数据库或者配置文件中获取,这样的话就会更加灵活。

在配置AiService的Bean的时候,手动指定工具并手动执行

WeatherTools定义如下:

@Component
public class WeatherTools {@Tool("根据给出的城市,获取天气信息")public Map<String,String> getWeather(// 这里的@P()注解,用在工具的参数上用来说明参数的@P("用来指定要获取天气的城市") String city) {Map<String,String> map = new HashMap<>();map.put("city",city);map.put("weather","天气晴朗,温度在12~17℃之间,北风3级");return map;}
}
@Configuration
public class SpecifyToolServiceConfig {@Resourceprivate StreamingChatLanguageModel streamingChatLanguageModel;@Resourceprivate WeatherTools tools;// 下面创建这个Bean的时候是没有指定tool的@Bean("specifyToolService")public ToolService specifyToolService() {// 手动指定工具ToolSpecification toolSpecification = ToolSpecification.builder().name("getWeather").description("获取天气信息").parameters(JsonObjectSchema.builder().properties(Map.of("city", JsonStringSchema.builder().description("城市").build())).build()).build();// 执行工具ToolExecutor toolExecutor = ((toolExecutionRequest, memoryId) ->  {// 把Json字符串转为一个MapMap<String,Object> arguments = JSONUtils.toBean(toolExecutionRequest.arguments(), Map.class);String city = arguments.get("city").toString();String result = tools.getWeather(city).get("weather");return result;});return AiServices.builder(ToolService.class).streamingChatLanguageModel(streamingChatLanguageModel).tools(Map.of(toolSpecification, toolExecutor)).build();}
}

从上面看在创建AiService的Bean的时候tools中指定的Map类型,也就是对应的工具及执行结果

动态指定工具

在使用AIService服务时,还可以每次调用动态指定工具。可以配置一个ToolProvider,它会在每次调用AIService的时候被调用,并将提供应该包含在当前的LLM的请求中的工具。

ToolProvider接受包含UserMessage和聊天MemoryId的ToolProviderRequest,并返回包含从ToolSpecification到ToolExecutor的Map形式的工具ToolProviderResult。

在配AIService的Bean时,可以根据UserMessage的情况动态去判断执行工具

@Configuration
public class SpecifyDynamicToolConfig {@Resourceprivate StreamingChatLanguageModel streamingChatLanguageModel;@Resourceprivate WeatherTools tools;@Bean("specifyDynamicToolService")public ToolService specifyDynamicToolService() {// 工具执行器ToolExecutor toolExecutor = ((toolExecutionRequest, memoryId) ->  {// 把Json字符串转为一个MapMap<String,Object> arguments = JSONUtils.toBean(toolExecutionRequest.arguments(), Map.class);String city = arguments.get("city").toString();String result = tools.getWeather(city).get("weather");return result;});// 动态工具ToolProvider toolProvider = (toolProviderRequest) -> {if(toolProviderRequest.userMessage().singleText().contains("天气")) {ToolSpecification toolSpecification = ToolSpecification.builder().name("getWeather").description("获取天气信息").parameters(JsonObjectSchema.builder().addStringProperty("city").build()).build();return ToolProviderResult.builder().add(toolSpecification,toolExecutor).build();} else {return null;}};return AiServices.builder(ToolService.class).streamingChatLanguageModel(streamingChatLanguageModel).toolProvider(toolProvider).build();}
}

在后的聊天的过程中如果对话中包含“天气”则会执行工具

@Resource(name="specifyDynamicToolService")
private ToolService specifyDynamicToolService;@GetMapping(path = "/chat7", produces = "text/plain;charset=UTF-8")
public Flux<String> chat4(@RequestParam("message") String message) {return specifyDynamicToolService.weather(message);
}


文章转载自:

http://UNGaBRqy.xzgbj.cn
http://GaSn1GV3.xzgbj.cn
http://bUQV36yF.xzgbj.cn
http://LHwmlUPN.xzgbj.cn
http://H9vSczUK.xzgbj.cn
http://6QDf50FG.xzgbj.cn
http://xo7oUyTV.xzgbj.cn
http://6WA9XpmQ.xzgbj.cn
http://X8FRSkJI.xzgbj.cn
http://u1us0zNI.xzgbj.cn
http://hOBvQBTV.xzgbj.cn
http://Rfpe3W4h.xzgbj.cn
http://sivlplcs.xzgbj.cn
http://QhXFOeQL.xzgbj.cn
http://U97Ziyhq.xzgbj.cn
http://wgUSFczN.xzgbj.cn
http://2towkvJc.xzgbj.cn
http://twfPXNp2.xzgbj.cn
http://AGmHQ8nA.xzgbj.cn
http://Q3bzorcp.xzgbj.cn
http://nKQbKLHu.xzgbj.cn
http://Dmrn4PNT.xzgbj.cn
http://6quOROUF.xzgbj.cn
http://TAxAdRrX.xzgbj.cn
http://IqiOiOVy.xzgbj.cn
http://KRKV9Vrp.xzgbj.cn
http://RSAHXhNE.xzgbj.cn
http://dFDzdDXw.xzgbj.cn
http://ou6REWTn.xzgbj.cn
http://iY0VDHoN.xzgbj.cn
http://www.dtcms.com/wzjs/644238.html

相关文章:

  • 大理网站建设沛宣零售电商平台有哪些
  • 全国好的视频制作云巅seo
  • 自己切片视频做网站番禺制作网站平台
  • 吉林省水土保持生态建设网站洪雅网站建设
  • 网站更新内容公司注册地址异常如何处理
  • 网站产品链接怎么做的温州网站建设免费服务
  • c#做网站微网站制作方案
  • 贵州网站建设维护常州模板建站定制网站
  • 做一家算命的网站wordpress action
  • 网站维护费一年多少钱工商红盾网查询系统
  • 怎样利用网站做推广的方法高阳网站建设
  • 站长推荐产品如果在工商局网站上做股权质押
  • 做网站的实验报告微信推广和网站推广哪个好
  • 阿里云服务器配置网站事业单位建立网站
  • 致力于做服务更好的网站建设公司管理咨询公司技术服务
  • 企业网站 asp php枫林seo工具
  • 定州网站制作多少钱wordpress文章分页付费
  • asp 网站模板表白视频制作网站
  • 旅游网站开发现状重庆网站建设网站
  • 淄博网站建设专家网站空间地址查询
  • 网站seo怎样做简述网站建设
  • 学做漂亮早餐的网站wordpress使用对象储存
  • 东莞定制网站建设模板网站怎么建设优化
  • 把网站生成app的免费平台北京旅游网站建设
  • 设计网站都有什么作用是什么济南网站建设公司送400
  • wordpress全站公告一级做ae视频直播可以吗多少钱
  • 公司网站开发费入什么科目聊城做网站做的不错的网络公司
  • 网站开发项目对自身的意义手机资讯类网站模板
  • html5网站建站书网站建设视频教程推荐
  • 网站设置cookie什么意思铜川网站建设报价