在前两篇教程中,我们介绍了 Spring AI 的基本概念以及如何使用 ChatClient 与智谱 AI 等大模型进行对话。本文将深入探讨三个实用的功能模块:文本嵌入(Embeddings)图像生成(Image Generation) 以及 聊天记忆(Chat Memory)。这些功能可以极大地增强你的 AI 应用能力,例如实现语义搜索、自动生成图片以及维护多轮对话的上下文。


1. 准备工作:项目依赖与配置

1.1 修改后的 pom.xml

在开始之前,请确保你的 Maven 项目包含以下依赖(基于 Spring Boot 3.5.14 和 Spring AI 1.1.6):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
    <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>cn.dianyu.ai</groupId>
    <artifactId>my-spring-ai</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 Starter -->
        <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 JDBC 支持 (用于 Chat Memory 持久化) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- DeepSeek 模型 (可选) -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-deepseek</artifactId>
        </dependency>
        <!-- 智谱模型 (包含 Chat、Embedding、Image) -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-zhipuai</artifactId>
        </dependency>
        <!-- Chat Memory JDBC Repository -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
        </dependency>
        <!-- H2 内存数据库 (用于测试,生产可替换为 MySQL/PostgreSQL) -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </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>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-configuration-processor</artifactId>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

说明:添加 spring-boot-starter-jdbc 是为了让 Spring Boot 自动配置 DataSourceJdbcTemplate,从而 JdbcChatMemoryRepository 能够正常工作。

1.2 application.yml 完整配置

server:
  port: 8188

spring:
  application:
    name: my-spring-ai
  # 数据源配置(用于 Chat Memory JDBC)
  datasource:
    url: jdbc:h2:mem:chatdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    driver-class-name: org.h2.Driver
    username: sa
    password:
  h2:
    console:
      enabled: true
      path: /h2-console
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  ai:
    # 智谱 AI 通用配置
    zhipuai:
      api-key: your-zhipuai-api-key   # 请替换为真实 key
      chat:
        enabled: true
        options:
          model: glm-4.5-air
          temperature: 0.7
      embedding:
        enabled: true
        options:
          model: embedding-2            # 或 embedding-3
          # dimensions: 2048            # 仅 embedding-3 支持
      image:
        enabled: true
        options:
          model: cogview-3
    # 聊天记忆 JDBC 仓库初始化
    chat:
      memory:
        repository:
          jdbc:
            initialize-schema: always   # 自动创建表

# 可选:DeepSeek 配置(若同时使用)
# spring.ai.deepseek.api-key=...

2. 文本嵌入模型 API(Embeddings Model API)

2.1 什么是嵌入(Embeddings)?

嵌入是将文本、图像或视频等内容转换为浮点数数组(称为向量)的过程。这些向量能够捕捉输入内容之间的语义关系。通过计算两个向量的数值距离(例如余弦相似度),我们可以判断原始内容的相似程度。

Spring AI 提供了 EmbeddingModel 接口,旨在以统一的方式集成各种嵌入模型。该接口的设计遵循两大原则:

  • 可移植性:只需更改配置即可切换不同的嵌入模型,无需修改业务代码。
  • 简单性:提供 embed(String text)embed(Document document) 等简洁方法,隐藏底层向量化算法的复杂性。

2.2 使用示例:EmbeddingController

以下控制器演示了如何获取单个/多个文本的嵌入向量,以及基于余弦相似度计算两个文本的相似度。

package cn.dianyu.ai.myspringai.embedding;

import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/embedding")
public class EmbeddingController {

    private final EmbeddingModel embeddingModel;

    public EmbeddingController(EmbeddingModel embeddingModel) {
        this.embeddingModel = embeddingModel;
    }

    @GetMapping("/single")
    public Map<String, Object> embedSingle(@RequestParam(defaultValue = "Hello World") String message) {
        EmbeddingResponse response = embeddingModel.embedForResponse(List.of(message));
        return Map.of("message", message, "embedding", response);
    }

    @GetMapping("/multiple")
    public Map<String, Object> embedMultiple() {
        List<String> texts = List.of("Hello World", "Spring AI is powerful", "ZhiPuAI provides great embedding");
        EmbeddingResponse response = embeddingModel.embedForResponse(texts);
        return Map.of("texts", texts, "embedding", response);
    }

    @GetMapping("/similarity")
    public Map<String, Object> similarity(@RequestParam String text1, @RequestParam String text2) {
        float[] vec1 = embeddingModel.embed(text1);
        float[] vec2 = embeddingModel.embed(text2);
        double similarity = cosineSimilarity(vec1, vec2);
        return Map.of("text1", text1, "text2", text2, "similarity", similarity);
    }

    private double cosineSimilarity(float[] v1, float[] v2) {
        double dot = 0, n1 = 0, n2 = 0;
        for (int i = 0; i < v1.length; i++) {
            dot += v1[i] * v2[i];
            n1 += v1[i] * v1[i];
            n2 += v2[i] * v2[i];
        }
        return dot / (Math.sqrt(n1) * Math.sqrt(n2));
    }
}

提示:嵌入向量通常用于向量数据库检索、语义缓存或聚类分析。Spring AI 还提供了 VectorStore 抽象,可以配合 EmbeddingModel 实现检索增强生成(RAG)。

2.3 自动装配原理:ZhiPuAiEmbeddingAutoConfiguration

Spring AI 为智谱 AI 的嵌入模型提供了开箱即用的自动配置。理解这个配置类的原理有助于你进行自定义和故障排查。

该配置类位于 org.springframework.ai.zhipuai.autoconfigure 包中,源码如下(简化):

@AutoConfiguration(after = { RestClientAutoConfiguration.class, SpringAiRetryAutoConfiguration.class })
@ConditionalOnClass(ZhiPuAiApi.class)   // 条件1:类路径存在 ZhiPuAiApi
@ConditionalOnProperty(name = SpringAIModelProperties.EMBEDDING_MODEL,
        havingValue = SpringAIModels.ZHIPUAI, matchIfMissing = true)  // 条件2:配置项 spring.ai.embedding.model=zhipuai
@EnableConfigurationProperties({ ZhiPuAiConnectionProperties.class, ZhiPuAiEmbeddingProperties.class })
public class ZhiPuAiEmbeddingAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public ZhiPuAiEmbeddingModel zhiPuAiEmbeddingModel(
            ZhiPuAiConnectionProperties commonProperties,
            ZhiPuAiEmbeddingProperties embeddingProperties,
            ObjectProvider<RestClient.Builder> restClientBuilderProvider,
            ObjectProvider<WebClient.Builder> webClientBuilderProvider,
            RetryTemplate retryTemplate,
            ResponseErrorHandler responseErrorHandler,
            ObjectProvider<ObservationRegistry> observationRegistry,
            ObjectProvider<EmbeddingModelObservationConvention> observationConvention) {

        // 1. 解析最终使用的 baseUrl 和 apiKey(优先使用 embedding 专用,否则回退通用)
        String resolvedBaseUrl = StringUtils.hasText(embeddingProperties.getBaseUrl()) ?
                embeddingProperties.getBaseUrl() : commonProperties.getBaseUrl();
        String resolvedApiKey = StringUtils.hasText(embeddingProperties.getApiKey()) ?
                embeddingProperties.getApiKey() : commonProperties.getApiKey();

        // 2. 构建 ZhiPuAiApi 实例(底层 HTTP 客户端)
        var zhiPuAiApi = ZhiPuAiApi.builder()
                .baseUrl(resolvedBaseUrl)
                .apiKey(new SimpleApiKey(resolvedApiKey))
                .restClientBuilder(restClientBuilderProvider.getIfAvailable(RestClient::builder))
                .webClientBuilder(webClientBuilderProvider.getIfAvailable(WebClient::builder))
                .responseErrorHandler(responseErrorHandler)
                .build();

        // 3. 创建 ZhiPuAiEmbeddingModel 并设置可观测性
        var embeddingModel = new ZhiPuAiEmbeddingModel(zhiPuAiApi,
                embeddingProperties.getMetadataMode(),
                embeddingProperties.getOptions(),
                retryTemplate,
                observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP));
        observationConvention.ifAvailable(embeddingModel::setObservationConvention);
        return embeddingModel;
    }
}

关键点

  • 条件加载:只有当 ZhiPuAiApi 类存在且配置 spring.ai.embedding.model=zhipuai(默认即为 zhipuai)时才生效。这允许你在同一个项目中同时使用多个嵌入模型提供商,只需修改配置即可切换。
  • 配置绑定ZhiPuAiConnectionProperties 绑定 spring.ai.zhipuai.*(通用属性),ZhiPuAiEmbeddingProperties 绑定 spring.ai.zhipuai.embedding.*(嵌入专用属性)。专用属性优先级更高。
  • Bean 创建:使用 RestClient.BuilderWebClient.Builder 构建 HTTP 客户端,并注入重试模板和错误处理器,最终返回 ZhiPuAiEmbeddingModel(实现了 EmbeddingModel 接口)。

3. 图像生成模型 API(Image Model API)

3.1 概述

Spring AI 的 ImageModel 接口用于统一调用各类图像生成模型(如 OpenAI DALL-E、智谱 AI CogView、Stability AI 等)。它遵循与 ChatModel 类似的设计模式:

  • ImagePrompt:封装生成图像的文本描述(可包含多个 ImageMessage,每个消息支持权重)。
  • ImageResponse:返回生成的图像列表(URL 或 Base64 编码)。
  • ImageOptions:定义生成数量、尺寸、响应格式等可移植选项。

3.2 使用示例:ImageGenerationController

package cn.dianyu.ai.myspringai.imagegeneration;

import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;
import org.springframework.ai.zhipuai.ZhiPuAiImageModel;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RequestMapping("/api/image")
public class ImageGenerationController {

    private final ZhiPuAiImageModel imageModel;

    public ImageGenerationController(ZhiPuAiImageModel imageModel) {
        this.imageModel = imageModel;
    }

    @PostMapping("/generate")
    public String generateImage(@RequestParam String prompt) {
        ImagePrompt imagePrompt = new ImagePrompt(prompt);
        ImageResponse response = imageModel.call(imagePrompt);
        return response.getResult().getOutput().getUrl();
    }

    @PostMapping("/generate/batch")
    public String[] generateBatch(@RequestParam String prompt,
                                  @RequestParam(defaultValue = "1") int count) {
        // 智谱 AI 最多生成 4 张
        if (count < 1 || count > 4) {
            throw new IllegalArgumentException("图片数量需在1-4之间");
        }
        ImagePrompt imagePrompt = new ImagePrompt(prompt);
        ImageResponse response = imageModel.call(imagePrompt);
        return response.getResults().stream()
                .map(r -> r.getOutput().getUrl())
                .toArray(String[]::new);
    }
}

注意:不同图像模型支持的参数有所差异。你可以通过 ZhiPuAiImageOptions 设置模型特有的参数(如风格、质量等),并在调用时传入 ImagePrompt

3.3 自动装配原理:ZhiPuAiImageAutoConfiguration

图像生成模型的自动配置与嵌入模型相似,但绑定了不同的配置属性和创建了不同的 Bean 类型。

@AutoConfiguration(after = { RestClientAutoConfiguration.class, SpringAiRetryAutoConfiguration.class })
@ConditionalOnClass(ZhiPuAiApi.class)
@ConditionalOnProperty(name = SpringAIModelProperties.IMAGE_MODEL,
        havingValue = SpringAIModels.ZHIPUAI, matchIfMissing = true)
@EnableConfigurationProperties({ ZhiPuAiConnectionProperties.class, ZhiPuAiImageProperties.class })
public class ZhiPuAiImageAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public ZhiPuAiImageModel zhiPuAiImageModel(
            ZhiPuAiConnectionProperties commonProperties,
            ZhiPuAiImageProperties imageProperties,
            ObjectProvider<RestClient.Builder> restClientBuilderProvider,
            RetryTemplate retryTemplate,
            ResponseErrorHandler responseErrorHandler) {

        String apiKey = StringUtils.hasText(imageProperties.getApiKey()) ?
                imageProperties.getApiKey() : commonProperties.getApiKey();
        String baseUrl = StringUtils.hasText(imageProperties.getBaseUrl()) ?
                imageProperties.getBaseUrl() : commonProperties.getBaseUrl();

        // 注意:图像 API 可能需要单独的客户端实现,这里假设 ZhiPuAiImageApi 存在
        var zhiPuAiImageApi = new ZhiPuAiImageApi(baseUrl, apiKey,
                restClientBuilderProvider.getIfAvailable(RestClient::builder), responseErrorHandler);

        return new ZhiPuAiImageModel(zhiPuAiImageApi, imageProperties.getOptions(), retryTemplate);
    }
}

区别点

  • 检查的配置属性是 spring.ai.image.model=zhipuai
  • 绑定 ZhiPuAiImageProperties(图像专用配置:model、width、height、responseFormat 等)。
  • 创建 ZhiPuAiImageModel 而非 ZhiPuAiEmbeddingModel

自定义与扩展

  • 覆盖默认 Bean:你可以通过 @Primary@ConditionalOnMissingBean 的机制,在自己的 @Configuration 类中定义相同类型的 Bean,从而替换自动配置的实现。
  • 自定义 HTTP 客户端:提供自己的 RestClient.BuilderWebClient.Builder Bean,即可全局修改请求超时、拦截器等。
  • 重试策略:通过定义 RetryTemplate Bean,可以定制重试次数和退避策略。

4. 聊天记忆(Chat Memory)

4.1 为什么需要聊天记忆?

大语言模型本质上是无状态的 —— 它们不会记住之前的对话内容。为了实现连贯的多轮对话,我们需要手动管理历史消息。Spring AI 提供了 ChatMemory 抽象,帮助开发者轻松实现对话记忆功能。

  • ChatMemory:负责存储和检索当前对话中需要保持上下文的消息(例如最近 N 条消息)。
  • ChatMemoryRepository:底层存储接口,支持内存、JDBC、Cassandra、Neo4j、MongoDB、Cosmos DB 等多种实现。
  • MessageWindowChatMemory:内置的记忆策略,保留最近 maxMessages 条消息(默认 20 条),超出时自动移除旧消息。

4.2 配置 JDBC 存储(以 H2 为例)

我们已在上面的 application.yml 中配置了数据源和 spring.ai.chat.memory.repository.jdbc.initialize-schema=always,Spring AI 会自动创建表 SPRING_AI_CHAT_MEMORY。接下来,通过 Java 配置显式创建 ChatMemory Bean(可选,Spring AI 也提供了自动配置的 ChatMemory,但此处我们自定义窗口大小)。

package cn.dianyu.ai.myspringai.config;

import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.memory.jdbc.JdbcChatMemoryRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Configuration
public class ChatMemoryConfig {

    @Bean
    public ChatMemory chatMemory(JdbcTemplate jdbcTemplate) {
        log.info("Creating ChatMemory with JdbcChatMemoryRepository");
        JdbcChatMemoryRepository repository = JdbcChatMemoryRepository.builder()
                .jdbcTemplate(jdbcTemplate)
                .build();
        return MessageWindowChatMemory.builder()
                .chatMemoryRepository(repository)
                .maxMessages(10)   // 保留最近10条消息
                .build();
    }

    // 可选:不同窗口大小的记忆 Bean
    @Bean
    public ChatMemory smallWindowChatMemory(JdbcTemplate jdbcTemplate) {
        JdbcChatMemoryRepository repository = JdbcChatMemoryRepository.builder()
                .jdbcTemplate(jdbcTemplate)
                .build();
        return MessageWindowChatMemory.builder()
                .chatMemoryRepository(repository)
                .maxMessages(5)
                .build();
    }

    @Bean
    public ChatMemory largeWindowChatMemory(JdbcTemplate jdbcTemplate) {
        JdbcChatMemoryRepository repository = JdbcChatMemoryRepository.builder()
                .jdbcTemplate(jdbcTemplate)
                .build();
        return MessageWindowChatMemory.builder()
                .chatMemoryRepository(repository)
                .maxMessages(20)
                .build();
    }
}

4.3 在 ChatClient 中使用聊天记忆

Spring AI 提供了 MessageChatMemoryAdvisor 适配器,可以无缝地将 ChatMemory 集成到 ChatClient 中。每次请求时,适配器会自动从记忆中加载历史消息,并将新的对话保存回去。

package cn.dianyu.ai.myspringai.chatmemory;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.*;
import org.springframework.ai.zhipuai.ZhiPuAiChatModel;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/chat-memory")
public class ChatMemoryController {

    @Resource
    private ZhiPuAiChatModel chatModel;
    @Resource
    private ChatMemory chatMemory;
    @Resource(name = "smallWindowChatMemory")
    private ChatMemory smallWindowChatMemory;
    @Resource(name = "largeWindowChatMemory")
    private ChatMemory largeWindowChatMemory;

    // ========== 1. 基础 ChatClient 集成 ==========
    @RequestMapping("/basic-chat")
    public String basicChat(String question, String conversationId) {
        String convId = conversationId != null ? conversationId : "default-conversation";
        ChatClient chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
                .build();
        return chatClient.prompt()
                .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, convId))
                .user(question != null ? question : "你好")
                .call()
                .content();
    }

    // ========== 2. 多轮对话保持上下文 ==========
    @RequestMapping("/multi-turn-with-memory")
    public Map<String, Object> multiTurnWithMemory(String conversationId) {
        String convId = conversationId != null ? conversationId : "multi-turn-demo";
        ChatClient chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
                .build();

        String q1 = "我叫张三,今年25岁,是一名软件工程师";
        String r1 = chatClient.prompt().advisors(a -> a.param(ChatMemory.CONVERSATION_ID, convId)).user(q1).call().content();

        String q2 = "我叫什么名字?";
        String r2 = chatClient.prompt().advisors(a -> a.param(ChatMemory.CONVERSATION_ID, convId)).user(q2).call().content();

        String q3 = "我的职业是什么?";
        String r3 = chatClient.prompt().advisors(a -> a.param(ChatMemory.CONVERSATION_ID, convId)).user(q3).call().content();

        return Map.of("conversationId", convId, "response1", r1, "response2", r2, "response3", r3);
    }

    // ========== 3. 不同窗口大小测试 ==========
    @RequestMapping("/small-window-memory")
    public Map<String, Object> smallWindowMemory(String conversationId) {
        String convId = conversationId != null ? conversationId : "small-window-demo";
        ChatClient chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(smallWindowChatMemory).build())
                .build();

        // 进行7轮对话,窗口只有5,最早的消息会被遗忘
        for (int i = 1; i <= 7; i++) {
            chatClient.prompt()
                    .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, convId))
                    .user("这是第" + i + "条消息,请记住这个序号")
                    .call();
        }
        String finalAnswer = chatClient.prompt()
                .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, convId))
                .user("第一条消息的序号是多少?")
                .call()
                .content();
        return Map.of("conversationId", convId, "finalAnswer", finalAnswer);
    }

    // ========== 4. 手动管理记忆 ==========
    @PostMapping("/manual-add-message")
    public String manualAddMessage(String conversationId) {
        String convId = conversationId != null ? conversationId : "manual-demo";
        chatMemory.add(convId, new SystemMessage("你是一个专业的技术顾问。"));
        chatMemory.add(convId, new UserMessage("我想学习 Spring AI"));
        chatMemory.add(convId, new AssistantMessage("Spring AI 是一个强大的框架..."));
        return "Added 3 messages manually. Total: " + chatMemory.get(convId).size();
    }

    @GetMapping("/get-memory-messages")
    public List<Message> getMessages(String conversationId) {
        String convId = conversationId != null ? conversationId : "manual-demo";
        return chatMemory.get(convId);
    }

    @DeleteMapping("/clear-memory")
    public String clearMemory(String conversationId) {
        String convId = conversationId != null ? conversationId : "manual-demo";
        chatMemory.clear(convId);
        return "Memory cleared for " + convId;
    }

    // ========== 5. 带系统提示的聊天记忆 ==========
    @RequestMapping("/with-system-prompt")
    public Map<String, Object> withSystemPrompt(String conversationId) {
        String convId = conversationId != null ? conversationId : "system-prompt-demo";
        ChatClient chatClient = ChatClient.builder(chatModel)
                .defaultSystem("你是一个专业的Python编程导师,擅长解释概念和提供代码示例。")
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
                .build();

        String r1 = chatClient.prompt().advisors(a -> a.param(ChatMemory.CONVERSATION_ID, convId))
                .user("什么是列表推导式?").call().content();
        String r2 = chatClient.prompt().advisors(a -> a.param(ChatMemory.CONVERSATION_ID, convId))
                .user("能给我一个实际的例子吗?").call().content();
        return Map.of("conversationId", convId, "answer1", r1, "answer2", r2);
    }
}

5. 总结

本文介绍了 Spring AI 中三个重要的 API:

模块 核心接口/类 主要功能 典型应用场景
Embeddings API EmbeddingModel 文本 → 向量,计算相似度 语义搜索、RAG、文本聚类
Image API ImageModel 文本 → 图像(URL/Base64) 创意生成、设计辅助
Chat Memory ChatMemory + Advisor 多轮对话上下文管理,支持持久化存储 客服机器人、个性化助手
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐