# 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 metadata); /** * 获取文档列表 * @param category 分类过滤(可选) * @param page 页码 * @param size 每页大小 * @return 文档列表 */ public PageResult 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 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 embedBatch(List 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 retrieve(String query, int topK, double threshold); /** * 带分类过滤的检索 * @param query 查询文本 * @param category 分类 * @param topK 返回结果数量 * @return 检索结果列表 */ public List 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 assessmentData, Map userProfile); /** * 回答问题 * @param question 问题 * @param context 上下文(可选) * @return 生成结果(回答+来源引用) */ public GenerationResult answerQuestion(String question, String context); /** * 生成矫治建议 * @param userProfile 用户档案 * @param assessmentData 测评数据 * @return 生成结果(建议+来源引用) */ public GenerationResult generateSuggestions(Map userProfile, Map 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 options); /** * 获取可用模型列表 * @return 模型列表 */ public List 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 documents, List embeddings, List> metadatas, List ids); /** * 查询相似文档 * @param collectionName 集合名称 * @param queryEmbedding 查询向量 * @param topK 返回数量 * @param filter 过滤条件 * @return 查询结果 */ public QueryResult query(String collectionName, float[] queryEmbedding, int topK, Map filter); /** * 删除文档 * @param collectionName 集合名称 * @param ids ID列表 */ public void deleteDocuments(String collectionName, List 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 split(String text); /** * 按句子分块(保持语义完整) * @param text 文本内容 * @return 文本块列表 */ public List splitBySentences(String text); } ``` #### 2.3 PromptBuilder (提示词构建器) **职责**: 构建发送给大模型的提示词 **接口**: ```java @Component public class PromptBuilder { /** * 构建报告生成提示词 * @param retrievedDocs 检索到的文档 * @param assessmentData 测评数据 * @param userProfile 用户档案 * @return 提示词 */ public String buildReportPrompt(List retrievedDocs, Map assessmentData, Map userProfile); /** * 构建问答提示词 * @param question 问题 * @param retrievedDocs 检索到的文档 * @return 提示词 */ public String buildQAPrompt(String question, List retrievedDocs); /** * 构建建议生成提示词 * @param userProfile 用户档案 * @param assessmentData 测评数据 * @param retrievedDocs 检索到的文档 * @return 提示词 */ public String buildSuggestionPrompt(Map userProfile, Map assessmentData, List 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 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 metadata; // 元数据 // getters and setters } ``` #### 2.3 生成结果 ```java public class GenerationResult { private String content; // 生成的内容(报告/回答) private List 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 assessmentData; // 测评数据 private Map 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 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 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 ids; // ID列表 private List documents; // 文档列表 private List embeddings; // 向量列表 private List> metadatas; // 元数据列表 // getters and setters } ``` #### 4.2 查询请求 ```java public class ChromaQueryRequest { private float[] queryEmbeddings; // 查询向量 private Integer nResults; // 返回数量 private Map where; // 过滤条件 // getters and setters } ``` #### 4.3 查询响应 ```java public class ChromaQueryResponse { private List ids; // ID列表 private List documents; // 文档列表 private List distances; // 距离列表 private List> 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. **细粒度权限**: 不同用户角色访问不同的知识库分类