Integrate Spring AI for intelligent file search, summarization, and classification
- [x] Analyze repository structure and existing codebase
- [x] Add Spring AI dependencies to pom.xml
- Added
spring-ai-openai-spring-boot-starterandspring-ai-ollama-spring-boot-starter - Updated to Spring AI
1.0.0stable release (from milestone1.0.0-M4) - Removed Spring Milestones repository (no longer needed for stable release)
- Added
- [x] Create AI configuration package (
com.jmal.clouddisk.ai)- [x] Create
AiProperties.java- AI configuration properties with provider, API key, model settings - [x] Create
AiConfig.java- AI main configuration class supporting OpenAI and Ollama
- [x] Create
- [x] Implement Embedding Service
- [x] Create
EmbeddingService.java- Generate text vectors with chunking for large texts
- [x] Create
- [x] Implement Vector Store Service
- [x] Create
VectorStoreService.java- Store and search vectors with Lucene KnnVectorField
- [x] Create
- [x] Implement AI Search Service
- [x] Create
AiSearchService.java- Natural language and semantic/hybrid search
- [x] Create
- [x] Implement File Summary Service
- [x] Create
FileSummaryService.java- Generate file summaries with AI
- [x] Create
- [x] Implement File Classification Service
- [x] Create
FileClassificationService.java- Auto classify and tag files
- [x] Create
- [x] Create VO classes for API responses
- [x] Create
FileSummaryVO.java - [x] Create
FileClassificationVO.java - [x] Create
TagSuggestionVO.java
- [x] Create
- [x] Implement REST API Controller
- [x] Create
AiController.javawith all endpoints under/api/ai
- [x] Create
- [x] Add default AI configuration to application.yml
- [x] Update data models
- [x] Add
summaryfield to FileDocument - [x] Add
summaryfield to FileMetadataDO - [x] Add new IFileDAO methods for search and summary operations
- [x] Implement MongoDB and JPA DAO methods
- [x] Add
- [x] Code review and security check passed
Original prompt
需求概述
在现有的 JmalCloud 私有云存储项目中集成 Spring AI,实现以下 AI 智能功能:
- 自然语言搜索文件 - 用户可以使用自然语言描述来搜索文件
- 向量化 - 对文件内容进行向量化存储,支持语义搜索
- 文件总结 - 自动生成文件内容摘要
- 智能分类 - 自动对文件进行分类和打标签
技术实现要求
1. 添加 Spring AI 依赖配置
在 pom.xml 中添加以下依赖:
-
spring-ai-openai-spring-boot-starter- OpenAI 支持 -
spring-ai-ollama-spring-boot-starter- Ollama 本地部署支持 - 相关的向量存储依赖
2. 创建 AI 配置类
创建 src/main/java/com/jmal/clouddisk/ai/ 包,包含:
-
AiConfig.java- AI 主配置类,支持多种 LLM 提供商切换 -
AiProperties.java- AI 配置属性类,包含:-
provider- 提供商类型(openai/ollama) -
apiKey- API 密钥 -
baseUrl- API 基础 URL -
model- 模型名称 -
embeddingModel- 向量模型名称 -
temperature- 温度参数 -
maxTokens- 最大 token 数 -
enabled- 是否启用 AI 功能 -
vectorDimension- 向量维度(默认 1536)
-
3. 实现向量存储服务 - 基于 Lucene 的向量索引
创建以下类:
-
VectorStoreService.java- 向量存储服务- 使用 Lucene 的
KnnVectorField存储文档向量 - 在现有
LuceneService的索引流程中集成向量化 - 支持向量相似度搜索(使用
KnnVectorQuery) - 方法:
-
storeVector(String fileId, float[] vector)- 存储向量 -
searchSimilar(float[] queryVector, int topK)- 相似度搜索 -
deleteVector(String fileId)- 删除向量
-
- 使用 Lucene 的
-
EmbeddingService.java- 向量生成服务- 调用 LLM 的 embedding API 生成向量
- 支持文本分块处理(大文件内容分块后取平均向量)
- 方法:
-
embed(String text)- 生成文本向量 -
embedBatch(List<String> texts)- 批量生成向量
-
4. 实现 AI 搜索服务 - 自然语言查询转换
创建 AiSearchService.java:
- 将用户的自然语言查询转换为结构化搜索条件
- 结合向量搜索和关键词搜索实现混合搜索
- 方法:
-
naturalLanguageSearch(String query, String userId)- 自然语言搜索 -
semanticSearch(String query, String userId, int topK)- 语义向量搜索 -
hybridSearch(String query, String userId)- 混合搜索(关键词+向量)
-
提示词模板示例:
你是一个文件搜索助手。用户会用自然语言描述他们要找的文件。
请分析用户的意图,提取关键信息:
- 文件类型(如:图片、文档、视频等)
- 时间范围(如:最近一周、上个月等)
- 关键词
- 其他条件
用户查询:{query}
请返回 JSON 格式:
{
"fileTypes": ["image", "document"],
"keywords": ["关键词1", "关键词2"],
"timeRange": {"start": "2024-01-01", "end": "2024-12-31"},
"sortBy": "updateDate",
"sortOrder": "desc"
}
5. 实现文件总结服务 - 自动生成文件摘要
创建 FileSummaryService.java:
- 对文件内容生成摘要
- 支持多种文件类型(利用现有 Tika 提取的内容)
- 摘要存储在数据库中,避免重复生成
- 方法:
-
generateSummary(String fileId)- 生成文件摘要 -
getSummary(String fileId)- 获取已有摘要 -
regenerateSummary(String fileId)- 重新生成摘要 -
batchGenerateSummary(List<String> fileIds)- 批量生成
-
提示词模板:
请对以下文件内容生成简洁的摘要(不超过200字):
文件名:{fileName}
文件类型:{fileType}
内容:
{content}
请用中文回复,摘要应该包含文件的主要内容和关键信息。
6. 实现智能分类服务 - 自动分类和标签
创建 FileClassificationService.java:
- 根据文件内容自动分类
- 自动生成标签建议
- 与现有的标签系统(TagService)集成
- 方法:
-
classifyFile(String fileId)- 分类文件 -
suggestTags(String fileId)- 建议标签 -
autoTagFile(String fileId)- 自动打标签 -
batchClassify(List<String> fileIds)- 批量分类
-
预定义分类:
- 工作文档
- 个人照片
- 视频媒体
- 音乐音频
- 代码项目
- 学习资料
- 财务文件
- 其他
提示词模板:
请分析以下文件内容,给出分类和标签建议:
文件名:{fileName}
文件类型:{fileType}
内容摘要:
{contentSummary}
请返回 JSON 格式:
{
"category": "分类名称",
"tags": ["标签1", "标签2", "标签3"],
"confidence": 0.95
}
可选分类:工作文档、个人照片、视频媒体、音乐音频、代码项目、学习资料、财务文件、其他
7. 添加 REST API 接口
创建 AiController.java(路径:/api/ai):
@RestController
@RequestMapping("/api/ai")
public class AiController {
// 自然语言搜索
@GetMapping("/search")
public ResponseResult<List<FileIntroVO>> naturalLanguageSearch(
@RequestParam String query,
@RequestParam(required = false) Integer page,
@RequestParam(required = false) Integer pageSize);
// 语义搜索
@GetMapping("/semantic-search")
public ResponseResult<List<FileIntroVO>> semanticSearch(
@RequestParam String query,
@RequestParam(defaultValue = "10") Integer topK);
// 获取文件摘要
@GetMapping("/summary/{fileId}")
public ResponseResult<FileSummaryVO> getFileSummary(@PathVariable String fileId);
// 生成文件摘要
@PostMapping("/summary/{fileId}")
public ResponseResult<FileSummaryVO> generateFileSummary(@PathVariable String fileId);
// 获取分类建议
@GetMapping("/classify/{fileId}")
public ResponseResult<FileClassificationVO> classifyFile(@PathVariable String fileId);
// 获取标签建议
@GetMapping("/suggest-tags/{fileId}")
public ResponseResult<List<String>> suggestTags(@PathVariable String fileId);
// 自动打标签
@PostMapping("/auto-tag/{fileId}")
public ResponseResult<Void> autoTagFile(@PathVariable String fileId);
// 获取 AI 配置状态
@GetMapping("/status")
public ResponseResult<AiStatusVO> getAiStatus();
// 更新 AI 配置
@PutMapping("/config")
public ResponseResult<Void> updateAiConfig(@RequestBody AiConfigDTO config);
}
8. 数据模型扩展
创建新的 VO/DTO 类:
-
FileSummaryVO.java- 文件摘要响应 -
FileClassificationVO.java- 文件分类响应 -
AiStatusVO.java- AI 状态响应 -
AiConfigDTO.java- AI 配置请求
在数据库中添加新字段(通过 MongoDB 文档或扩展现有模型):
-
summary- 文件摘要 -
aiCategory- AI 分类 -
aiTags- AI 建议的标签 -
embedding- 向量(可选,也可以存在 Lucene 中)
9. 在现有索引流程中集成向量化
修改 LuceneService.java:
- 在
updateIndex方法中,当读取文件内容后,调用EmbeddingService生成向量 - 将向量存储到 Lucene 索引中(使用
KnnVectorField) - 添加配置开关控制是否启用向量索引(考虑...
This pull request was created as a result of the following prompt from Copilot chat.
需求概述
在现有的 JmalCloud 私有云存储项目中集成 Spring AI,实现以下 AI 智能功能:
- 自然语言搜索文件 - 用户可以使用自然语言描述来搜索文件
- 向量化 - 对文件内容进行向量化存储,支持语义搜索
- 文件总结 - 自动生成文件内容摘要
- 智能分类 - 自动对文件进行分类和打标签
技术实现要求
1. 添加 Spring AI 依赖配置
在
pom.xml中添加以下依赖:
spring-ai-openai-spring-boot-starter- OpenAI 支持spring-ai-ollama-spring-boot-starter- Ollama 本地部署支持- 相关的向量存储依赖
2. 创建 AI 配置类
创建
src/main/java/com/jmal/clouddisk/ai/包,包含:
AiConfig.java- AI 主配置类,支持多种 LLM 提供商切换AiProperties.java- AI 配置属性类,包含:
provider- 提供商类型(openai/ollama)apiKey- API 密钥baseUrl- API 基础 URLmodel- 模型名称embeddingModel- 向量模型名称temperature- 温度参数maxTokens- 最大 token 数enabled- 是否启用 AI 功能vectorDimension- 向量维度(默认 1536)3. 实现向量存储服务 - 基于 Lucene 的向量索引
创建以下类:
VectorStoreService.java- 向量存储服务
- 使用 Lucene 的
KnnVectorField存储文档向量- 在现有
LuceneService的索引流程中集成向量化- 支持向量相似度搜索(使用
KnnVectorQuery)- 方法:
storeVector(String fileId, float[] vector)- 存储向量searchSimilar(float[] queryVector, int topK)- 相似度搜索deleteVector(String fileId)- 删除向量
EmbeddingService.java- 向量生成服务
- 调用 LLM 的 embedding API 生成向量
- 支持文本分块处理(大文件内容分块后取平均向量)
- 方法:
embed(String text)- 生成文本向量embedBatch(List<String> texts)- 批量生成向量4. 实现 AI 搜索服务 - 自然语言查询转换
创建
AiSearchService.java:
- 将用户的自然语言查询转换为结构化搜索条件
- 结合向量搜索和关键词搜索实现混合搜索
- 方法:
naturalLanguageSearch(String query, String userId)- 自然语言搜索semanticSearch(String query, String userId, int topK)- 语义向量搜索hybridSearch(String query, String userId)- 混合搜索(关键词+向量)提示词模板示例:
你是一个文件搜索助手。用户会用自然语言描述他们要找的文件。 请分析用户的意图,提取关键信息: - 文件类型(如:图片、文档、视频等) - 时间范围(如:最近一周、上个月等) - 关键词 - 其他条件 用户查询:{query} 请返回 JSON 格式: { "fileTypes": ["image", "document"], "keywords": ["关键词1", "关键词2"], "timeRange": {"start": "2024-01-01", "end": "2024-12-31"}, "sortBy": "updateDate", "sortOrder": "desc" }5. 实现文件总结服务 - 自动生成文件摘要
创建
FileSummaryService.java:
- 对文件内容生成摘要
- 支持多种文件类型(利用现有 Tika 提取的内容)
- 摘要存储在数据库中,避免重复生成
- 方法:
generateSummary(String fileId)- 生成文件摘要getSummary(String fileId)- 获取已有摘要regenerateSummary(String fileId)- 重新生成摘要batchGenerateSummary(List<String> fileIds)- 批量生成提示词模板:
请对以下文件内容生成简洁的摘要(不超过200字): 文件名:{fileName} 文件类型:{fileType} 内容: {content} 请用中文回复,摘要应该包含文件的主要内容和关键信息。6. 实现智能分类服务 - 自动分类和标签
创建
FileClassificationService.java:
- 根据文件内容自动分类
- 自动生成标签建议
- 与现有的标签系统(TagService)集成
- 方法:
classifyFile(String fileId)- 分类文件suggestTags(String fileId)- 建议标签autoTagFile(String fileId)- 自动打标签batchClassify(List<String> fileIds)- 批量分类预定义分类:
- 工作文档
- 个人照片
- 视频媒体
- 音乐音频
- 代码项目
- 学习资料
- 财务文件
- 其他
提示词模板:
请分析以下文件内容,给出分类和标签建议: 文件名:{fileName} 文件类型:{fileType} 内容摘要: {contentSummary} 请返回 JSON 格式: { "category": "分类名称", "tags": ["标签1", "标签2", "标签3"], "confidence": 0.95 } 可选分类:工作文档、个人照片、视频媒体、音乐音频、代码项目、学习资料、财务文件、其他7. 添加 REST API 接口
创建
AiController.java(路径:/api/ai):@RestController @RequestMapping("/api/ai") public class AiController { // 自然语言搜索 @GetMapping("/search") public ResponseResult<List<FileIntroVO>> naturalLanguageSearch( @RequestParam String query, @RequestParam(required = false) Integer page, @RequestParam(required = false) Integer pageSize); // 语义搜索 @GetMapping("/semantic-search") public ResponseResult<List<FileIntroVO>> semanticSearch( @RequestParam String query, @RequestParam(defaultValue = "10") Integer topK); // 获取文件摘要 @GetMapping("/summary/{fileId}") public ResponseResult<FileSummaryVO> getFileSummary(@PathVariable String fileId); // 生成文件摘要 @PostMapping("/summary/{fileId}") public ResponseResult<FileSummaryVO> generateFileSummary(@PathVariable String fileId); // 获取分类建议 @GetMapping("/classify/{fileId}") public ResponseResult<FileClassificationVO> classifyFile(@PathVariable String fileId); // 获取标签建议 @GetMapping("/suggest-tags/{fileId}") public ResponseResult<List<String>> suggestTags(@PathVariable String fileId); // 自动打标签 @PostMapping("/auto-tag/{fileId}") public ResponseResult<Void> autoTagFile(@PathVariable String fileId); // 获取 AI 配置状态 @GetMapping("/status") public ResponseResult<AiStatusVO> getAiStatus(); // 更新 AI 配置 @PutMapping("/config") public ResponseResult<Void> updateAiConfig(@RequestBody AiConfigDTO config); }8. 数据模型扩展
创建新的 VO/DTO 类:
FileSummaryVO.java- 文件摘要响应FileClassificationVO.java- 文件分类响应AiStatusVO.java- AI 状态响应AiConfigDTO.java- AI 配置请求在数据库中添加新字段(通过 MongoDB 文档或扩展现有模型):
summary- 文件摘要aiCategory- AI 分类aiTags- AI 建议的标签embedding- 向量(可选,也可以存在 Lucene 中)9. 在现有索引流程中集成向量化
修改
LuceneService.java:
- 在
updateIndex方法中,当读取文件内容后,调用EmbeddingService生成向量- 将向量存储到 Lucene 索引中(使用
KnnVectorField)- 添加配置开关控制是否启用向量索引(考虑性能和成本)
10. 配置文件示例
在
application.yml中添加:jmal: ai: enabled: true provider: openai # openai 或 ollama api-key: ${AI_API_KEY:} base-url: ${AI_BASE_URL:https://api.openai.com} model: gpt-4o-mini embedding-model: text-embedding-3-small temperature: 0.7 max-tokens: 2000 vector-dimension: 1536 # Ollama 配置 ollama: base-url: http://localhost:11434 model: llama3 embedding-model: nomic-embed-text注意事项
- 性能优化:向量化和 AI 调用应该异步处理,不阻塞主流程
- 成本控制:添加配置开关,允许用户选择性启用 AI 功能
- 错误处理:AI 服务不可用时应该优雅降级,不影响核心功能
- 缓存机制:摘要和分类结果应该缓存,避免重复调用
- 安全性:API 密钥应该通过环境变量配置,不硬编码
- 国际化:提示词应该支持中英文
文件结构
src/main/java/com/jmal/clouddisk/ ├── ai/ │ ├── config/ │ │ ├── AiConfig.java │ │ └── AiProperties.java │ ├── service/ │ │ ├── EmbeddingService.java │ │ ├── VectorStoreService.java │ │ ├── AiSearchService.java │ │ ├── FileSummaryService.java │ │ └── FileClassificationService.java │ ├── controller/ │ │ └── AiController.java │ ├── dto/ │ │ ├── AiConfigDTO.java │ │ ├── AiSearchResultDTO.java │ │ └── NaturalLanguageQueryDTO.java │ └── vo/ │ ├── FileSummaryVO.java │ ├── FileClassificationVO.java │ └── AiStatusVO.java测试要求
- 单元测试覆盖所有 AI 服务类
- 集成测试验证与 LLM 的通信
- Mock 测试确保 AI 服务不可用时的降级处理
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.
springboot 已经升级至
<groupId>org.springframework.ai</groupId> <artifactId>spring-ai-client-chat</artifactId> ...
Updated Spring AI from milestone 1.0.0-M4 to stable 1.0.0 release and removed the Spring Milestones repository since it's no longer needed. (01c6124)