乐于分享
好东西不私藏

Weknora知识库文档处理全流程详解:RAG 管道与 Wiki 生成

Weknora知识库文档处理全流程详解:RAG 管道与 Wiki 生成

TECH DEEP DIVE

Weknora知识库文档处理全流程详解

RAG 管道与 Wiki 生成的完整技术架构拆解

目 录 CONTENTS

01

总体架构

两条独立管道的全景概览

02

RAG 管道详解

文档解析 → 分块 → 向量化 → 双存储

03

Wiki 管道详解

MAP/REDUCE 两阶段 + 容错机制

04

RAG 与 Wiki 的关系总结

两条管道的对比与协作

RAG 管道负责"搜得到",Wiki 管道负责"看得懂"

PART 01

总体架构

知识库文档处理分为两条独立但可并行的管道,共享"文档解析"和"文本分块"两个阶段后分道扬镳:

管道
用途
默认状态
RAG 管道(Vector + Keywords)
语义搜索 + 关键词搜索
默认开启
Wiki 管道
自动生成知识库 Wiki 页面
默认关闭,需手动开启

两条管道共享"文档解析""文本分块"两个阶段,之后分道扬镳。

PART 02

RAG 管道详解

2.1 整体流程

上传文档后,RAG 管道依次经过 5 个阶段:

1

文档解析 — 调用外部 docreader 服务,将各种格式统一转为 Markdown 文本 + 图片列表

2

文本分块 — 三级自适应策略链(标题感知 → 启发式边界 → 递归分割)

3

父子分块(可选) — 父 chunk(4096字符)+ 子 chunk(384字符)双层结构

4

向量化 + 索引入库 — 批量 embedding,同时写入向量库和关系数据库

5

后处理(可选) — 摘要生成 + 问题生成(为每个 chunk 生成可能的检索问题)

2.2 文档解析

调用外部 docreader 服务(独立微服务)

支持 PDF、Word、Markdown、HTML、TXT、图片(OCR)等格式

输出:统一的 Markdown 格式文本 + 图片链接列表

解析结果不直接入库,而是传给分块模块继续处理

2.3 文本分块:三级自适应策略链

分块策略按优先级自动回退,上一级不适用则自动 fallback 到下一级:

Tier 1

标题感知分割

Tier 2

启发式边界分割

Tier 3

递归分割(兜底)

优先级从高到低,自动 fallback

✦ Tier 1:标题感知分割

适用场景:有 Markdown 标题结构(# ## ### 等)的文档

核心逻辑:按标题边界切分文档,维护标题层级栈(HeadingHierarchy),追踪"面包屑"路径。小节内容放得下 → 整个小节作为一个 chunk;太大 → 交给下一级。每个 chunk 带上 ContextHeader,如 # 第一章 > ## 1.1 概述,帮助 embedding 模型理解上下文。

✦ Tier 2:启发式边界分割

适用场景:论文、法律文档、技术规范等有结构化线索的文档

按优先级扫描边界信号:换页符 → 章节标记 → 编号章节 → 全大写标题行 → 分隔符 → 连续空行。使用贪心装箱算法:逐个累加段落,超过 chunk_size 时开新 chunk。

✦ Tier 3:递归分割(万能兜底)

适用场景:所有文档的最终兜底方案

分隔符优先级:\n\n(段落)→ \n(行)→ 。?!(句子结束)→ 字符级强制截断

保护机制:LaTeX 公式、Markdown 表格、代码块、图片链接被视为原子单元,绝不切割。硬上限:所有 chunk 最多 7500 字符。Markdown 表格被切分时,后续 chunk 自动 prepend 表头行,防止列名信息丢失。

重叠机制:优先在 \n\n → \n → 。?! 处切分,确保重叠内容在语义边界处开始,而不是在句子中间截断。

2.4 父子分块机制

父子分块是一种双层粒度设计:用小子 chunk 做精准检索,命中后返回父 chunk 的大段上下文给 LLM。

类型
存储位置
向量索引
用途
子 chunk
关系数据库 + 向量库
语义检索(小粒度匹配精准)
父 chunk
仅关系数据库
作为 LLM 上下文

✦ 检索流程

语义搜索

命中子 chunk

查父 chunk

SQL 读取大段内容

喂给 LLM

大窗口上下文

小粒度检索 → 大粒度上下文

父子关系建立:纯数据结构,不依赖语义。分割阶段父 chunk 按数组排列,子 chunk 记录 ParentIndex → 入库时转为 UUID 写入 parent_chunk_id → 检索时通过外键关联。

无标题文档:父子分块与文档有没有标题完全无关。无标题时 Tier 3 递归分割兜底,ContextHeader 为空字符串,父子关系靠 ParentIndex → parent_chunk_id 纯机械链路建立。

2.5 向量化与索引入库

关键设计:同一条记录同时支持向量搜索和关键词搜索。不是分别写两份数据,而是同一个 IndexInfo 对象存入向量库的一条记录中:

字段
用途
content
原始文本 → 用于关键词/BM25 搜索
embedding
语义向量 → 用于向量相似度搜索
chunk_id
关联 chunks 表
knowledge_id
所属文档
knowledge_base_id
所属知识库
is_enabled
是否启用检索

不同向量库的 BM25 实现方式

向量库
BM25 存储方式
检索方式
Elasticsearch
ES 自带倒排索引,content 自动分词
match 查询 + BM25 打分
PostgreSQL (ParadeDB)
ParadeDB 扩展自动建 BM25 索引
content || ? 运算符 + score 函数
Milvus
内置 BM25 转稀疏向量
稀疏向量 ANN 搜索
Qdrant
原生全文搜索
内置 BM25

核心结论:没有独立的 BM25 倒排索引表,BM25 是向量数据库引擎自身提供的能力。写入只做一次,检索时分两路:Vector → 向量相似度搜索,Keywords → BM25 关键词搜索,结果在应用层做融合排序。

✦ 批量处理策略

每批 40 条 IndexInfo 为一组

最多 5 个并发批次同时处理

失败时 5 次指数退避重试(200ms → 3200ms)

单条输入最长 20000 字符,图片 base64 替换为 [image] 占位符

2.6 双存储模型

存储位置
内容
用途
关系数据库(chunks 表)
原始内容 + 元数据 + 父子关系 + 双向链表
上下文检索、Wiki 生成
向量数据库
embedding + content + 元数据
语义搜索 + 关键词搜索

chunks 表关键字段

字段
说明
id
UUID 主键
knowledge_id
所属文档
content
文本内容
context_header
标题面包屑(embedding 时 prepend)
chunk_type
text / parent_text / image_ocr / wiki_page
parent_chunk_id
父 chunk UUID
pre/next_chunk_id
双向链表(前后相邻 chunk)
chunk_index
在文档中的序号
start_at / end_at
在原文本中的字符位置
PART 03

Wiki 管道详解

3.1 整体流程

Wiki 管道在 RAG 管道完成后启动,经历 5 个阶段:

1

入队 — 延迟 30 秒去抖,创建 WikiPendingOp,触发异步任务

2

MAP 阶段 — 并发处理每个文档:候选 Slug 提取 → 摘要生成 → Chunk Citation 分类

3

目录规划 — LLM 为所有新增实体/概念规划目录结构,复用已有 wiki_folders

4

REDUCE 阶段 — 按 slug 聚合多文档贡献,合并生成或更新 Wiki 页面

5

Finalize 收尾 — 清理死链接、注入交叉链接、更新索引页面、记录变更

3.2 触发条件

Wiki 管道需要同时满足以下条件才会启动:

1

知识库的 IndexingStrategy.WikiEnabled == true

2

文档解析后有文本类 chunk(非纯图片文档)

3

知识库配置了 synthesis model(用于 LLM 生成)

3.3 入队机制

文档处理完成(RAG 管道入库后),后处理阶段检查 WikiEnabled:是 → 创建 WikiPendingOp 持久化到 task_pending_ops 表,触发 Wiki Ingest 异步任务(延迟 30 秒去抖);否 → 跳过。

去抖设计:30 秒内多次上传同一知识库的文档,只触发一次 Wiki Ingest 任务,避免频繁重建。

3.4 MAP 阶段详细逻辑

✦ 并发模型

默认 10 个并发(可通过 WikiConfig 调整)

每个文档独立处理,互不干扰

失败不阻塞整个批次,记录失败后继续

✦ Pass 0:候选 Slug 提取

对每个文档,LLM 分析其全部 chunk 内容,提取实体和概念的骨架:

Slug 提取输出示例

{

  "name": "循环神经网络",

  "slug": "concept/recurrent-neural-network",

  "aliases": ["RNN", "循环神经网路"],

  "description": "一种用于处理序列数据的神经网络架构"

}

✦ 文档摘要生成

用 LLM 为文档生成结构化摘要,摘要中包含关键实体/概念的 [[slug]] 链接。摘要页面类型为 summary。

3.5 目录规划(Taxonomy Plan)

用 LLM 分析当前批次所有提取出的实体/概念 slug,规划它们应该放在哪个目录下。复用已有的 wiki_folders,如果目录路径已存在则直接关联,不存在则创建新目录。

3.6 REDUCE 阶段详细逻辑

Wiki 管道最核心的阶段

MAP 阶段的输出(slugUpdates)按 slug 分组,并发处理(默认 10 并发)。对每个 slug:读取现有 Wiki 页面 → 合并新贡献 → LLM 重写/更新 → 写入 wiki_pages 表。

并发控制:不同批次的 Map 可能产生同一 slug 的更新,用 Redis 分布式锁(withSlugLock)保证同一时间只有一个 Reduce 在写同一 slug。

操作类型
触发条件
处理方式
ingest(新增/更新)
文档被上传或更新
合并新贡献,LLM 重写页面
retract(撤回)
文档被删除
移除贡献,必要时归档页面

3.7 Finalize 收尾

所有 slug 的 Reduce 完成后,触发 Finalize 任务(延迟执行,合并在一个任务中):

1

清理死链接 — 扫描所有 Wiki 页面中的 [[slug]] 链接,移除指向已删除页面的链接

2

注入交叉链接 — 在相关页面之间添加 [[链接]]

3

重建索引页面 — 更新 wiki 首页的目录结构和"最近更新"列表

4

文件夹清理 — 删除空目录

3.8 Wiki 数据库存储

wiki_pages 表

字段
说明
id
UUID 主键
slug
URL 友好标识(entity/acme-corp、concept/rag)
title
页面标题
page_type
summary / entity / concept / index
status
draft / published / archived
content
完整 Markdown 内容
aliases
别名列表(JSON 数组)
source_refs
来源文档引用(JSON)

wiki_folders 表

字段
说明
id
UUID 主键
parent_id
父目录 ID
name
目录名称
path
完整路径
depth / sort_order
目录深度 / 排序顺序

wiki_page_revisions 表

字段
说明
page_id
关联的 wiki_page
version
版本号
content
该版本的完整内容
edit_source
human / agent / ingest

wiki_page_issues 表

字段
说明
slug
关联的 wiki 页面
issue_type
问题类型
status
pending / resolved

task_pending_ops 表(持久化任务队列)

字段
说明
task_type
wiki_ingest / wiki_finalize
op
ingest / retract / slug / change
dedup_key
去重键(同一 knowledge_id 只保留最新)
claimed_at
领取时间(并发控制)
fail_count
失败次数

3.9 容错与并发控制

去抖:30 秒内同一知识库多次上传,只触发一次 Ingest

并发领取:多个 Worker 通过 claimed_at 领取互不重叠的批次

slug 锁:同一 slug 的 Reduce 操作串行化(Redis 分布式锁)

Finalize 合流:多个批次的 Finalize 合并为一个任务执行

失败重试:失败文档重新入队,有 fail_count 上限

知识库删除保护:删除时自动清理所有待处理任务

PART 04

RAG 与 Wiki 的关系总结

维度
RAG 管道
Wiki 管道
目的
提供搜索能力(语义 + 关键词)
生成结构化知识库页面
触发
文档上传后自动
需开启 WikiEnabled
核心操作
embedding 向量化 + 索引入库
LLM 提取实体/概念 + 生成页面
存储
向量库 + chunks 表
wiki_pages + wiki_folders
并发
40条/批,5并发
Map/Reduce 两阶段,10并发
延迟
实时(上传后立即处理)
准实时(30秒去抖延迟)
依赖
需要 embedding 模型
需要 synthesis model(LLM)

两条管道共享文档解析和文本分块的结果,但后续处理完全独立

RAG 管道负责"搜得到",Wiki 管道负责"看得懂"

既然看到这里了,如果觉得有用,随手点个赞、在看、转发三连吧。

点赞
在看
转发

THANKS FOR READING