1. 功能特性
- 单轮对话:提供无状态的单次问答功能
- 多轮对话:支持带会话ID的连续对话,维护对话上下文
- 对话历史持久化:使用H2数据库存储对话历史,支持服务重启后恢复对话
- 线程安全:使用ConcurrentHashMap确保多线程环境下的安全性
- 历史消息管理:自动清理过旧的历史消息,防止内存占用过大
2. 技术栈
- Java 17
- Spring Boot 3.5.6
- Spring Web
- Spring Data JPA
- H2 Database (持久化存储)
- Lombok
- Jackson (处理JSON)
- Ollama API集成
3. 项目结构
src/main/java/com/example/springaialibaba/
├── config/ # 应用配置类
│ └── AppConfig.java # 提供RestTemplate实例配置
├── controller/ # 控制器层
│ └── LocalAiController.java # AI相关API接口
├── entery/ # 实体类
│ ├── Message.java # 对话消息实体
│ ├── OllmaChatRequest.java # Ollma请求实体
│ ├── OllmaChatResponse.java # Ollma响应实体
│ ├── ChatRequest.java # 对话请求实体
│ ├── ChatResponse.java # 对话响应实体
│ └── ConversationHistory.java # 持久化对话历史实体
├── exception/ # 异常处理
│ └── GlobalExceptionHandler.java # 全局异常处理器
├── repository/ # 数据访问层
│ └── ConversationHistoryRepository.java # 对话历史存储接口
└── service/ # 服务层
└── OllmaClient.java # AI服务集成类
4. 业务流程图
以下是Spring AI Alibaba与Ollama集成的对话处理流程:
流程说明:
- 用户发送AI请求到LocalAiController
- 控制器将请求转发给OllmaClient服务层
- OllmaClient根据请求类型判断是单轮还是多轮对话
- 对于多轮对话,会涉及对话历史的持久化存储和加载
- 最终调用Ollama API获取AI回答并返回给用户
- 整个流程确保了对话历史的持久化,支持服务重启后恢复对话
5. 核心代码实现
5.1 实体类设计
ConversationHistory.java - 用于持久化存储的对话历史实体类
java
package com.example.springaialibaba.entery;
import jakarta.persistence.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "conversation_history")
public class ConversationHistory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "session_id", nullable = false, length = 36)
private String sessionId;
@Column(name = "role", nullable = false, length = 20)
private String role; // user/assistant
@Column(name = "content", nullable = false, columnDefinition = "TEXT")
private String content;
@Column(name = "timestamp", nullable = false)
private LocalDateTime timestamp;
}
5.2 数据访问层
ConversationHistoryRepository.java
java
package com.example.springaialibaba.repository;
import com.example.springaialibaba.entery.ConversationHistory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ConversationHistoryRepository extends JpaRepository<ConversationHistory, Long> {
List<ConversationHistory> findBySessionIdOrderByTimestampAsc(String sessionId);
void deleteBySessionId(String sessionId);
long countBySessionId(String sessionId);
}
5.3 OllamaClient - AI服务集成类
OllamaClient.java的核心功能包括:
- 支持单轮和多轮对话
- 对话历史持久化存储
- 应用启动时自动加载历史对话
- 限制历史消息数量,防止内存占用过大
关键方法:
singleTurnChat(String question)
: 单轮对话,不保存历史multiTurnChat(String sessionId, String question)
: 多轮对话,保存历史到数据库afterPropertiesSet()
: 应用启动时从数据库加载对话历史saveMessageToDb(String sessionId, String role, String content)
: 保存消息到数据库loadConversationHistoryFromDb(String sessionId)
: 从数据库加载对话历史
6. 数据库配置
项目使用H2数据库进行对话历史的持久化存储,配置如下:
properties
# H2数据库配置
spring.datasource.url=jdbc:h2:file:./data/ai_conversation_db
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
# JPA配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=true
# H2控制台配置
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.h2.console.settings.trace=false
spring.h2.console.settings.web-allow-others=false
7. API使用说明
7.1 单轮对话接口
- URL :
/api/ai/single-turn
- 方法: GET
- 参数 :
question
(用户问题) - 返回: AI回答内容
7.2 多轮对话接口
- 创建新会话 : POST
/api/ai/multi-turn/new
- 继续会话 : POST
/api/ai/multi-turn/continue
,参数:sessionId, question - 获取历史 : GET
/api/ai/multi-turn/history/{sessionId}
- 清除历史 : DELETE
/api/ai/multi-turn/{sessionId}
8. 依赖管理
项目使用Maven进行依赖管理,主要依赖包括:
- Spring Boot Starter Web
- Spring Boot Starter Data JPA
- H2 Database
- Lombok
- Jackson Databind
9. 常见问题与解决方案
- Ollama服务连接失败:检查Ollama服务是否启动,以及配置文件中的URL是否正确。
- H2数据库配置问题:确保application.properties中的数据库配置正确,可以通过访问/h2-console来检查数据库内容。
- 对话历史查询问题:确保会话ID正确,且该会话确实存在历史记录。