【langchain】加载、处理和分割源数据文件
文章目录
- 1 文件的加载
- 1.1 Markdown 的加载
- 1.2 PDF 的加载
- 2 数据的清理(以PDF的第一页数据为例)
- 3 内容的分割
- 总结
本文主要讲解
langchain
如何加载PDF、Markdown源文件。清理的PDF文件为南瓜书。
1 文件的加载
1.1 Markdown 的加载
from langchain.document_loaders.markdown import UnstructuredMarkdownLoaderloader = UnstructuredMarkdownLoader("data_base/example.md") # 实例化对象,传入Markdown文件地址
md_pages = loader.load() # 加载文件内容,返回Document对象列表,List[Document]type(md_pages), len(md_pages), md_pages[0].metadata, md_pages[0].page_content # 使用返回结果,可以查看类型、页数、文件名、内容等等
1.2 PDF 的加载
from langchain.document_loaders import PyMuPDFLoaderloader = PyMuPDFLoader("data_base/example.pdf") # 实例化对象,传入PDF文件地址
pdf_pages = loader.load() # 加载文件内容,返回Document对象列表type(pdf_pages), len(pdf_pages), pdf_pages[0].metadata, pdf_pages[0].page_content# 使用返回结果,可以查看类型、页数、文件名、内容等等
这里给出一个document
数据的示例(pdf_pages[0]
):
2 数据的清理(以PDF的第一页数据为例)
这里我们要处理的是数据内容,也就是content部分。
使用正则表达式处理。
# 提取第一页内容
pdf_page = pdf_pages[0]# 引入re模块
import re"替换掉每句话之间的换行符和两个符号之间的\n"
pattern = re.compile(r'["\u4e00-\u9fff](n)["\u4e00-\u9fff]', re.DOTALL) # 正则表达式
pdf_page.page_content = re.sub(pattern, lambda match: match.group(0).replace('n', ''), pdf_page.page_content) # 替换操作。re.sub(pattern, repl, string) # 清除多余'•'和空格
pdf_page.page_content = pdf_page.page_content.replace('•', '')
pdf_page.page_content = pdf_page.page_content.replace(' ', '')
3 内容的分割
由于上下文过长会导致检索得到的知识太长,超过模型能处理能力。因此,不会直接将单个文件转为向量存入向量数据库,进行检索。
在存入向量数据库之前,需要将其进行分割,以便于后续处理。
通常,将单个文档按长度或某规则分割成若干个chunk,然后将每个chunk转化为词向量,并存储到向量数据库中。
chunk指的是文档的片段,比如一个文档有1000个字符,那么将其按500个字符进行分割,就会得到5个chunk。
在检索时,会以chunk为元单位进行检索。每一次检索到k个chunk,其作为参考的知识,来回答用户。k的值有我们决定。
我们可以使用langchain
的CharacterTextSplitter
分割方法:
langchain.text_splitter.CharacterTextSplitter(separator: str = "(n(n"chunk_size=4000,chunk_overlap=200,length_function=<builtin function len>,)
Methods:create_documents()-Create documents from a list of texts.split_documents()-Split documents.
chunk_size
指每个块包含的字符或Token(如单词、句子等)的数量chunk_overlap
指两个块之间共享的字符数量,用于保持上下文的连贯性,避免分割丢失上下文信息
langchain还有其它文档分割方式,区别在怎么确定块与块之间的边界、块由哪些字符/token组成、以及如何测量块大小。
接下来,
# 引入模块
from langchain_text_splitters import RecursiveCharacterTextSplitte # 实例化RecursiveCharacterTextSplitter对象
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)"""对文本切割 .split_text()"""
chunks = text_splitter.split_text(pdf_page.page_content) # 对pdf_page.page_content进行分割,得到List列表"""对文件切割 .split_documents()"""
chunks = text_splitter.split_documents(pdf_pages[0:3]) # 返回List列表
额外地,这里其实可以对文件总数tokens进行统计。
sum([len(chunk.page_content) for chunk in chunks])
总结
以上就是如何对源文件数据进行处理。
- 加载。 使用
langchain.document_loaders
下的模块,实例化后,.load()
加载文件 - 清理。 使用正则表达式或简单替换删除不需要的字符
- 分割。 使用
langchain_text_splitters
下的模块,实例化后,.split_text() 或 .split_documents()
分割内容为多个chunks,为后续存入数据库做准备