Skip to content

文档摄入概览

文档摄入是 Knowledge 服务的核心流程,负责将各类文档自动转换为可检索的知识片段。

摄入流程

文档摄入采用 三阶段流水线 设计:

各阶段说明

阶段输入输出说明
CONVERT原始文档 (PDF/Word/Excel 等)Markdown 文件调用外部转换服务
SPLITMarkdown 文件分片列表 (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-tasks3-5避免 Embedding API 限流
poll-interval-minutes5-10平衡实时性与资源消耗
batch-size (向量化)10批量向量化,提升吞吐
batch-delay-ms100批次间延迟,避免 API 限流

下一步