前面的文章在构建RAG并检索时,既使用了国外大模型,也使用了国内大模型;既运用了内存向量检索库FAISS,也运用了磁盘向量数据库Chroma。
但知识库的原始来源却是knowledge数组,这与现实场合有所出入,因为实际资料都保存在TXT、PDF、WORD等格式的文档中,甚至来自互联网上的HTML网页,于是RAG的前置条件就成了如何从这些文档中提取文本信息。
一、读取TXT文件中的文本
TXT文件是最简单的文本格式,读写TXT无需任何第三方库。
Python代码先调用open函数打开TXT,再调用read函数读取全部文本内容,也可循环调用readline函数依次读取每行文本。
比如下面代码依次读取TXT文件的每行文本,并把各行文本依次添加到知识库数组knowledge中。
# ===================== 从文本文件读取知识库(替代原数组) =====================
def load_knowledge_from_txt(file_path):
knowledge = []
with open(file_path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if line: # 非空行才加入
knowledge.append(line)
return knowledge
# 加载知识(自动读 knowledge.txt)
knowledge = load_knowledge_from_txt("knowledge.txt")
二、兼容GBK字符集的TXT文件
首先确保Python代码的同目录下存在knowledge.txt,并且文件内容非空,再运行上面的Python测试代码。
可是Windows系统多半会报错"UnicodeDecodeError: 'utf-8' codec can't decode byte 0xca in position 4: invalid continuation byte",这是因为Windows系统默认把TXT文件保存为ASCII编码,而非UTF-8编码。而Python代码企图以UTF-8编码打开TXT,就会报编码格式不符的错误了。
为了解决字符集编码冲突的问题,需要改造前面的Python代码,使得既支持UTF-8编码,又支持GBK形式的ASCII编码。
改造后的Python文件读取代码如下:
# ===================== 从文本文件读取知识库(替代原数组) =====================
def load_knowledge_from_txt(file_path):
knowledge = []
encoding_type = "utf-8"
try:
with open(file_path, "r", encoding=encoding_type) as f:
f.readline()
except:
encoding_type = "gbk"
with open(file_path, "r", encoding=encoding_type) as f:
for line in f:
line = line.strip()
if line: # 非空行才加入
knowledge.append(line)
return knowledge
# 加载知识(自动读 knowledge.txt)
knowledge = load_knowledge_from_txt("knowledge.txt")
可见上面代码先以UTF-8方式打开TXT,如果遇到异常再以GBK方式打开TXT,从而实现了同时兼容UTF-8与GBK的目标。
三、对文本内容自动分块
不过TXT文件中的文本很可能不是一句话一行字,而是一段一段的文字,每段都包含好几个句子,那么上面代码依次调用readline函数并添加到数组,每个数组元素都包含一大段文字,十分臃肿。
为此需要根据句号来拆分文本内容,而非根据段落来拆分文本内容。基本要求如下:
1、读取TXT文件的所有文本内容。
2、按照句号分割文本。
3、每条知识设定字数下限,比如不得少于50个汉字;如果某条知识小于这个长度,就要跟下一条知识合并。
4、处理过程注意去除无效字符,例如剔除空行、删除空格等等。
根据上述逻辑,可编写自动分块的Python测试代码如下:
# ===================== 加载一整段 TXT 文本 =====================
def load_text(file_path):
try:
with open(file_path, "r", encoding="utf-8") as f:
return f.read().strip()
except:
with open(file_path, "r", encoding="gbk") as f:
return f.read().strip()
# 读取一整段文本
raw_text = load_text("knowledge.txt")
# ===================== 自动把一段文字切成多段(关键!) =====================
def split_text(text, max_len=50):
sentences = text.split("。") # 按句号分割
chunks = []
current = ""
for sen in sentences:
sen = sen.strip()
if not sen:
continue
# 加回去句号,让语义完整
sen += "。"
if len(current) <= max_len:
current += sen
else:
if current:
chunks.append(current.strip())
current = sen
if current:
chunks.append(current.strip())
return chunks
# 自动分块
knowledge = split_text(raw_text)
至此初步实现了对TXT文件的读取和分块功能,拆分后的每条知识仍然保存于knowledge数组,后续的RAG构建及检索操作可套用之前的RAG测试代码框架。
本系列的AI应用开发文章目录为《15天学会AI应用开发全目录(零基础小白,零Token消耗)》。