Files
my-springboot-project/docs/文件上传与处理功能重构文档.md

11 KiB
Raw Permalink Blame History

文件上传与处理功能重构文档 📋 修改概述 将文件上传、向量化、出题三个功能解耦,实现分步式独立控制,支持灵活的业务场景组合。

🔧 核心改动

  1. 数据库表结构变更 1.1 File 表新增字段 tags (JSON类型):存储文件自定义标签,如版本信息、分类标识等元数据 1.2 Question 表新增字段 is_deleted (INT类型默认0)软删除标志0表示正常1表示已删除

  2. 实体类修改 2.1 File 实体 新增 tags 字段JSON格式支持存储任意自定义标签 2.2 Question 实体 新增 isDeleted 字段,实现题目软删除功能

  3. DTO 修改 FileUpdateRequest 新增 tags 字段Map类型支持通过更新接口设置文件标签

  4. Service 层功能增强 4.1 QuestionService 新增方法 软删除题目相关: softDeleteByFileId(Long fileId)根据文件ID软删除该文件关联的所有题目 softDeleteByDocumentName(String documentName):根据文档名软删除所有关联题目 实现逻辑: 查询指定文件/文档名的所有未删除题目 将题目的 isDeleted 字段设置为 1 更新 updatedAt 时间戳 返回实际删除的题目数量 4.2 FileService 接口调整 uploadFile 方法签名变更: 新增参数 autoVectorizeBoolean类型 控制上传后是否自动触发了向量化流程 实现逻辑: autoVectorize = false仅上传文件不向量化 autoVectorize = true上传后自动触发向量化需无需审核 需要审核的文件无论参数如何都暂不向量化

  5. Controller 层接口调整 5.1 FileController 修改 5.1.1 文件上传接口 (POST /file/upload) 新增参数: autoVectorize是否自动向量化默认 false 功能说明: 用户上传文件到服务器 根据 autoVectorize 参数决定是否自动触发了向量化 需要审核的文件暂存待审核区,不向量化 5.1.2 文件删除接口 (DELETE /file/{id}) 返回值变更: 从 Result 改为 Result<Map<String, Object>> 功能增强: 改为软删除(标记 status=0不物理删除 自动级联软删除该文件对应的所有题目 返回删除的题目数量统计 返回数据:

{ "success": true, "message": "文件和题目已成功软删除", "fileId": 123, "fileName": "document.pdf", "deletedQuestionCount": 15 }

5.1.3 文件更新接口 (PUT /file/{id}) 新增功能: 支持更新文件的 tags 字段 用户可自定义存储各种元数据(版本、分类、自定义字段等)

5.2 CollectionController 新增接口 5.2.1 级联软删除接口 (POST /collection/cascade-delete/{fileId}) 功能说明: 软删除指定文件并自动软删除其关联的所有题目 与 FileController 的删除接口功能类似,提供统一入口 前置条件: 用户已登录 文件存在且未被软删除 返回数据:{ "success": true, "message": "文件和题目已成功软删除", "fileId": 123, "fileName": "document.pdf", "deletedQuestionCount": 15 }

5.2.2 删除向量化数据接口 (POST /collection/{name}/devectorize?fileId=xxx) 功能说明: 删除文件的向量化数据(从 RAG 服务中移除) 如果存在关联题目,先自动软删除题目 清理本地数据库的文档关联记录 触发 AI 端同步 执行流程: 验证文件是否存在且有向量化数据 调用 questionService.softDeleteByFileId() 软删除关联题目 调用 RAG 服务删除向量化文档 清空文件的 vectorDbAddress 字段 重置文件状态为 PENDING 删除 collection_file 关联记录 触发同步 返回数据:{ "success": true, "message": "向量化数据已删除", "fileId": 123, "fileName": "document.pdf", "deletedQuestionCount": 10 }

5.2.3 文件生成题目接口 (POST /collection/{name}/generate-exam) 功能说明: 对已向量化完成的文件生成考试题目 异步执行,立即返回任务提交状态 请求参数: fileId必填文件ID questionTypes可选题目类型逗号分隔如 "single,multiple",默认 "single" difficulty可选难度等级 1-5默认 3 questionCount可选题目数量默认 10 前置条件: 文件必须已完成向量化vectorDbAddress 不为空) 执行流程: 验证文件存在且已完成向量化 更新文件状态为 "GENERATING_EXAM" 异步调用 examService.generateQuestionsWithFileId() 根据结果更新文件状态和题目生成状态 返回数据:

{ "success": true, "message": "题目生成任务已提交,正在后台处理中", "fileId": 123, "fileName": "document.pdf", "collection": "public_kb", "requestId": "EXAM_1234567890_123", "status": "GENERATING" }

🎯 业务场景支持 场景 1只上传不向量化 适用情况: 临时存储文件,后续再决定是否处理 操作流程POST /file/upload?autoVectorize=false

结果: 文件保存到服务器 数据库记录创建 不触发了向量化

场景 2上传并自动向量化 适用情况: 标准流程,上传后立即建立向量索引 操作流程POST /file/upload?autoVectorize=true

结果: 文件保存到服务器 自动触发了异步向量化 向量化完成后自动更新状态

场景 3手动触发了向量化 适用情况: 之前上传时未向量化,现在需要补充 操作流程POST /collection/{name}/vectorize?fileId=123

结果: 对指定文件进行向量化处理 异步执行,返回任务提交状态

场景 4向量化后生成题目 适用情况: 文件已向量化,需要基于内容生成考试题目 操作流程POST /collection/{name}/generate-exam?fileId=123&questionTypes=single,multiple&difficulty=3&questionCount=10

结果: 异步生成题目 题目保存到数据库 更新文件出题状态

场景 5新文件替换旧文件 适用情况: 上传新版本文件,需要清理旧文件及其衍生数据 操作流程1. 上传新文件

POST /file/upload?autoVectorize=true

  1. 级联删除旧文件(包括题目)

POST /collection/cascade-delete/{oldFileId}

结果: 旧文件标记为删除status=0 旧文件关联的所有题目标记为删除is_deleted=1 新文件正常处理

场景 6删除向量化但保留文件 适用情况: 需要重新向量化或不再需要向量检索 操作流程POST /collection/{name}/devectorize?fileId=123

结果: 先软删除关联题目(避免脏数据) 从 RAG 服务删除向量化数据 清空文件的向量化地址 重置文件状态为待处理

场景 7删除文件及所有关联数据 适用情况: 完全移除文件及其所有衍生数据 操作流程DELETE /file/{id}

结果: 文件软删除status=0 关联题目全部软删除is_deleted=1 数据保留在数据库中,可通过恢复操作还原

场景 8给文件添加自定义标签 适用情况: 为文件添加版本、分类等元数据 操作流程PUT /file/{id} { "tags": { "version": "v2", "category": "important", "custom_field": "any_value" } }

结果: 文件的 tags 字段更新为指定的 JSON 对象 支持任意自定义字段

📊 状态流转 文件状态 (processStatus) PENDING待处理上传完成但未向量化 VECTORIZING正在向量化 INDEXED向量化完成 GENERATING_EXAM正在生成题目 EXAM_GENERATED题目生成成功 EXAM_FAILED题目生成失败 DELETED已软删除 文件步骤状态 (processStepStatus) UPLOADED已上传 VECTORIZING向量化中 VECTORIZED已向量化 VECTORIZE_FAILED向量化失败 DELETED已删除 题目状态 (examStatus in File) UNGENERATED未生成题目 GENERATED已生成题目 FAILED生成失败 题目软删除 (isDeleted in Question) 0正常 1已删除软删除 文件软删除 (status in File) 1正常 0已删除软删除

⚙️ 技术特性

  1. 软删除机制 文件软删除:标记 status=0不物理删除文件和数据 题目软删除:标记 is_deleted=1保留历史记录 优势:数据可追溯、可恢复、符合审计要求

  2. 级联删除 删除文件时自动软删除关联题目 删除向量化时先软删除题目再清理向量数据 保证数据一致性,避免孤儿数据

  3. 异步处理 向量化操作异步执行,不阻塞接口响应 题目生成异步执行,支持大批量处理 通过状态字段追踪进度

  4. 标签系统 JSON 格式存储,灵活扩展 支持任意自定义字段 便于后续筛选和分类

  5. 权限控制 所有接口都需要用户登录验证 文件删除遵循原有权限规则 管理员可操作本部门文件

  6. 日志记录 完整记录关键操作流程 包含文件ID、文件名、操作结果等信息 便于问题排查和审计

  7. 🔄 接口依赖关系

文件上传 (POST /file/upload)
    ├─ autoVectorize=false → 仅上传
    └─ autoVectorize=true  → 上传 + 自动向量化

向量化 (POST /collection/{name}/vectorize)
    └─ 前提:文件已上传且路径有效

批量向量化 (POST /collection/{name}/vectorize/batch)
    └─ 前提:所有文件已上传且路径有效

生成题目 (POST /collection/{name}/generate-exam)
    └─ 前提:文件已完成向量化

删除向量化 (POST /collection/{name}/devectorize)
    ├─ 先软删除关联题目
    ├─ 再删除 RAG 中的向量数据
    └─ 最后清理本地关联记录

级联删除 (POST /collection/cascade-delete/{fileId})
    ├─ 软删除文件
    └─ 软删除关联题目

删除文件 (DELETE /file/{id})
    ├─ 软删除文件
    └─ 软删除关联题目

更新标签 (PUT /file/{id})
    └─ 更新 tags 字段

✅ 测试建议
单元测试
测试 softDeleteByFileId 方法的正确性
测试 softDeleteByDocumentName 方法的正确性
测试上传接口不同 autoVectorize 参数的行为
集成测试
测试完整的上传→向量化→出题流程
测试级联删除的数据一致性
测试删除向量化后的状态重置
测试标签的读写功能
边界测试
文件不存在时的错误处理
重复删除的处理
未完成向量化时尝试出题的处理
空标签、null 值的处理

📝 注意事项
数据库迁移:部署前需执行 SQL 脚本添加新字段
兼容性:旧的上传接口调用需要添加 autoVectorize 参数
性能考虑:级联删除可能涉及大量题目,注意监控执行时间
数据恢复:软删除的数据可通过手动更新状态恢复
标签格式tags 字段为 JSON 格式,前端需注意序列化/反序列化

🚀 后续优化方向
增加批量标签更新接口
支持按标签筛选文件
增加软删除数据的恢复接口
增加删除操作的回滚机制
优化大批量题目软删除的性能