创建首个 SpringAI 应用

创建应用

  • 从SpringAI文档上可以看到,是基于Spring Boot的,支持3.4.X、3.5.X,JDK需要17及以上。
  • 我是在 https://start.spring.io/ 上面创建了一个Spring Boot应用,选择3.5.X的版本,JDK 17的Maven应用。
  • SpringAI 选择了 1.1.0-SNAPSHOT 版本。

POM

  • 依赖管理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <properties>
    <spring.ai.version>1.1.0-SNAPSHOT</spring.ai.version>
    </properties>

    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-bom</artifactId>
    <version>${spring.ai.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>
  • 依赖引入,这里跟Spring Boot类似,需要什么依赖引入对应的starter即可。比如这里我暂时仅需要deepseek的依赖(这一步可以后面需要的时候再加也可)。

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-deepseek</artifactId>
    </dependency>
  • 如果你Maven使用的镜像拉不到依赖,可以找找其他镜像。我这里是按官方文档添加的组件仓库 repository (如果是在 https://start.spring.io/ 上面创建的,应该是自动添加好的)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <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的快照仓库,比如我自己使用的如下

    1
    2
    3
    4
    5
    6
    <mirror>
    <id>aliyunmaven</id>
    <mirrorOf>*</mirrorOf>
    <name>阿里云公共仓库</name>
    <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
  • 则需要修改成

    1
    2
    3
    4
    5
    6
    <mirror>
    <id>aliyunmaven</id>
    <mirrorOf>*,!spring-snapshots,!central-portal-snapshots</mirrorOf>
    <name>阿里云公共仓库</name>
    <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
  • 如果还不行,那可能需要科学上网。

简单使用 ChatClient

使用ChatClient调用Deepseek

  • 引入 spring-ai-starter-model-deepseek 依赖

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-deepseek</artifactId>
    </dependency>
  • 配置 api-key

    1
    2
    3
    4
    spring:
    ai:
    deepseek:
    api-key: sk-6a3e********************9bd
  • 案例:这里指定了模型的提示词为“你是一个Java专家,请帮忙解答提出的Java相关问题。”。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @Slf4j
    @Component
    @RequiredArgsConstructor
    public class CreateChatClientExample {

    private final ChatModel chatModel;

    private static final String SYSTEM_PROMPT = "你是一个Java专家,请帮忙解答提出的Java相关问题。";

    public void createChatClient(String userMessage) {
    // 创建一个 client
    ChatClient chatClient = ChatClient.create(chatModel);
    // 调用 deepseek
    String content = chatClient.prompt()
    .system(SYSTEM_PROMPT)
    .user(userMessage)
    .call()
    .content();

    log.info("\nCreate ChatClient content -> \n{}", content);
    }
    }
  • 测试及执行结果,这里问了“Java为什么要使用双亲委派模型?”

    ![image](img/2. SpringAI - ChatClient(一)/image-20250620162040724.png)

多模型使用ChatClient,调用Deepseek和OpenAi

  • Deepseek的依赖上面引入过了,这里增加OpenAi的依赖 spring-ai-starter-model-openai

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>
  • 需要增加OpenAi的配置 api-key

    1
    2
    3
    4
    5
    6
    7
    spring:
    ai:
    deepseek:
    api-key: sk-6a3e********************9bd
    openai:
    api-key: sk-proj-_Mj********************rsA

  • 这里把 ChatClient 通过 @Configuration 注入到Spring容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @Configuration
    public class ChatClientConfiguration {

    private static final String DEFAULT_PROMPT = "你是一个Java专家,请帮忙解答提出的Java相关问题。";

    @Bean
    public ChatClient deepseekClient(DeepSeekChatModel chatModel) {
    // 其实也是调用的构造者模式
    return ChatClient.create(chatModel);
    }

    @Bean
    public ChatClient openAiClient(OpenAiChatModel chatModel) {
    // 构造者模式
    return ChatClient.builder(chatModel)
    .defaultSystem(DEFAULT_PROMPT) // 默认设置一个提示词
    .build();
    }

    }
  • 案例(与上面案例类似),这里OpenAi因为设置过默认提示词,所以这里并没有设置提示词了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    @Slf4j
    @Component
    @RequiredArgsConstructor
    public class MultiChatClientExample {

    private final ChatClient deepseekClient;

    private final ChatClient openAiClient;

    private static final String SYSTEM_PROMPT = "你是一个Java专家,请帮忙解答提出的Java相关问题。";

    public void multiChatClient(String userMessage) {
    String content = deepseekClient.prompt()
    .system(SYSTEM_PROMPT)
    .user(userMessage)
    .call()
    .content();
    log.info("\nDeepseek result content -> \n{}", content);


    content = openAiClient.prompt()
    .user(userMessage)
    .call()
    .content();
    log.info("\nOpenAi result content -> \n{}", content);
    }
    }
  • 测试及结果,这里问的是“Java 有锁为什么还需要volatile关键字?”

    Deepseek

    OpenAi

使用stream模式

  • 非常简单,将上面案例中吊用.call()换成.stream()即可。比较简单,输出结果也就记录了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @Slf4j
    @Component
    @RequiredArgsConstructor
    public class StreamChatClientExample {

    private final ChatClient deepseekClient;

    private static final String SYSTEM_PROMPT = "你是一个Java专家,请帮忙解答提出的Java相关问题。";

    public void streamExample(String userMessage) {
    deepseekClient.prompt()
    .system(SYSTEM_PROMPT)
    .user(userMessage)
    // 使用 stream 模式
    .stream()
    // 返回的是Flux<String>
    .content()
    // 直接订阅后通过日志打印出来了
    .doOnNext(log::info)
    .subscribe();
    }
    }

总结

  • 通过上面案例就可以简单的使用ChatClient调用相应模型了,使用不同AI模型引入不同的starter即可。
  • 从案例中可以看到,不同的AI模型其实就对应着不同的ChatModel,且由SpringAI是自动装配了的。是可以通过配置关闭装配的,相关配置后面在学习模型的时候再继续学习。
  • 这里只学习使用了一些最基本的操作,响应结果直接取的字符串content、构造者模式也只使用默认的提示词;所以更多的操作还需要深入学习。

最后

  • 所有案例的源码,都会提交在GitHub上。包:com.spring.ai.example.client.one