Spring AI 第一讲 之 Chat Client API

 Chat Client API

ChatClient 提供了与人工智能模型通信的流畅 API。它同时支持同步和反应编程模型。

流畅的应用程序接口(API)提供了一些方法,用于构建作为输入传递给人工智能模型的 "提示"(Prompt)的各个组成部分。提示包含指导人工智能模型输出和行为的指示文本。从应用程序接口的角度来看,提示由一系列信息组成。

人工智能模型主要处理两类信息:用户信息和系统信息,前者是用户的直接输入,后者则由系统生成,用于引导对话。

这些信息通常包含占位符,在运行时根据用户输入进行替换,以定制人工智能模型对用户输入的响应。

此外,还可以指定提示选项,如要使用的人工智能模型名称和控制生成输出的随机性或创造性的温度设置。

创建聊天客户端

ChatClient 是使用 ChatClient.Builder 对象创建的。您可以为任何 ChatModel Spring Boot 自动配置获取一个自动配置的 ChatClient.Builder 实例,也可以通过编程创建一个。

使用自动配置的 ChatClient.Builder

在最简单的使用案例中,Spring AI 提供了 Spring Boot 自动配置功能,创建了一个 ChatClient.Builder Bean 原型,供您注入到您的类中。下面是一个对简单用户请求检索字符串响应的简单示例。

@RestController
public class MyController {private final ChatClient chatClient;public MyController(ChatClient.Builder chatClientBuilder) {this.chatClient = chatClientBuilder.build();}@GetMapping("/ai")String generation(String userInput) {return this.chatClient.prompt().user(userInput).call().content();}
}

在这个简单的例子中,用户输入设置了用户信息的内容。调用方法向人工智能模型发送请求,而上下文方法则以字符串形式返回人工智能模型的响应。

以编程方式创建聊天客户端

通过设置属性 spring.ai.chat.client.enabled=false,可以禁用 ChatClient.Builder 自动配置。如果同时使用多个聊天模型,这将非常有用。然后以编程方式为每个 ChatModel 创建一个 ChatClient.Builder 实例:

ChatModel myChatModel = ... // usually autowiredChatClient.Builder builder = ChatClient.builder(myChatModel);// or create a ChatClient with the default builder settings:ChatClient chatClient = ChatClient.create(myChatModel);

聊天客户端回复

ChatClient API 提供了几种格式化 AI 模型响应的方法。

返回聊天响应

人工智能模型的响应是一种丰富的结构,由 ChatResponse 类型定义。它包括关于如何生成回复的元数据,也可以包含多个回复,即所谓的 "代",每个 "代 "都有自己的元数据。元数据包括用于创建回复的标记数(每个标记约为一个单词的 3/4)。这一信息非常重要,因为托管人工智能模型是根据每个请求所使用的标记数来收费的。

下面是在 call() 方法后调用 chatResponse() 返回包含元数据的 ChatResponse 对象的示例。

ChatResponse chatResponse = chatClient.prompt().user("Tell me a joke").call().chatResponse();

返回实体

您经常希望返回一个实体类,该实体类由返回的字符串映射而成。实体方法提供了这种功能。
例如,给定 Java record:

record ActorFilms(String actor, List<String> movies) {
}

您可以使用实体方法轻松地将人工智能模型的输出映射到该记录,如下所示:

ActorFilms actorFilms = chatClient.prompt().user("Generate the filmography for a random actor.").call().entity(ActorFilms.class);

还有一个重载的实体方法,其签名为 entity(ParameterizedTypeReference<T> type),可让您指定通用列表等类型:

List<ActorFilms> actorFilms = chatClient.prompt().user("Generate the filmography of 5 movies for Tom Hanks and Bill Murray.").call().entity(new ParameterizedTypeReference<List<ActorsFilms>>() {});

流式响应

流可让您获得异步响应,如下所示(目前市面上都采用此方法:前后端交互【见下期案例】)

Flux<String> output = chatClient.prompt().user("Tell me a joke").stream().content();

您还可以使用 Flux<ChatResponse> chatResponse() 方法流式传输 ChatResponse。
在 1.0.0 M2 版本中,我们将提供一种方便的方法,让您使用反应式 stream() 方法返回 Java 实体。与此同时,您应该使用结构化输出转换器来转换聚合响应,如下图所示。这也演示了流畅 API 中参数的使用,我们将在后面的文档中详细讨论。

 var converter = new BeanOutputConverter<>(new ParameterizedTypeReference<List<ActorsFilms>>() {});Flux<String> flux = this.chatClient.prompt().user(u -> u.text("""Generate the filmography for a random actor.{format}""").param("format", converter.getFormat())).stream().content();String content = flux.collectList().block().stream().collect(Collectors.joining());List<ActorFilms> actorFilms = converter.convert(content);

call() return values

在指定 ChatClient 的调用方法后,有几种不同的响应类型可供选择。

  • 字符串 content():返回响应的字符串内容
  • ChatResponse chatResponse():返回 ChatResponse 对象,该对象包含多代内容和有关响应的元数据,例如创建响应时使用了多少标记。
  • 实体返回 Java 类型
    • entity(ParameterizedTypeReference<T> type):用于返回实体类型集合。
    • entity(Class<T> type):用于返回特定的实体类型。
    • entity(StructuredOutputConverter<T>结构化输出转换器):用于指定结构化输出转换器的实例,以将字符串转换为实体类型。

您还可以调用流方法,而不是调用和

stream() return values

在 ChatClient 上指定流方法后,有几个响应类型选项:

  • Flux<String> content(): 返回人工智能模型生成的字符串的 Flux。
  • Flux<ChatResponse> chatResponse():返回人工智能模型生成的字符串的 Flux: 返回 ChatResponse 对象的 Flux,其中包含有关响应的附加元数据。

使用默认值

在 @Configuration 类中创建带有默认系统文本的 ChatClient 可简化运行时代码。通过设置默认值,您只需在调用 ChatClient 时指定用户文本,而无需在运行时代码路径中为每个请求设置系统文本。

默认系统文本

在下面的示例中,我们将配置系统文本始终以海盗的声音回复。为了避免在运行时代码中重复系统文本,我们将在 @Configuration 类中创建一个 ChatClient 实例。

@Configuration
class Config {@BeanChatClient chatClient(ChatClient.Builder builder) {return builder.defaultSystem("You are a friendly chat bot that answers question in the voice of a Pirate").build();}}

和调用它的 @RestController

@RestController
class AIController {private final ChatClient chatClient;AIController(ChatClient chatClient) {this.chatClient = chatClient;}@GetMapping("/ai/simple")public Map<String, String> completion(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {return Map.of("completion", chatClient.prompt().user(message).call().content());}
}

通过 curl 调用它,可以得到

❯ curl localhost:8080/ai/simple
{"generation":"Why did the pirate go to the comedy club? To hear some arrr-rated jokes! Arrr, matey!"}

带参数的默认系统文本

在下面的示例中,我们将在系统文本中使用占位符,在运行时而不是设计时指定完成的语音。

@Configuration
class Config {@BeanChatClient chatClient(ChatClient.Builder builder) {return builder.defaultSystem("You are a friendly chat bot that answers question in the voice of a {voice}").build();}}
@RestController
class AIController {private final ChatClient chatClientAIController(ChatClient chatClient) {this.chatClient = chatClient;}@GetMapping("/ai")Map<String, String> completion(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message, String voice) {return Map.of("completion",chatClient.prompt().system(sp -> sp.param("voice", voice)).user(message).call().content());}
}

答复是

http localhost:8080/ai voice=='Robert DeNiro'
{"completion": "You talkin' to me? Okay, here's a joke for ya: Why couldn't the bicycle stand up by itself? Because it was two tired! Classic, right?"
}

其他默认设置

在 ChatClient.Builder 层级,您可以指定默认提示。

  • defaultOptions(ChatOptions chatOptions): 输入在 ChatOptions 类中定义的可移植选项或特定于模型的选项(如 OpenAiChatOptions 中的选项)。有关特定模型 ChatOptions 实现的更多信息,请参阅 JavaDocs。
  • defaultFunction(String name, String description, java.util.function.Function<I, O> function): 名称用于在用户文本中引用函数。描述解释了函数的用途,并帮助人工智能模型选择正确的函数以做出准确的响应。函数参数是一个 Java 函数实例,模型将在必要时执行该函数。
  • defaultFunctions(String... functionNames): 应用程序上下文中定义的 `java.util.Function`s 的 bean 名称。
  • defaultUser(String text)、defaultUser(Resource text)、defaultUser(Consumer<UserSpec> userSpecConsumer): 通过这些方法可以定义用户文本。Consumer<UserSpec> 允许您使用 lambda 来指定用户文本和任何默认参数。
  • defaultAdvisors(RequestResponseAdvisor...advisor): 顾问允许修改用于创建提示的数据。QuestionAnswerAdvisor 实现通过在提示中附加与用户文本相关的上下文信息来启用检索增强生成模式。
  • defaultAdvisors(Consumer<AdvisorSpec> advisorSpecConsumer): 该方法允许您定义一个消费者,以便使用 AdvisorSpec 配置多个顾问。顾问可以修改用于创建最终提示的数据。Consumer<AdvisorSpec> 可让您指定一个 lambda 来添加顾问,例如 QuestionAnswerAdvisor,它支持检索增强生成(Retrieval Augmented Generation),可根据用户文本在提示中附加相关上下文信息。

您可以在运行时使用不带默认前缀的相应方法覆盖这些默认值。

  • options(聊天选项 chatOptions)
  • function(String name, String description, java.util.function.Function<I, O> function)
  • `functions(String... functionNames)
  • user(String text) , user(Resource text), user(Consumer<UserSpec> userSpecConsumer)
  • advisor(RequestResponseAdvisor... advisor)
  • advisor(Consumer<AdvisorSpec> advisorSpecConsumer)

Advisors

在使用用户文本调用人工智能模型时,一种常见的模式是使用上下文数据附加或增强提示。
这种上下文数据可以是不同类型的。常见类型包括

  • 你自己的数据: 这是人工智能模型尚未训练过的数据。即使模型看过类似的数据,在生成回复时也会优先使用附加的上下文数据。
  • 对话历史: 聊天模型的 API 是无状态的。如果您告诉人工智能模型您的名字,它不会在随后的交互中记住您的名字。必须在每次请求时发送对话历史记录,以确保在生成响应时考虑到之前的交互。

检索增强生成

向量数据库存储了人工智能模型不知道的数据。当用户向人工智能模型发送问题时,QuestionAnswerAdvisor 会查询向量数据库中与用户问题相关的文档。

向量数据库中的回复会附加到用户文本中,为人工智能模型生成回复提供上下文。

假设您已经将数据加载到向量存储中,您可以通过向聊天客户端提供一个 QuestionAnswerAdvisor 实例来执行检索增强生成(RAG)。

ChatResponse response = ChatClient.builder(chatModel).build().prompt().advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults())).user(userText).call().chatResponse();

在本例中,SearchRequest.defaults() 将对矢量数据库中的所有文档执行相似性搜索。为了限制搜索的文档类型,SearchRequest 使用了类似 SQL 的过滤表达式,这种表达式可以在所有 VectorStores 中使用。

聊天记忆

接口 ChatMemory 表示聊天对话历史记录的存储空间。它提供了向*对话添加信息、从对话中检索信息和清除对话历史记录的方法。
有一个 InMemoryChatMemory 实现可为聊天对话历史记录提供内存存储。
有两个顾问实现使用 ChatMemory 接口为提示对话历史提供建议,它们在如何将内存添加到提示对话历史的细节上有所不同

  • MessageChatMemoryAdvisor:内存是作为消息集合添加到提示符中的
  • PromptChatMemoryAdvisor : 将内存添加到提示符的系统文本中。
  • VectorStoreChatMemoryAdvisor:通过构造函数 "VectorStoreChatMemoryAdvisor(VectorStore vectorStore, String defaultConversationId, int chatHistoryWindowSize)",您可以指定要从哪个 VectorStore 获取聊天记录、未确定的对话 ID、聊天记录的大小(以标记大小表示)。

使用多个顾问的 @Service 实现示例如下所示

@Service
public class CustomerSupportAssistant {private final ChatClient chatClient;public CustomerSupportAssistant(ChatClient.Builder builder, VectorStore vectorStore, ChatMemory chatMemory) {this.chatClient = builderh.defaultSystem("""您是一家名为 "Funnair "的航空公司的客户聊天支持人员、乐于助人。
在提供预订信息或取消预订之前,您必须始终
从用户处获取以下信息:预订号、客户名和姓。
在更改预订之前,必须确保条款允许更改预订。
如果更改需要收费,则必须在征得用户同意后方可进行。""").defaultAdvisors(new PromptChatMemoryAdvisor(chatMemory),// new MessageChatMemoryAdvisor(chatMemory), // CHAT MEMORYnew QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()),new LoggingAdvisor()) // RAG.defaultFunctions("getBookingDetails", "changeBooking", "cancelBooking") // FUNCTION CALLING.build();
}public Flux<String> chat(String chatId, String userMessageContent) {return this.chatClient.prompt().user(userMessageContent).advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)).stream().content();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/22423.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RK3588 AB镜像升级学习(一)

参考资料&#xff1a;Android A/B 系统_洛奇看世界的博客-CSDN博客 一、AB镜像分区 区分了OTA升级镜像的两种方式&#xff1a; 传统的升级方式&#xff1a;设备有Android系统和Recovery系统&#xff0c;如果Android需要升级时&#xff0c;把内容存到cache分区。重启后进入re…

15 条 QA 测试技巧

越来越多的企业开始寻求独立人才来增强或拓展其技术能力。软件开发行业是目前向混合团队转变的关键领域之一。与此同时&#xff0c;自由职业软件质量保证测试人员已成为任何软件开发团队的宝贵补充。 本指南将概述质量保证 (QA) 测试人员的职责以及成为测试人员的实用技巧。 Q…

Diffusers代码学习-Dreambooth

在Diffusers代码中&#xff0c;可以使用train_dreambooth.py脚本进行模型训练。 下载源代码及安装。 在运行脚本之前&#xff0c;请确保从以下源安装库&#xff1a; git clone https://github.com/huggingface/diffusers cd diffusers pip install . 导航到包含train_dr…

P3. 创建个人中心页面

P3. 创建个人中心页面 0 概述Tips1 个人中心页面1.1 创建 Bot 表及 pojo, mapper1.2 实现 Bot 增删改查的 API1.3 实现个人中心页面前端 0 概述 主要介绍了一下添加一个表(类)&#xff0c;及其CRUD的前端和后端的实现方式&#xff0c;介绍的是通用的方法。 后端的CRUD很好写&am…

5 - 无效的推文(高频 SQL 50 题基础版)

5. 无效的推文 知识点&#xff1a;计算字符长度 -- 查询所有无效推文的编号&#xff08;ID&#xff09; -- CHAR_LENGTH() 或 LENGTH() 函数来计算列中字符串的字符数。 -- 这两个函数的区别在于处理非 ASCII 字符时的行为&#xff1a; -- CHAR_LENGTH() 返回字符串的字符数&a…

可能是当下最能打的MCU图形库:LVGL

在讨论图形用户界面&#xff08;GUI&#xff09;库时&#xff0c;很多人会想到emWin、TouchGFX以及QT等。这些库虽然功能强大&#xff0c;但它们普遍存在一个共同的问题&#xff1a;对资源的需求较高&#xff0c;不适用于资源有限的微控制器&#xff08;MCU&#xff09;。有没有…

Spring Boot既打jar包又打war包如何做

你好&#xff0c;我是柳岸花开。 引言 在软件开发中&#xff0c;根据不同的部署需求&#xff0c;我们可能需要将应用打包成不同的格式。Spring Boot作为目前流行的Java应用开发框架&#xff0c;提供了一种简单的方式来打包应用。本文将介绍如何利用Maven Profiles在Spring Boot…

【linux】swap学习

在 Linux 系统中&#xff0c;swap 是一种用于扩展系统内存的技术。当物理内存&#xff08;RAM&#xff09;不足时&#xff0c;系统会将一部分不常用的内存数据移至 swap 空间&#xff0c;从而释放物理内存供其他程序使用。Swap 空间可以是一个单独的分区&#xff08;swap 分区&…

交互规范:苹果 iOS 11 设计规范

文件格式&#xff1a;PDF&#xff08;请与班主任联系获取原型文档&#xff09; 文件名称&#xff1a;苹果 iOS 11 设计规范 文件大小&#xff1a;29.2 MB 文档内容介绍 免费领取资料 添加班主任回复 “210421” 领取

泛微OA调用发送消息接口 .Net C#示例

泛微OA调用接口步骤文档 泛微OA发送消息接口文档 详细步骤查看上面两个文档 泛微OA发送消息&#xff0c;只有java代码示例&#xff0c;这里整理了一套.Net版本的示例&#xff0c;仅供参考&#xff0c;目前写的可以调用&#xff0c;后期泛微接口做调整&#xff0c;本文章不做…

数据结构_手撕七大排序(快排,归并,堆排,希尔,选择,插入,冒泡)

✨✨所属专栏&#xff1a;数据结构✨✨ ✨✨作者主页&#xff1a;嶔某✨✨ 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序…

企业数据安全管理容易忽视的关键点:云存储权限管控

云存储已经广泛应用于企业用户、教育领域、医疗领域以及政府和公共服务部门。具体应用场景包括文件共享、数据备份、在线课程、教学资源库、电子病历、医学影像、实验室数据、政务数据的集中管理和共享等。 云存储的优势非常明显&#xff1a; 可扩展性&#xff1a;云存储空间可…

Nginx漏洞解析及复现

Nginx漏洞 Nginx能做到正向代理、反向代理、负载均衡、HTTP服务器等&#xff0c;强大的功能不言而喻&#xff0c;但也伴随着使用 上的风险&#xff0c;深入理解Nginx的漏洞有助于创建安全的业务系统。 Nginx解析漏洞 漏洞原理 Nginx的解析漏洞的出现和Nginx的版本没有关系&…

基于深度学习的中文标点预测模型-中文标点重建(Transformer模型)【已开源】

基于深度学习的中文标点预测模型-中文标点重建&#xff08;Transformer模型&#xff09;提供模型代码和训练好的模型 前言 目前以深度学习对文本自动添加标点符号研究很少&#xff0c;已知的开源项目并不多&#xff0c;详细的介绍就更少了&#xff0c;但对文本自动添加标点符号…

三菱MR-J4系列伺服驱动器E7.1和32.3故障报警处理总结

三菱MR-J4系列伺服驱动器E7.1和32.3故障报警处理总结 三菱MR-J4系列伺服驱动器出现报警,故障代码为:E7.1和32.3,查阅手册可以看到E7.1和32.3的报警解释信息, 如下图所示,此时简单运动控制模块上的ERROR灯亮, 如下图所示,用GX WORKS3打开备份程序,找到FX5-80SSC-…

【Axure视频教程】推动和拉起

今天教大家在Axure制作推动和拉起效果的原型模板&#xff0c;点击上下能头可以展开或收起对应的内容&#xff0c;并且推动或拉起下方对应的元件。该教程从0开始制作&#xff0c;手把手教学&#xff0c;无论是新手小白还是有一定基础的同学&#xff0c;都可以学习的哦。 【视频…

插件:vite-plugin-electron

源文档地址:vite-plugin-electron 安装 npm i -D vite-plugin-electron 将vite-plugin-electron添加到vite.config.ts的插件部分 import electron from vite-plugin-electron/simpleexport default {plugins: [electron({main: {// build.lib.entry的快捷方式entry: electr…

3 - 大的国家(高频 SQL 50 题基础版)

3.大的国家 -- 查询属性&#xff1a;国家名称、人口和面积 select name,population,area fromWorld where area>3000000 OR population>25000000;

组件框架信息泄露

后端spring-boot框架 actuator组件信息泄露 Actuator是Spring-Boot提供的服务监控和管理中间件&#xff0c;默认配置会出现接口未授权 访问&#xff0c;部分接口会泄露网站流量信息和内存信息等&#xff0c;使用Jolokia库特性甚至可以远程执行任意代码&#xff0c;获 取服务器…

科技赋能,无障碍出行的新纪元

在现代社会&#xff0c;公共设施的建设不仅是衡量城市文明程度的标尺&#xff0c;更是实现社会公平与包容的重要载体。对于盲人群体而言&#xff0c;一个完善的公共设施网络&#xff0c;意味着他们能够更加独立、自信地融入社会&#xff0c;享受与视力健全者同等的公共服务与便…