1. 项目依赖配置
首先需要在 pom.xml
中添加 SpringAI 相关依赖。以下是关键依赖项:
xml
<!-- SpringAI 核心依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-core</artifactId>
<version>0.8.0</version>
</dependency>
<!-- SpringAI 智谱 AI 支持 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-zhipuai</artifactId>
<version>0.8.0</version>
</dependency>
<!-- SpringAI Redis 向量存储支持 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-vectorstore-redis</artifactId>
<version>0.8.0</version>
</dependency>
<!-- 其他必要依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
知识总结:这些依赖提供了 SpringAI 的核心功能、智谱 AI 模型支持、Redis 向量存储以及项目所需的基础组件(如 Web 服务和服务发现)。
2. 应用配置
在 application.yml
中配置 SpringAI 和相关服务:
yaml
server:
port: 8081
spring:
application:
name: railway-Ai
# SpringAI 配置
ai:
zhipuai:
chat:
enabled: true
options:
model: GLM-4-Air # 使用的智谱 AI 模型
base-url: http://open.bigmodel.cn/api/paas
api-key: # 智谱 AI API 密钥
embedding:
enabled: true
base-url: http://open.bigmodel.cn/api/paas
api-key: # 智谱 AI API 密钥
options:
model: embedding-2 # 使用的智谱 AI 嵌入模型
# Redis 向量存储配置
vectorstore:
redis:
index: my_vector_index # 向量索引名称
prefix: chatbot # 键前缀
initialize-schema: true # 自动初始化模式
# Redis 配置
data:
redis:
host: 121.43.138.23
database: 0
port: 6379
# Nacos 服务发现配置
cloud:
nacos:
discovery:
server-addr: 121.43.138.23:8848
namespace: public
group: DEFAULT_GROUP
知识总结:
spring.ai.zhipuai
部分配置了智谱 AI 的连接信息和使用的模型spring.ai.vectorstore.redis
配置了 Redis 向量存储的参数- Redis 和 Nacos 是项目运行的基础设施,分别用于向量存储和服务注册发现
3. 核心组件配置
配置聊天内存和文本分割器:
java
// ChatClientConfig.java
import org.springframework.ai.chat.ChatMemory;
import org.springframework.ai.chat.inmemory.InMemoryChatMemory;
import org.springframework.ai.text.splitter.TokenTextSplitter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ChatClientConfig {
@Bean
ChatMemory chatMemory() {
return new InMemoryChatMemory();
}
@Bean
public TokenTextSplitter tokenTextSplitter() {
return new TokenTextSplitter();
}
}
知识总结:
ChatMemory
用于存储对话历史,支持对话上下文感知TokenTextSplitter
将文本分割为合适的 token 块,便于向量嵌入处理
4. 数据处理与向量存储
实现 PDF 文件内容提取并存储到向量数据库:
java
// PdfStoreServiceImpl.java
import org.springframework.ai.document.Document;
import org.springframework.ai.document.DocumentReader;
import org.springframework.ai.document.PagePdfDocumentReader;
import org.springframework.ai.document.TextSplitter;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.function.Function;
@Service
public class PdfStoreServiceImpl {
private final ResourceLoader resourceLoader;
private final VectorStore vectorStore;
private final Function<List<Document>, List<Document>> tokenTextSplitter;
public PdfStoreServiceImpl(ResourceLoader resourceLoader,
VectorStore vectorStore,
Function<List<Document>, List<Document>> tokenTextSplitter) {
this.resourceLoader = resourceLoader;
this.vectorStore = vectorStore;
this.tokenTextSplitter = tokenTextSplitter;
}
// 按页分割并存储 PDF 内容
public void saveSourceByPage(String url) {
Resource resource = resourceLoader.getResource(url);
// 配置 PDF 读取器
PdfDocumentReaderConfig loadConfig = PdfDocumentReaderConfig.builder()
.build();
PagePdfDocumentReader pagePdfDocumentReader = new PagePdfDocumentReader(resource, loadConfig);
// 分割文档并存储到向量库
vectorStore.accept(tokenTextSplitter.apply(pagePdfDocumentReader.get()));
}
// 其他存储方法...
}
知识总结:
DocumentReader
负责从不同来源读取内容TextSplitter
将文档分割为可管理的块VectorStore
将文本转换为向量并存储,支持相似性检索
5. 聊天服务实现
实现基于向量检索和通用聊天的服务:
java
// ChatServiceImpl.java
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.adapter.zhipuai.ZhiPuAiChatModel;
import org.springframework.ai.chat.memory.MessageChatMemoryAdvisor;
import org.springframework.ai.prompt.Prompt;
import org.springframework.ai.prompt.messages.UserMessage;
import org.springframework.ai.retriever.QuestionAnswerAdvisor;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;
@Service
public class ChatServiceImpl implements ChatService {
private static final String PROFESSIONAL_SYSTEM_PROMPT =
"You are a professional railway maintenance advisor. " +
"Provide accurate, concise, and actionable advice based on the context.";
private final ZhiPuAiChatModel chatModel;
private final VectorStore vectorStore;
private final ToolConfig toolConfig;
private final ChatMemory chatMemory;
public ChatServiceImpl(ZhiPuAiChatModel chatModel,
VectorStore vectorStore,
ToolConfig toolConfig,
ChatMemory chatMemory) {
this.chatModel = chatModel;
this.vectorStore = vectorStore;
this.toolConfig = toolConfig;
this.chatMemory = chatMemory;
}
@Override
public String chatByVectorStore(String message) {
// 创建聊天客户端并设置系统提示
ChatResponse response = ChatClient.builder(chatModel)
.defaultSystem(PROFESSIONAL_SYSTEM_PROMPT)
.build()
.prompt()
.tools(toolConfig) // 注册工具
.advisors(
new MessageChatMemoryAdvisor(chatMemory), // 聊天历史顾问
new QuestionAnswerAdvisor(vectorStore) // 向量检索顾问
)
.user(message) // 用户消息
.call(); // 调用模型生成回复
return response.getContent();
}
@Override
public String chatByGeneral(String message) {
// 通用聊天,不使用向量检索
return ChatClient.create(chatModel)
.prompt()
.advisors(new MessageChatMemoryAdvisor(chatMemory))
.user(message)
.tools(toolConfig)
.call()
.content();
}
}
知识总结:
ChatClient
是与 AI 模型交互的核心接口MessageChatMemoryAdvisor
提供对话历史功能QuestionAnswerAdvisor
利用向量存储进行相似内容检索ToolConfig
注册可在对话中调用的工具
6. 控制器实现
提供 REST API 接口:
java
// ChatController.java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/chat/")
public class ChatController {
private final ChatService chatService;
public ChatController(ChatService chatService) {
this.chatService = chatService;
}
@GetMapping("think")
public String think(@RequestParam("msg") String msg) {
return chatService.chatByGeneral(msg);
}
@GetMapping("advisorThink")
public String advisorThink(@RequestParam("msg") String msg) {
return chatService.chatByVectorStore(msg);
}
}
知识总结:
/chat/think
提供通用聊天功能/chat/advisorThink
提供基于向量检索的专业问答功能
7. 工具配置
配置可在对话中调用的工具:
java
// ToolConfig.java
import org.springframework.ai.tool.Tool;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
@Service
public class ToolConfig {
@Autowired
private RailwayFeignClient railwayFeignClient;
@Tool(name = "拿到当前时间", description = "拿到用户当前的日期时间")
public String getCurrentDateTime() {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
return now.format(formatter);
}
@Tool(name = "发送邮件", description = "帮助用户发送邮件")
public void sendMail(
@ToolParam(description = "需要维修的设备的相关信息name、model、station")
List<Map<String, String>> maintInfoList,
@ToolParam(description = "距离维修日期的天数") Integer day,
@ToolParam(description = "要发送的对象的工号") List<String> emailList) {
// 实现邮件发送逻辑
}
@Tool(name = "获取维修信息", description = "拿到需要维修的设备")
public String getExpire() {
return railwayFeignClient.expire(TokenConstant.getToken()).toString();
}
}
知识总结:
@Tool
注解将方法标记为可被 AI 模型调用的工具- 工具方法可以扩展 AI 系统的功能,如获取实时数据、执行操作等
- 参数注解
@ToolParam
提供参数描述,帮助模型理解工具使用方式
使用流程总结
- 初始化项目:添加必要依赖,配置 SpringAI 和基础设施
- 准备数据:将领域知识(如 PDF 文档)处理并存储到向量数据库
- 配置聊天服务:设置聊天客户端、历史记忆和检索功能
- 注册工具:根据业务需求配置可调用的工具
- 提供接口:通过控制器暴露聊天功能
- 前端集成:开发前端界面与后端 API 交互(您的项目中未包含,需补充)