Spring AI ChatClient

打印 上一主题 下一主题

主题 1953|帖子 1953|积分 5859

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Spring AI中的ChatClient是一个提供流畅API(Fluent API)的客户端,它重要用于与各种AI模子进行通讯。ChatClient 提供了与 AI 模子通讯的 Fluent API,它支持同步和反应式(Reactive)编程模子。与 ChatModel、Message、ChatMemory 等原子 API 相比,使用 ChatClient 可以将与 LLM 及其他组件交互的复杂性隐藏在背后,由于基于 LLM 的应用步伐通常要多个组件协同工作(比方,提示词模板、聊天记忆、LLM Model、输出解析器、RAG 组件:嵌入模子和存储),并且通常涉及多个交互,因此和谐它们会让编码变得繁琐。固然使用 ChatModel 等原子 API 可以为应用步伐带来更多的灵活性,成本就是您需要编写大量样板代码。
一、核心功能与特点


  • 与AI模子通讯:

    • ChatClient可以或许与各种支持HTTP哀求交互的AI模子进行通讯,如GPT系列模子、BERT模子等。
    • 它通过发送HTTP哀求到AI模子的端点,并解析响应来实现与AI模子的通讯。

  • 流畅API筹划:

    • ChatClient采用了Fluent API的筹划模式,通过方法链的方式简化了与AI模子通讯的过程。
    • 开发者可以通过链式调用的方式设置哀求参数、发起哀求,并获取响应结果。
    • 这种筹划方式提高了代码的可读性,减少了样板代码的量。

  • 支持同步和异步处置惩罚:

    • ChatClient支持同步和反应式(Reactive)编程模子。
    • 同步处置惩罚模式下,开发者可以直接获取AI模子的响应结果。
    • 异步处置惩罚模式下,开发者可以流式地吸收AI模子的响应结果,提高体系的并发处置惩罚本领和响应速度。

  • 丰富的响应格式化选项:

    • ChatClient提供了多种方法来格式化AI模子的响应结果。
    • 开发者可以根据需要选择返回字符串、实体对象或流式响应等差别类型的输出格式。

  • 自界说提示与配置:

    • ChatClient答应开发者通过Prompt对象来自界说与AI模子的交互过程。
    • 开发者可以设置差别的提示语和参数来引导AI模子的复兴方向和内容。
    • ChatClient还支持在运行时通过Prompt的配置项覆盖初始化的配置项,以实现更灵活的配置管理。

二、应用场景

ChatClient可以应用于多种业务场景,包罗但不限于:

  • 客户服务:

    • ChatClient可以用于构建智能客服体系,通过集成先进的AI模子(如ChatGPT),自动回答用户的题目,提供24/7不中断的服务。
    • 这不仅可以提高客户满意度,还能低落企业的人力成本。

  • 教育培训:
    C - hatClient可以用于构建智能辅导体系,通过集成各种知识图谱和AI模子,根据学生的学习环境和爱好爱好提供个性化的学习建媾和辅导。

    • 这不仅可以提高学生的学习服从,还能引发他们的学习爱好。

  • 娱乐游戏:

    • ChatClient可以用于构建智能NPC(非玩家角色),通过集成先进的对话体系和情绪盘算模子,与玩家进行更加自然和有趣的互动。
    • 这不仅可以提高游戏的沉浸感和趣味性,还能增加玩家的粘性和活跃度。

三、使用方式


  • 引入依赖:

    • 如果使用的是Maven项目,可以在pom.xml文件中添加Spring AI的依赖来引入ChatClient。

  • 创建ChatClient实例:

    • 可以使用Spring Boot的自动配置功能来创建ChatClient实例,也可以通过编程方式来创建。
      自动配置方式下,只需在类中注入ChatClient的Bean即可。
    • 编程方式下,需要手动创建ChatClient.Builder实例,并通过它来构建ChatClient。

  • 设置哀求参数并发起哀求:

    • 使用ChatClient的prompt()方法来设置哀求参数,如用户输入、体系提示等。
    • 调用call()方法向AI模子发送哀求,并获取响应结果。
    • 可以根据需要使用chatResponse()、entity()等方法来格式化响应结果。

  • 处置惩罚响应结果:

    • 根据需要处置惩罚AI模子的响应结果,如将其映射为实体类、进行流式处置惩罚等。

四、源代码解读

ChatClient接口

  1. public interface ChatClient {
  2.         ..... 创建ChatClient方法。
  3.         create
  4.         .....
  5.         ..... 创建Builder方法
  6.         builder
  7.         .....
  8.         .....用于设置聊天请求的规范,如提示信息等。
  9.         ChatClientRequestSpec prompt();
  10.         ChatClientRequestSpec prompt(String content);
  11.         ChatClientRequestSpec prompt(Prompt prompt);
  12.         .....
  13.         .....用于创建新的 Builder  其设置将复制自当前客户端的默认
  14.         Builder mutate();
  15.         .....配置用户提示
  16.         interface PromptUserSpec {......}
  17.         .....
  18.         .....配置系统提示
  19.         interface PromptSystemSpec {......}
  20.         .....
  21.         interface AdvisorSpec {......}
  22.         ......回调的响应规格
  23.         interface CallResponseSpec {......}
  24.         ......
  25.         ......流式响应的规格
  26.         interface StreamResponseSpec {......}
  27.         ......提示响应响应的规格
  28.         interface CallPromptResponseSpec {......}
  29.         ......
  30.         ......流式提示响应响应的规格       
  31.         interface StreamPromptResponseSpec {......}
  32.         ......       
  33.         ......聊天客户端的请求规格
  34.         interface ChatClientRequestSpec {......}
  35.         ......
  36.         ......提供了一种构建 ChatClient 对象的方式,允许设置默认的顾问、选项、用户和系统提示等。
  37.         interface Builder {
  38.                 Builder defaultAdvisors(Advisor... advisor);
  39.                 Builder defaultAdvisors(Consumer<AdvisorSpec> advisorSpecConsumer);
  40.                 Builder defaultAdvisors(List<Advisor> advisors);
  41.                 Builder defaultOptions(ChatOptions chatOptions);
  42.                 Builder defaultUser(String text);
  43.                 Builder defaultUser(Resource text, Charset charset);
  44.                 Builder defaultUser(Resource text);
  45.                 Builder defaultUser(Consumer<PromptUserSpec> userSpecConsumer);
  46.                 Builder defaultSystem(String text);
  47.                 Builder defaultSystem(Resource text, Charset charset);
  48.                 Builder defaultSystem(Resource text);
  49.                 Builder defaultSystem(Consumer<PromptSystemSpec> systemSpecConsumer);
  50.                 /**
  51.                  * @deprecated use {@link #defaultFunctions(FunctionCallback...)} instead.
  52.                  */
  53.                 @Deprecated
  54.                 <I, O> Builder defaultFunction(String name, String description, java.util.function.Function<I, O> function);
  55.                 /**
  56.                  * @deprecated use {@link #defaultFunctions(FunctionCallback...)} instead.
  57.                  */
  58.                 @Deprecated
  59.                 <I, O> Builder defaultFunction(String name, String description,
  60.                                 java.util.function.BiFunction<I, ToolContext, O> function);
  61.                 Builder defaultFunctions(String... functionNames);
  62.                 Builder defaultFunctions(FunctionCallback... functionCallbacks);
  63.                 Builder defaultToolContext(Map<String, Object> toolContext);
  64.                 Builder clone();
  65.                 ChatClient build();
  66.         }
  67. }
复制代码
ChatClient 实现类 DefaultChatClient类
创建

使用 ChatClient.Builder 对象创建 ChatClient 实例,您可以自动注入由Spring Boot 自动配置创建的默认 ChatClient.Builder 实例,您也可以通过编程方式自行创建一个 ChatClient.Builder 实例并用它来得到 ChatClient 实例。

  • 使用自动配置的 ChatClient.Builder
    在快速开始示例中,就是使用的 Spring Boot 自动装配默认生成的 ChatClient.Builder 的 bean,把它注入到您自己的类中。这里是根据用户提问并从模子得到文本回答的简朴例子:
  1.     @RestController
  2.     public class ChatController {
  3.       private final ChatClient chatClient;
  4.       public ChatController(ChatClient.Builder builder) {
  5.         this.chatClient = builder.build();
  6.       }
  7.       @GetMapping("/chat")
  8.       public String chat(String input) {
  9.         return this.chatClient.prompt()
  10.             .user(input)
  11.             .call()
  12.             .content();
  13.       }
  14.     }
复制代码
  在这个示例中,首先设置了用户消息的内容,call 方法向 AI 模子发送哀求,content 方法以字符串情势返回 AI 模子的响应。
  

  • 以编程方式创建 ChatClient
    可以通过设置属性 spring.ai.chat.client.enabled=false 来禁用 ChatClient.Builder bean 的自动配置,如果需要多个聊天模子一起使用,这会很有效,然后以编程方式创建 ChatClient.Builder,如许可以为每个聊天模子创建一个实例 ChatModel:
  1.     ChatModel myChatModel = ... // usually autowired
  2.     ChatClient.Builder builder = ChatClient.builder(myChatModel);
  3.     // or create a ChatClient with the default builder settings:
  4.     ChatClient chatClient = ChatClient.create(myChatModel);
复制代码
ChatClient 响应


  • 返回 ChatResponse
    AI 模子的响应是一种由ChatResponse类型界说的丰富结构。它包含响应生成相关的元数据,同时它还可以包含多个子响应(称为Generation),每个子响应都有自己的元数据。元数据包罗用于创建响应的令牌(token)数目信息(在英文中,每个令牌约莫为一个单词的 3/4)。
    ChatResponse
  1. public class ChatResponse implements ModelResponse<Generation> {
  2.     private final ChatResponseMetadata chatResponseMetadata;
  3.         private final List<Generation> generations;
  4.         @Override
  5.         public ChatResponseMetadata getMetadata() {...}
  6.     @Override
  7.         public List<Generation> getResults() {...}
  8.     // other methods omitted
  9. }
复制代码
Generation
  1. public class Generation implements ModelResult<AssistantMessage> {
  2.         private final AssistantMessage assistantMessage;
  3.         private ChatGenerationMetadata chatGenerationMetadata;
  4.         @Override
  5.         public AssistantMessage getOutput() {...}
  6.         @Override
  7.         public ChatGenerationMetadata getMetadata() {...}
  8.     // other methods omitted
  9. }
复制代码
下面的代码段表现了通过调用 chatResponse() 返回 ChatResponse 的示例,相比于调用 content() 方法,这里在调用 call() 方法之后调用 chatResponse()。
  1.     ChatResponse chatResponse = chatClient.prompt()
  2.         .user("Tell me a joke")
  3.         .call()
  4.         .chatResponse();
复制代码

  • 返回实体类(Entity)
    Spring AI 框架可以自动替我们完成从 String 到实体类的转换,调用entity() 方法可完成响应数据转换。
  1.   ActorFilms aFilms = chatClient.prompt()
  2.         .user("Generate the filmography for a random actor.")
  3.         .call()
  4.         .entity(ActorFilms.class);
复制代码
entity 还有一种带有参数的重载方法 entity(ParameterizedTypeReference<T> type),可让您指定如泛型 List 等类型:
  1.     List<ActorFilms> aFilms = chatClient.prompt()
  2.         .user("Generate the filmography of 5 movies for Tom Hanks and Bill Murray.")
  3.         .call()
  4.         .entity(new ParameterizedTypeReference<List<ActorFilms>>() {
  5.         });
复制代码

  • 流式响应
    stream 方法是一种异步的、持续的得到模子响应的方式:
  1.     Flux<String> oput = chatClient.prompt()
  2.         .user("Tell me a joke")
  3.         .stream()
  4.         .content();
复制代码
还可以使用 Flux<ChatResponse> chatResponse() 方法得到 ChatResponse 响应数据流。
   call 返回值
ChatClient.call() 方法支持几种差别类型的响应格式。
  

  • String content():返回响应的字符串内容
  • ChatResponse chatResponse():返回ChatResponse包含多个代以及有关响应的元数据的对象,比方,使用了多少个令牌来创建响应。
  • entity 返回 Java 类型

    • entity(ParameterizedTypeReference type):用于返回实体类型的聚集。
    • entity(Class type): 用于返回特定的实体类型。
    • entity(StructuredOutputConverter structuredOutputConverter): 用于指定一个实例 StructuredOutputConverter,将 String 转换为实体类型。

    stream() 返回值
还可以调用该stream方法而call不是,在指定stream方法后ChatClient,响应类型有几个选项:
  

  • Flux<String> content():返回由AI模子生成的字符串的Flux。
  • Flux<ChatResponse> chatResponse():返回对象的 Flux ChatResponse,其中包含有关响应的附加元数据。
  示例代码:

由ChatClient.Builder创建
  1. @RestController
  2. public class MyController {
  3.     private final ChatClient chatClient;
  4.     // 通过构造函数注入ChatClient的Bean
  5.     public MyController(ChatClient.Builder chatClientBuilder) {
  6.         this.chatClient = chatClientBuilder.build();
  7.     }
  8.     @GetMapping("/ai")
  9.     public String generateResponse(String userInput) {
  10.         // 设置请求参数并发起请求
  11.         ChatResponse chatResponse = chatClient.prompt()
  12.                 .user(userInput) // 设置用户输入
  13.                 .call() // 向AI模型发送请求
  14.                 .chatResponse(); // 获取包含元数据的ChatResponse对象
  15.         // 处理响应结果(这里只是简单地返回响应内容)
  16.         return chatResponse.getContent();
  17.     }
  18. }
复制代码
ChatClient 默认值

使用 ChatClient.Builder.build() 快速创建了一个 ChatClient 实例,开发者还可以通过修改 ChatClient.Builder 定制 ChatClient 实例。
   注意,创建 ChatClient 时指定的配置将作为与模子交互时的默认参数,如许可以避免每次调用都重复设置。
  

  • 示例:设置默认 System Message
    为 ChatClient 设置了一个默认的 system message(以海盗风格回答所有题目),如许,当 ChatClient 与模子交互时都会自动携带这条 system message,用户只需要指定 user message 即可。
  1.        @Configuration
  2.     class Config {
  3.         @Bean
  4.         ChatClient chatClient(ChatClient.Builder builder) {
  5.             return builder.defaultSystem("You are a friendly chat bot that answers question in the voice of a {voice}")
  6.                     .build();
  7.         }
  8.     }
  9.     @RestController
  10.     class AIController {
  11.       private final ChatClient chatClient
  12.       AIController(ChatClient chatClient) {
  13.         this.chatClient = chatClient;
  14.       }
  15.       @GetMapping("/ai")
  16.       Map<String, String> completion(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message, String voice) {
  17.         return Map.of(
  18.             "completion",
  19.             chatClient.prompt()
  20.                 .system(sp -> sp.param("voice", voice))
  21.                 .user(message)
  22.                 .call()
  23.                 .content());
  24.       }
  25.     }
复制代码
启动示例,通过 curl 测试效果:
  1. > curl http localhost:8080/ai?voice=='Robert DeNiro'
  2.     {
  3.         "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?"
  4.     }
复制代码

  • 其他默认设置

    • defaultOptions(ChatOptions chatOptions):传入 ChatOptions 类中界说的可移植选项或特定于模子实现的如 DashScopeChatOptions 选项。有关特定于模子的ChatOptions实现的更多信息,请参阅 JavaDocs。
    • defaultFunction(String name, String description, java.util.function.Function<I, O> function):name 用于在用户文本中引用该函数,description表明该函数的用途并帮助 AI 模子选择正确的函数以得到准确的响应,参数 function 是模子将在必要时执行的 Java 函数实例。
    • defaultFunctions(String… functionNames):应用步伐上下文中界说的 java.util.Function 的 bean 名称。
    • defaultUser(String text)、defaultUser(Resource text)、defaultUser(Consumer userSpecConsumer) 这些方法答应您界说用户消息输入,Consumer<UserSpec>答应您使用 lambda 指定用户消息输入和任何默认参数。
    • defaultAdvisors(RequestResponseAdvisor… advisor):Advisors 答应修改用于创建 Prompt 的数据,QuestionAnswerAdvisor 实现通过在 Prompt 中附加与用户文本相关的上下文信息来实现 Retrieval Augmented Generation 模式。
    • defaultAdvisors(Consumer advisorSpecConsumer):此方法答应您界说一个 Consumer 并使用 AdvisorSpec 配置多个 Advisor,Advisor 可以修改用于创建 Prompt 的最终数据,Consumer<AdvisorSpec> 答应您指定 lambda 来添加 Advisor 比方 QuestionAnswerAdvisor。

Advisors

使用上下文数据附加或扩充 Prompt,最终使用扩充后的 Prompt 与模子交互。
扩充 Prompt 的上下文数据可以是差别类型的,常见类型包罗:
- 自己的数据:这是 AI 模子尚未训练过的数据,如特定领域知识、产物文档等,即使模子已经看到过类似的数据,附加的上下文数据也会优老师成响应。
- 对话历史记载:聊天模子的 API 是无状态的,如果告诉 AI 模子您的姓名,它不会在后续交互中记住它,每次哀求都必须发送对话历史记载,以确保在生成响应时思量到先前的交互。
检索增强生成(RAG)

向量数据库存储的是 AI 模子不知道的数据,当用户题目被发送到 AI 模子时,会在向量数据库中查询与用户题目相关的文档。
来自向量数据库的响应被附加到用户消息 Prompt 中,为 AI 模子生成响应提供上下文。
假设已将数据加载到中 VectorStore,则可以通过向 ChatClient 提供 QuestionAnswerAdvisor 实例来执行检索增强生成 (RAG ) 。
  1.     ChatResponse response = ChatClient.builder(chatModel)
  2.             .build().prompt()
  3.             .advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
  4.             .user(userText)
  5.             .call()
  6.             .chatResponse();
复制代码
在此示例,SearchRequest.defaults() 将对 Vector 向量数据库中的所有文档执行相似性搜索。为了限定要搜索的文档类型。
记忆

ChatMemory 接口表示聊天对话历史记载存储,提供向对话添加消息、从对话中检索消息以及扫除对话历史记载的方法。
目条件供两种实现方式 InMemoryChatMemoryCassandraChatMemory,分别为聊天对话历史记载提供内存存储time-to-live 类型的恒久存储。
创建一个包含 time-to-live 配置的 CassandraChatMemory
  1. CassandraChatMemory.create(CassandraChatMemoryConfig.builder().withTimeToLive(Duration.ofDays(1)).build());
复制代码
以下 Advisor 实现使用 ChatMemory 接口来使用对话历史记载来增强(advice)Prompt,这些 advisor 实现在怎样将对话历史记载添加到 Prompt 的细节上有所差别。


  • MessageChatMemoryAdvisor:内存被检索并作为消息聚集添加到提示中
  • PromptChatMemoryAdvisor:检索内存并将其添加到提示的体系文本中。
  • VectorStoreChatMemoryAdvisor :构造函数VectorStoreChatMemoryAdvisor(VectorStore vectorStore, String defaultConversationId, int chatHistoryWindowSize)答应指定要从中检索聊天历史记载的 VectorStore、唯一的对话 ID、要检索的聊天历史记载的巨细(以令牌巨细为单位)。
下面的 @Service 提供了一个使用多个 Advisor 的示例实现:
  1.     import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
  2.     import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;
  3.     @Service
  4.     public class CustomerSupportAssistant {
  5.         private final ChatClient chatClient;
  6.         public CustomerSupportAssistant(ChatClient.Builder builder, VectorStore vectorStore, ChatMemory chatMemory) {
  7.         this.chatClient = builder
  8.                 .defaultSystem("""
  9.                         You are a customer chat support agent of an airline named "Funnair".", Respond in a friendly,
  10.                         helpful, and joyful manner.
  11.                         If there is a charge for the change, you MUST ask the user to consent before proceeding.
  12.                         """)
  13.                 .defaultAdvisors(
  14.                         new PromptChatMemoryAdvisor(chatMemory),
  15.                         // new MessageChatMemoryAdvisor(chatMemory), // CHAT MEMORY
  16.                         new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()),
  17.                         new LoggingAdvisor()) // RAG
  18.                 .defaultFunctions("getBookingDetails", "changeBooking", "cancelBooking") // FUNCTION CALLING
  19.                 .build();
  20.     }
  21.     public Flux<String> chat(String chatId, String userMessageContent) {
  22.         return this.chatClient.prompt()
  23.                 .user(userMessageContent)
  24.                 .advisors(a -> a
  25.                         .param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
  26.                         .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100))
  27.                 .stream().content();
  28.         }
  29.     }
复制代码
日记记载

SimpleLoggerAdvisor 是一个用于记载 ChatClient 的 request 和 response 数据 Advisor,这对于调试和监控 AI 交互非常有效。
要启用日记记载,请在创建 ChatClient 时将 SimpleLoggerAdvisor 添加到 Advisor 链中。建议将其添加到链的末尾:
  1.     ChatResponse response = ChatClient.create(chatModel).prompt()
  2.             .advisors(new SimpleLoggerAdvisor())
  3.             .user("Tell me a joke")
  4.             .call()
  5.             .chatResponse();
复制代码
要查察日记,请将 Advisor 包的日记记载级别设置为 DEBUG:
  1. org.springframework.ai.chat.client.advisor=DEBUG
复制代码
将其添加到 application.properties 或 application.yaml 文件中。
可以使用以下构造函数自界说怎样使用 SimpleLoggerAdvisor 记载来自 AdvisedRequest 和 ChatResponse 的数据:
  1.     SimpleLoggerAdvisor(
  2.         Function<AdvisedRequest, String> requestToString,
  3.         Function<ChatResponse, String> responseToString
  4.     )
复制代码
使用示例:
  1.     javaCopySimpleLoggerAdvisor customLogger = new SimpleLoggerAdvisor(
  2.         request -> "Custom request: " + request.userText,
  3.         response -> "Custom response: " + response.getResult()
  4.     );
复制代码
参考项目

紫汐AI
   综上所述,Spring AI的ChatClient是一个功能强大且灵活的客户端工具,它可以或许帮助开发者轻松地与各种AI模子进行通讯,并实现丰富的交互功能。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

知者何南

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表