文档摄入概览
文档摄入是 Knowledge 服务的核心流程,负责将各类文档自动转换为可检索的知识片段。
摄入流程
文档摄入采用 三阶段流水线 设计:
各阶段说明
| 阶段 | 输入 | 输出 | 说明 |
|---|---|---|---|
| CONVERT | 原始文档 (PDF/Word/Excel 等) | Markdown 文件 | 调用外部转换服务 |
| SPLIT | Markdown 文件 | 分片列表 (Chunk) | 结构感知分割 |
| VECTORIZE | 分片列表 | 向量 ID 列表 | 批量生成向量并存储 |
任务调度机制
文档摄入通过 异步任务队列 处理,支持多种调度策略:
轮询机制
系统启动时自动启动后台轮询线程:
yaml
molandev:
rag:
ingest:
enabled: true # 启用摄入任务
poll-interval-minutes: 10 # 每 10 分钟轮询一次并发控制
使用 信号量 控制并发任务数,避免 Embedding API 限流:
yaml
molandev:
rag:
ingest:
max-concurrent-tasks: 3 # 最多 3 个任务并发分布式锁
使用分布式锁防止同一任务被多个实例重复执行:
java
// 伪代码
LockUtils.executeWithLock(taskId, () -> {
processIngestTask(task);
});失败重试
任务失败后自动重试,最大重试次数可配置:
yaml
molandev:
rag:
ingest:
max-retry: 3 # 最多重试 3 次超时重置
长时间未完成的任务会被自动重置为待处理状态:
yaml
molandev:
rag:
ingest:
task-timeout-minutes: 30 # 30 分钟超时任务状态机
任务阶段 (IngestStage)
| 阶段 | 说明 |
|---|---|
CONVERT | 格式转换中 |
SPLIT | 分片处理中 |
VECTORIZE | 向量化中 |
虚拟线程池
Knowledge 使用 Java 21 的 虚拟线程 处理摄入任务,提升并发能力:
java
// 使用虚拟线程执行器
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();虚拟线程相比传统线程的优势:
- 轻量级 — 可创建数百万个虚拟线程
- 高效 — 阻塞操作不会占用平台线程
- 简单 — 无需复杂的线程池配置
错误处理
错误信息记录
任务失败时,错误信息会记录到数据库:
json
{
"taskId": 1,
"status": "FAILED",
"errorMsg": "PDF 转换失败: MinerU 服务不可用",
"retryCount": 2
}人工干预
对于持续失败的任务,可人工干预:
- 检查转换服务是否正常运行
- 修改文档格式后重新上传
- 通过系统界面手动重试
系统提供重新转换功能,方便处理转换失败的文档。
性能优化建议
| 优化项 | 建议值 | 说明 |
|---|---|---|
max-concurrent-tasks | 3-5 | 避免 Embedding API 限流 |
poll-interval-minutes | 5-10 | 平衡实时性与资源消耗 |
batch-size (向量化) | 10 | 批量向量化,提升吞吐 |
batch-delay-ms | 100 | 批次间延迟,避免 API 限流 |