知識庫 / Spring / Spring AI RSS 訂閱

Spring AI 聊天記憶

Artificial Intelligence,Spring AI
HongKong
9
10:44 AM · Dec 06 ,2025

1. 概述

我們經常需要在與 AI 應用的對話中獲得類似人類的交互體驗。因此,維護與 LLM 模型的對話是必要的,Spring AI 通過其聊天記憶功能來解決這個問題。

在本教程中,我們將探索 Spring AI 中提供的各種聊天記憶選項,並提供如何將聊天記憶與聊天客户端集成的示例。

2. 聊天記憶

大型語言模型 (LLM) 是無狀態的,不具備任何記憶功能。 每次向 LLM 發送的提示都被視為一個獨立的查詢,這意味着模型不會記住任何之前的消息。

在人工智能應用程序中,保持之前的對話至關重要,以便 LLM 能夠產生有意義的響應。 此時,聊天記憶的作用就是彌補這一不足,提供:

  • 語境理解 – 這使得 LLM 能夠根據整個對話產生響應。
  • 個性化 – 這有助於基於聊天記憶提供個性化響應。
  • 持久性 – 根據實現方式,聊天記憶可以跨多個會話持久存在。

3. 聊天記憶存儲庫

Spring AI 提供 ChatMemory 接口以及一些現成的實現,以幫助我們輕鬆地將聊天記憶集成到我們的應用程序中。

首先,添加 Maven 依賴項 spring-ai-starter-model-openai 以啓用 OpenAI 集成。 此依賴項將轉義導入 Spring AI 的核心庫:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
    <version>1.0.0</version>
</dependency>

當我們創建聊天記憶時,必須提供 ChatMemoryRepository 的實現,該接口負責將聊天消息持久化到存儲中:

ChatMemoryRepository chatMemoryRepository;

ChatMemory chatMemory = MessageWindowChatMemory.builder()
  .chatMemoryRepository(chatMemoryRepository)
  .maxMessages(10)
  .build();

Spring AI 提供不同類型的聊天記憶存儲庫供我們根據項目的技術棧進行選擇。我們將在下面討論其中兩個。

3.1. 內存存儲器

如果未明確定義聊天內存,Spring AI 默認使用內存存儲器。它會在 ConcurrentHashMap 中內部存儲聊天消息,其中會話 ID 作為鍵,值是一個該會話中的消息列表:

public final class InMemoryChatMemoryRepository implements ChatMemoryRepository {
    Map<String, List<Message>> chatMemoryStore = new ConcurrentHashMap();

    // other methods
}

內存倉庫非常簡單,在不需要任何持久化存儲的情況下效果良好。 如果需要持久化存儲,則需要選擇其他方案。

3.2. JDBC 倉庫

JDBC 倉庫用於在關係型數據庫中持久化聊天消息。 Spring AI 提供對多個關係型數據庫的內置支持,包括 MySQL、PostgreSQL、SQL Server 和 HSQLDB。

如果需要將聊天內存存儲在關係型數據庫中,則需要包含 Maven 依賴項 以支持它:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-model-chat-memory-repository-jdbc</artifactId>
    <version>1.0.0</version>
</dependency>

每個內置支持的數據庫都有其自身的方言實現,它為聊天記憶表上的 CRUD 操作提供 SQL 語句。在初始化 JdbcChatMemoryRepository 時,我們需要提供方言。

JdbcChatMemoryRepositoryDialect dialect = ...; // The choose repository dialect
ChatMemoryRepository repository = JdbcChatMemoryRepository.builder()
  .jdbcTemplate(jdbcTemplate)
  .dialect(dialect)
  .build();

對於沒有內置支持的數據庫,我們需要實現 JdbcChatMemoryRepositoryDialect 接口並提供每個 CRUD 操作的 SQL 語句:

public interface JdbcChatMemoryRepositoryDialect {
    String getSelectMessagesSql();

    String getInsertMessageSql();

    String getSelectConversationIdsSql();

    String getDeleteMessagesSql();
}

對於 Spring AI 中實現的方言,CRUD 操作遵循標準 SQL 且不依賴於特定供應商。因此,我們可以直接使用提供的實現,例如 MysqlChatMemoryRepositoryDialect,而無需實現我們自定義的方言。

在使用之前,我們需要初始化 schema。對於支持的方言,Spring AI 也提供了 schema 創建腳本。這些腳本可以在 classpath:org/springframework/ai/chat/memory/repository/jdbc 中找到。

4. 將 Chat 記憶應用到 Chat 客户端

Spring AI 提供 Chat 記憶的自動配置,在 ChatMemoryAutoConfiguration 中。 如果我們選擇使用內存倉庫,則無需顯式定義,因為這是默認設置。

但是,如果我們想使用 JDBC 倉庫,則需要為 ChatMemoryRepository 的 bean 方法提供覆蓋默認內存倉庫的定義。

@Configuration
public class ChatConfig {
    @Bean
    public ChatMemoryRepository getChatMemoryRepository(JdbcTemplate jdbcTemplate) {
        return JdbcChatMemoryRepository.builder()
          .jdbcTemplate(jdbcTemplate)
          .dialect(new HsqldbChatMemoryRepositoryDialect())
          .build();
    }
}

請注意,我們無需顯式定義 ChatMemory 的 Bean 方法,因為該方法已在 ChatMemoryAutoConfiguration 中定義。

讓我們在 Spring Boot 中創建一個 ChatService

@Component
@SessionScope
public class ChatService {
    private final ChatClient chatClient;
    private final String conversationId;

    public ChatService(ChatModel chatModel, ChatMemory chatMemory) {
        this.chatClient = ChatClient.builder(chatModel)
          .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
          .build();
        this.conversationId = UUID.randomUUID().toString();
    }

    public String chat(String prompt) {
        return chatClient.prompt()
          .user(userMessage -> userMessage.text(prompt))
          .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
          .call()
          .content();
    }
}

在構造函數中,Spring Boot 會自動注入 ChatMemory 實現。我們通過使用 MemoryChatMemoryAdvisor 初始化 ChatClient

我們定義 chat 方法來接受提示並向聊天模型發送消息。此外,我們還將會話 ID 作為聊天顧問參數傳遞,以便根據當前會話唯一標識對話。

需要注意的是,我們必須使用 @SessionScope 註解標記服務,以便其實例可以在多個請求之間保持持久化。

5. 與 OpenAI 集成

在我們的演示中,我們將集成聊天記憶功能與 OpenAI,並考察 Spring AI 如何調用 OpenAI API,以及採用 HSQL DB 作為持久化存儲。

讓我們為 application.yml 添加屬性,以添加 OpenAI API 密鑰、設置數據庫連接以及在應用程序啓動期間初始化模式:

spring:
  ai:
    openai:
      api-key: "<YOUR-API-KEY>"

  datasource:
    url: jdbc:hsqldb:mem:chatdb
    driver-class-name: org.hsqldb.jdbc.JDBCDriver
    username: sa
    password:

  sql:
    init:
      mode: always
      schema-locations: classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-hsqldb.sql

現在,配置已全部設置完成。讓我們創建一個 REST 端點,以便我們可以調用我們之前定義的 ChatService

@RestController
public class ChatController {
    private final ChatService chatService;

    public ChatController(ChatService chatService) {
        this.chatService = chatService;
    }

    @PostMapping("/chat")
    public ResponseEntity<String> chat(@RequestBody @Valid ChatRequest request) {
        String response = chatService.chat(request.getPrompt());
        return ResponseEntity.ok(response);
    }
}

ChatRequest 是一個簡單的 DTO,它包含 prompt 作為字符串:

public class ChatRequest {
    @NotNull
    private String prompt;

    // getter and setter
}

6. 測試運行

現在我們準備好向 REST 端點發送請求。我們將使用 Postman 向 REST 端點發送請求,並利用 HTTP 工具包 攔截 Spring Boot 應用程序與 OpenAI 之間的 HTTP 請求,以瞭解它們如何協同工作。

6.1. 首次請求

讓我們在 Postman 中發起一個請求,要求一個笑話,並檢查響應:

當我們觀察 HTTP 工具包中攔截的請求時,我們會看到發往 OpenAI 的 HTTP 請求:

{
  "messages": [
    {
      "content": "Tell me a joke",
      "role": "user"
    }
  ],
  "model": "gpt-4o-mini",
  "stream": false,
  "temperature": 0.7
}

這是一個相當簡單的請求,它使用用户角色發送我們的提示負載。

6.2. 第二請求

現在,讓我們發起另一個請求以進行比較:

當我們這次讀取攔截的 OpenAI HTTP 請求時,我們發現 Spring AI 不僅將我們的提示負載發送到 OpenAI,還發送了之前的提示和響應:

{
  "messages": [
    {
      "content": "Tell me a joke",
      "role": "user"
    },
    {
      "content": "Why did the scarecrow win an award? \n\nBecause he was outstanding in his field!",
      "role": "assistant"
    },
    {
      "content": "Tell me another one",
      "role": "user"
    }
  ],
  "model": "gpt-4o-mini",
  "stream": false,
  "temperature": 0.7
}

在此示例中,我們觀察到 Spring AI 將整個聊天曆史發送到聊天模型。 這種方法有助於聊天模型保持整個對話的上下文,使交互感覺更自然。

7. 結論

在本文中,我們學習了 Spring AI 如何通過聊天記憶來增強對話體驗,從而在多個聊天請求之間保持聊天曆史。

我們探討了不同的記憶存儲庫,並説明了如何將聊天記憶與 Spring AI 和 OpenAI 集成。我們還研究了 Spring AI 聊天記憶在 OpenAI 背後是如何工作的。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.