pdf 文档向量化详细过程

读取文件

使用的 pdf 文档是一个 langchain.pdf 文档,内容截图如下:

参数说明

基本的文档处理参数如下:

ini 复制代码
chunk_overlap = 50
chunk_size = 250
embed_model = 'bge-large-zh-v1.5'
vs_type = 'fassi'
zh_title_enhance = False

详细解释如下:

  1. chunk_overlap = 50: chunk_overlap 是指在进行文本分块时,每个块之间的重叠量。在处理文本时,通常将文本分成多个块以便更有效地处理,而重叠量可以确保在相邻的块之间不会丢失重要的信息。在这个例子中,重叠量为 50,表示相邻块之间会有 50 个字符的重叠。

  2. chunk_size = 250chunk_size 是指每个文本块的大小。将长文本分成适当大小的块有助于更高效地处理文本数据。在这里每个文本块的大小为 250 个字符。

  3. embed_model = 'bge-large-zh-v1.5'embed_model 是指用于文本嵌入(embedding)的模型。文本嵌入是将文本数据转换成向量的过程,通常用于表示文本数据。在这里,使用了名为 'bge-large-zh-v1.5' 的嵌入模型。

  4. vs_type = 'fassi'vs_type 是向量数据库名称。

  5. zh_title_enhance = Falsezh_title_enhance 是一个布尔值,用于指示是否要增强中文标题。当设置为 True 时,表示对中文标题进行增强处理;当设置为 False 时,表示不进行增强处理。

加载自定义的 Loader 处理 pdf 文件

因为我使用的是一份 pdf 文件,所以可以根据 .pdf 后缀可以选择使用自定义的 RapidOCRPDFLoader 类来作为我们的 Loader ,日志打印如下:

rust 复制代码
RapidOCRPDFLoader used for D:\Langchain-Chatchat-torch2-240402\knowledge_base\samples\content\test_files/DRL.pdf

下面的代码看起来很长,其实关键的逻辑就是在 pdf2text 函数中,先通过 doc = fitz.open(filepath) 提取出每一页 pdf 的信息 doc 列表 ,然后遍历 doc 列表中每一个 的 page 信息。这里的 page 里面包含了可能出现的文本图片,如果有文本就把 ocr 识别的这一页 pdf 文本长字符串加入到 resp 中,如果有图片就通过可能的旋转和 ocr 等操作,将识别出来的图片中的文本加入到 resp 中,最后将 resp 返回即可。我们此时拿到的是一个非常长的字符串,里面包含了全部 pdf 的文字信息,这里我们用到了一个现成的函数 partition_text ,其实就是根据内置的参数算法,将长文本都切分成了短字符串列表。

ini 复制代码
class RapidOCRPDFLoader(UnstructuredFileLoader):
    def _get_elements(self) -> List:
        def rotate_img(img, angle):
            '''
            img   --image
            angle --rotation angle
            return--rotated img
            '''
            
            h, w = img.shape[:2]
            rotate_center = (w/2, h/2)
            #获取旋转矩阵
            # 参数1为旋转中心点;
            # 参数2为旋转角度,正值-逆时针旋转;负值-顺时针旋转
            # 参数3为各向同性的比例因子,1.0原图,2.0变成原来的2倍,0.5变成原来的0.5倍
            M = cv2.getRotationMatrix2D(rotate_center, angle, 1.0)
            #计算图像新边界
            new_w = int(h * np.abs(M[0, 1]) + w * np.abs(M[0, 0]))
            new_h = int(h * np.abs(M[0, 0]) + w * np.abs(M[0, 1]))
            #调整旋转矩阵以考虑平移
            M[0, 2] += (new_w - w) / 2
            M[1, 2] += (new_h - h) / 2

            rotated_img = cv2.warpAffine(img, M, (new_w, new_h))
            return rotated_img
        
        def pdf2text(filepath):
            import fitz # pyMuPDF里面的fitz包,不要与pip install fitz混淆
            import numpy as np
            ocr = get_ocr()
            doc = fitz.open(filepath)
            resp = ""

            b_unit = tqdm.tqdm(total=doc.page_count, desc="RapidOCRPDFLoader context page index: 0")
            for i, page in enumerate(doc):
                b_unit.set_description("RapidOCRPDFLoader context page index: {}".format(i))
                b_unit.refresh()
                text = page.get_text("")
                resp += text + "\n"

                img_list = page.get_image_info(xrefs=True)
                for img in img_list:
                    if xref := img.get("xref"):
                        bbox = img["bbox"]
                        # 检查图片尺寸是否超过设定的阈值
                        if ((bbox[2] - bbox[0]) / (page.rect.width) < PDF_OCR_THRESHOLD[0]
                            or (bbox[3] - bbox[1]) / (page.rect.height) < PDF_OCR_THRESHOLD[1]):
                            continue
                        pix = fitz.Pixmap(doc, xref)
                        samples = pix.samples
                        if int(page.rotation)!=0:  #如果Page有旋转角度,则旋转图片
                            img_array = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, -1)
                            tmp_img = Image.fromarray(img_array);
                            ori_img = cv2.cvtColor(np.array(tmp_img),cv2.COLOR_RGB2BGR)
                            rot_img = rotate_img(img=ori_img, angle=360-page.rotation)
                            img_array = cv2.cvtColor(rot_img, cv2.COLOR_RGB2BGR)
                        else:
                            img_array = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, -1)

                        result, _ = ocr(img_array)
                        if result:
                            ocr_result = [line[1] for line in result]
                            resp += "\n".join(ocr_result)

                # 更新进度
                b_unit.update(1)
            return resp

        text = pdf2text(self.file_path)
        from unstructured.partition.text import partition_text
        return partition_text(text=text, **self.unstructured_kwargs)

chunk

经过一系列的变化处理之后又整合成一个长文本,然后将得到文本之后还要进行分块,这里默认使用的是 ChineseRecursiveTextSplitter ,所以我们要进行切分成较小的片段方便去后面的语义的 encoding 和 search 。然后将分块后的每个文本片段和文件路径包装成 Document ,再将这些 Document 形成列表。如下:

vbnet 复制代码
[
Document(
page_content='See discussions, stats, and author profiles for this publication at: https://www.researchgate.net/publication/372669736\nCreating Large Language Model Applications Utilizing LangChain: A Primer on\nDeveloping LLM Apps Fast\nArticle\xa0\xa0in\xa0\xa0International Conference on Applied Engineering and Natural Sciences · July 2023\nDOI: 10.59287/icaens.1127\nCITATIONS\n0\nREADS\n47\n2 authors:\nSome of the authors of this publication are also working on these related projects:\nTHALIA: Test Harness for the Assessment of Legacy Information Integration Approaches View project\nAnalysis of Feroresonance with Signal Processing Technique View project\nOguzhan Topsakal\nFlorida Polytechnic University\n29 PUBLICATIONS\xa0\xa0\xa0155 CITATIONS\nSEE PROFILE\nT. Cetin Akinci\nIstanbul Technical University & University of California Riverside\n116 PUBLICATIONS\xa0\xa0\xa0745 CITATIONS\nSEE PROFILE\nAll content following this page was uploaded by Oguzhan Topsakal on 07 August 2023.', 
metadata={'source': 'D:\\Langchain-Chatchat-torch2-240402\\knowledge_base\\samples\\content\\test_files/langchain.pdf'}
), 
Document(
page_content='116 PUBLICATIONS\xa0\xa0\xa0745 CITATIONS\nSEE PROFILE\nAll content following this page was uploaded by Oguzhan Topsakal on 07 August 2023.\nThe user has requested enhancement of the downloaded file.\nAll Sciences Proceedings\nhttp://as-proceeding.com/\n5th International Conference on Applied\nEngineering and Natural Sciences\nJuly 10-12, 2023 : Konya, Turkey\nhttps://www.icaens.com/\n© 2023 Published by All Sciences Proceedings\n1050\nCreating Large Language Model Applications Utilizing LangChain: A\nPrimer on Developing LLM Apps Fast\nOguzhan Topsakal1*, and Tahir Cetin Akinci 2\n1Computer Science Department, Florida Polytechnic University, FL, USA\n2WCGEC, University of California at Riverside, CA, USA\n(otopsakal@floridapoly.edu) Email of the corresponding author\nAbstract -- This study focuses on the utilization of Large Language Models (LLMs) for the rapid', 
metadata={'source': 'D:\\Langchain-Chatchat-torch2-240402\\knowledge_base\\samples\\content\\test_files/langchain.pdf'}
)
...]

存入向量库

随便找一个可以使用的向量模型,我这里使用的是 bge-large-zh-v1.5 ,另外还有找自己合适的向量数据库,我这里使用的是 fassi ,将上面处理好的 chunk 都经过向量化存入 fassi 中,后面结合大模型即可即可进行文档的问答和检索。

相关推荐
lijianhua_97121 小时前
国内某顶级大学内部用的ai自动生成论文的提示词
人工智能
EDPJ1 小时前
当图像与文本 “各说各话” —— CLIP 中的模态鸿沟与对象偏向
深度学习·计算机视觉
蔡俊锋1 小时前
用AI实现乐高式大型可插拔系统的技术方案
人工智能·ai工程·ai原子能力·ai乐高工程
自然语1 小时前
人工智能之数字生命 认知架构白皮书 第7章
人工智能·架构
大熊背1 小时前
利用ISP离线模式进行分块LSC校正的方法
人工智能·算法·机器学习
eastyuxiao2 小时前
如何在不同的机器上运行多个OpenClaw实例?
人工智能·git·架构·github·php
诸葛务农2 小时前
AGI 主要技术路径及核心技术:归一融合及未来之路5
大数据·人工智能
光影少年2 小时前
AI Agent智能体开发
人工智能·aigc·ai编程
ai生成式引擎优化技术2 小时前
TSPR-WEB-LLM-HIC (TWLH四元结构)AI生成式引擎(GEO)技术白皮书
人工智能
帐篷Li2 小时前
9Router:开源AI路由网关的架构设计与技术实现深度解析
人工智能