文章目录
- [Spring AI ChatModel 使用记录(入门 Demo)](#Spring AI ChatModel 使用记录(入门 Demo))
Spring AI ChatModel 使用记录(入门 Demo)
最近简单体验了一下 Spring AI ,基于 spring-ai 1.1.0 写了一个最小可用的 Chat Demo,主要用于熟悉 ChatModel 的基本使用方式,顺便记录一下踩坑和实现思路。
当前 Demo 实现的功能非常基础,主要包括:
- ✅ 简单对话调用
- ✅ 基于内存的上下文缓存(多轮对话)
本文未引入持久化、并发隔离等复杂设计。
一、依赖配置
⚠️ 注意:Spring Boot 与 Spring AI 的版本要匹配,否则很容易遇到类缺失或 Bean 无法注入的问题。
当前使用版本:
- Spring Boot:
3.3.5 - Spring AI:
1.1.0 - JDK:
17
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.3.5</version>
<relativePath/>
</parent>
<groupId>com.ljx.ai</groupId>
<artifactId>demo</artifactId>
<version>1.0.0</version>
<properties>
<java.version>17</java.version>
<!-- Spring AI 版本 -->
<spring-ai.version>1.1.0</spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>group.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二、配置项说明
这里使用的是 硅基流动提供的 OpenAI 兼容接口,如果想切换到:
- 本地模型(如 Ollama)
- 其他 OpenAI 兼容平台
只需要调整:
base-urlmodel
即可。
yml
spring:
application:
name: ai
ai:
openai:
# OpenAI 兼容接口(硅基流动)
base-url: https://api.siliconflow.cn
api-key: ${SILICONFLOW_API_KEY:自己的密钥}
chat:
options:
model: deepseek-ai/DeepSeek-V3.2
temperature: 0.7
max-tokens: 1024
三、上下文存储设计
Spring AI 的多轮对话,本质就是 Prompt 中携带历史 Message 列表。
这里用到了三个 Message 类型:
SystemMessage:系统指令(人设、规则)UserMessage:用户输入AssistantMessage:模型回复
设计思路
- 使用一个 内存 List 保存对话历史
- 第 0 条永远保留
SystemMessage - 限制最大上下文轮数,避免 prompt 过长
示例实现
java
import groovy.util.logging.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class ChatStore {
/**
* 历史上下文
*/
private static final List<Message> history = new ArrayList<>();
/**
* 最大保留轮数(不含 system)
*/
private static final int MAX_HISTORY = 10;
private static final Logger log = LoggerFactory.getLogger(ChatStore.class);
/**
* 将当前用户消息加入上下文,并返回裁剪后的历史
*/
public static List<Message> trimHistory(String message) {
if (ObjectUtils.isEmpty(history)) {
history.add(new SystemMessage("你是一个金发兽耳小萝莉,请讨好你的主人"));
}
// system message 永远保留
Message system = history.get(0);
// 先加入用户消息
history.add(new UserMessage(message));
// 超出最大上下文长度则裁剪
if (history.size() > MAX_HISTORY + 1) {
List<Message> recent = history.subList(
history.size() - MAX_HISTORY,
history.size()
);
history.clear();
history.add(system);
history.addAll(recent);
}
return history;
}
/**
* 记录模型回复
*/
public static void addHistory(Message message) {
history.add(message);
}
/**
* 查看当前上下文内容
*/
public static String showHistory() {
StringBuilder sb = new StringBuilder();
if (ObjectUtils.isNotEmpty(history)) {
for (Message message : history) {
if (message instanceof SystemMessage) {
continue;
} else if (message instanceof UserMessage) {
sb.append("You say: ");
} else if (message instanceof AssistantMessage) {
sb.append("She say: ");
}
sb.append(message.getContent()).append("\n");
}
}
return sb.toString();
}
/**
* 清空上下文
*/
public static void clear() {
history.clear();
}
}
⚠️ 注意:
这是 全局静态上下文 ,不支持多用户 ,真实项目应至少按
session / userId隔离。
四、聊天调用逻辑
这里基本就是 Spring AI 的标准用法:
- 生成上下文
List<Message> - 构造
Prompt - 调用
ChatModel - 保存 AssistantMessage
java
import groovy.util.logging.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Slf4j
public class ChatServiceImpl extends ChatService {
private static final Logger log = LoggerFactory.getLogger(ChatServiceImpl.class);
@Autowired
private ChatModel chatModel;
@Override
public String sendMessage(String message) {
// 生成上下文
List<Message> messages = ChatStore.trimHistory(message);
// 构造 Prompt
Prompt prompt = new Prompt(messages);
// 调用模型
String result = chatModel
.call(prompt)
.getResult()
.getOutput()
.getContent();
// 保存回复
ChatStore.addHistory(new AssistantMessage(result));
return result;
}
@Override
public String show() {
return ChatStore.showHistory();
}
@Override
public void clear() {
ChatStore.clear();
}
}