1. 项目概述与背景
最近在开发一个基于SpringAI和DeepSeek大模型的智能对话系统,这个项目让我深刻体会到了现代AI开发框架的强大之处。SpringAI作为Spring生态中的AI集成框架,极大简化了大模型应用的开发流程,而DeepSeek作为国产大模型的优秀代表,在中文理解和生成方面表现尤为出色。
这个项目主要实现了以下几个核心功能:
- 完整的对话机器人系统(支持同步/流式调用)
- 会话记忆持久化(内存/MySQL存储)
- RAG知识库集成(文档解析与智能分片)
- 完善的日志和监控体系
下面我将从技术选型、实现细节到避坑经验,完整分享这个项目的开发过程。无论你是刚接触AI应用开发的Java工程师,还是想了解SpringAI框架的实践者,都能从中获得可直接复用的代码和经验。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与基础配置
2.1 开发环境要求
- JDK 17+(SpringAI 1.0.0-M6的最低要求)
- Maven 3.6+
- DeepSeek API Key(或本地部署的DeepSeek模型)
- 可选:Ollama本地模型服务(用于开发测试)
建议使用IntelliJ IDEA作为开发IDE,其对Spring Boot和Maven的支持最为完善
2.2 Maven依赖配置
核心依赖包括Spring Boot Web、SpringAI和Lombok。特别注意SpringAI目前还处于里程碑版本,需要添加Spring快照仓库:
xml复制<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-M6</spring-ai.version>
</properties>
<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>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
2.3 模型连接配置
根据使用场景不同,我们提供两种连接方式:
方式一:Ollama本地服务(开发测试推荐)
yaml复制spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
model: deepseek-r1:7b
options:
temperature: 0.8
方式二:直接API连接(生产环境)
yaml复制spring:
ai:
openai:
base-url: https://api.deepseek.com
api-key: your-api-key
chat:
options:
model: deepseek-chat
temperature: 0.8
关键参数说明:
- temperature:控制生成结果的随机性(0-1)
- 0.2-0.5:事实性回答推荐
- 0.6-0.8:创意性内容推荐
0.9:高度随机,适合头脑风暴
3. 对话机器人核心实现
3.1 基础对话功能
3.1.1 ChatClient配置
创建配置类初始化ChatClient:
java复制@Configuration
public class CommonConfiguration {
@Bean
public ChatClient chatClient(OpenAiChatModel openAiChatModel) {
return ChatClient.builder(openAiChatModel)
.defaultSystem("你是一个智能助手,名字叫煋玥")
.build();
}
}
3.1.2 同步调用实现
适合需要完整响应结果的场景:
java复制@RestController
@RequestMapping("/ai")
public class ChatController {
@Autowired
private ChatClient client;
@GetMapping("/chat")
public String chat(@RequestParam String prompt) {
return client.prompt()
.user(prompt)
.call()
.content();
}
}
测试方式:
code复制http://localhost:8080/ai/chat?prompt=你好
3.1.3 流式调用实现
基于WebFlux的流式响应,适合长文本生成场景:
java复制@GetMapping(value = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestParam String question) {
return client.prompt()
.user(question)
.stream()
.content();
}
前端调用示例(使用EventSource):
javascript复制const eventSource = new EventSource('/ai/chatStream?question=你好');
eventSource.onmessage = (event) => {
console.log(event.data);
};
3.2 日志增强功能
3.2.1 添加日志Advisor
修改ChatClient配置,增加日志记录:
java复制@Bean
public ChatClient chatClient(OpenAiChatModel openAiChatModel) {
return ChatClient.builder(openAiChatModel)
.defaultSystem("你是一个智能助手,名字叫煋玥")
.defaultAdvisors(new SimpleLoggerAdvisor())
.build();
}
3.2.2 日志级别配置
application.yaml中添加:
yaml复制logging:
level:
org.springframework.ai: debug
com.yourpackage: debug
日志输出示例:
code复制DEBUG o.s.ai.chat.client.ChatClient - User prompt: 你好
DEBUG o.s.ai.chat.client.ChatClient - AI response: 你好!我是煋玥,有什么可以帮您的吗?
3.3 会话记忆实现
3.3.1 内存存储方案
java复制@Bean
public ChatMemory chatMemory() {
return MessageWindowChatMemory.builder()
.maxMessages(10) // 保留最近10条消息
.build();
}
@Bean
public ChatClient chatClient(OpenAiChatModel openAiChatModel, ChatMemory chatMemory) {
return ChatClient.builder(openAiChatModel)
.defaultAdvisors(
new SimpleLoggerAdvisor(),
MessageChatMemoryAdvisor.builder(chatMemory).build()
)
.build();
}
3.3.2 数据库持久化方案
- 创建MySQL存储表:
sql复制CREATE TABLE chat_memory (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
chat_id VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL,
content TEXT NOT NULL,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
- 实现自定义ChatMemory:
java复制@Component
public class MySqlChatMemory implements ChatMemory {
private final ChatMemoryMapper mapper;
@Override
public List<Message> get(String conversationId, int lastN) {
List<ChatRecord> records = mapper.selectByChatId(conversationId);
// 转换为Message对象
return records.stream()
.map(this::toMessage)
.limit(lastN)
.collect(Collectors.toList());
}
// 其他接口方法实现...
}
- 完整代码结构:
code复制├── entity
│ └── ChatRecord.java
├── mapper
│ └── ChatMemoryMapper.java
└── impl
└── MySqlChatMemory.java
4. RAG知识库集成
4.1 核心流程
- 文档收集 → 2. 文本分片 → 3. 向量存储 → 4. 查询增强
4.2 文档处理实现
4.2.1 文件解析器接口
java复制public interface RagDocParserService {
List<Document> parse(InputStream inputStream) throws Exception;
}
@SupportFileTypes({".pdf", ".txt"})
@Service
public class PdfParserServiceImpl implements RagDocParserService {
@Override
public List<Document> parse(InputStream inputStream) {
// PDF解析实现
}
}
4.2.2 智能文本分片
java复制public List<String> processAndSplit(MultipartFile file, int chunkSize, int chunkOverlap) {
// 1. 按文件类型选择解析器
// 2. 使用TokenTextSplitter分片
TokenTextSplitter splitter = new TokenTextSplitter(
chunkSize, // 每个分片最大token数
350, // 最小字符数
5, // 最小嵌入长度
10000, // 最大分片数
true // 保留分隔符
);
return splitter.split(documents);
}
分片参数建议:
- 常规文档:chunkSize=500-800,overlap=50-100
- 技术文档:chunkSize=300-500,overlap=30-50
- 对话记录:chunkSize=200-300,overlap=20-30
5. 性能优化与问题排查
5.1 常见性能问题
-
流式响应延迟高
- 检查网络延迟
- 调整temperature参数降低复杂度
- 启用响应压缩
-
记忆检索慢
- 为chat_id字段添加索引
- 考虑使用Redis缓存热点会话
5.2 监控指标建议
java复制@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags(
"application", "ai-chatbot",
"region", System.getenv("REGION")
);
}
关键监控项:
- 请求耗时(histogram)
- 令牌使用量(counter)
- 错误率(gauge)
6. 项目扩展方向
-
多模态支持
java复制@Bean public ImageClient imageClient(OpenAiImageModel imageModel) { return ImageClient.builder(imageModel).build(); } -
函数调用集成
java复制@Bean public FunctionCallingOptions functionOptions() { return FunctionCallingOptions.builder() .withFunction("weather", "getWeather") .build(); } -
分布式会话管理
java复制@Bean public ChatMemoryRepository redisChatMemoryRepository(RedisTemplate<String, Object> redisTemplate) { return new RedisChatMemoryRepository(redisTemplate); }
7. 避坑指南
-
版本兼容性问题
- SpringAI 1.0.0-M6需要Spring Boot 3.2+
- 与Spring Cloud 2023.x存在部分兼容性问题
-
Ollama连接失败
bash复制# 检查服务状态 curl http://localhost:11434/api/tags # 拉取模型 ollama pull deepseek-r1:7b -
中文处理异常
- 确保系统编码为UTF-8
- 添加请求头:
Accept-Charset: utf-8
这个项目从零开始搭建到最终上线,让我对SpringAI框架有了更深入的理解。特别是在会话持久化方案的选择上,经过多次测试发现:对于中小规模应用,MySQL+本地缓存的混合方案在保证数据可靠性的同时,性能表现最为均衡。希望我的这些实践经验能对正在探索AI应用开发的你有所帮助。
