1. ChatModel和Chat Client对象对比在与各个模型进行对话时使用对应模型的 ChatModel 对象例如DeepSeekChatModel、OllamaChatModel。然后通过 chatModel.call(…)、chatModel.stream(…) 直接调用模型。这期间我们需要手动构造 Prompt、处理流式响应例如将返回结果封装成对象、从模型响应中获取回复内容、拼装调用链RAG 需要自己构建流程等操作。Spring AI 中提供了 ChatClient 对象该对象可以看做一个更高级的“客户端 API”建立在 ChatModel 之上可以用链式的方式快速搭配 Prompt、系统设定、变量替换、上下文记忆等并支持文本、JSON、实体对象等多种形式的输出。1.1 多模态ChatClient创建resources/application.properties//手动管理 ChatClient 的创建需要设置为false即不再使用ChatClient.Builder Bean 注入 spring.ai.chat.client.enabledfalseConfigurationpublicclassMultiChatClientConfig{//创建DeepSeekChatClientBeanpublicChatClientdeepSeekChatClient(DeepSeekChatModeldeepSeekChatModel){returnChatClient.builder(deepSeekChatModel).defaultSystem(你是一个人工智能助手你的名字叫做小智).build();}//创建zhipuAIChatClientBeanpublicChatClientzhipuAIChatClient(ZhiPuAiChatModelzhiPuAiChatModel){returnChatClient.builder(zhiPuAiChatModel).build();}}1.2 多模态的使用privateChatClientdeepSeekChatClient;privateChatClientzhipuAIChatClient;publicMultiModelController(Qualifier(deepSeekChatClient)ChatClientdeepSeekChatClient,Qualifier(zhipuAIChatClient)ChatClientzhipuAIChatClient){this.deepSeekChatClientdeepSeekChatClient;this.zhipuAIChatClientzhipuAIChatClient;}GetMapping(/deepseek)publicStringchatWithDeepseek(RequestParam(message)Stringmessage){StringresultdeepSeekChatClient.prompt().user(message).call().content();returnresult;}GetMapping(/idCardAnaly)publicIdCardInfoidCardAnaly(){ClassPathResourceresourcenewClassPathResource(身份证.jpg);IdCardInfoidCardInfozhipuAIChatClient.prompt(你是一个图像识别的高手可以对用户关于图片识别问题进行精准回复,以json格式输出识别到的身份证中姓名(name)、性别(sex)、民族(nation)、出生日期(birth)、住址address、身份证号idNo).user(c-c.text(请对图片进行描述).media(MediaType.IMAGE_JPEG,resource)).call().entity(IdCardInfo.class);returnidCardInfo;}2. Chat Memory大语言模型LLMs是无状态的即它们不会自动保留先前对话信息。Spring AI引入Chat Memory可以将最近N次对话上下文信息保存在内存或者外部数据库例如PostgreSQL、MySQL、SQL Server、HSQLDB、Cassandra、Neo4j) 。以便LLM在同一会话的多轮互动中保持语义连贯。2.1 ChatMemory接口Ø ChatMemory接口提供在指定对话中添加消息、检索记忆内容、以及清理旧消息的能力。Ø ChatMemoryRepository接口负责消息的底层储存与提取。ChatMemory默认实现为MessageWindowChatMemory类如下方式创建ChatMemory:MessageWindowChatMemorymemoryMessageWindowChatMemory.builder().maxMessages(20).build();ChatMemory对象默认将保存最近N条对话信息默认20条超出后按时间顺序清理系统消息不会被清除。最近N条对话消息存储到哪里由ChatMemoryRepository的实现决定存储后端。2.2 ChatMemoryRepositoryChatMemoryRepository有如下四种实现InMemoryChatMemoryRepository使用 ConcurrentHashMap 存储消息这种也是默认方式。ConfigurationpublicclassConfig{//准备 ChatMemory 对象将聊天记忆放在内存中BeanpublicChatMemorychatMemory(){returnMessageWindowChatMemory.builder().maxMessages(20).build();}BeanpublicChatClientchatClient(ChatModelchatModel,ChatMemorymemory){ChatClientclientChatClient.builder(chatModel)//设置 chatMemory.defaultAdvisors(MessageChatMemoryAdvisor.builder(memory).build()).build();returnclient;}}JdbcChatMemoryRepository基于 JDBC 的关系型数据库PostgreSQL、MySQL、SQL Server、HSQLDB存储数据支持通过 Spring 属性配置 schema 初始化时机与脚本位置。#MySQL 配置 提前在MySQL中创建数据库和表spring.datasource.urljdbc:mysql://localhost:3306/chat_memory?useUnicodetruecharacterEncodingUTF-8connectionCollationutf8mb4_unicode_ci spring.datasource.usernameroot spring.datasource.password123456 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver#自动创建ChatMemory存储的表结构#Spring AI 的 JdbcChatMemoryRepository 会尝试自动创建所需表结构spring.ai.chat.memory.repository.jdbc.initialize-schemaalways#告诉框架当前数据库是 MariaDB/MySQL会加载 schema-mariadb.sql 初始化脚本自行创建表 SPRING_AI_CHAT_MEMORY表#官方暂时未提供schema-mysql.sql 初始化脚本。当配置 platformmysql 时框架会尝试加载 schema-mysql.sql 文件但该文件在官方 JAR 包中不存在因此会导致启动失败。所以推荐使用 platformmariadb。#而MariaDB 的脚本与 MySQL 高度兼容可以作为替代方案使用。spring.ai.chat.memory.repository.jdbc.platformmariadb#确保每条 JDBC 连接都使用 utf8mb4 字符集并指定 utf8mb4_unicode_ci 排序spring.datasource.hikari.connection-init-sqlSETNAMES utf8mb4 COLLATE utf8mb4_unicode_ci# 配置 Deepseek URL、API Key、模型spring.ai.deepseek.base-urlhttps://api.deepseek.com spring.ai.deepseek.api-keyyour_api_key spring.ai.deepseek.chat.options.modeldeepseek-chatConfigurationpublicclassConfig{//准备 ChatMemory 对象将聊天记忆放在 Mysql 中BeanpublicChatMemorychatMemory(JdbcChatMemoryRepositoryrepo){returnMessageWindowChatMemory.builder().chatMemoryRepository(repo).maxMessages(20).build();}BeanpublicChatClientchatClient(ChatModelchatModel,ChatMemorymemory){ChatClientclientChatClient.builder(chatModel)//设置 chatMemory.defaultAdvisors(MessageChatMemoryAdvisor.builder(memory).build()).build();returnclient;}}CassandraChatMemoryRepository使用 Cassandra可配置 TTL例如 3 年实现自动过期。Neo4jChatMemoryRepository基于图数据库 Neo4j存储消息。Advisor是 Spring AI 中用于增强方法执行逻辑的组件类似于一个拦截器通过 Advisor将 ChatMemory 集成到ChatClient中。importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.memory.ChatMemory;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;RestControllerRequestMapping(/ai)publicclassChatMemoryInMySQLController{AutowiredprivateChatClientchatClient;GetMapping(/chatMemory)publicStringchatMemory(RequestParam(valuecid)StringconversationID,RequestParam(valuemessage,defaultValue你是谁)Stringmessage){StringresultchatClient.prompt().user(message)//加入聊天的会话.advisors(advisorSpec-advisorSpec.param(ChatMemory.CONVERSATION_ID,conversationID)).call().content();returnresult;}}使用ChatClient时传入对话ID与模型交互时通过CONVERSATION_ID标记会话advisor会自动上下文管理。