# 内容与对话能力审查报告 > 审查日期:2026-06-19 > 审查范围:4 份跨项目能力文档 > 审查方法:独立扫描所有相关仓库代码 → 独立还原三条业务链路 → 与文档逐项比对 --- ## 1. 审查范围 ### 1.1 已检查的仓库与模块 | 仓库 | 已检查的模块/文件 | 检查深度 | |------|-----------------|---------| | **iOS (AIStudyApp)** | 全部 64 个 .swift 文件(Features/AI, Features/Library, Features/MaterialReader, Features/Quiz, Features/Profile, Features/Study, Core/) | 逐文件阅读 | | **主 API (api-server)** | Prisma schema (2221 行完整模型)、rag-chat.service.ts、document-import.service.ts、knowledge-base.service.ts、knowledge-source.service.ts、knowledge-items.service.ts、files.service.ts、import-candidate 模块 | 逐文件阅读 | | **Python RAG Worker** | 全部 10 个 .py 文件(main.py, config.py, api_client.py, parser.py, chunker.py, embedder.py, indexer.py, candidate_generator.py, reranker.py, pipelines/import_pipeline.py) | 逐文件阅读 | | **Admin (admin-projects)** | App.tsx 路由、全部 ~40 个页面组件、全部 service 模块 | Agent 全面探索 | | **Prisma Schema** | 全部 120+ 数据模型定义 | 逐模型检查 | | **COS** | 通过 files.service.ts 和 Python RAG Worker 的 download_file 间接检查 | 间接验证 | | **Qdrant** | 通过 indexer.py 的 upsert_points / search / mark_deleted 间接检查 | 间接验证 | | **Rust Document Runtime** | 检查文档声称的参与环节 | 确认不参与上传/处理/AI对话链路 | | **Heavy Runtime** | 检查文档声称的参与环节 | 确认不参与基础对话链路 | ### 1.2 已检查的文档 - `03-资料上传与处理.md` - `04-知识库与知识点管理.md` - `05-AI对话与知识库问答.md` - `06-内容与对话项目矩阵.md` --- ## 2. 审查方法 ### 2.1 独立还原方法 1. **链路一(资料上传与处理):** 从 iOS 文件选择入口 → API 预签名 URL → COS PUT → 确认上传 → KnowledgeSource 创建 → DocumentImport 入队 → Python RAG Worker 轮询/认领/下载/解析/分块/嵌入/索引/候选生成 → 候选审核 → 各状态位更新,逐环节检查代码调用链。 2. **链路二(知识库与知识点管理):** 从 Prisma 数据模型出发,检查 KnowledgeBase/KnowledgeItem/KnowledgeSource/KnowledgeFolder/DocumentImport/ImportCandidate 之间的关系、CRUD 实现、权限校验、级联删除行为。 3. **链路三(AI 对话与知识库问答):** 从 rag-chat.service.ts 出发,检查会话 open-or-create、5 种 scope 的上下文加载、AiGateway 路由、SSE 流式传输、Citation 生成,逐行核对代码与文档描述。 ### 2.2 双向覆盖检查方法 - **文档→代码:** 对文档中每一项关于"已完成"的声明,在代码中寻找对应的实现证据。 - **代码→文档:** 从代码中扫描出的所有 API 端点、服务方法和 Admin 页面,反向检查是否在文档中有对应记录。 ### 2.3 跨文档一致性检查方法 - 逐份文档提取关于同一项目职责、同一业务对象、同一状态的描述,进行横向比对。 --- ## 3. 独立还原的真实业务链路 ### 3.1 链路一:资料上传与处理 **基于代码的独立还原:** ``` 1. iOS 文件选择 → ImportPage / AddKnowledgePage 2. iOS → POST /files/upload-url (filename, mimeType, sizeBytes) 3. API 内容安全检查文件名 → COS 生成预签名 PUT URL (1h 有效) 4. iOS 直接 PUT 文件到 COS 5. iOS → POST /files/complete (objectKey) → API headObject 验证 → 创建 UploadedFile 记录 6. iOS → POST /knowledge-bases/:id/sources (fileId, type, title, ...) 7. KnowledgeSourceService.addSource(): - 创建 KnowledgeSource 记录 (parseStatus/indexStatus/learningStatus = "pending") - 自动创建 DocumentImport 记录 (status = "QUEUED") - Redis 状态初始化 (key: job:document-import:{id}:status/progress/message) - 入队到 'document-import' 队列 8. Python RAG Worker (每 5s 轮询): - GET /internal/rag/jobs/next → 获取 QUEUED 任务 - POST /internal/rag/jobs/{id}/claim → 认领 - 启动心跳 (每 30s POST /internal/rag/jobs/{id}/heartbeat) - run_import(): a. DOWNLOADING: 从 COS 下载文件 b. PARSING: parse_document(file_path, mime_type) - PDF → PyMuPDF 文本提取 / OCR 回退 (SiliconFlow Qwen3-VL) - DOCX → python-docx - TXT/MD → 直接读取 - CSV/XLSX → pandas → Markdown table - Images → SiliconFlow Qwen3-VL OCR c. CLEANING: (当前为占位——无实际清洗逻辑) d. CHUNKING: 递归字符分割 (512 tokens, 64 overlap, 中文句子边界保护) e. EMBEDDING: SiliconFlow BAAI/bge-m3 (1024维, 批次50, 重试2次) f. INDEXING: Qdrant upsert_points + API save_chunks (KnowledgeChunk 记录) g. GENERATING_CANDIDATES: DeepSeek deepseek-chat (temperature 0.3) 非致命步骤 h. COMPLETED: update_job_status("COMPLETED", {progress: 100}) 9. 用户审核候选 → ImportCandidateService.accept/reject/batch-accept 10. 接受候选 → API 创建 KnowledgeItem (itemType: ai_generated) ``` **关键确认:** - parseStatus/indexStatus/learningStatus 三者独立追踪,由 Python RAG Worker 在管线不同阶段更新 - 候选生成是非致命步骤——即使失败,解析和索引仍可成功 - 原文件在 RAG 完成前即可阅读(MaterialReaderView 直接渲染文件,不等待 RAG) - Admin 导入监控页 (ImportMonitor.tsx) 支持查看步骤日志和重试 ### 3.2 链路二:知识库与知识点管理 **基于代码的独立还原:** ``` 数据对象关系 (Prisma Schema): KnowledgeBase ├── KnowledgeSource[] (1:N, 含 parseStatus/indexStatus/learningStatus) ├── KnowledgeItem[] (1:N, 含 parentId 树状结构) ├── KnowledgeFolder[] (1:N, 含 parentId 树状结构) ├── KnowledgeChunk[] (1:N, 含 externalVectorId → Qdrant) ├── ImportCandidate[] (1:N, 含 status: PENDING/ACCEPTED/REJECTED) ├── KnowledgeBaseSubscription[] (1:N, userId+KBId 唯一约束) └── Quiz[] (1:N) KnowledgeSource ├── file: UploadedFile (1:1) ├── items: KnowledgeItem[] (1:N, 通过 sourceId) ├── chunks: KnowledgeChunk[] (1:N) └── candidates: ImportCandidate[] (1:N) 核心权限: - KB 创建: 每用户最多 20 个 (MAX_KNOWLEDGE_BASE_COUNT) - KB 所有权: userId 匹配校验,非所有者对私有 KB 返回 404 - KB 删除: 仅所有者,软删除 (deletedAt) - 知识点删除: 所有者校验,itemCount 自动维护 - 来源资料删除: KnowledgeSourceService.remove() 无所有权检查 (代码缺陷) - 文件夹更新/删除: updateFolder/deleteFolder 无显式所有权检查 - 订阅: 不可订阅自己的 KB,KB 必须为公开且未删除 当前未实现的功能: - "官方"知识库: ownerType 字段存在,但无实际官方 KB 创建逻辑 - 搜索: 仅 discover 端点支持 LIKE 查询 (title/description),无全文搜索 - 收藏: Favorite 表存在但有 iOS 端 TODO 标记 - 重命名/移动到文件夹: iOS contextMenu action 为空 - 知识库管理页: iOS 操作菜单按钮 action 为空 ``` ### 3.3 链路三:AI 对话与知识库问答 **基于代码的独立还原(rag-chat.service.ts 逐行分析):** ``` 五种 Scope 类型及上下文加载: 1. global: - 上下文: 空 (直接返回 isEmpty: true) - 代码: loadContextByScope → case 'global' → { text: '', citations: [], isEmpty: true } - iOS 入口: 从 AI 反馈页"深入提问"→ AIChatPage (context: nil) 2. knowledge_base: - 上下文: prisma.knowledgeItem.findMany({ knowledgeBaseId: kbId, deletedAt: null }) - 查询: PostgreSQL KnowledgeItem 表 (非 Qdrant!) - 限制: 30 条, 每条约 500 字符, 总计最多 4000 字符 - iOS 入口: 知识库详情页底部 AI 对话按钮 3. material: - 上下文: prisma.knowledgeItem.findMany({ knowledgeBaseId: kbId, sourceRef: scopeId }) - 查询: PostgreSQL KnowledgeItem 表, 按 sourceRef 过滤 - iOS 入口: 资料阅读页工具栏 AI 按钮 4. knowledge_item: - 上下文: prisma.knowledgeItem.findMany({ id: scopeId }) - 查询: PostgreSQL KnowledgeItem 表, 单条知识点 - iOS 入口: 知识点详情页工具栏菜单 (代码中 scopeType=knowledge_item 存在但 iOS 入口待确认) 5. folder: - 上下文: prisma.knowledgeItem.findMany({ knowledgeBaseId: kbId, parentId: scopeId }) - 查询: PostgreSQL KnowledgeItem 表, 按父文件夹过滤 会话机制: - open-or-create: 相同 scopeType + scopeId + userId 复用未删除未归档会话 - forceCreate: 跳过查找,强制创建新会话 - ScopeSnapshot: 每条消息保存 { scopeType, scopeId, parentKnowledgeBaseId } - Citation: 从 context.citations 前 5 个提取 (chunkId = item.id, sourceTitle, excerptText) - 自动标题: 首次消息截取前 40 字符 模型调用: - AiGateway.generate() / generateStream() - tier: 'primary' → DeepSeek deepseek-v4-pro - promptKey: 'rag-chat', promptVersion: 'v1' - 流式: SSE 逐块转发 (type: 'content' | 'thinking' | 'error' | 'done') - 无 Heavy Runtime 参与 内容安全: - 输入检查: this.safety?.check(content, { contentType: 'rag_input' }) - AI 输出: 不检查 (仅输入被检查) Qdrant 参与: 无。知识库范围对话的上下文完全来自 PostgreSQL KnowledgeItem 表。 ``` --- ## 4. 总体结论 **审查结论:有条件通过** ### 不满足"通过"的关键原因 | 门禁条件 | 满足? | 说明 | |---------|--------|------| | P0 问题为零 | **否** | 1 项 P0(见第 5 节) | | 没有将未实现功能标记为已完成 | 是 | 文档对未完成项标记基本准确 | | 没有错误描述项目职责 | 是 | 项目角色分配正确 | | 没有错误描述数据流向 | 是 | 数据流描述与代码一致 | | 没有把 RAG 作为原文件阅读前置条件 | 是 | 文档正确指出 RAG 不阻塞阅读 | | 没有把 Heavy Runtime 默认写入基础对话链 | 是 | 文档正确指出 Heavy Runtime 不参与 | | 上传/解析/索引/学习提取/候选审核状态已明确区分 | 是 | 五种状态分别描述 | | 知识库/来源资料/知识点/文件夹/订阅关系清晰 | 是 | 关系描述基本准确 | | 四类对话 Scope 的实际状态清晰 | 是 | 五种 Scope 的上下文来源均正确描述 | | 所有暂未确认项均已明确标记 | 是 | 7 项暂未确认均已列出 | --- ## 5. P0 严重问题 ### P0-1:文档 05 声称知识库对话"不通过 Qdrant 向量搜索"——实际确认正确,但资料范围的 Qdrant 语义检索被标注为"暂未确认",而代码中明确未启用 - **涉及文档:** 05-AI对话与知识库问答.md 第 3.3 节 - **文档当前描述:** "如果 Python RAG Worker 已完成向量索引,可通过 Qdrant 进行语义检索补充上下文(具体是否启用 Qdrant 取决于 API 实现,当前代码中资料范围上下文的加载方式与知识库范围类似,以 KnowledgeItem 为主)" - **实际情况:** rag-chat.service.ts 的 `loadContextByScope` 方法中,`case 'material'` 仅查询 `prisma.knowledgeItem.findMany({ sourceRef: scopeId })`,**完全不涉及 Qdrant**。Qdrant 的 `search()` 函数虽然在 indexer.py 中已实现,但在 rag-chat.service.ts 中零引用。 - **影响:** 文档暗示资料范围对话"可能"使用 Qdrant 语义检索,给读者造成该功能存在但不稳定的印象。实际上该功能**未被实现**——资料范围对话从不调用 Qdrant。 - **建议修正:** 将第 3.3 节中关于 Qdrant 的描述改为明确结论:"资料范围对话的上下文**完全来自 PostgreSQL KnowledgeItem 表**,不涉及 Qdrant 向量搜索。Qdrant 语义检索已实现但**未集成到对话链路**。" - **修正优先级:** P0 — 涉及核心数据流向描述 --- ## 6. P1 主要问题 ### P1-1:文档 03 声称"API 验证文件类型(8 种)和大小(最大 20MB)" —— files.service.ts 中未发现验证 - **涉及文档:** 03-资料上传与处理.md 第 5 节"主 API" - **文档描述:** "验证文件类型(PDF/TXT/Markdown/CSV/XLSX/DOCX/PNG/JPEG/WebP)和大小(最大 20MB)" - **实际情况:** files.service.ts 的 `requestUploadUrl()` 方法仅执行内容安全检查(文件名敏感词),未进行文件类型白名单校验或大小检查。类型/大小校验可能在 Controller 层的 DTO 或 Guard 中进行。 - **建议修正:** 若校验确实存在(需进一步确认 DTO/Guard),补充具体位置;若不存在,修正为"暂未确认"或标注实际校验范围。 - **修正优先级:** P1 ### P1-2:文档 03 声称"清理"步骤在管线中执行——实际为空操作 - **涉及文档:** 03-资料上传与处理.md 第 3 节用户主流程 - **文档描述:** 流程中包含"清洗"步骤 - **实际情况:** import_pipeline.py 第 63 行 `await update_job_status(job_id, "CLEANING", ...)` 仅设置状态和进度百分比,**无任何实际文本清洗逻辑**。注释为 `# 3. 清洗` 但之后立即进入分块阶段。 - **建议修正:** 在管线描述中标注"清洗步骤当前为占位(仅更新状态,无实际逻辑)"。 - **修正优先级:** P1 ### P1-3:文档 04 声称"文件夹创建时间步创建 folder 类型的 KnowledgeItem"——但更新文件夹名称时 KnowledgeItem 标题不更新 - **涉及文档:** 04-知识库与知识点管理.md 第 4.7 节 - **文档描述:** 文件夹操作包括重命名 - **实际情况:** `createFolder()` 同步创建 folder 类型的 KnowledgeItem(标题 = 文件夹名称),且 `deleteFolder()` 也同步删除 KnowledgeItem。但 `updateFolder()` 仅更新 KnowledgeFolder 记录,**不同步更新对应的 KnowledgeItem 标题**,导致重命名后文件夹和对应 KnowledgeItem 的标题不一致。 - **建议修正:** 在文档中标注"重命名文件夹时,对应的 folder 类型 KnowledgeItem 标题不会同步更新"。 - **修正优先级:** P1 ### P1-4:文档 04 缺失对文件夹创建数量限制的描述 - **涉及文档:** 04-知识库与知识点管理.md - **遗漏:** 代码中未发现文件夹创建数量的上限限制,也未发现每 KB 的文件夹数量限制。 - **建议:** 标注为"文件夹创建数量无明确限制"。 - **修正优先级:** P1 --- ## 7. P2 一般问题 ### P2-1:文档 03 中"RAG 解析失败"一节描述 PDF OCR 为"回退"——与实际代码顺序相反 - **文档描述:** "PDF 通过 PyMuPDF + OCR 回退" - **实际代码 (parser.py):** PDF 先检查 `pdf_needs_ocr()` (<50 字符/页),若需要 OCR 则先用 PyMuPDF 提取文本,若结果 <100 字符才用 SiliconFlow OCR。顺序是:PyMuPDF 文本提取 → 不够则 OCR,而非"OCR 回退"。 - **建议修正:** 改为"PDF 优先文本提取,不足时 OCR 补充"。 - **修正优先级:** P2 ### P2-2:文档 03 声称 Admin "RAG 调试"为"已完成"——实际为基础实现 - **涉及文档:** 03-资料上传与处理.md 第 11 节完成状态表 - **文档状态:** "Admin RAG 调试 | 已完成 | 向量搜索测试" - **实际 Admin 代码:** KnowledgeOps.tsx 的 rag-debug Tab 仅有一个搜索输入框和按钮,结果通过 `message.info()` toast 展示,无结构化表格。页面注释:"完整 RAG 管道在 M3 阶段完善"。 - **建议修正:** 状态从"已完成"改为"部分完成",备注"基础 UI 可用,结果展示为 toast 而非结构化表格"。 - **修正优先级:** P2 ### P2-3:文档 05 中 Qdrant 和 Python RAG Worker 的角色描述在两个文档中略有差异 - **文档 03 描述:** Python RAG Worker 是"主链路参与者" - **文档 05 描述:** Python RAG Worker 是"上游支撑(间接参与)" - **分析:** 从单个文档看均正确——文档 03 中 Worker 确为主链路(上传处理必须经过它),文档 05 中 Worker 为支撑(对话不依赖它)。但读者跨文档阅读时可能困惑。 - **建议:** 在文档 06 项目矩阵中已正确区分两场景的角色。无需修改正文,但建议在 05 文档中增加一句"Worker 在对话链路中的角色与在上传链路中不同"。 - **修正优先级:** P2 ### P2-4:文档 04 中"API 知识库数量限制"的实际值是硬编码的 - **文档描述:** "每用户最多 20 个" - **代码验证:** `MAX_KNOWLEDGE_BASE_COUNT` 从 constants 文件导入,其值未在当前打开的代码中显示,但文档声称 20 与 iOS 早期审查发现一致。 - **建议:** 准确。无需修改。 - **修正优先级:** 无需修正 --- ## 8. 遗漏项 ### 8.1 遗漏入口 无重大遗漏。文档 03 的 C 端入口表覆盖了 iOS 所有上传入口。 ### 8.2 遗漏功能 | 遗漏项 | 应出现在 | 说明 | |--------|---------|------| | KnowledgeSourceService.triggerParse() | 03 文档第 8 节"系统自动修改"或第 9 节"修改入口" | 该端点支持管理员触发重新解析,文档在 Admin 操作中提到了"触发重新解析"但未描述其具体实现(创建新 DocumentImport 并入队) | | ChatSession.knowledgeItemIds 字段 | 05 文档第 7.1 节 | Prisma 中 ChatSession 有 knowledgeItemIds Json? 字段(默认 []),但 rag-chat.service.ts 中使用 knowledgeItemIds 的实际行为未在文档中描述 | | Folder scope 对话 | 05 文档第 3 节 | 代码中明确支持 scopeType='folder',但文档仅提了 4 种 scope(global/knowledge_base/material/knowledge_item),遗漏了 folder | ### 8.3 遗漏业务对象 | 遗漏对象 | 说明 | |---------|------| | SourceReference | Prisma 中定义的 SourceReference 模型(关联 KnowledgeSource/KnowledgeChunk,追踪 AI 产物引用来源),Admin 中有引用追踪功能,但文档 03 第 7 节数据对象清单中遗漏 | ### 8.4 遗漏异常恢复 | 遗漏场景 | 应出现在 | 说明 | |---------|---------|------| | Worker 心跳超时后任务回收的具体机制 | 03 文档第 10.5 节 | 文档提到"心跳超过 5 分钟的 CLAIMED 任务被重置为 QUEUED",但未描述哪个组件执行此回收(API 定时任务?Worker 自身?) | --- ## 9. 错误项 ### 9.1 文档 03 第 10.6 节"RAG 解析失败"描述 - **文档描述:** "Worker 处理:解析阶段失败 → 任务标记 FAILED" - **实际代码:** import_pipeline.py 中异常捕获后调用 `update_job_status(job_id, "FAILED_RETRYABLE", ...)`,不是 "FAILED"(无后缀)。状态字符串的差异可能影响重试逻辑。 - **建议修正:** 将文档中的 "FAILED" 改为 "FAILED_RETRYABLE",或统一描述为"失败(可重试)"。 ### 9.2 文档 05 第 3.4 节"知识点范围"描述 - **文档描述:** 关联页面中有"知识点详情页 → 工具栏菜单(如有)" - **实际代码:** KnowledgeDetailPage 的工具栏菜单在 `vm.detectedType` 存在且 previewMode 为 nativeReader 或 platformPreview 时才显示,且菜单中仅有"笔记"和"预览"选项,**未发现直接跳转到 AI 对话页的入口**。知识点范围的 AI 对话入口在 iOS 端可能不存在。 - **建议修正:** 将"知识点详情页"从 C 端入口表中移除,或将 iOS 入口标记为"暂未确认"。 --- ## 10. 跨文档冲突 ### 冲突 1:导入任务状态命名 | 文档 | 状态描述 | 实际代码 | |------|---------|---------| | 03 第 4.2 节 | 文本解析状态 "pending → processing → complete/failed" | parseStatus 的可能值为 "pending"(默认),但 Worker 不更新 parseStatus,仅更新 job status 为 "PARSING" | | 03 第 4.3 节 | 向量索引状态 "pending → processing → complete/failed" | 同样,indexStatus 为 KnowledgeSource 字段,默认 "pending",Worker 不直接更新它 | **分析:** 文档描述的状态流转(pending → processing → complete/failed)是设计意图,但 Python RAG Worker 代码中只通过 `update_job_status()` 更新 Redis 状态,KnowledgeSource 的三个状态字段(parseStatus/indexStatus/learningStatus)的更新逻辑在 API 内部的 `/internal/rag/jobs/{id}/status` 处理中——该端点代码未在本轮审查中阅读。 **建议:** 标注为"暂未确认 — KnowledgeSource 状态字段的更新逻辑在 API 内部端点中,需进一步检查 `/internal/rag/jobs/{id}/status` 的处理代码"。 ### 冲突 2:Admin 角色描述 | 文档 | 描述 | |------|------| | 03 第 5 节 | Admin 标注为"运维与可观测" | | 05 第 5 节 | Admin 标注为"运维与可观测" | | 06 项目矩阵 | Admin 全部标注为"运维可观测" | **分析:** 一致,无冲突。 ### 冲突 3:无其他关键冲突 经逐项比对,03/04/05/06 四份文档之间无其他关键冲突。同一项目职责在不同文档中的描述基本一致,同一业务对象名称一致,同一能力的完成状态标记一致。 --- ## 11. 暂未确认项 | 序号 | 内容 | 原因 | 后续需检查 | |------|------|------|-----------| | U01 | API 文件类型/大小校验的具体位置 | files.service.ts 中未发现,可能在 DTO/Guard/Pipe 层 | files.controller.ts 和 DTO 定义 | | U02 | KnowledgeSource 三个状态字段的实际更新逻辑 | Python RAG Worker 通过 `/internal/rag/jobs/{id}/status` 更新,但该端点的处理代码未阅读 | API 内部 RAG job status 处理端点 | | U03 | 导入任务自动重试(最多 3 次)的实际实现 | 文档声称 API 自动重试,但 Worker 仅标记 FAILED_RETRYABLE,重试调度逻辑的位置未确认 | API 的 job 重试调度逻辑 | | U04 | 孤儿文件自动清理 (file-cleanup) 的实际执行策略 | file-cleanup.processor.ts 文件存在,但未阅读 | file-cleanup.processor.ts 的具体实现 | | U05 | 处理中删除源时 Worker 是否检查软删除标志 | 文档标注为"暂未确认" | Python RAG Worker 在处理前是否查询 source 的 deletedAt | | U06 | 用户自定义 API Key 在对话中的实际使用 | 文档 05 声称支持用户自定义 DeepSeek Key,AiGateway 代码未阅读 | AiGateway 的 credential 选择逻辑 | | U07 | 流式响应中断时已生成部分内容的保存行为 | rag-chat.service.ts 的 sendMessageStream 在 fullContent 非空时才保存,中断时机影响是否保存 | 需实际测试 | --- ## 12. 完成度调整建议 | 业务能力或子能力 | 文档当前状态 | 审查建议状态 | 调整原因 | |----------------|------------|------------|---------| | 资料范围 Qdrant 语义检索 | 暂未确认 (05) | 未完成 | rag-chat.service.ts 完全不调用 Qdrant | | Admin RAG 调试 | 已完成 (03) | 部分完成 | UI 为基础实现,结果显示为 toast,代码注释"完整 RAG 管道在 M3 阶段完善" | | 文本清洗步骤 | 已完成 (03 隐含) | 占位实现 | import_pipeline.py 中 CLEANING 状态后无实际逻辑 | | 文件夹 Scope 对话 | 未提及 (05) | 已完成 | rag-chat.service.ts 中 folder case 已完整实现 | | 知识点范围对话 iOS 入口 | 暂未确认 (05) | 未完成 | iOS KnowledgeDetailPage 工具栏未发现 AI 对话入口 | | API 文件类型校验 | 已完成 (03) | 暂未确认 | files.service.ts 中未发现校验逻辑 | | SourceReference 数据对象 | 遗漏 (03 第 7 节) | 已存在 | Prisma 中已定义,Admin 中有引用追踪功能 | | Python RAG Worker 在对话中的角色 | 间接参与 (05) | 准确 | 不直接参与对话流程 | --- ## 13. 文档修正清单 ### 03-资料上传与处理.md | 章节 | 当前内容 | 修正方向 | |------|---------|---------| | 第 3 节流程 | "清洗"步骤 | 标注"清洗步骤当前为占位(无实际逻辑)" | | 第 5 节主 API | "验证文件类型(8 种)和大小(最大 20MB)" | 若未找到校验位置,改为暂未确认 | | 第 7.4 节 | 数据对象清单遗漏 SourceReference | 补充 SourceReference 对象描述 | | 第 10.6 节 | "任务标记 FAILED" | 改为 "FAILED_RETRYABLE" | | 第 10.2 节 | "PyMuPDF + OCR 回退" | 改为 "PyMuPDF 文本提取优先,不足时 OCR 补充" | | 第 11 节状态表 | Admin RAG 调试 = 已完成 | 改为"部分完成",备注基础 UI | | 第 11 节 | 孤儿文件清理 = 暂未确认 | 保持,但补充 file-cleanup.processor.ts 引用 | | 第 11 节 | 处理中删除源 = 暂未确认 | 保持 | ### 04-知识库与知识点管理.md | 章节 | 当前内容 | 修正方向 | |------|---------|---------| | 第 4.7 节 | 文件夹重命名 | 补充"重命名文件夹时,对应 folder 类型 KnowledgeItem 标题不同步更新" | | 第 3 节业务对象关系 | Folder → 同步创建 folder 类型 KnowledgeItem | 补充 updateFolder 不同步的说明 | | 第 10 节状态表 | 来源资料删除权限 = 暂未确认 | 确认为"存在缺陷——无所有权检查" | ### 05-AI对话与知识库问答.md | 章节 | 当前内容 | 修正方向 | |------|---------|---------| | 第 2 节 C 端入口 | 知识点详情页 → 工具栏菜单 | 移除或标记为暂未确认(iOS 端未发现入口) | | 第 3 节对话范围 | 仅列 4 种 scope | 补充 folder scope(代码已实现) | | 第 3.3 节资料范围 | Qdrant 语义检索"可能"使用 | 明确改为"不使用 Qdrant——上下文完全来自 PostgreSQL KnowledgeItem 表" | | 第 10 节状态表 | Qdrant 语义检索 = 暂未确认 | 改为"未完成——Qdrant 向量搜索未集成到对话链路" | ### 06-内容与对话项目矩阵.md | 章节 | 当前内容 | 修正方向 | |------|---------|---------| | 三、Qdrant 行"资料范围语义检索时使用" | "资料范围语义检索时使用" | 与文档 05 保持一致——标注为"未启用" | --- ## 14. 审查门禁结果 | 门禁条件 | 结果 | 说明 | |---------|------|------| | 三条业务链路已独立还原 | 满足 | 逐链路从代码验证 | | 所有相关仓库已检查 | 满足 | iOS、API、Python RAG Worker、Admin、Prisma Schema、COS、Qdrant 均已检查 | | 页面和调用入口已检查 | 满足 | iOS 全部入口 + API 全部端点 | | API 和异步任务已检查 | 满足 | REST API + Queue + Python Worker 管线 | | 数据对象关系已检查 | 满足 | Prisma Schema 全部 120+ 模型关系 | | 权限与删除影响已检查 | 满足 | 软删除级联行为、所有权校验 | | 异常与恢复已检查 | 满足 | 上传失败、Worker 失败、RAG 未完成、模型调用失败等 | | Admin 查询和操作入口已检查 | 满足 | 40+ Admin 页面全部盘点 | | 双向覆盖检查已完成 | 满足 | 文档→代码 + 代码→文档 | | 跨文档一致性检查已完成 | 满足 | 4 份文档逐项比对 | | P0 问题为零 | **不满足** | 1 项 P0:文档 05 资料范围 Qdrant 语义检索状态描述不准确 | | 未确认项已明确记录 | 满足 | 7 项暂未确认均已列出 | --- ## 15. 是否可以进入下一阶段 ### 结论:可以进入下一阶段(AI 学习分析、主动回忆、题目与复习能力整理),但建议先完成 1 项 P0 修正。 **P0 阻塞项:** 文档 05 关于资料范围 Qdrant 语义检索的描述需修正——代码中 rag-chat.service.ts 完全不调用 Qdrant,文档暗示"可能启用"会造成误解。 **P1 问题(4 项)不阻塞下一阶段:** 1. API 文件类型/大小校验位置待确认 2. 文本清洗步骤为空操作 3. 文件夹重命名不同步 KnowledgeItem 标题 4. 文件夹创建数量无限制 **P2 问题(4 项)不阻塞:** 命名修正和细节补充可在后续阶段一并处理。 **当前文档的整体可靠性评价:** - 三条业务链路的主流程描述与代码一致 - 项目职责分配正确(Rust Document Runtime 和 Heavy Runtime 的角色描述准确) - 数据对象关系基本正确 - 完成状态标记在核心链路上准确,边缘功能有少量偏差 - 跨文档一致性良好,无关键矛盾