跳转到主要内容
DocumentService 负责文档的完整处理流程:从上传到解析、分块、向量化、存储。

支持的文件格式

格式扩展名解析器fallback
PDF.pdfPyPDFLoaderUnstructuredFileLoader
Word.doc, .docxUnstructuredWordDocumentLoaderUnstructuredFileLoader
Excel.xls, .xlsxUnstructuredExcelLoader(elements 模式)UnstructuredFileLoader
PowerPoint.ppt, .pptxUnstructuredPowerPointLoaderUnstructuredFileLoader
Markdown.md, .markdownUnstructuredMarkdownLoader纯文本读取
CSV.csvCSVLoader纯文本读取
纯文本.txt直接读取
每种格式都有 fallback 策略 — 如果专用 Loader 失败或未安装依赖,会自动降级到通用 Loader。Excel 文档以 elements 模式加载并标记表格内容,PowerPoint 按幻灯片编号标记。

处理管线

详细步骤

  1. 上传文件:保存到本地 data/documents/{user_id}/{kb_id}/{uuid}_{filename},生成唯一文件名防冲突
  2. 创建记录:通过 Next.js API 创建文档元数据(fileName、filePath、fileType、fileSize)
  3. 触发处理:调用 POST /{kb_id}/documents/{doc_id}/process,加入 BackgroundTasks 异步执行
  4. 加载文档:根据文件扩展名选择对应的 LangChain Loader
  5. 智能分块:优先使用 SmartChunker,fallback 到 RecursiveCharacterTextSplitter
  6. 生成向量:使用用户配置的 Embedding 模型(create_embeddings(user_id)
  7. 存储到 pgvector:每个 chunk 附带元数据 — user_idknowledge_base_iddocument_idchunk_indexsourcepagecreated_at
  8. 使 BM25 失效:通知 BM25Store 该知识库的索引需要重建(下次检索时自动构建)
  9. 更新状态:通过 Next.js API 更新文档状态为 completed,记录 chunkCount

文档状态

状态说明
pending已上传,未开始处理
processing正在处理(异步后台)
completed处理完成
failed处理失败(记录 errorMessage)

SmartChunker 智能分块

SmartChunker 借鉴 RAGFlow 的 DeepDoc 设计,根据文档类型选择最优分块策略,实现语义感知分块而非固定大小切分。

分块策略

文档类型策略说明
MarkdownMarkdownHeaderTextSplitter按标题层级(H1~H6)分块,保留层级结构元数据
代码文件Language-aware splitter按函数/类语法结构分块,支持 15+ 语言
表格表格完整性保持表格作为独立块,避免被切断
PDF / 其他RecursiveCharacterTextSplitter递归字符分块 + 段落感知

支持的代码语言

Python、JavaScript/TypeScript、Java、Go、C/C++、C#、Ruby、PHP、Rust、Scala、Swift、Kotlin 等。

处理配置

处理配置可以在知识库级别自定义,通过 GET /api/knowledge-base/{id}/config 获取:
参数默认值说明
chunkSize1000分块最大字符数
chunkOverlap200分块重叠字符数
separators["\n\n", "\n", "。", ".", "!", "?", ";", ";", " ", ""]递归分隔符
indexMethodhigh_quality索引方法
replaceConsecutiveSpacestrue替换连续空格
deleteUrlsAndEmailsfalse删除 URL 和邮箱
useSmartChunkingtrue是否启用 SmartChunker(关闭则使用传统分块)
如果获取配置失败,自动使用默认配置。

分块预览

提供客户端预览接口,可在配置分块参数时实时查看效果:
POST /api/knowledge-base/preview-chunks
{
  "content": "要预览的文本内容...",
  "chunk_size": 1024,
  "chunk_overlap": 50,
  "delimiter": "\n\n"
}
返回分块结果,包含每个分块的 indexcontentlength