22 KiB
22 KiB
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 是否检查软删除标志待确认 |