Spring AI开发跃迁指南(第二章:极速上手——ChatClient20行代码构建人工智能应用)

在这里插入图片描述


1.版本引入

在第一章的第五小节已经介绍了Spring AI所需要的java版本及spring boot的版本,接下来我们spring AI所有的依赖皆使用1.0.0-M7版本(1.0.0-SNAPSHOT还有些小问题)。

  • 引入spring官方repository
<repositories>
  <repository>
    <id>spring-snapshots</id>
    <name>Spring Snapshots</name>
    <url>https://repo.spring.io/snapshot</url>
    <releases>
      <enabled>false</enabled>
    </releases>
  </repository>
  <repository>
    <name>Central Portal Snapshots</name>
    <id>central-portal-snapshots</id>
    <url>https://central.sonatype.com/repository/maven-snapshots/</url>
    <releases>
      <enabled>false</enabled>
    </releases>
    <snapshots>
      <enabled>true</enabled>
    </snapshots>
  </repository>
</repositories>	

  • 引入spring AI的dependencyManagement
	<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.0.0-M7</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
  • 引入springboot
	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-parent</artifactId>
        <version>3.4.0</version>
    </parent>
  • 引入大模型客户端

    本次测试我们都使用minimax大模型作测试

 	<dependency>
         <groupId>org.springframework.ai</groupId>
         <artifactId>spring-ai-starter-model-minimax</artifactId>
     </dependency>

2.创建Chat client及使用

使用大模型API需要创建此大模型的API KEY,每个模型都要去其官网申请,minmax申请 (登陆后在“我的”那块申请)
在这里插入图片描述

2.1.手动配置

手动配置只使用spring-ai-minimax包,而不需要使用springboot相关的容器等,其他所有的的大模型客户端都是一样的,其springboot集成的spring-ai-starter-model-minimax客户端都包含spring-ai-minimax包。

  • spring-ai-starter-model-minimax依赖关系
    在这里插入图片描述

  • 千帆spring-ai-starter-model-qianfan依赖关系
    在这里插入图片描述


  • 调用minmax大模型 API ->>
package com.service;

import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.minimax.MiniMaxChatModel;
import org.springframework.ai.minimax.MiniMaxChatOptions;
import org.springframework.ai.minimax.api.MiniMaxApi;

public class TestChatClient {
    public void createChatClient() {
        // 创建客户端
        var miniMaxApi = new MiniMaxApi("你的API KEY");
        // 配置客户端
        var chatModel = new MiniMaxChatModel(miniMaxApi, MiniMaxChatOptions.builder()
                .model(MiniMaxApi.ChatModel.ABAB_6_5_S_Chat.getValue())
                .temperature(0.4)
                .maxTokens(200)
                .build());
        // 配置提示词
        var prompt = new Prompt("你是谁");
        var response = chatModel.call(prompt);
        System.out.println(response.getResult().getOutput().getText());
    }
    public static void main(String[] args) {
        var testChatClient = new TestChatClient();
        testChatClient.createChatClient();
    }

输出:
在这里插入图片描述

2.2. Spring Boot 自动配置

ChatClient提供了流畅的 API 用于与 AI 模型进行通信。它支持同步和流式编程模型。ChatClient使用对象创建。ChatClient.Builder中可以获取任何Spring Boot ChatModel`自动配置的实例,也可以通过编程方式创建一个。


  • application.properties配置
spring.ai.minimax.api-key=你的API KEY
spring.ai.minimax.chat.options.model=abab6.5s-chat
spring.ai.minimax.chat.options.temperature=0.4

  • service及其实现类
package com.service;

public interface TestSpringAIService {
    String generate(String message);
}

serviceImpl实现类:

package com.service.impl;

import com.service.TestSpringAIService;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

@Service
public class TestSpringAIServiceImpl implements TestSpringAIService {
    private final ChatClient chatClient;
	// 通过ChatClient.Builder自动注入
    public TestSpringAIServiceImpl(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    @Override
    public String generate(String message) {
        return chatClient.prompt().user(message).call().content();
    }
}

[!NOTE]

  • AI 模型主要有两种类型的提示词:系统提示词SystemPrompt )和用户提示词UserPrompt ),前者优先级高于后者。

  • 这些提示词通常包含占位符,这些占位符会在运行时根据用户输入进行替换,以定制 AI 模型对用户输入的响应。

  • 可以指定提示词选项,例如要使用的 AI 模型的名称以及控制生成输出的随机性创造性的温度设置


  • controller层
package com.controller;

import com.service.TestSpringAIService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class TestSpringAIController {
    @Autowired
    private TestSpringAIService service;
    
    @GetMapping("/ai/generate")
    public String generate(@RequestParam(value = "message", defaultValue = "你是谁") String message) {
        return service.generate(message);
    }
}
  • 运行结果

在这里插入图片描述

3.ChatClient进阶详解

3.1.ChatClient提示词构建

ChatClientFluent API提供了三种不同的方式来创建提示词,通过重载prompt方法启动Fluent API流程:

在这里插入图片描述

三种函数都返回ChatClientRequestSpec类型,后续都可以使用Fluent API的方式继续构建系统提示词和用户提示词

3.2.ChatClient请求响应

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

3.2.1.同步响应

AI模型的响应是ChatResponse类型。它是spring-ai-model包中的类,也是上面我们2.1章节中调用大模型响应的类型。所有spring基础的大模型包返回的都是这个类型,spring boot集成的大模型包再此基础上做了一层包装组合。其ChatClientRequestSpec.call()方法返回的是ChatClient.CallResponseSpec接口类型,该接口中存在获取ChatResponse的接口、content和映射为Entity<T.class>实体类的方法。

public interface CallResponseSpec {
        @Nullable
        <T> T entity(ParameterizedTypeReference<T> type);

        @Nullable
        <T> T entity(StructuredOutputConverter<T> structuredOutputConverter);

        @Nullable
        <T> T entity(Class<T> type);

        @Nullable
        ChatResponse chatResponse(); // 获取ChatResponse定义的接口

        @Nullable
        String content();

        <T> ResponseEntity<ChatResponse, T> responseEntity(Class<T> type);

        <T> ResponseEntity<ChatResponse, T> responseEntity(ParameterizedTypeReference<T> type);

        <T> ResponseEntity<ChatResponse, T> responseEntity(StructuredOutputConverter<T> structuredOutputConverter);
    }
3.2.1.1.返回ChatResponse
ChatResponse chatResponse = chatClient.prompt()
    .user("你是谁")
    .call()
    .chatResponse();
public class ChatResponse implements ModelResponse<Generation> {
    // 包含有关响应生成方式的元数据
    private final ChatResponseMetadata chatResponseMetadata;
    // 多个响应
    private final List<Generation> generations;
    ......
}

[!NOTE]

元数据包含用于创建响应的令牌数量(每个令牌大约占一个单词的 3/4)。此信息非常重要,因为托管的 AI 模型会根据每个请求使用的令牌数量收费。

3.2.1.2.返回Entity<T.class>

此返回方式可以将返回内容String映射成一个实体类Entity,他会自动识别返回内容与实体类的关系并做映射。

如下面的示例:

message为“生成一个中国女演员及其电影作品”,controller层我们省略。

  1. 直接返回String
    public String generate(String message) {
        return chatClient.prompt().user(message).call().content();
    }

返回值:

中国女演员:赵丽颖 电影作品: 1. 《乘风破浪》(2017年):在这部电影中,赵丽颖饰演小花,一个温柔贤惠的妻子和母亲,与邓超饰演的角色有一段感人的爱情故事。 2. 《西游记之女儿国》(2018年):赵丽颖在这部魔幻喜剧电影中扮演女儿国国王,与冯绍峰饰演的唐僧有一段跨越种族和信仰的爱情。 3. 《密战》(2017年):在这部谍战片中,赵丽颖饰演地下工作者兰芳,与郭富城饰演的角色共同为抗战胜利而奋斗。 4. 《新永不消逝的电波》(2019年):赵丽颖在这部战争片中扮演共产党员何兰芬,与佟大为饰演的角色一起在敌后进行秘密电报工作。 5. 《刺杀小说家》(2021年):在这部奇幻动作电影中,赵丽颖饰演反派角色屠灵,与雷佳音、杨幂等演员共同演绎一场关于现实与小说世界的冒险故事

  1. 使用Entity映射

实体类:

package com.model;

import java.util.List;

public class ActorFilmsModel {
    private String actor;
    private List<String> movies;

    public ActorFilmsModel() {

    }

    public ActorFilmsModel(String actor, List<String> movies) {
        this.actor = actor;
        this.movies = movies;
    }
	// 此处省略set and get
}

service调用并映射:

    public ActorFilmsModel generateActorFilms(String message) {
         var res= chatClient.prompt()
                .user(message)
                .call();
        return res.entity(ActorFilmsModel.class);
    }

返回值:

{
    "actor": "赵薇",
    "movies": [
        "致我们终将逝去的青春",
        "画皮",
        "亲爱的",
        "天下无贼"
    ]
}

根据两次返回值的判断,我们充分感觉到返回Entity类映射会对返回值做处理,提取相关的内容映射到Entity<T.class>实体类中。

还有一种entity带有签名的重载方法entity(ParameterizedTypeReference<T> type),可让指定诸如通用列表之类的类型:

List<ActorFilms> actorFilms = chatClient.prompt()
    .user("生成两位中国女演员及其电影作品")
    .call()
    .entity(new ParameterizedTypeReference<List<ActorFilmsModel>>() {});

返回结果:

[
    {
        "actor":"赵薇",
        "movies":["致我们终将逝去的青春","画皮"]},
    {
        "actor":"周迅",
        "movies":["如果・爱","李米的猜想"]
    }
]
3.2.2.流式响应

stream()方法可让获得异步响应。

Flux<String> output = chatClient.prompt()
    .user("你是谁")
    .stream()
    .content();

stream()方法返回StreamResponseSpec接口类型,其中有两个接口:

	interface StreamResponseSpec {
		Flux<ChatResponse> chatResponse(); //返回由AI模型生成的字符串的Flux

		Flux<String> content(); // 返回ChatResponse对象的Flux,该对象包含有关响应的附加元数据
	}

ChatResponse还可以使用该方法进行流式传输Flux<ChatResponse> chatResponse()

spring ai也提供了一种更便捷的方法,使用响应式stream()方法返回 Java 实体的同时使用结构化输出转换器(Structured Output Converter)显式转换聚合响应。

例如:

public String generateStream() {
        var converter = new BeanOutputConverter<>(new ParameterizedTypeReference<List<ActorFilmsModel>>() {
        });

        Flux<String> flux = this.chatClient.prompt()
                .user(u -> u.text("""
                                  生成一位中国女演员及其电影作品
                                  {format}
                                """)
                        .param("format", converter.getFormat()))
                .stream()
                .content();

        return flux.collectList().block().stream().collect(Collectors.joining());
    }

返回值:

{
    "actor": "赵薇",
    "movies": [
        "致我们终将逝去的青春",
        "画皮",
        "亲爱的",
        "天下无贼"
    ]
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值