# 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。 - **失败后如何处理:** 被内容安全拦截的候选标记为 BLOCKED,Admin 可查看但不可恢复。 --- ## 5. 项目职责 ### iOS — 主链路参与者 - 提供文件选择器、相册选择器、链接输入弹窗 - 校验文件类型和大小(图片 >2MB 自动 JPEG 压缩) - 调用 API 获取 COS 预签名上传 URL - 直接 PUT 文件到 COS - 调用 API 确认上传 - 展示上传进度和 AI 处理状态 - 提供导入候选审核界面(接受/拒绝/批量接受) ### 主 API — 主链路参与者 - 提供 COS 预签名上传 URL(POST /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) - 提供候选审核 API(accept/reject/batch-accept) - 文件下载 URL 生成(COS 预签名链接) - 速率限制(文件上传端点) ### COS(腾讯云对象存储)— 主链路参与者 - 存储用户上传的原始文件 - 提供预签名 PUT URL(iOS 直接上传,不经 API 中转) - 提供预签名 GET URL(iOS 下载,Python RAG Worker 下载) - 对象键格式:`{userId}/{YYYYMM}/{sanitizedFilename}` ### Python RAG Worker — 主链路参与者 - 轮询 API 获取待处理导入任务(每 5 秒) - 定期发送心跳保持任务活跃(每 30 秒) - 完整处理管线:下载文件 → 解析文本 → 清洗(当前仅做 >10 字符长度验证,无实质性文本清洗) → 分块 → 向量嵌入 → 索引到 Qdrant → 生成知识点候选 - 解析器支持:PDF(PyMuPDF 提取文本层 → 若每页平均 <50 字符则回退到 SiliconFlow Qwen3-VL OCR)、DOCX(python-docx)、TXT/MD(直接读取)、CSV/XLSX(pandas 转 Markdown 表格)、图片(SiliconFlow 多模态 OCR) - 分块策略:递归字符分割,中文句子边界保护,Markdown 标题感知,512 token 块 + 64 token 重叠 - 嵌入模型:BAAI/bge-m3(1024 维),通过 SiliconFlow API - 候选生成:DeepSeek 分析全文提取知识点(标题、摘要、内容、标签、回忆问题、难度、置信度) - 更新 KnowledgeSource 的 parseStatus/indexStatus/learningStatus ### Qdrant(向量数据库)— 主链路参与者 - 存储文档块的向量索引(集合 `zhixi_chunks`,1024 维,余弦距离) - 每个向量点携带 payload:userId、knowledgeBaseId、sourceId、chunkId、pageNumber、sectionTitle - 支持按 sourceId 软删除(mark_deleted) - 为资料范围 AI 问答和语义检索提供向量搜索能力 ### Admin — 运维与可观测 - 文件管理页(查看所有上传文件,删除) - 来源文件页(查看所有 KnowledgeSource,按解析/索引状态筛选) - 导入监控页(查看所有导入任务,步骤级日志,重试失败任务) - 候选巡检 Tab(查看所有候选及其审核状态) - 分块管理 Tab(按 sourceId 查看分块详情) - RAG 调试 Tab(向量搜索调试) ### Rust Document Runtime — 不参与 文件上传和异步处理链路不涉及 Rust Document Runtime。Rust 仅在用户打开已上传资料进行阅读时参与文件解析。 ### 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 在知识库详情页来源 Tab;Admin 在来源文件页。 - **用途:** 知识库中每个导入资料的记录,追踪处理状态。 ### 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 → ACCEPTED,reject → REJECTED,edit → 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-chat,temperature 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 中存在但数据库无记录(孤儿文件)。 - **恢复:** 用户重新上传(生成新的 objectKey);Admin 可手动清理孤儿文件(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 是否检查软删除标志待确认 |