ios-projects/docs/system-map/capabilities/03-资料上传与处理.md

447 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 03 资料上传与处理 — 跨项目完整能力分析
> 项目角色分类主链路参与者iOS、主 API、COS、Python RAG Worker、Qdrant——资料上传后必须经过这些项目才能完成处理、运维可观测Admin
> Rust Document Runtime 不参与上传与处理链路。Heavy Runtime 不参与此链路。
> 注意Python RAG Worker 和 Qdrant 在本能力中是主链路参与者;在"知识库与知识点管理"和"AI 对话与知识库问答"能力中角色不同(分别为上游支撑和不参与对话上下文加载)。
---
## 1. 能力目标
用户将外部学习资料PDF、Word、Markdown、图片等上传至知识库系统自动完成文本解析、分块、向量索引和知识点候选提取使资料成为可阅读、可检索、可被 AI 引用的结构化知识。
---
## 2. C 端入口
| 入口页面 | 触发方式 | 进入场景 |
|---------|---------|---------|
| 知识库详情页 | 操作菜单 → "上传" | 向已有知识库导入资料 |
| 知识库详情页 | 操作菜单 → "添加" → 文件模式 | 以文件形式添加知识点 |
| 添加知识点页·文件模式 | 点击"选择文件"或"图片"按钮 | 选择文件/照片作为知识点 |
| 导入资料页 | 点击"文件导入"/"相册导入"/"链接导入" | 三种导入方式 |
用户可执行的操作:
- 从系统文件选择器选择文件PDF、纯文本、图片等
- 从相册选择照片(自动压缩大于 2MB 的图片)
- 输入 URL 进行链接导入
- 查看上传进度
- 查看导入任务的 AI 处理状态(处理中/就绪/失败)
- 审核 AI 提取的知识点候选(接受/拒绝/批量接受)
---
## 3. 用户主流程
```
用户选择资料
→ iOS 校验文件类型和大小(图片 >2MB 自动压缩)
→ iOS 调用 API 获取 COS 预签名上传 URL
→ iOS 将文件直接 PUT 到 COS
→ iOS 调用 API 确认上传完成API 验证 COS 中文件存在)
→ API 创建资料记录KnowledgeSource
→ API 创建导入任务DocumentImport状态 QUEUED
→ Python RAG Worker 轮询获取导入任务
→ Worker 下载文件 → 解析文本 → 清洗 → 分块 → 向量嵌入 → 索引到 Qdrant → 生成知识点候选
→ Worker 更新 KnowledgeSource 的 parseStatus/indexStatus/learningStatus
→ 用户可在资料详情页查看 AI 处理状态
→ 用户可在导入候选审核页审核 AI 提取的知识点候选
→ 用户接受候选 → API 创建 KnowledgeItem
→ 资料进入可阅读、可被 AI 检索的状态
```
---
## 4. 处理阶段与状态
资料上传后经历多个异步处理阶段,每个阶段有独立的状态追踪:
### 4.1 原文件上传状态
- **谁创建:** iOS 调用 API 确认上传后API 创建 UploadedFile 记录。
- **谁更新:** 上传完成后状态不再变化。文件删除时 API 从 COS 和数据库移除。
- **用户在哪里看到:** iOS 上传过程中显示进度指示器;上传完成后在资料详情页看到文件名、格式、大小。
- **Admin 在哪里看到:** Admin 文件管理页查看所有上传文件列表,可按类型筛选。
- **失败后如何处理:** COS 上传失败时 iOS 显示错误提示,用户可重试。
### 4.2 文本解析状态parseStatus
- **谁创建:** API 创建 KnowledgeSource 时默认为 `pending`
- **谁更新:** Python RAG Worker 在处理过程中更新pending → processing → complete/failed。同时更新 textLength、parsedObjectKey、errorCode、errorMessage。
- **用户在哪里看到:** iOS 资料详情页的 AI 处理状态横幅(处理中为琥珀色、就绪为绿色、失败为红色)。
- **Admin 在哪里看到:** Admin 来源文件页的 parseStatus 列;导入监控页的步骤日志。
- **失败后如何处理:** Admin 可触发重新解析POST /knowledge-bases/:kbId/sources/:id/parse导入任务自动重试最多 3 次。
### 4.3 向量索引状态indexStatus
- **谁创建:** API 创建 KnowledgeSource 时默认为 `pending`
- **谁更新:** Python RAG Worker 在嵌入和索引阶段更新pending → processing → complete/failed
- **用户在哪里看到:** iOS 不单独展示索引状态(合并在 AI 处理状态中)。
- **Admin 在哪里看到:** Admin 来源文件页的 indexStatus 列。
- **失败后如何处理:** 同解析失败Admin 可触发重新解析,系统自动重试。
### 4.4 学习内容提取状态learningStatus
- **谁创建:** API 创建 KnowledgeSource 时默认为 `pending`
- **谁更新:** Python RAG Worker 在知识点候选生成完成后更新为 `complete`
- **用户在哪里看到:** 不直接展示;用户通过导入候选审核页间接感知(有候选 = 已完成提取)。
- **Admin 在哪里看到:** Admin 来源文件详情中查看。
- **失败后如何处理:** 候选生成是非致命步骤——即使失败,解析和索引仍可成功。
### 4.5 候选审核状态
- **谁创建:** Python RAG Worker 生成候选后API 创建 ImportCandidate 记录(状态 PENDING
- **谁更新:** iOS 用户操作:接受 → ACCEPTED拒绝 → REJECTED编辑 → EDITED。内容安全拦截 → BLOCKED。
- **用户在哪里看到:** iOS 导入候选审核页(候选列表含置信度分数、标题、摘要)。
- **Admin 在哪里看到:** Admin 知识运营页的候选巡检 Tab。
- **失败后如何处理:** 被内容安全拦截的候选标记为 BLOCKEDAdmin 可查看但不可恢复。
---
## 5. 项目职责
### iOS — 主链路参与者
- 提供文件选择器、相册选择器、链接输入弹窗
- 校验文件类型和大小(图片 >2MB 自动 JPEG 压缩)
- 调用 API 获取 COS 预签名上传 URL
- 直接 PUT 文件到 COS
- 调用 API 确认上传
- 展示上传进度和 AI 处理状态
- 提供导入候选审核界面(接受/拒绝/批量接受)
### 主 API — 主链路参与者
- 提供 COS 预签名上传 URLPOST /files/upload-url
- 验证文件类型和大小iOS 端进行初步校验文件选择器限制可选类型、图片压缩API 端进行最终校验(允许 PDF/TXT/Markdown/CSV/XLSX/DOCX/PNG/JPEG/WebP最大 20MB
- 文件名内容安全检查
- 确认上传完成POST /files/complete验证 COS 中文件存在后创建记录
- 创建 KnowledgeSource 记录并自动创建 DocumentImport 任务
- 管理导入任务状态Redis 实时状态 + 数据库持久化)
- 提供导入状态查询GET /imports/:id/status
- 提供候选审核 APIaccept/reject/batch-accept
- 文件下载 URL 生成COS 预签名链接)
- 速率限制(文件上传端点)
### COS腾讯云对象存储— 主链路参与者
- 存储用户上传的原始文件
- 提供预签名 PUT URLiOS 直接上传,不经 API 中转)
- 提供预签名 GET URLiOS 下载Python RAG Worker 下载)
- 对象键格式:`{userId}/{YYYYMM}/{sanitizedFilename}`
### Python RAG Worker — 主链路参与者
- 轮询 API 获取待处理导入任务(每 5 秒)
- 定期发送心跳保持任务活跃(每 30 秒)
- 完整处理管线:下载文件 → 解析文本 → 清洗(当前仅做 >10 字符长度验证,无实质性文本清洗) → 分块 → 向量嵌入 → 索引到 Qdrant → 生成知识点候选
- 解析器支持PDFPyMuPDF 提取文本层 → 若每页平均 <50 字符则回退到 SiliconFlow Qwen3-VL OCR)、DOCXpython-docx)、TXT/MD直接读取)、CSV/XLSXpandas Markdown 表格)、图片SiliconFlow 多模态 OCR
- 分块策略递归字符分割中文句子边界保护Markdown 标题感知512 token + 64 token 重叠
- 嵌入模型BAAI/bge-m31024 通过 SiliconFlow API
- 候选生成DeepSeek 分析全文提取知识点标题摘要内容标签回忆问题难度置信度
- 更新 KnowledgeSource parseStatus/indexStatus/learningStatus
### Qdrant向量数据库— 主链路参与者
- 存储文档块的向量索引集合 `zhixi_chunks`1024 余弦距离
- 每个向量点携带 payloaduserIdknowledgeBaseIdsourceIdchunkIdpageNumbersectionTitle
- 支持按 sourceId 软删除mark_deleted
- 为资料范围 AI 问答和语义检索提供向量搜索能力
### Admin — 运维与可观测
- 文件管理页查看所有上传文件删除
- 来源文件页查看所有 KnowledgeSource按解析/索引状态筛选
- 导入监控页查看所有导入任务步骤级日志重试失败任务
- 候选巡检 Tab查看所有候选及其审核状态
- 分块管理 Tab sourceId 查看分块详情
- RAG 调试 Tab向量搜索调试
### Rust Document Runtime — 不参与
文件上传和异步处理链路不涉及 Rust Document RuntimeRust 仅在用户打开已上传资料进行阅读时参与文件解析
### Heavy Runtime — 不参与
Heavy Runtime 不参与文件上传解析分块索引和候选生成流程
---
## 6. 项目间调用关系
### 6.1 iOS → API
| 调用目的 | 业务结果 |
|---------|---------|
| 请求上传授权 | 返回 COS 预签名 PUT URL + objectKey |
| 确认上传完成 | API 验证 COS 文件存在创建 UploadedFile 记录 |
| 创建知识源 | 创建 KnowledgeSource + DocumentImport 任务QUEUED |
| 查询导入状态 | 返回 Redis 实时状态进度百分比 + 文字描述 |
| 获取下载 URL | 返回 COS 预签名下载链接 |
### 6.2 iOS → COS直接
| 调用目的 | 业务结果 |
|---------|---------|
| 上传文件 | 文件直接 PUT COS不经 API 中转 |
### 6.3 Python RAG Worker → API
| 调用目的 | 业务结果 |
|---------|---------|
| 轮询待处理任务 | 获取 QUEUED 状态的导入任务 |
| 锁定任务 | 原子转换 QUEUED CLAIMED |
| 心跳上报 | 保持任务活跃防止超时回收 |
| 更新任务状态 | 更新 Redis 进度/消息 |
| 更新 KnowledgeSource | 更新 parseStatus/indexStatus/learningStatus |
| 保存分块 | 批量写入 KnowledgeChunk 记录 |
| 保存候选 | 批量写入 ImportCandidate 记录 |
### 6.4 Python RAG Worker → COS
| 调用目的 | 业务结果 |
|---------|---------|
| 下载文件 | 通过预签名 URL 下载原始文件用于处理 |
### 6.5 Python RAG Worker → Qdrant
| 调用目的 | 业务结果 |
|---------|---------|
| 写入向量 | 将文档块的嵌入向量写入 zhixi_chunks 集合 |
| 软删除 | 标记指定 sourceId 的向量为 deleted |
### 6.6 Python RAG Worker → 模型服务
| 调用目的 | 业务结果 |
|---------|---------|
| 文本嵌入 | 调用 SiliconFlow BAAI/bge-m3 生成 1024 维向量 |
| 图片 OCR | 调用 SiliconFlow Qwen3-VL 多模态模型提取图片文字 |
| 候选生成 | 调用 DeepSeek 分析全文提取知识点候选 |
### 6.7 Admin → API运维可观测
| 调用目的 | 业务结果 |
|---------|---------|
| 查看/删除文件 | 文件管理 |
| 查看来源文件 | 列表 + 按状态筛选 |
| 查看导入任务 | 列表 + 步骤日志 |
| 重试导入 | 重置失败任务为 QUEUED |
| 查看候选 | 候选巡检 |
| 查看分块 | sourceId 查看分块详情 |
---
## 7. 核心业务数据
### 7.1 上传文件UploadedFile
- **谁创建** API 在确认上传时创建
- **谁更新** 不更新创建后不可变)。
- **谁查询** iOS 在上传后获取文件信息Admin 在文件管理页查询
- **用途** 记录已上传到 COS 的文件作为 KnowledgeSource fileId 引用来源
### 7.2 知识源KnowledgeSource
- **谁创建** API 在添加来源时创建关联 fileId)。
- **谁更新** Python RAG Worker 更新 parseStatus/indexStatus/learningStatus
- **谁查询** iOS 在知识库详情页来源 TabAdmin 在来源文件页
- **用途** 知识库中每个导入资料的记录追踪处理状态
### 7.3 导入任务DocumentImport
- **谁创建** API 在创建 KnowledgeSource 时自动创建状态 QUEUED)。
- **谁更新** Python RAG Worker 更新状态进度步骤日志Admin 可重置为 QUEUED重试)。
- **谁查询** iOS 查询导入状态Admin 在导入监控页
- **用途** 追踪单个文档的完整处理生命周期从排队到完成或失败
### 7.4 知识分块KnowledgeChunk
- **谁创建** Python RAG Worker 在分块和索引阶段批量创建
- **谁更新** 创建后不可修改软删除通过 Qdrant 实现)。
- **谁查询** Admin 在分块管理 Tab sourceId 查看系统内部通过 Qdrant 向量搜索使用
- **用途** 文档的语义分块每个块有向量嵌入用于资料范围 AI 问答的语义检索
### 7.5 导入候选ImportCandidate
- **谁创建** Python RAG Worker 在候选生成阶段批量创建状态 PENDING)。
- **谁更新** iOS 用户操作accept ACCEPTEDreject REJECTEDedit EDITED)。内容安全拦截 BLOCKED
- **谁查询** iOS 在候选审核页按 sourceId 查询Admin 在候选巡检 Tab 查看
- **用途** AI 从文档中提取的知识点候选等待用户审核确认
### 7.6 知识点KnowledgeItem由候选接受生成
- **谁创建** API 在用户接受候选时创建itemType: ai_generated)。
- **谁更新** 用户在编辑知识点页修改
- **谁查询** iOS 在知识点详情页和知识库详情页
- **用途** 用户确认后的正式知识点进入知识库内容体系
### 7.7 向量索引Qdrant Collection
- **谁创建** Python RAG Worker 在索引阶段写入
- **谁更新** 软删除通过 mark_deleted(sourceId) 实现
- **谁查询** API 在资料范围 AI 问答时通过向量搜索检索相关块Admin 通过向量管理页查看统计
- **用途** 为资料范围 AI 问答提供语义级检索能力
---
## 8. 查询入口
### 用户查询
- **上传进度** iOS 添加知识点页/导入资料页的上传进度指示器
- **AI 处理状态** iOS 资料详情页的 AI 处理状态横幅处理中/就绪/失败)。
- **导入候选** iOS 导入候选审核页列表含置信度标题摘要)。
- **来源文件列表** iOS 知识库详情页来源 Tab含处理状态标签)。
### Admin 查询
- **文件列表** Admin 文件管理页按类型查看删除)。
- **来源文件列表** Admin 来源文件页按解析/索引状态筛选)。
- **导入任务列表** Admin 导入监控页状态进度步骤日志重试)。
- **候选巡检** Admin 知识运营页候选巡检 Tab
- **分块管理** Admin 知识运营页分块管理 Tab sourceId 查看)。
- **RAG 调试** Admin 知识运营页 RAG 调试 Tab向量搜索测试)。
### 系统内部查询
- **RAG Worker 轮询任务** Python RAG Worker 定期轮询 QUEUED 导入任务
- **向量搜索** API 在资料范围 AI 问答时查询 Qdrant 获取相关块
- **Redis 状态查询** API 提供导入任务实时状态24 小时 TTL)。
---
## 9. 修改入口
### 用户操作
- **上传新文件** iOS 导入资料页/添加知识点页
- **接受候选** iOS 候选审核页接受单个候选
- **拒绝候选** iOS 候选审核页拒绝单个候选
- **批量接受** iOS 候选审核页"全部接受"按钮
- **编辑候选** iOS 可编辑候选内容后再接受
### Admin 操作
- **删除文件** Admin 文件管理页删除上传文件同时从 COS 删除)。
- **重试导入** Admin 导入监控页重试失败任务重置为 QUEUED最多 3 次系统自动重试Admin 手动重置不占重试次数)。
- **触发重新解析** Admin 可触发知识源的重新解析
### 系统自动修改
- **导入任务自动重试** Python RAG Worker 失败时系统自动重试最多 3 超时后标记 FAILED_FINAL)。
- **过期任务回收** 心跳超过 5 分钟的 CLAIMED 任务被重置为 QUEUED
- **内容安全检查** 文件名KB 标题候选内容接受时自动进行敏感词检查
- **Redis 状态过期** 导入任务 Redis 状态在 24 小时后自动清除
- **分布式锁过期** 重复上传防护锁在 5 分钟后自动释放
### 配置修改
- **允许的文件类型** API 端配置PDF/TXT/Markdown/CSV/XLSX/DOCX/PNG/JPEG/WebP)。
- **最大文件大小** API 端硬编码 20MB
- **COS 预签名 URL 有效期** 上传 1 小时下载 24 小时知识点详情页 7 )。
- **分块参数** Python RAG Worker 配置512 token 块大小64 token 重叠)。
- **嵌入模型** Python RAG Worker 配置BAAI/bge-m3)。
- **候选生成模型** Python RAG Worker 配置deepseek-chattemperature 0.3)。
---
## 10. 异常与恢复
### 10.1 文件类型不支持
- **场景** 用户选择不支持的文件类型
- **iOS 处理** 文件选择器限制可选类型PDF/纯文本/图片API 在请求上传 URL 时二次校验返回错误
- **用户感知** iOS 提示"不支持的文件格式"。
### 10.2 文件过大
- **场景** 文件超过 20MB 限制
- **iOS 处理** 图片 >2MB 自动 JPEG 压缩;非图片文件 >20MB 时 API 拒绝。
- **用户感知:** API 返回文件过大错误。
### 10.3 COS 上传失败
- **场景:** 网络问题或 COS 服务异常导致 PUT 失败。
- **iOS 处理:** 显示上传错误提示,用户可重试。上传使用预签名 URL不经过 API 中转。
- **API 处理:** 确认上传时如果 COS 中文件不存在headObject 失败),返回确认失败。
### 10.4 上传成功但 API 创建记录失败
- **场景:** COS 上传成功,但确认 API 调用失败(网络中断、服务错误)。
- **结果:** 文件在 COS 中存在但数据库无记录(孤儿文件)。
- **恢复:** 用户重新上传(生成新的 objectKeyAdmin 可手动清理孤儿文件file-cleanup 队列定期执行)。
### 10.5 导入任务失败
- **场景:** Python RAG Worker 处理过程中出错下载失败、解析失败、API 调用失败)。
- **系统处理:** 自动重试最多 3 次,每次重置为 QUEUED。3 次失败后标记 FAILED_FINAL。
- **用户感知:** iOS 资料详情页 AI 处理状态显示红色"失败"横幅。
- **Admin 恢复:** Admin 在导入监控页查看步骤日志,手动重试(不占系统重试次数)。
### 10.6 RAG 解析失败
- **场景:** PDF 损坏、DOCX 格式异常、OCR 无法识别。
- **Worker 处理:** 解析阶段失败 → 任务标记 FAILED更新 parseStatus 为 failed记录 errorCode 和 errorMessage。
- **影响范围:** 解析失败的文件无法进行后续分块、嵌入和索引。
- **恢复:** Admin 触发重新解析;用户可尝试重新上传。
### 10.7 向量索引失败
- **场景:** Qdrant 不可用、嵌入 API 调用失败。
- **Worker 处理:** 索引阶段失败 → 任务标记 FAILED。parseStatus 可能已 complete但 indexStatus 为 failed。
- **影响范围:** 资料可阅读但不可用于语义检索。
- **恢复:** Admin 重试导入任务;系统自动重试。
### 10.8 重复上传
- **场景:** 用户短时间内上传相同文件多次。
- **API 处理:** 使用 Redis 分布式锁(`lock:document-import:{fileName}:{timestamp}`5 分钟 TTL防止并发重复导入。
- **边界:** 锁只防止并发重复;用户间隔 5 分钟后仍可上传相同文件创建新的 KnowledgeSource。
### 10.9 用户删除处理中资料
- **场景:** 用户在导入任务处理过程中删除知识源。
- **API 处理:** KnowledgeSource 使用软删除(设置 deletedAt。Python RAG Worker 在处理前应检查源是否已被删除(具体行为待确认)。
- **影响:** 已生成的 KnowledgeChunk 和 ImportCandidate 可能成为孤儿数据。
### 10.10 候选审核失败
- **场景:** 接受候选时内容安全检查失败。
- **API 处理:** 候选标记为 BLOCKED返回原因。用户无法强制接受。
- **Admin 查看:** Admin 可在候选巡检中看到 BLOCKED 状态的候选。
---
## 11. 当前完成状态
| 组件 | 状态 | 说明 |
|------|------|------|
| iOS 文件选择与上传 | 已完成 | 文件选择器 + 相册选择器 + 链接导入 |
| iOS 图片压缩 | 已完成 | >2MB 自动 JPEG 压缩 |
| iOS 上传进度展示 | 已完成 | 进度指示器 |
| iOS 候选审核界面 | 已完成 | 接受/拒绝/批量接受 |
| iOS AI 处理状态展示 | 已完成 | 资料详情页三色横幅(处理中/就绪/失败) |
| API COS 预签名 URL 上传流程 | 已完成 | 请求 URL → 直接 PUT → 确认 |
| API 文件类型与大小校验 | 已完成 | 8 种类型,最大 20MB |
| API 内容安全检查(文件名) | 已完成 | 敏感词匹配 |
| API 速率限制 | 已完成 | 文件上传端点 |
| API KnowledgeSource 创建与管理 | 已完成 | 含自动 DocumentImport 任务创建 |
| API 导入状态查询 | 已完成 | Redis 实时状态(进度+消息) |
| API 候选审核 API | 已完成 | accept/reject/batch-accept |
| Python RAG Worker 轮询与锁定 | 已完成 | 每 5 秒轮询,心跳每 30 秒 |
| Python RAG Worker 文本解析 | 已完成 | PDF/DOCX/TXT/MD/CSV/XLSX/图片 OCR |
| Python RAG Worker 分块与嵌入 | 已完成 | 递归分割 + BAAI/bge-m3 |
| Python RAG Worker 向量索引 | 已完成 | Qdrant zhixi_chunks 集合 |
| Python RAG Worker 候选生成 | 已完成 | DeepSeek 提取知识点 |
| Python RAG Worker 状态更新 | 已完成 | parseStatus/indexStatus/learningStatus |
| 导入任务自动重试 | 已完成 | 最多 3 次,过期任务自动回收 |
| Admin 文件管理 | 已完成 | 查看/删除 |
| Admin 来源文件查看 | 已完成 | 列表 + 按状态筛选 |
| Admin 导入监控 | 已完成 | 步骤日志 + 重试 |
| Admin 候选巡检 | 已完成 | 列表查看 |
| Admin 分块管理 | 已完成 | 按 sourceId 查看 |
| Admin RAG 调试 | 部分完成 | 基础向量搜索测试工具,展示原始 JSON 响应;非生产级检索调试界面 |
| 孤儿文件自动清理 | 暂未确认 | file-cleanup 队列存在但清理策略待确认 |
| 处理中删除源的行为 | 暂未确认 | Worker 是否检查软删除标志待确认 |