文档解析任务耗时长处理
- 文档上传后,要经历 *读取文件 → 解析内容 → OCR/表格识别 → 切分 chunk → 生成向量 → 写入向量库 → 建索引
- 这一整套流程,这每个流程阶段都会有一定的时间,都可以进行优化
| 阶段 | 为什么慢 |
|---|---|
| PDF 解析 | PDF 结构复杂,有些 PDF 文字顺序混乱 |
| OCR | 扫描件、图片识别非常慢 |
| 表格解析 | 表格结构需要额外识别 |
| 大模型摘要/抽取 | 如果每个 chunk 都调用 LLM,成本和时间都高 |
| Embedding | 文档量大时要批量调用向量模型 |
| 向量库写入 | 大量 chunk 写入数据库需要时间 |
| 索引构建 | HNSW、IVF 等索引构建本身也耗时 |
文档上传解析优化
用户上传文档,不要让用户等完整解析完成才给响应,会体验不好
- 异步解析
- 任务队列
- 状态通知
- 增量处理
异步解析任务队列工作流程处理
文档解析属于 耗时任务,不适合直接在接口里执行
- 用户上传文档
- 后端保存文档,接入业务数据库
- 后端创建任务记录,放在消息任务队列
- python woker后台进程 从队列中消费队列
- python下载文件、解析文档、切分chunk、生成向量、写入向量数据库
- python更新任务状态为 完成
- 前端轮询任务状态/ WebSocket 接收进度
工作场景分工流程处理
Node 或 Java 负责业务后端,Python 负责 Agent 和 RAG 知识库,那么用户上传文件时,我会让 Node / Java 先接收上传请求,而不是让 Python 直接暴露给前端,后端先做用户鉴权、知识库权限校验、文件类型和大小校验,然后把原始文件保存到对象存储 (比如OSS),后端会在业务数据库中创建文档表的记录、任务解析记录
- Node/Java/Go 负责业务后端和上传入口,Python 做 Agent 和 RAG 知识库处理
用户上传文件
↓
前端调用 Node / Java / GO 上传接口
↓
后端校验用户权限、文件类型、文件大小
↓
后端把原始文件保存到对象存储
↓
后端在数据库创建 document 记录
↓
后端创建 document_parse_task 任务记录
↓
后端把任务投递到消息队列
↓
立即返回 task_id 给前端
↓
Python Worker 从队列消费任务
↓
Python 下载文件
↓
Python 解析文档
↓
Python 切分 chunk
↓
Python 生成 embedding
↓
Python 写入向量数据库
↓
Python 更新任务状态为 completed
↓
前端轮询任务状态 / WebSocket 接收进度
Node / Java / GO 和 Python 如何通信
- 通过消息队列通信
- Node / Java 和 Python Worker 最常见的通信方式是:Node / Java 把任务消息发到队列,Python Worker 从队列消费任务
↓
发送任务到 Redis / RabbitMQ / Kafka
↓
Python Worker 消费任务
- Node / Java 调用 Python 服务接口
↓ HTTP
Python RAG Service
↓
Python 自己创建后台任务
消息队列通信流程
- node/java/go后端和python连接同一个消息队列,并约定好消息格式,就可以通信
- 消息队列可以理解为一个独立运行的中间服务
Node/Java/Go → 往队列里发消息
消息队列 → 保存消息、分发消息
Python 项目 → 从队列里消费消息
本地开发流程
- 用 Docker 启动一个 RabbitMQ,然后 Node/Java 后端项目连接 RabbitMQ 发送任务,Python Worker 项目也连接同一个 RabbitMQ 消费任务
1. RabbitMQ:消息队列服务
2. Node / Java 后端:负责上传文件、发送任务
3. Python Worker:负责监听任务、处理文档