spring ai入门教程一

Spring AI入门教程(一):简介与ChatClient API详解


一、引言:什么是Spring AI

随着生成式人工智能的爆发,Python 生态中出现了 LangChain、LlamaIndex 等优秀框架,但 Java 开发者却缺乏类似的原生支持。Spring AI 的出现填补了这一空白。

Spring AI 是 Spring 社区推出的一个旨在简化 AI 应用程序开发的框架。它借鉴了 Python 项目的思想,但并非简单移植,而是为 Java 开发者量身打造了一套与 AI 模型交互的标准化 API。其核心理念是:将企业数据和 API 与 AI 模型无缝连接,帮助开发者用熟悉的 Spring 范式快速构建 AI 应用,避免陷入复杂的底层实现。

Spring AI 支持主流的大语言模型(如 OpenAI、DeepSeek、智谱AI 等),并提供了模型抽象、提示模板、检索增强生成(RAG)、工具调用(Tool Calling)等一系列高级功能的封装。


二、快速认知:几个核心概念

在深入代码之前,让我们先快速了解几个 Spring AI 中的重要概念:

  • 模型(Model):指各类 AI 算法,如文本生成、图像生成、嵌入向量等。Spring AI 当前重点支持语言、图像、音频三种输入输出类型。
  • 提示(Prompt):与模型交互的输入。不同于简单字符串,Spring AI 支持多角色(系统、用户、助手)的提示结构。
  • 提示模板(Prompt Template):利用模板引擎(如 StringTemplate)动态填充提示中的变量,类似 Spring MVC 中的视图。
  • 嵌入(Embedding):将文本转换为浮点数向量,用于衡量语义相似度,是实现 RAG 的基础。
  • Token:模型计费和上下文限制的基本单位。1 个 token 约等于 0.75 个英文单词。
  • 结构化输出(Structured Output):将模型生成的字符串解析为 Java 对象(如 JSON → POJO)。
  • RAG(检索增强生成):将私有数据分段存入向量数据库,并检索相关片段补充到提示中,使模型能回答训练数据之外的问题。
  • 工具调用(Tool Calling):允许模型调用外部 API(如查询天气、发送邮件),扩展模型能力。

对于入门而言,你只需先理解 模型、提示、结构化输出 即可,其余概念将在后续教程中展开。


三、快速开始:搭建第一个 Spring AI 项目
3.1 创建 Maven 项目并添加依赖

使用 Spring Boot 3.x,并引入 Spring AI 的 BOM 及对应的模型 starter(以 DeepSeek 和智谱AI 为例)。

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.14</version>   <!-- 请使用你实际可用的版本 -->
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-ai-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <java.version>17</java.version>
        <spring-ai.version>1.1.6</spring-ai.version>
    </properties>
    <dependencies>
        <!-- Spring Boot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Lombok(可选) -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- Spring AI DeepSeek Starter -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-deepseek</artifactId>
        </dependency>
        <!-- Spring AI 智谱AI Starter -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-zhipuai</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <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>
</project>

注意 :实际使用时,请将 spring-ai.version 替换为官方最新版本。

3.2 配置文件 application.yaml

配置多个模型(DeepSeek 和智谱AI),注意 API Key 建议使用环境变量,切勿硬编码到代码中。

yaml 复制代码
spring:
  application:
    name: spring-ai-demo
  ai:
    chat:
      client:
        enabled: false   # 本教程手动配置 ChatClient Bean,故禁用自动配置
    deepseek:
      base-url: https://api.deepseek.com
      api-key: ${DEEPSEEK_API_KEY}   # 从环境变量读取
      chat:
        enabled: true
        options:
          model: deepseek-chat
          temperature: 0.7
    zhipuai:
      api-key: ${ZHIPU_API_KEY}
      chat:
        enabled: true
        options:
          model: glm-4-flash
          temperature: 0.7

server:
  port: 8188
3.3 配置 ChatClient Bean

ChatClient 是 Spring AI 的核心 API,它提供了流式构建器风格的方法。我们需要为每个模型创建独立的 ChatClient 实例。

java 复制代码
package com.example.config;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.ai.zhipuai.ZhiPuAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ChatClientConfig {

    @Bean
    public ChatClient deepSeekChatClient(DeepSeekChatModel chatModel) {
        return ChatClient.create(chatModel);
    }

    @Bean
    public ChatClient zhiPuAiChatClient(ZhiPuAiChatModel chatModel) {
        return ChatClient.create(chatModel);
    }
}

至此,项目环境已准备就绪,下面正式进入 ChatClient API 的使用。


四、ChatClient API 详解与实战

ChatClient 采用了流畅的建造者模式,核心方法包括:

  • prompt():开始构建提示。
  • user() / system():添加用户或系统角色消息。
  • call():同步调用并获取 ChatResponsecontent()
  • stream():异步流式调用。
  • entity():将模型输出直接映射为 Java 对象。
  • metadata():为消息附加元数据。

下面通过一个 RestController 来展示各种用法。

4.1 基础对话:选择合适的模型
java 复制代码
@RestController
@Slf4j
public class ChatController {

    @Resource(name = "deepSeekChatClient")
    private ChatClient deepSeekClient;

    @Resource(name = "zhiPuAiChatClient")
    private ChatClient zhiPuClient;

    @RequestMapping("/chat")
    public String chat(String question, String model) {
        ChatClient client = "deepSeek".equals(model) ? deepSeekClient : zhiPuClient;
        return client.prompt(question).call().content();
    }
}

访问 http://localhost:8188/chat?question=你好&model=deepSeek 即可获得回答。

4.2 多客户端流程演示

有时我们需要同时使用不同的 API Key 或不同模型进行对比,可以手动创建 ChatClient 实例。

java 复制代码
@Resource
private ZhiPuAiChatModel zhiPuAiChatModel;  // 注入默认配置的模型

@RequestMapping("/multi-client")
public String multiClientDemo() {
    // 创建第二个独立配置的智谱模型 (glm-4-plus)
    ZhiPuAiApi api2 = ZhiPuAiApi.builder()
            .apiKey("your-second-api-key")
            .build();
    ZhiPuAiChatModel model2 = new ZhiPuAiChatModel(api2,
            ZhiPuAiChatOptions.builder().model("glm-4-plus").temperature(0.8).build());
    ChatClient client2 = ChatClient.create(model2);

    String response1 = zhiPuAiChatModel.call("介绍一下人工智能").getResult().getOutput().getText();
    String response2 = client2.prompt("介绍一下人工智能").call().content();

    return "Default Model: " + response1 + "\n\nCustom Model: " + response2;
}
4.3 返回结构化实体

AI 模型的原始输出是字符串,但我们可以通过 entity() 方法并提供一个 POJO 类,让 Spring AI 自动将输出解析为对象。这背后使用了精心构造的提示词和 JSON 转换器。

定义实体类:

java 复制代码
public record ActorFilms(String actor, List<String> movies) {}

控制器方法:

java 复制代码
@RequestMapping("/entity")
public ActorFilms getActorFilms(@RequestParam(defaultValue = "周星驰") String actorName) {
    return zhiPuClient.prompt()
            .user("请生成演员" + actorName + "的代表作电影列表,包含5部电影")
            .call()
            .entity(ActorFilms.class);
}

返回 List 泛型时需要使用 ParameterizedTypeReference

java 复制代码
@RequestMapping("/entity-list")
public List<ActorFilms> getActorList() {
    return zhiPuClient.prompt()
            .user("生成 Tom Hanks 和 Leonardo DiCaprio 的电影列表,每人5部")
            .call()
            .entity(new ParameterizedTypeReference<List<ActorFilms>>() {});
}
4.4 流式响应

对于长文本生成,流式输出能提升用户体验。返回类型需设置为 text/event-stream

java 复制代码
@RequestMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamResponse(@RequestParam(defaultValue = "讲一个故事") String question) {
    return zhiPuClient.prompt(question).stream().content();
}

如果需要获取完整的 ChatResponse 对象(包含 token 使用量等元数据):

java 复制代码
@RequestMapping(value = "/stream-response", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ChatResponse> streamChatResponse(@RequestParam(defaultValue = "讲一个笑话") String question) {
    return zhiPuClient.prompt(question).stream().chatResponse();
}
4.5 使用元数据标记消息

metadata() 可以为系统或用户消息附加额外的键值对信息,便于追踪、调试或下游处理。

java 复制代码
@RequestMapping("/metadata")
public String metadataDemo() {
    return zhiPuClient.prompt()
            .system(s -> s.text("你是一个技术客服")
                    .metadata("agentId", "agent-001")
                    .metadata("version", "2.0"))
            .user(u -> u.text("Spring AI 如何配置多模型?")
                    .metadata("userId", "12345")
                    .metadata("sessionId", UUID.randomUUID().toString()))
            .call()
            .content();
}
相关推荐
jaychouchannel1 小时前
RecursiveCharacterTextSplitter 中文切分隐形缺陷:重叠、断语义、列表割裂完整复现与修复
人工智能·机器学习
掉鱼的猫1 小时前
用 ChatModel 构建 LLM 驱动的 Java 应用
java·llm
用户938515635071 小时前
手把手教你实现一个 MCP 文件读取服务器:从协议到代码的深度解析
javascript·人工智能
4154111 小时前
JTS 空间运算实战:线 × 线、线 × 面、面 × 面叠加分析
java·jts·叠加分析
matlab代码1 小时前
基于CNN卷积神经网络手写汉字识别系统 (GUI界面)【源码38期】
人工智能·神经网络·cnn·汉字识别
用户938515635071 小时前
RAG 实战:从零搭建语义搜索系统,彻底告别关键词匹配的尴尬
javascript·人工智能
EMA1 小时前
Rag中Query改写的实践方案总结
人工智能
阿部多瑞 ABU1 小时前
论“轻小说”之异化
人工智能
墨染天姬1 小时前
【AI】opencode 使用手册
人工智能