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

Spring AI Alibaba ChatClient使用

一、ChatClient简介

Chat Client:https://java2ai.com/docs/1.0.0-M5.1/tutorials/chat-client/

1、ChatClient 简介

ChatClient 提供了与 AI 模型通信的 Fluent API,它支持同步和反应式(Reactive)编程模型。与 ChatModel、Message、ChatMemory 等原子 API 相比,使用 ChatClient 可以将与 LLM 及其他组件交互的复杂性隐藏在背后。

因为基于 大型语言模型 (LLM) 的应用程序通常要多个组件协同工作(例如,提示词模板、聊天记忆、LLM Model、输出解析器、RAG 组件:嵌入模型和存储),并且通常涉及多个交互,因此协调它们会让编码变得繁琐。

当然使用 ChatModel 等原子 API 可以为应用程序带来更多的灵活性,成本就是您需要编写大量样板代码。

ChatClient 类似于应用程序开发中的服务层,它为应用程序直接提供 AI 服务,开发者可以使用 ChatClient Fluent API 快速完成一整套 AI 交互流程的组装。

2、创建 ChatClient

使用 ChatClient.Builder 对象创建 ChatClient 实例,有两种方式:

  • 可以自动注入由Spring Boot 自动配置创建的默认 ChatClient.Builder 实例。
  • 也可以通过编程方式自行创建一个 ChatClient.Builder 实例并用它来得到 ChatClient 实例。
    @RestController
    public class ChatController {

      private final ChatClient chatClient;

      public ChatController(ChatClient.Builder builder) {
        this.chatClient = builder.build();
      }

      @GetMapping("/chat")
      public String chat(String input) {
        return this.chatClient.prompt()
            .user(input)
            .call()
            .content();
      }
    }

3、处理 ChatClient 响应

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

3.1 call()返回值

ChatClient.call() 方法支持几种不同类型的响应格式。

响应类型有几个选项:

  • String content():返回响应的字符串内容
  • ChatResponse chatResponse():返回ChatResponse包含多个代以及有关响应的元数据的对象,例如,使用了多少个令牌来创建响应。
  • entity 返回 Java 类型
    • entity(ParameterizedTypeReference type):用于返回实体类型的集合。
    • entity(Class type): 用于返回特定的实体类型。
    • entity(StructuredOutputConverter structuredOutputConverter): 用于指定一个实例 StructuredOutputConverter,将 String 转换为实体类型。

3.2 stream() 返回值

流式响应:ChatClient.stream() 方法是一种异步的、持续的获得模型响应的方式。

响应类型有几个选项:

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

4、定制 ChatClient 默认值

使用 ChatClient.Builder.build() 快速创建了一个 ChatClient 实例,开发者还可以通过修改 ChatClient.Builder 定制 ChatClient 实例。

注意:

  • 全局设置:创建 ChatClient 时指定的配置将作为与模型交互时的默认参数,这样可以避免每次调用都重复设置。
  • 每次请求设置:每次调用也可以设置与模型交互时的参数,每次会覆盖系统默认值。

4.1 角色预设

角色预设:我们为 ChatClient 设置了一个默认的 system message(角色预设,比如:以海盗风格回答所有问题),这样,当 ChatClient 与模型交互时都会自动携带这条 system message,用户只需要指定 user message 即可。

@Configuration
pubic 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();
        }

}

除了 defaultSystem 之外,还可以在 ChatClient.Builder 级别上指定其他默认提示。同时,在运行时使用 ChatClient 提供的不带 default 前缀的相应方法覆盖这些默认值。

二、ChatClient使用

Spring AI Alibaba快速使用:https://blog.csdn.net/qq_42402854/article/details/146350253

1、编写 Controller接口

在普通 Controller Bean 中注入 ChatClient 实例,实现下面几个功能:

  • 简单调用
  • 流式调用
  • 角色预设流式|简单调用。
@Slf4j
@RestController
@RequestMapping("/dashscope/chat-client")
public class DashScopeChatClientController {

    private static final String DEFAULT_PROMPT = "你好,介绍下你自己!";


    private final ChatClient dashScopeChatClient;

    /**
     * 使用如下的方式自动注入 ChatClient
     *
     * @param chatClientBuilder
     */
    //public DashScopeChatClientController(ChatClient.Builder chatClientBuilder) {
    //
    //    this.dashScopeChatClient = chatClientBuilder.build();
    //}

    private final ChatModel chatModel;

    /**
     * 编程方式自行创建一个 ChatClient.Builder 实例.
     * 使用自动注入 ChatModel
     *
     * @param chatModel
     */
    public DashScopeChatClientController(ChatModel chatModel) {

        this.chatModel = chatModel;

        // 构造时,可以设置 ChatClient 的参数
        // {@link org.springframework.ai.chat.client.ChatClient};
        this.dashScopeChatClient = ChatClient.builder(chatModel)
                // 实现 Chat Memory 的 Advisor
                // 在使用 Chat Memory 时,需要指定对话 ID,以便 Spring AI 处理上下文。
                .defaultAdvisors(
                        new MessageChatMemoryAdvisor(new InMemoryChatMemory())
                )
                // 实现 Logger 的 Advisor
                .defaultAdvisors(
                        new SimpleLoggerAdvisor()
                )
                // 设置 ChatClient 中 ChatModel 的 Options 参数
                .defaultOptions(
                        DashScopeChatOptions.builder()
                                .withTopP(0.7)
                                .build()
                )
                // 设置默认 System Message
                //.defaultSystem("你是一个AI搞笑段子手,以搞笑,幽默,风趣的风格回答所有的问题。")
                .build();
    }


    /**
     * ChatClient 简单调用
     */
    @GetMapping("/simple/chat")
    public String simpleChat(String userInputPrompt) {
        if (StringUtils.isBlank(userInputPrompt)) {
            userInputPrompt = DEFAULT_PROMPT;
        }
        String aiOutput = dashScopeChatClient.prompt(userInputPrompt).call().content();
        log.info("\nsimpleChat --> userInputPrompt ={}, \n aiOutput = {}", userInputPrompt, aiOutput);
        return aiOutput;
    }

    /**
     * ChatClient 流式调用。
     * 可以使大模型的输出信息实现打字机效果。
     */
    @GetMapping("/stream/chat")
    public Flux<String> streamChat(HttpServletResponse response, String userInputPrompt) {
        if (StringUtils.isBlank(userInputPrompt)) {
            userInputPrompt = DEFAULT_PROMPT;
        }
        // 避免接口返回乱码
        response.setCharacterEncoding("UTF-8");
        log.info("\n streamChat -->  userInputPrompt ={},", userInputPrompt);
        Flux<String> aiOutput = dashScopeChatClient.prompt(DEFAULT_PROMPT).stream().content();
        return aiOutput;
    }

    /**
     * 角色预设 ChatClient 流式调用。
     * 可以使大模型的输出信息实现打字机效果。
     */
    @GetMapping("/stream/chatByRole")
    public Flux<String> streamChatByRole(HttpServletResponse response, String userInputPrompt) {
        if (StringUtils.isBlank(userInputPrompt)) {
            userInputPrompt = DEFAULT_PROMPT;
        }
        // 避免接口返回乱码
        response.setCharacterEncoding("UTF-8");
        log.info("\n streamChatByRole -->  userInputPrompt ={},", userInputPrompt);
        Flux<String> aiOutput = dashScopeChatClient
                .prompt()
                .system("你是一个AI搞笑段子手,以搞笑,幽默,风趣的风格回答所有的问题。")
                .user(userInputPrompt)
                .stream().content();
        return aiOutput;
    }


}

在这里插入图片描述

– 求知若饥,虚心若愚。

相关文章:

  • 分布式中间件:基于 Redis 实现分布式锁
  • 二分查找上下界问题的思考
  • VS Code PowerShell、Windows PowerShell、CMD 的区别与联系
  • 探究Three.js中模型移动与旋转的交互逻辑
  • 《概率论与数理统计》期末复习笔记_下
  • [极客大挑战 2019]Knife——3.20BUUCTF练习day4(1)
  • 推荐算法分析
  • 文件传输之FTP协议(FTP Protocol for File Transfer)
  • EXADATA一体机新建数据库遇到的报错ORA-00603 AND ORA-27515
  • vivo 湖仓架构的性能提升之旅
  • Cadence学习笔记之---SMD焊盘、通孔焊盘、过孔制作
  • C语言-数组指针和指针数组
  • 移动WEB开发之rem适配布局
  • 基于Jina AI的研究工作,探讨提升搜索质量的两大技术:长网页最优文本段提取与URL智能重排
  • AudioTrack
  • ​「Java-API帮助文档」
  • 如何自定义知行之桥Webhook端口返回的Response消息
  • flutter 开发web端的性能优化
  • JavaScript语法与DOM操作
  • Java 记忆链表,LinkedList 的升级版
  • 因操纵乙烯价格再遭诉讼,科莱恩等四家企业被陶氏索赔60亿
  • 第十届影像上海博览会落幕后,留给中国摄影收藏的三个问题
  • 寒武纪陈天石:公司的产品力获得了行业客户广泛认可,芯片市场有望迎来新增量需求
  • 中方发布会:中美经贸高层会谈氛围是坦诚的、深入的、具有建设性的
  • 重庆三峡学院回应“中标价85万设备网购300元”:已终止采购
  • 工行回应两售出金条发现疑似杂质:情况不属实,疑似杂质应为金条售出后的外部附着物