xinli/.kiro/specs/local-rag-knowledge-base/design.md

1275 lines
39 KiB
Markdown
Raw Permalink Normal View History

# Design Document
## Overview
本设计文档描述了基于Ollama本地大模型和ChromaDB向量数据库的RAG知识库系统。系统采用纯Java实现所有功能集成在Spring Boot应用中通过HTTP直接调用Ollama API。核心功能包括文档管理、向量检索、RAG增强生成和智能问答。系统支持监听指定文件夹自动加载文档部署时只需一个JAR包。
### 技术栈
- **后端框架**: Spring Boot 2.x
- **向量数据库**: ChromaDB (通过HTTP API调用)
- **嵌入模型**: nomic-embed-text (768维向量)
- **生成模型**: deepseek-r1:32b (32B参数)
- **文档解析**: Apache PDFBox (PDF), Apache POI (Word)
- **HTTP客户端**: OkHttp / RestTemplate
- **前端**: Vue.js (现有系统)
### 部署架构
```
[Vue.js前端]
↓ HTTP
[Spring Boot JAR包:8080]
├── 知识库管理模块
├── RAG检索模块
├── AI生成模块
└── 文件监听模块
↓ HTTP ↓ 文件系统
[Ollama:11434] [ChromaDB数据: D:\wwwroot\RAG\data\chroma_db]
[文档文件: D:\wwwroot\RAG\uploads]
```
## Architecture
### 系统分层架构
```
┌─────────────────────────────────────────────────────────────┐
│ Presentation Layer │
│ - Vue.js前端界面 │
│ - 知识库管理页面 │
│ - 报告展示页面 │
│ - 智能问答界面 │
└──────────────────────┬──────────────────────────────────────┘
│ REST API
┌──────────────────────▼──────────────────────────────────────┐
│ Spring Boot Application Layer │
│ Controllers: │
│ - PsyKnowledgeController (知识库管理) │
│ - PsyAIAnalysisController (AI分析) │
│ - PsyAIChatController (智能问答) │
└──────────────────────┬──────────────────────────────────────┘
┌──────────────────────▼──────────────────────────────────────┐
│ Service Layer │
│ - KnowledgeService (文档管理) │
│ - EmbeddingService (向量化) │
│ - RetrievalService (RAG检索) │
│ - GenerationService (AI生成) │
│ - OllamaClient (Ollama API调用) │
│ - ChromaDBClient (ChromaDB HTTP API调用) │
│ - FileWatcherService (文件夹监听) │
└──────────────────────┬──────────────────────────────────────┘
┌──────────────────────▼──────────────────────────────────────┐
│ Utility Layer │
│ - DocumentParser (文档解析: PDF, Word, TXT) │
│ - TextSplitter (文本分块) │
│ - PromptBuilder (提示词构建) │
│ - VectorUtils (向量计算工具) │
└──────────────┬────────────────────┬─────────────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Ollama API │ │ ChromaDB │
│ (Port 11434) │ │ HTTP API │
│ - embed │ │ (Port 8000) │
│ - generate │ │ │
└──────────────────┘ └──────────────────┘
│ │
▼ ▼
┌──────────────────────────────────────┐
│ File System │
│ D:\wwwroot\RAG\ │
│ ├── data\chroma_db\ (向量数据) │
│ ├── uploads\ (文档文件) │
│ └── logs\ (日志文件) │
└──────────────────────────────────────┘
```
### 数据流
#### 文档上传流程
```
用户上传文档 → Spring Boot Controller接收
→ DocumentParser解析文档 → TextSplitter分块
→ OllamaClient调用nomic-embed-text向量化
→ ChromaDBClient存储向量 → 保存原文件到uploads目录
→ 返回成功响应
```
#### 文件夹自动加载流程
```
管理员放置文档到 D:\wwwroot\RAG\uploads
→ FileWatcherService检测到新文件
→ 自动触发文档解析流程 → 分块 → 向量化 → 存储
→ 记录处理日志
```
#### RAG报告生成流程
```
用户请求报告 → Spring Boot Controller接收
→ GenerationService构建查询(测评数据+用户档案)
→ EmbeddingService向量化查询
→ RetrievalService从ChromaDB语义检索(Top-5)
→ 过滤低相似度结果(threshold=0.7)
→ PromptBuilder构建提示词(检索知识+用户数据)
→ OllamaClient调用deepseek-r1生成报告
→ 存储报告到MySQL → 返回报告+引用来源
→ 前端展示报告
```
#### 智能问答流程
```
用户提问 → Spring Boot Controller接收
→ EmbeddingService向量化问题
→ RetrievalService从ChromaDB语义检索
→ PromptBuilder构建提示词
→ OllamaClient调用deepseek-r1生成回答
→ 返回回答+引用来源 → 前端展示
```
## Components and Interfaces
### 1. Service Layer (Spring Boot Services)
#### 1.1 KnowledgeService (知识库管理服务)
**职责**: 管理文档的上传、存储、检索和删除
**接口**:
```java
@Service
public class KnowledgeService {
/**
* 上传并处理文档
* @param file 上传的文件
* @param category 文档分类
* @param metadata 元数据
* @return 文档信息
*/
public DocumentInfo uploadDocument(MultipartFile file, String category, Map<String, Object> metadata);
/**
* 获取文档列表
* @param category 分类过滤(可选)
* @param page 页码
* @param size 每页大小
* @return 文档列表
*/
public PageResult<DocumentInfo> listDocuments(String category, int page, int size);
/**
* 获取文档详情
* @param docId 文档ID
* @return 文档详情
*/
public DocumentInfo getDocument(String docId);
/**
* 删除文档
* @param docId 文档ID
* @return 是否成功
*/
public boolean deleteDocument(String docId);
/**
* 搜索文档
* @param keyword 关键词
* @return 文档列表
*/
public List<DocumentInfo> searchDocuments(String keyword);
/**
* 重建索引
* @return 重建结果
*/
public RebuildResult rebuildIndex();
}
```
#### 1.2 EmbeddingService (向量化服务)
**职责**: 使用nomic-embed-text模型生成文本向量
**接口**:
```java
@Service
public class EmbeddingService {
private final OllamaClient ollamaClient;
private static final String MODEL_NAME = "nomic-embed-text";
/**
* 将单个文本转换为768维向量
* @param text 文本内容
* @return 768维向量数组
*/
public float[] embedText(String text);
/**
* 批量向量化
* @param texts 文本列表
* @return 向量列表
*/
public List<float[]> embedBatch(List<String> texts);
}
```
#### 1.3 RetrievalService (RAG检索服务)
**职责**: 从ChromaDB检索相关文档片段
**接口**:
```java
@Service
public class RetrievalService {
private final ChromaDBClient chromaDBClient;
private final EmbeddingService embeddingService;
private static final String COLLECTION_NAME = "psychology_knowledge";
/**
* 语义检索相关文档
* @param query 查询文本
* @param topK 返回结果数量
* @param threshold 相似度阈值
* @return 检索结果列表
*/
public List<RetrievalResult> retrieve(String query, int topK, double threshold);
/**
* 带分类过滤的检索
* @param query 查询文本
* @param category 分类
* @param topK 返回结果数量
* @return 检索结果列表
*/
public List<RetrievalResult> retrieveWithFilter(String query, String category, int topK);
}
```
#### 1.4 GenerationService (AI生成服务)
**职责**: 调用deepseek-r1模型生成报告和回答
**接口**:
```java
@Service
public class GenerationService {
private final OllamaClient ollamaClient;
private final RetrievalService retrievalService;
private static final String MODEL_NAME = "deepseek-r1:32b";
/**
* 生成综合分析报告
* @param assessmentData 测评数据
* @param userProfile 用户档案
* @return 生成结果(报告内容+来源引用)
*/
public GenerationResult generateReport(Map<String, Object> assessmentData, Map<String, Object> userProfile);
/**
* 回答问题
* @param question 问题
* @param context 上下文(可选)
* @return 生成结果(回答+来源引用)
*/
public GenerationResult answerQuestion(String question, String context);
/**
* 生成矫治建议
* @param userProfile 用户档案
* @param assessmentData 测评数据
* @return 生成结果(建议+来源引用)
*/
public GenerationResult generateSuggestions(Map<String, Object> userProfile, Map<String, Object> assessmentData);
}
```
#### 1.5 OllamaClient (Ollama API客户端)
**职责**: 封装Ollama HTTP API调用
**接口**:
```java
@Component
public class OllamaClient {
private final RestTemplate restTemplate;
private final String baseUrl = "http://localhost:11434";
/**
* 调用嵌入API
* @param model 模型名称
* @param text 文本内容
* @return 向量数组
*/
public float[] embed(String model, String text);
/**
* 调用生成API
* @param model 模型名称
* @param prompt 提示词
* @param options 生成选项
* @return 生成的文本
*/
public String generate(String model, String prompt, Map<String, Object> options);
/**
* 获取可用模型列表
* @return 模型列表
*/
public List<ModelInfo> listModels();
/**
* 检查连接状态
* @return 是否连接成功
*/
public boolean checkConnection();
}
```
#### 1.6 ChromaDBClient (ChromaDB HTTP API客户端)
**职责**: 封装ChromaDB HTTP API调用
**接口**:
```java
@Component
public class ChromaDBClient {
private final RestTemplate restTemplate;
private final String baseUrl = "http://localhost:8000";
/**
* 添加文档向量
* @param collectionName 集合名称
* @param documents 文档列表
* @param embeddings 向量列表
* @param metadatas 元数据列表
* @param ids ID列表
*/
public void addDocuments(String collectionName, List<String> documents,
List<float[]> embeddings, List<Map<String, Object>> metadatas, List<String> ids);
/**
* 查询相似文档
* @param collectionName 集合名称
* @param queryEmbedding 查询向量
* @param topK 返回数量
* @param filter 过滤条件
* @return 查询结果
*/
public QueryResult query(String collectionName, float[] queryEmbedding, int topK, Map<String, Object> filter);
/**
* 删除文档
* @param collectionName 集合名称
* @param ids ID列表
*/
public void deleteDocuments(String collectionName, List<String> ids);
/**
* 获取集合信息
* @param collectionName 集合名称
* @return 集合信息
*/
public CollectionInfo getCollection(String collectionName);
}
```
#### 1.7 FileWatcherService (文件夹监听服务)
**职责**: 监听uploads文件夹自动处理新文档
**接口**:
```java
@Service
public class FileWatcherService {
private final KnowledgeService knowledgeService;
private final String watchPath = "D:\\wwwroot\\RAG\\uploads";
/**
* 启动文件监听
*/
@PostConstruct
public void startWatching();
/**
* 处理新文件
* @param file 新文件
*/
private void processNewFile(File file);
/**
* 停止文件监听
*/
@PreDestroy
public void stopWatching();
}
```
### 2. Utility Components
#### 2.1 DocumentParser (文档解析器)
**职责**: 解析不同格式的文档
**接口**:
```java
@Component
public class DocumentParser {
/**
* 解析PDF文档
* @param filePath 文件路径
* @return 文本内容
*/
public String parsePdf(String filePath);
/**
* 解析Word文档
* @param filePath 文件路径
* @return 文本内容
*/
public String parseDocx(String filePath);
/**
* 解析TXT文档
* @param filePath 文件路径
* @return 文本内容
*/
public String parseTxt(String filePath);
/**
* 自动识别格式并解析
* @param filePath 文件路径
* @return 文本内容
*/
public String parse(String filePath);
}
```
#### 2.2 TextSplitter (文本分块器)
**职责**: 将长文本分割成适合向量化的块
**接口**:
```java
@Component
public class TextSplitter {
private int chunkSize = 800;
private int chunkOverlap = 200;
/**
* 按字符数分块
* @param text 文本内容
* @return 文本块列表
*/
public List<String> split(String text);
/**
* 按句子分块(保持语义完整)
* @param text 文本内容
* @return 文本块列表
*/
public List<String> splitBySentences(String text);
}
```
#### 2.3 PromptBuilder (提示词构建器)
**职责**: 构建发送给大模型的提示词
**接口**:
```java
@Component
public class PromptBuilder {
/**
* 构建报告生成提示词
* @param retrievedDocs 检索到的文档
* @param assessmentData 测评数据
* @param userProfile 用户档案
* @return 提示词
*/
public String buildReportPrompt(List<RetrievalResult> retrievedDocs,
Map<String, Object> assessmentData,
Map<String, Object> userProfile);
/**
* 构建问答提示词
* @param question 问题
* @param retrievedDocs 检索到的文档
* @return 提示词
*/
public String buildQAPrompt(String question, List<RetrievalResult> retrievedDocs);
/**
* 构建建议生成提示词
* @param userProfile 用户档案
* @param assessmentData 测评数据
* @param retrievedDocs 检索到的文档
* @return 提示词
*/
public String buildSuggestionPrompt(Map<String, Object> userProfile,
Map<String, Object> assessmentData,
List<RetrievalResult> retrievedDocs);
}
```
### 3. Controller Layer
#### 3.1 PsyKnowledgeController (知识库管理控制器)
**职责**: 提供知识库管理的REST API
**接口**:
```java
@RestController
@RequestMapping("/psychology/knowledge")
public class PsyKnowledgeController {
@PostMapping("/upload")
public AjaxResult uploadDocument(@RequestParam("file") MultipartFile file,
@RequestParam("category") String category);
@GetMapping("/list")
public TableDataInfo listDocuments(@RequestParam(required = false) String category,
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "10") int pageSize);
@GetMapping("/{id}")
public AjaxResult getDocument(@PathVariable String id);
@DeleteMapping("/{id}")
public AjaxResult deleteDocument(@PathVariable String id);
@PostMapping("/search")
public AjaxResult searchDocuments(@RequestParam String keyword);
@PostMapping("/rebuild")
public AjaxResult rebuildIndex();
}
```
#### 3.2 PsyAIAnalysisController (AI分析控制器)
**职责**: 提供AI分析功能的REST API
**接口**:
```java
@RestController
@RequestMapping("/psychology/ai")
public class PsyAIAnalysisController {
@PostMapping("/generate-report")
public AjaxResult generateReport(@RequestBody AIReportRequest request);
@PostMapping("/chat")
public AjaxResult chat(@RequestBody AIChatRequest request);
@GetMapping("/system/status")
public AjaxResult getSystemStatus();
}
```
## Data Models
### 1. ChromaDB Collection Schema
ChromaDB通过HTTP API访问数据格式如下
```json
// Collection: psychology_knowledge
{
"name": "psychology_knowledge",
"metadata": {
"description": "监狱心理学知识库",
"embedding_model": "nomic-embed-text",
"dimension": 768
}
}
// Document Schema
{
"id": "doc_uuid_chunk_index",
"document": "文档内容文本...",
"embedding": [0.1, 0.2, ...],
"metadata": {
"doc_id": "doc_uuid",
"filename": "心理学教材.pdf",
"category": "人格心理学",
"chunk_index": 0,
"total_chunks": 10,
"upload_time": "2025-01-01 10:00:00",
"file_size": 1024000,
"page_number": 1
}
}
```
### 2. Java Domain Models
#### 2.1 文档信息
```java
public class DocumentInfo {
private String docId; // 文档唯一ID
private String filename; // 文件名
private String category; // 分类
private Integer totalChunks; // 总分块数
private Long fileSize; // 文件大小(字节)
private Date uploadTime; // 上传时间
private Map<String, Object> metadata; // 其他元数据
// getters and setters
}
```
#### 2.2 检索结果
```java
public class RetrievalResult {
private String docId; // 文档ID
private String filename; // 文件名
private Integer chunkIndex; // 分块索引
private Double similarity; // 相似度分数
private String content; // 文档片段内容
private Map<String, Object> metadata; // 元数据
// getters and setters
}
```
#### 2.3 生成结果
```java
public class GenerationResult {
private String content; // 生成的内容(报告/回答)
private List<SourceReference> sources; // 来源引用
private Double generationTime; // 生成耗时(秒)
// getters and setters
}
public class SourceReference {
private String docId; // 文档ID
private String filename; // 文件名
private Integer chunkIndex; // 分块索引
private Double similarity; // 相似度
private String content; // 引用片段
// getters and setters
}
```
#### 2.4 AI报告请求
```java
public class AIReportRequest {
private Map<String, Object> assessmentData; // 测评数据
private Map<String, Object> userProfile; // 用户档案
// getters and setters
}
```
#### 2.5 AI问答请求
```java
public class AIChatRequest {
private String question; // 问题
private String context; // 上下文(可选)
// getters and setters
}
```
#### 2.6 系统状态响应
```java
public class SystemStatusResponse {
private Boolean ollamaConnected; // Ollama连接状态
private Boolean chromaDBConnected; // ChromaDB连接状态
private List<String> availableModels; // 可用模型列表
private KnowledgeStats knowledgeStats; // 知识库统计
// getters and setters
}
public class KnowledgeStats {
private Integer totalDocuments; // 文档总数
private Integer totalChunks; // 向量总数
private Long storageSize; // 存储空间(字节)
// getters and setters
}
```
#### 2.7 重建结果
```java
public class RebuildResult {
private Boolean success; // 是否成功
private String message; // 消息
private Integer processedFiles; // 处理的文件数
private Integer totalChunks; // 生成的向量数
private Double elapsedTime; // 耗时(秒)
// getters and setters
}
```
### 3. Ollama API Models
#### 3.1 嵌入请求
```java
public class OllamaEmbedRequest {
private String model; // 模型名称
private String prompt; // 文本内容
// getters and setters
}
```
#### 3.2 嵌入响应
```java
public class OllamaEmbedResponse {
private float[] embedding; // 向量数组
// getters and setters
}
```
#### 3.3 生成请求
```java
public class OllamaGenerateRequest {
private String model; // 模型名称
private String prompt; // 提示词
private Boolean stream; // 是否流式输出
private Map<String, Object> options; // 生成选项
// getters and setters
}
```
#### 3.4 生成响应
```java
public class OllamaGenerateResponse {
private String response; // 生成的文本
private Boolean done; // 是否完成
// getters and setters
}
```
### 4. ChromaDB API Models
#### 4.1 添加文档请求
```java
public class ChromaAddRequest {
private List<String> ids; // ID列表
private List<String> documents; // 文档列表
private List<float[]> embeddings; // 向量列表
private List<Map<String, Object>> metadatas; // 元数据列表
// getters and setters
}
```
#### 4.2 查询请求
```java
public class ChromaQueryRequest {
private float[] queryEmbeddings; // 查询向量
private Integer nResults; // 返回数量
private Map<String, Object> where; // 过滤条件
// getters and setters
}
```
#### 4.3 查询响应
```java
public class ChromaQueryResponse {
private List<String> ids; // ID列表
private List<String> documents; // 文档列表
private List<Double> distances; // 距离列表
private List<Map<String, Object>> metadatas; // 元数据列表
// getters and setters
}
```
## Data Models
### ChromaDB存储路径
```
D:\wwwroot\RAG\
├── data\
│ └── chroma_db\ # ChromaDB数据目录
│ ├── chroma.sqlite3 # 元数据数据库
│ └── [向量数据文件]
├── uploads\ # 上传文件临时存储
│ └── [原始文档文件]
└── logs\ # 日志文件
└── ai_service.log
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property Reflection
在编写具体属性之前,我们需要识别并消除冗余的属性:
**识别的冗余情况**:
1. 属性3.1和4.1都测试向量维度为768可以合并为一个通用的"向量化输出维度"属性
2. 属性3.2和4.2都测试Top-K检索返回不超过5个结果可以合并
3. 属性3.6和4.5都测试返回格式包含内容和来源,可以合并为通用的"响应格式完整性"属性
4. 属性1.1、1.2、1.3都测试文档解析,可以合并为一个"文档解析正确性"属性
5. 属性1.6和8.5都测试数据持久化,可以合并为"数据持久化round-trip"属性
**合并后的核心属性集**:
- 文档处理: 解析、分块、向量化、存储
- 检索功能: Top-K检索、相似度过滤、分类过滤
- 生成功能: 报告生成、问答、响应格式
- 管理功能: CRUD操作、索引重建
- 系统功能: 错误处理、状态查询、数据持久化
### Core Properties
**Property 1: 文档解析正确性**
*For any* 支持格式的文档PDF、Word、TXT解析后提取的文本内容应该与文档中的实际文本内容一致
**Validates: Requirements 1.1, 1.2, 1.3**
**Property 2: 文档分块大小约束**
*For any* 文档分块后除最后一块外每个块的字符数应该在500到1000之间
**Validates: Requirements 1.4**
**Property 3: 向量维度一致性**
*For any* 文本输入文档块、查询、问题使用nomic-embed-text生成的向量维度应该恰好为768
**Validates: Requirements 1.5, 3.1, 4.1**
**Property 4: 数据持久化round-trip**
*For any* 文档及其向量和元数据存储到ChromaDB后应该能检索到完全相同的数据AI服务重启后数据应该保持完整
**Validates: Requirements 1.6, 8.5**
**Property 5: 上传失败状态不变性**
*For any* 导致上传失败的无效输入系统应该返回错误信息且ChromaDB中的文档数量保持不变
**Validates: Requirements 1.7**
**Property 6: 文档列表完整性**
*For any* 知识库状态上传N个新文档后文档列表的长度应该增加N
**Validates: Requirements 2.1**
**Property 7: 文档删除有效性**
*For any* 已存在的文档删除后该文档ID不应该出现在文档列表中且无法通过该ID检索到文档详情
**Validates: Requirements 2.3**
**Property 8: 分类过滤正确性**
*For any* 分类查询返回的所有文档的category字段都应该等于查询的分类值
**Validates: Requirements 2.4**
**Property 9: 文件名搜索匹配性**
*For any* 搜索关键词,返回的所有文档的文件名都应该包含该关键词(不区分大小写)
**Validates: Requirements 2.5**
**Property 10: Top-K检索数量约束**
*For any* 查询向量从ChromaDB检索时返回的结果数量应该不超过指定的top_k值默认5
**Validates: Requirements 3.2, 4.2**
**Property 11: 相似度阈值过滤**
*For any* 检索结果所有返回的文档片段的相似度分数都应该大于或等于0.7
**Validates: Requirements 3.3**
**Property 12: 上下文包含必要信息**
*For any* 报告生成请求,构建的上下文字符串应该同时包含检索到的知识片段、测评数据和用户档案信息
**Validates: Requirements 3.4**
**Property 13: 生成响应非空性**
*For any* 有效的上下文输入AI模型生成的报告或回答内容应该是非空字符串
**Validates: Requirements 3.5, 4.4**
**Property 14: 响应格式完整性**
*For any* 成功的生成请求(报告或问答),响应应该同时包含生成的内容字段和来源引用列表字段
**Validates: Requirements 3.6, 4.5**
**Property 15: 错误响应包含信息**
*For any* 导致失败的请求,响应应该包含非空的错误消息字段
**Validates: Requirements 3.7**
**Property 16: 提示词包含查询和知识**
*For any* 问答请求,构建的提示词应该同时包含用户问题和检索到的知识片段
**Validates: Requirements 4.3**
**Property 17: 系统状态响应完整性**
*For any* 系统状态查询响应应该包含Ollama连接状态、ChromaDB状态和可用模型列表这三个字段
**Validates: Requirements 5.1**
**Property 18: 连接测试返回明确状态**
*For any* Ollama连接测试响应应该明确指示连接成功或失败布尔值或状态码
**Validates: Requirements 5.2**
**Property 19: 统计数据准确性**
*For any* 知识库状态,统计查询返回的文档总数应该等于文档列表的长度
**Validates: Requirements 5.3**
**Property 20: 错误日志记录完整性**
*For any* 捕获的异常,日志文件应该包含该异常的时间戳和堆栈跟踪信息
**Validates: Requirements 5.4**
**Property 21: HTTP请求包含必要数据**
*For any* Spring Boot发起的报告生成请求HTTP请求体应该包含assessmentData和userProfile字段
**Validates: Requirements 6.1**
**Property 22: 报告持久化round-trip**
*For any* AI服务返回的报告存储到MySQL后应该能通过报告ID查询到相同的报告内容
**Validates: Requirements 6.2**
**Property 23: 错误处理日志记录**
*For any* AI服务返回的错误响应Spring Boot应该在日志中记录该错误
**Validates: Requirements 6.4**
**Property 24: 问答请求包含问题**
*For any* Spring Boot发起的问答请求HTTP请求体应该包含question字段
**Validates: Requirements 6.5**
**Property 25: API响应JSON格式有效性**
*For any* AI服务的HTTP响应响应体应该是有效的JSON格式
**Validates: Requirements 8.2**
**Property 26: 本地存储路径正确性**
*For any* 向量存储操作数据文件应该出现在配置的ChromaDB目录路径D:\wwwroot\RAG\data\chroma_db
**Validates: Requirements 9.3**
**Property 27: 文件本地存储验证**
*For any* 上传的文档原始文件应该存在于本地uploads目录中
**Validates: Requirements 9.5**
**Property 28: 索引重建后数据一致性**
*For any* 重建索引操作重建完成后ChromaDB中的文档数量应该等于uploads目录中的文档文件数量
**Validates: Requirements 10.1, 10.2, 10.3**
**Property 29: 重建进度范围有效性**
*For any* 重建过程中的进度查询返回的进度值应该在0到100之间包含边界
**Validates: Requirements 10.4**
**Property 30: 重建完成响应完整性**
*For any* 成功完成的重建操作,响应应该包含成功状态标志和统计信息(文档数、向量数)
**Validates: Requirements 10.5**
## Error Handling
### 错误分类
1. **输入验证错误**
- 无效文件格式
- 文件大小超限
- 缺少必需参数
- 响应: HTTP 400, 明确的错误消息
2. **资源不存在错误**
- 文档ID不存在
- 分类不存在
- 响应: HTTP 404, 资源标识信息
3. **外部服务错误**
- Ollama API不可用
- ChromaDB连接失败
- 响应: HTTP 503, 服务名称和错误详情
4. **处理超时错误**
- 文档解析超时
- AI生成超时
- 响应: HTTP 504, 超时操作描述
5. **系统内部错误**
- 未预期的异常
- 文件系统错误
- 响应: HTTP 500, 通用错误消息(不暴露内部细节)
### 错误处理策略
```python
# 统一错误响应格式
{
"code": 400, # HTTP状态码
"message": "文件格式不支持", # 用户友好消息
"error_type": "INVALID_FILE_FORMAT", # 错误类型代码
"details": { # 可选的详细信息
"supported_formats": ["pdf", "docx", "txt"]
},
"timestamp": "2025-01-01T10:00:00Z"
}
```
### 日志记录
- **INFO级别**: 正常操作(文档上传、报告生成)
- **WARNING级别**: 可恢复错误(相似度过滤、重试成功)
- **ERROR级别**: 需要关注的错误API调用失败、数据损坏
- **CRITICAL级别**: 系统级故障ChromaDB不可用、Ollama崩溃
日志格式:
```
[2025-01-01 10:00:00] [ERROR] [knowledge_service.py:123] 文档上传失败: doc_id=abc123, error=FileNotFoundError
Traceback: ...
```
## Testing Strategy
### 单元测试 (Unit Tests)
使用pytest框架测试各个组件的独立功能
**测试范围**:
- DocumentParser: 测试各种格式文档的解析
- TextSplitter: 测试分块算法的边界情况
- EmbeddingService: 测试向量化API调用使用mock
- RetrievalService: 测试检索逻辑使用内存ChromaDB
- PromptBuilder: 测试提示词模板构建
**示例测试**:
```python
def test_text_splitter_chunk_size():
"""测试分块大小约束"""
splitter = TextSplitter(chunk_size=800, chunk_overlap=200)
text = "a" * 5000
chunks = splitter.split(text)
for i, chunk in enumerate(chunks[:-1]): # 除最后一块
assert 500 <= len(chunk) <= 1000
```
### 属性测试 (Property-Based Tests)
使用Hypothesis库进行属性测试验证correctness properties
**配置**: 每个属性测试运行至少100次迭代
**测试库**: Hypothesis (Python)
**示例属性测试**:
```python
from hypothesis import given, strategies as st
@given(st.text(min_size=1000, max_size=10000))
def test_property_2_chunk_size_constraint(text):
"""
Feature: local-rag-knowledge-base, Property 2: 文档分块大小约束
"""
splitter = TextSplitter(chunk_size=800, chunk_overlap=200)
chunks = splitter.split(text)
# 除最后一块外每块应在500-1000字符之间
for chunk in chunks[:-1]:
assert 500 <= len(chunk) <= 1000
@given(st.text(min_size=10, max_size=1000))
def test_property_3_vector_dimension(text):
"""
Feature: local-rag-knowledge-base, Property 3: 向量维度一致性
"""
embedding_service = EmbeddingService()
vector = embedding_service.embed_text(text)
assert len(vector) == 768
```
### 集成测试 (Integration Tests)
测试组件之间的交互:
**测试场景**:
1. 完整的文档上传流程(解析→分块→向量化→存储)
2. 端到端的报告生成流程(查询→检索→生成→返回)
3. Spring Boot与Flask AI服务的HTTP通信
4. ChromaDB数据持久化和恢复
**测试环境**:
- 使用测试专用的ChromaDB实例
- 使用本地Ollama服务需要预先启动
- 使用测试数据库MySQL
### 测试数据
**文档测试数据**:
- 准备10-20个心理学相关的测试文档PDF、Word、TXT
- 包含不同长度1页、10页、100页
- 包含特殊字符、多语言内容
**测评数据测试数据**:
- 模拟MMPI、SCL-90等量表的答题数据
- 包含边界情况全选A、随机选择
### 性能测试
**基准指标**:
- 文档上传处理时间: <5秒/MB
- 向量检索时间: <1秒
- 报告生成时间: <30秒
- 并发请求支持: 10个并发用户
**测试工具**: pytest-benchmark, locust
### 测试覆盖率目标
- 代码覆盖率: >80%
- 属性覆盖率: 100%所有correctness properties都有对应测试
- API覆盖率: 100%所有API端点都有测试
## Deployment Considerations
### 环境要求
**硬件要求**:
- CPU: 8核以上推荐16核
- 内存: 32GB以上deepseek-r1:32b需要约20GB
- 存储: 100GB以上模型+知识库+日志)
- GPU: 可选,可加速推理
**软件要求**:
- Java 8+ (JDK)
- Ollama (已安装nomic-embed-text和deepseek-r1:32b)
- ChromaDB (通过Docker或直接安装)
- MySQL 5.7+
### 部署步骤
1. **创建目录结构**
```cmd
mkdir D:\wwwroot\RAG\data\chroma_db
mkdir D:\wwwroot\RAG\uploads
mkdir D:\wwwroot\RAG\logs
```
2. **启动Ollama服务**
```cmd
ollama serve
```
3. **启动ChromaDB服务**
```cmd
# 方式1: 使用Docker
docker run -p 8000:8000 chromadb/chroma
# 方式2: 使用Python安装
pip install chromadb
chroma run --path D:\wwwroot\RAG\data\chroma_db --port 8000
```
4. **配置Spring Boot**
```yaml
# application.yml
rag:
ollama:
url: http://localhost:11434
embed-model: nomic-embed-text
generate-model: deepseek-r1:32b
chromadb:
url: http://localhost:8000
collection: psychology_knowledge
storage:
upload-path: D:/wwwroot/RAG/uploads
log-path: D:/wwwroot/RAG/logs
file-watcher:
enabled: true
watch-path: D:/wwwroot/RAG/uploads
```
5. **打包Spring Boot应用**
```cmd
mvn clean package -DskipTests
```
6. **启动Spring Boot应用**
```cmd
java -jar ry-xinli-admin/target/xinli-admin.jar
```
### 一键部署方案
**部署包结构**:
```
xinli-rag-deploy/
├── xinli-admin.jar # Spring Boot应用
├── start.bat # 启动脚本
├── stop.bat # 停止脚本
├── config/
│ └── application.yml # 配置文件
├── data/ # 数据目录(自动创建)
├── uploads/ # 文档上传目录(自动创建)
└── logs/ # 日志目录(自动创建)
```
**start.bat 内容**:
```batch
@echo off
echo 正在启动心理评估系统...
REM 检查Ollama是否运行
curl -s http://localhost:11434/api/tags >nul 2>&1
if errorlevel 1 (
echo [错误] Ollama服务未启动请先启动Ollama
pause
exit /b 1
)
REM 检查ChromaDB是否运行
curl -s http://localhost:8000/api/v1/heartbeat >nul 2>&1
if errorlevel 1 (
echo [警告] ChromaDB服务未启动正在启动...
start /b chroma run --path D:\wwwroot\RAG\data\chroma_db --port 8000
timeout /t 5
)
REM 启动Spring Boot应用
echo 正在启动Spring Boot应用...
java -jar xinli-admin.jar
pause
```
### 监控和维护
**监控指标**:
- Spring Boot健康状态/actuator/health
- Ollama API响应时间
- ChromaDB存储空间使用率
- 请求成功率和错误率
- 文件监听服务状态
**日志管理**:
- 使用Logback按天切分日志
- 保留最近30天的日志
- 自动压缩归档旧日志
- 日志级别可配置INFO/DEBUG/ERROR
**备份策略**:
- 每天自动备份ChromaDB数据目录
- 每周备份uploads目录
- 保留最近7天的备份
- 支持手动触发备份
### 安全考虑
1. **访问控制**:
- Spring Security权限控制
- 知识库管理需要管理员权限
- API接口需要登录认证
2. **文件验证**:
- 上传文件格式白名单PDF、Word、TXT
- 文件大小限制默认50MB
- 文件内容安全扫描
3. **输入清理**:
- 防止SQL注入
- 防止XSS攻击
- 参数验证和清理
4. **日志脱敏**:
- 日志中不记录敏感个人信息
- 自动脱敏身份证号、手机号等
5. **数据安全**:
- 所有数据本地存储
- 不依赖外网服务
- 可选文档加密存储
## Future Enhancements
1. **知识库版本管理**: 支持文档的版本控制和回滚
2. **多模型支持**: 支持切换不同的嵌入模型和生成模型
3. **增量更新**: 支持文档的增量更新而非完全重新处理
4. **缓存机制**: 缓存常见查询的检索结果
5. **批量处理**: 支持批量上传和处理文档
6. **知识图谱**: 构建心理学概念的知识图谱
7. **多语言支持**: 支持英文等其他语言的文档
8. **细粒度权限**: 不同用户角色访问不同的知识库分类