本地知识库搭建-分块(chunk)
最近因为项目上的需要,加上 Deepseek-R1 的能力也很出众,打算重新尝试和研究一下企业级完整的知识库搭建的流程,以及在搜集和尝试的过程中遇到的问题
整体流程
无论是企业级还是本地知识库的部署,原理都是类似的:
- 文档分块 (Chunking)
- 文本向量化 (Embedding)
- 向量检索 (Vector Search)
- 大模型生成 (LLM)
- 将检索到的内容作为上下文 (Context),让模型基于上下文回答问题
区别最大的是可拓展性,并发性以及安全的考虑。
接下来先介绍分块:
分块
因为有如下的几个限制,所以目前所有的输入文本最好还是先进行分解:
- 文本太长:Embedding 模型通常有最大长度限制(例如 512 或 1024 tokens)。
- 细粒度检索:如果索引整个文档,当用户提问时,很难精确检索到相关内容。
- 存储和检索效率:向量数据库存储的单位通常是“段落”或“句子级别”的小块,而不是整个文档。
结合上面的场景,简单的的分块方法有如下几种:
- 固定长度分块
- 滑动窗口
- 按照标点或者自然语言逻辑切分
固定长度切分
比较简单粗暴。直接按照字符或者 token 长度来进行切分
车辆启动后,驾驶员发现发动机声音异常,有较大噪音。经检查,发现排气系统存在泄漏。 维修人员建议更换排气管。更换后,噪音消失,问题解决。 |
优点:
- 计算简单,易于实现。
- 适用于结构化文本,如 JSON、数据库数据、API 文档。
缺点: - 可能把相关内容截断,导致语义理解丢失。
- 可能会把一个完整的概念切开,影响后续检索。
滑动窗口
在固定长度切分的基础上,每个块可能会与部份重复的语义和内容,相比上一种可以减少信息的丢失
- Chunk 1: 车辆启动后,驾驶员发现发动机声音异常,有较大噪音。 |
优点:
- 解决了固定长度切分导致的“上下文丢失”问题。
- 避免问答时检索不到完整上下文信息。
缺点: - 存储量增加(重复存储部分内容),索引占用空间变大。
- 需要优化重叠大小,避免重复度过高导致信息冗余。
自然语言切分
基于句子和段落的内容来进行切分。比如可以根据句号或者换行来实现,再叠加上 Token 的长度限制等条件。如果还是超长可以叠加使用一些 NLP 工具来拆分
- Chunk 1: 车辆启动后,驾驶员发现发动机声音异常,有较大噪音。 |
优点:
- 语义完整,检索时不容易丢失关键信息。
- 适合 PDF、Markdown、文章、法规等结构化文本。
缺点: - 需要 NLP 解析库,处理较复杂。
- 对不同文档格式可能要调整切分规则。
现有分块方法
Langchain
Langchain 的 Langchain.text_splitter.RecursiveCharacterTextSplitter
,可以实现递归分割文本,先按照换行符,然后再按照字符数切分
from langchain.text_splitter import RecursiveCharacterTextSplitter |
Hugging Face Tokenizer
可以用 BERT/GPT 的分词器 来计算 Token 数,然后按 最大 Token 限制切分
from transformers import AutoTokenizer |
基于 NLP(Spacy/NLTK)
import spacy |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 小何的岛🏝️!