
文件上传、任务队列与知识库管理一套完整 API 如何设计码海寻道 · 大模型、智能体与 RAG 工程组件系列第 44 篇知识库 API 的难点不在于写出一个上传接口而在于把文件、文档版本、异步任务、向量索引和用户操作串成可追踪的生命周期。一、从用户动作倒推接口用户通常需要创建或选择知识库上传一个或多个文件查看解析进度查看文档状态和错误重新处理或删除文档搜索和问答查看引用来源。因此接口不应只围绕文件而要围绕knowledge_base、document、job和run建模。确认接口应校验上传对象是否属于当前用户和租户并重新核对大小、MIME、哈希和病毒扫描状态。大文件可以使用分片或多段上传但服务端必须记录分片状态、校验和和过期时间未完成的临时对象要由生命周期任务清理。二、推荐资源关系Tenant └── KnowledgeBase └── Document ├── DocumentVersion ├── ProcessingJob └── Chunk / Vector Index一个文件可能有多个版本一个版本可能有多次处理任务。不要用一个file_status字段覆盖所有生命周期。三、创建知识库和上传流程POST /api/v1/knowledge-bases{name:财务制度库,description:内部财务制度和报销规则,embedding_profile:zh-embedding-v2}上传可以采用预签名 URLPOST /api/v1/knowledge-bases/{kb_id}/upload-sessions{filename:travel-policy.pdf,content_type:application/pdf,size_bytes:2048000,sha256:...}服务端返回短时上传地址和upload_id。客户端上传完成后调用确认接口POST /api/v1/upload-sessions/{upload_id}/complete服务端重新检查对象存在、大小、哈希和租户范围再创建文档版本和处理任务。四、任务接口和状态GET /api/v1/jobs/{job_id} POST /api/v1/jobs/{job_id}/cancel POST /api/v1/jobs/{job_id}/retry GET /api/v1/jobs/{job_id}/events状态示例{job_id:job-001,document_id:doc-001,status:running,stage:embedding,progress:65,processed:130,total:200,error:null}任务状态由服务端维护前端可以轮询或使用 SSE 订阅。不能只依赖前端上传回调判断任务完成。建议把状态转换限制为明确的状态机例如queued → running → succeeded失败进入failed取消进入cancelled每次转换记录job_id、attempt、worker_id、错误码、时间和输入版本。只有解析、切分、向量写入和可检索检查都通过文档才进入published或ready。五、文档管理接口GET /api/v1/knowledge-bases/{kb_id}/documents GET /api/v1/documents/{document_id} GET /api/v1/documents/{document_id}/versions POST /api/v1/documents/{document_id}/reindex DELETE /api/v1/documents/{document_id}列表接口应支持分页、状态过滤、标题搜索和排序。分页参数需要设置上限避免一次返回整个知识库。六、文档发布和索引状态建议区分文件状态uploaded / deleted 处理状态queued / running / failed / completed 索引状态pending / indexing / ready / stale 发布状态draft / published / archived只有满足解析成功、向量可检索、权限元数据完整的版本才可以发布为published。发布操作应具备幂等性和审计记录。七、删除和重建不能只删一张表删除文档时要同步处理PostgreSQL 文档状态 对象存储原始文件 解析结果和临时文件 Milvus / pgvector Chunk Redis 缓存 异步任务和事件通常先做软删除和禁止新检索再由后台执行向量和文件清理。删除失败要进入补偿任务不能默默留下可访问的旧索引。八、幂等键和并发控制客户端重试上传确认、用户重复点击重试和消息重复消费都可能造成重复任务。推荐请求支持Idempotency-Key文档版本使用唯一约束任务状态更新带版本号同一文档同一版本只允许一个活动索引任务Worker 根据事件 ID 和业务键幂等处理。同一文档的解析、删除、发布和重建要使用版本号或分布式锁控制顺序。队列至少一次投递意味着 Worker 可能重复执行处理器必须以document_id version stage判断是否已完成并把业务提交与 ACK 顺序固定下来。九、问答接口如何与知识库资源关联POST /api/v1/chat/completions{knowledge_base_ids:[kb-001],conversation_id:conv-001,message:差旅住宿标准是什么,stream:true}服务端要检查用户是否能访问这些知识库并在检索时注入租户、部门和发布版本过滤。不能因为请求体带了kb-001就默认用户拥有权限。十、API 分层示意API Router ↓ 鉴权、校验、状态码 Application Service ↓ 事务、权限、业务规则 Repository / Gateway ├── PostgreSQL ├── Object Storage ├── Redis ├── Queue └── Milvus这样可以在测试中替换外部依赖也可以避免路由层直接耦合多个基础设施。结语一套完整的知识库 API应该围绕知识库、文档版本、处理任务、索引状态和问答运行设计。文件上传只是入口真正的工程质量体现在幂等、权限、状态、一致性、删除和恢复。下一篇将进入多租户如何隔离用户、团队、文档和向量数据。参考资料FastAPI 官方文档Amazon S3 官方文档Presigned URLsHTTP Semantics202 Accepted本文为“码海寻道”原创技术文章。文件、任务和索引删除涉及数据安全正式上线前应进行失败补偿和恢复演练。