SpringAI ChatClient Fluent API详解及使用指南

ChatClient提供了fluent API用于与AI模型进行通信,支持同步和流式编程模型。

  1. 创建ChatClient的两种方式:
  • builder:ChatClient.Builder builder = ChatClient.builder(myChatModel).build();允许对ChatClient进行详细地定制,包括可以设置系统prompt和用户prompt以及一些其他的选项等等。
  • create:ChatClient chatClient = ChatClient.create(myChatModel); 简化版的快捷创建方法,适合不需要太多自定义的情况。

注:Fluent API 是一种面向对象的 API 设计风格,它通过方法链(method chaining)的方式让代码更易读、更流畅地表达逻辑。

  1. ChatClient fluent API 允许使用三种不同的方法创建prompt:
  • Prompt():没有参数,使用fluent API构建完整的提示。 例如:
    String response = chatClient.prompt()
        .system("You are a helpful assistant.")
        .user("Explain quantum computing in simple terms.")
        .call()
        .content();
    
  • prompt(Prompt prompt):接收一个完整的prompt,用于已经有一个构造好的prompt对象的场景。
  • prompt(String content):只传入用户输入,不需要其他高级功能,用于快速构建简单的prompt
  1. ChatClient API提供了多种使用流畅 API 格式化 AI 模型响应的方法。
  • ChatResponse:包含响应生成相关的元数据,包括token数量,结束的原因,返回来的实际数据等等。
  • Entity:将AI模型的返回数据封装成想要的实体,需要传入实体的类。 例如:
    ActorFilms actorFilms = chatClient.prompt()
        .user("Generate the filmography for a random actor.")
        .call()
        .entity(EntityClass.class);
    
  • Stream:使用stream()方法可以获得异步响应,这里我觉得并非是一种实际的格式,只是一种数据返回的形式。
  1. Prompt Templates:ChatClient fluent API允许提供用户和系统文本作为模板,并在运行时替换变量。 例如:
String answer = ChatClient.create(chatModel).prompt()
    .user(u -> u
        .text("Tell me the names of 5 movies whose soundtrack was composed by {composer}")
        .param("composer", "John Williams"))
    .call()
    .content();
  1. 返回值:
  • String content:返回的是AI模型实际响应的字符串 例如:
    String result = chatClient.prompt()
        .user("What is the capital of France?")
        .call()
        .content();
    System.out.println(result); // 输出类似:"The capital of France is Paris."
    
  • Entity:返回的是你给出的实体类的一个实体对象
  • ChatResponse:ChatResponse对象,包含更多的元信息
    ChatResponse response = chatClient.prompt()
        .user("Explain quantum computing in simple terms.")
        .call()
        .chatResponse();
    
  • ChatClientResponse:这是最全面的响应对象,不仅包含 ChatResponse,还包含整个请求执行过程中的一些附加信息(如 RAG 中检索到的文档) 注:这种返回类型虽然SpringAI框架文档中提到了,但是在我用1.0.0-M6中没有这个返回方法。
  • 上述所说的返回值是call()方法的返回值,stream流式请求同理,但是stream没有提到Entity返回方法。
  1. ChatClient中的一些默认值设置
  • 默认的system text:在构建chatClient的时候设置默认system text(像一个“角色设定”或“人格模板”,在每次对话中都会被 AI 使用,决定它的语气、风格和行为方式。) 例如:
    @Configuration
    class Config {
    
        @Bean
        ChatClient chatClient(ChatClient.Builder builder) {
            return builder.defaultSystem("You are a friendly chat bot that answers question in the voice of a Pirate")
                    .build();
        }
    
    }
    
  • defaultFunction(String name, String description, java.util.function.Function function):这个方法允许在 Java 应用中定义一个“外部函数”,然后把这个函数的能力告诉 AI 模型。这样,当用户输入需要调用这个函数时,AI 模型会自动识别并调用它。
  • defaultOptions(ChatOptions chatOptions):传入ChatOptions类中定义的可移植选项或模型特定的选项例如 OpenAiChatOptions。
  • defaultFunctions(String… functionNames):应用程序上下文中定义的 java.util.Function 的 bean 名称。
  1. Advisors:Advisor是SpringAI提供的一种拦截机制,可以在请求前对请求进行处理,或者请求后对结果进行处理。
  • 常用场景包括:
    • 添加对话历史(让模型记住上下文)
    • 插入外部数据(如文档、数据库内容)——这是 RAG 的核心
    • 修改系统提示词
    • 记录日志、统计 token 使用等

Advisor配置接口AdvisorSpec:

interface AdvisorSpec {
    AdvisorSpec param(String k, Object v);      
    AdvisorSpec params(Map p);  
    AdvisorSpec advisors(Advisor... advisors);  
    AdvisorSpec advisors(List advisors);
}
  • 添加advisor的顺序很重要,因为在实行过程中,是按照添加顺序执行的。

几种常见的 Advisor 实现类

  1. MessageChatMemoryAdvisor
  • 将记忆作为一组 Message(角色+内容)插入到 prompt 中。
  • 适合保留完整的对话结构(用户说的、AI 回答的)。
  1. PromptChatMemoryAdvisor
  • 把记忆内容插入到系统提示词(system message)中。
  • 适用于只需要简单摘要式历史的情况。
  1. QuestionAnswerAdvisor
  • 结合 VectorStore 使用,实现 RAG(Retrieval-Augmented Generation)。
  • 根据用户问题检索相关文档并插入 prompt。

Advisor示例:

@Service
public class CustomerSupportAssistant {
  
  private final ChatClient chatClient;
  
  public CustomerSupportAssistant(ChatClient.Builder builder, VectorStore vectorStore, ChatMemory chatMemory) {
  
      this.chatClient = builder
          .defaultSystem("""
              You are a customer chat support agent of an airline named \"Funnair\".
              Respond in a friendly, helpful, and joyful manner.
  
              Before providing information about a booking or cancelling a booking,
              you MUST always get the following information from the user:
              booking number, customer first name and last name.
  
              Before changing a booking you MUST ensure it is permitted by the terms.
  
              If there is a charge for the change, you MUST ask the user to consent before proceeding.
              """)
          .defaultAdvisors(
              new MessageChatMemoryAdvisor(chatMemory), // CHAT MEMORY
              new QuestionAnswerAdvisor(vectorStore),   // RAG
              new SimpleLoggerAdvisor()                 // LOGGING
          )
          .defaultFunctions("getBookingDetails", "changeBooking", "cancelBooking") // FUNCTION CALLING
          .build();
  }
  
  public Flux 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();
  }
}

你可能感兴趣的:(SpingAI框架,SpringAI,ChatClient,Fluent,API,Java,AI模型,编程)