企业私有知识库RAG系统完整架构,文档解析、切片、向量化
企业私有知识库RAG系统,简单说就是把公司内部文档交给大模型之前的“加工流水线”。
这条流水线分为文档解析、切片、向量化三部分:解析负责把 PDF、Word、Markdown 转成纯文本;
切片负责把长文档切成适合检索的片段;
向量化负责把文本转成数字向量存入向量数据库。
本文按这套完整架构,带你把每一步跑通,最终实现"提问—检索—增强—回答"的私有知识库闭环。
搭建前需要准备哪些东西
这套系统不依赖昂贵硬件,普通云服务器或本地 Linux 机器即可,建议内存不低于 8G、磁盘预留 100G。
软件层面准备三样:
- Python 3.10 及以上环境,用于运行处理脚本。
- Docker,用于快速启动向量数据库和中间件。
- 一个开源向量数据库,推荐 Milvus 或 Chroma,小规模用 Chroma 更简单。
还要准备几份测试文档,比如 PDF、Word、Markdown 各一份,内容尽量包含明确段落和小标题,方便后面验证效果。
文档解析:把不同格式统一成纯文本
企业文档最头疼的是格式杂。
解析这一步的目标是去掉 PDF 的排版、Word 的样式、PPT 的动画,只保留文字本身。
推荐使用 Python 的 unstructured 库,它能自动识别常见格式,不需要每类文件单独写解析器。
安装命令:
pip install "unstructured[pdf,docx,pptx]"
解析示例:
from unstructured.partition.auto import partition
elements = partition("企业制度手册.pdf")
text = "\n".join([e.text for e in elements if e.text])
with open("output.txt", "w", encoding="utf-8") as f:
f.write(text)
解析后务必检查纯文本是否保留段落结构。
有些扫描版 PDF 没有文字层,需要先 OCR,这一步建议优先用开源 PaddleOCR,不要直接跳过。
切片策略:怎么切才能让检索更准
切片不是简单按字符数硬切,而是要让每个片段语义完整。
常见思路是先按文档标题或段落切出“候选块”,再把过长的候选块按固定长度进一步拆分。
推荐一个能直接用的策略:
- 优先按 Markdown 标题和段落换行切分。
- 单块长度控制在 200-500 个 token(中英文混合时约 150-400 字)。
- 相邻块之间重叠 50-100 字符,避免关键句被截断。
代码示例:
def split_text(text, chunk_size=400, overlap=80):
start = 0
chunks = []
while start < len(text):
end = start + chunk_size
chunks.append(text[start:end])
start = end - overlap
return chunks
这只是基础版。
更讲究的做法是先用 tiktoken 按 token 数切,或者用 semantic-text-splitter 做语义切分。
真实项目中建议先把表格单独抽出来,因为表格一旦被切开,内容就完全失义。
向量化:把文本变成可检索的向量
向量化需要选一个 Embedding 模型,它负责把文本映射成一组浮点数向量。
企业私有部署推荐使用开源模型 BAAI/bge-large-zh-v1.5,中文效果好,显存占用也不高。
下载模型:
pip install sentence-transformers
生成向量并入库:
from sentence_transformers import SentenceTransformer
import chromadb
model = SentenceTransformer("BAAI/bge-large-zh-v1.5")
client = chromadb.PersistentClient(path="./kb")
collection = client.get_or_create_collection("enterprise_kb")
chunks = split_text(text)
embeddings = model.encode(chunks).tolist()
collection.add(
ids=[str(i) for i in range(len(chunks))],
embeddings=embeddings,
documents=chunks
)
向量数据库选型时,几十万条以内用 Chroma 足够,规模更大则换 Milvus。
注意 Embedding 模型要和检索时保持一致,换模型或升级版本都会导致向量空间变化,老向量全部失效。
最容易踩坑的三个地方
第一,文档解析后内容乱码或顺序错乱。
大多数是 PDF 本身没有文字层,或者表格内容被横竖拆散。
建议解析前先用工具看 PDF 结构,解析后抽查几处关键段落。
第二,切片不设重叠,导致问题刚好落在切缝上。
这种情况检索到的片段会缺头缺尾,回答自然不准。
设置重叠后能明显提升命中率。
第三,向量化时没有考虑 batch_size。
几百份文档一次性编码容易撑爆内存,建议按 64 或 128 条分批处理,并加上进度打印。
如何验证整套系统是否可用
验证分两层:一是检查数据是否完整入库,二是检查检索效果。
先在向量数据库中执行统计:
print(collection.count())
再随便提一个能从测试文档中找到答案的问题,比如"公司的年假制度是什么",用相同模型编码后检索 top 3:
top_k = collection.query(
query_embeddings=[model.encode("公司的年假制度是什么")],
n_results=3
)
for doc in top_k["documents"][0]:
print(doc)
如果返回片段和问题相关,说明解析、切片、向量化这条链路已经打通。
之后再接大模型做生成,把检索结果拼进 prompt 即可。
真正落地时,还要针对常见问题准备一套评测问句,批量测试准确率。
好的 RAG 系统不是一次配完就结束,而是靠持续调切片参数和 Embedding 模型迭代出来的。
遇到文档解析异常时,回头检查源文件格式;
检索不准时优先调切片长度和重叠值,不要盲目换大模型。
按照本文顺序走一遍,你已经具备一套可迭代的私有知识库底座。