【高階RAG技巧】在大模型知識庫問答中增強文件分割與表格提取

深度学习机器發表於2024-04-18

前言

文件分割是一項具有挑戰性的任務,它是任何知識庫問答系統的基礎。高質量的文件分割結果對於顯著提升問答效果至關重要,但是目前大多數開源庫的處理能力有限。
這些開源的庫或者方法缺點大致可以羅列如下:

  • 只能處理文字,無法提取表格中的內容
  • 缺乏有效的分割策略,要麼是一整個文件全部提取,要麼是詞粒度的獲取

對於第一點,一般是把表格中的內容識別成文字,這樣餵給大模型的時候就會出現一連串數字或者字母,這無疑會增大模型的理解難度;對於第二點,則是需要按照指定的長度對文件進行切分,或者把詞按照一定的規則拼接到一塊,這同樣會損失到文字自身的上下文資訊。

而本文接下來介紹的Open-parse這個庫可以直接從文字中提取出多個節點,每個節點就是一個chunk,已經分好了,因此無需再按照長度進行split,這樣同時也比單獨提取一個詞再進行合併又簡化了不少操作;同時還支援同時提取表格和文字,無需分開提取。

快速開始

安裝

pip install openparse

使用pip進行安裝,同時這個庫依賴Pymupdfpdfminer等其他庫,也會同時安裝。

識別文字

pdf = "c:\\人口.pdf"
parser = openparse.DocumentParser()
parsed_basic_doc = parser.parse(pdf)
for node in parsed_basic_doc.nodes:
    node
    print('\n--------------------\n')

可以看到每一頁的pdf被分成多個chunk,且還能保留原始文字中的加粗斜體等資訊。

print(parsed_basic_doc.nodes[0])

elements=(TextElement(text='Aging Research老齡化研究, 2022, 9(3), 26-34\nPublished Online September 2022 in Hans. http://www.hanspub.org/journal/ar \nhttps://doi.org/10.12677/ar.2022.93004 ', lines=(LineElement(bbox=(56.64, 739.57, 232.44, 750.01), spans=(TextSpan(text='Aging Research ', is_bold=True, is_italic=False, size=9.0), TextSpan(text='老齡化研究', is_bold=False, is_italic=False, size=9.0), TextSpan(text=', 2022, 9(3), 26-34 ', is_bold=True, is_italic=False, size=9.0)), style=None, text='Aging Research老齡化研究, 2022, 9(3), 26-34'), LineElement(bbox=(56.65, 728.28, 348.95, 737.28), spans=(TextSpan(text='Published Online September 2022 in Hans. http://www.hanspub.org/journal/ar ', is_bold=False, is_italic=False, size=9.0),), style=None, text='Published Online September 2022 in Hans. http://www.hanspub.org/journal/ar '), LineElement(bbox=(56.64, 717.36, 225.23, 726.36), spans=(TextSpan(text='https://doi.org/10.12677/ar.2022.93004 ', is_bold=False, is_italic=False, size=9.0),), style=None, text='https://doi.org/10.12677/ar.2022.93004 ')), bbox=Bbox(page=0, page_height=807.96, page_width=595.32, x0=56.64, y0=717.36, x1=348.95, y1=750.01), variant=<NodeVariant.TEXT: 'text'>, embed_text='Aging Research老齡化研究, 2022, 9(3), 26-34\nPublished Online September 2022 in Hans. http://www.hanspub.org/journal/ar \nhttps://doi.org/10.12677/ar.2022.93004 '),) variant={'text'} tokens=66 bbox=[Bbox(page=0, page_height=807.96, page_width=595.32, x0=56.64, y0=717.36, x1=348.95, y1=750.01)] text='Aging Research老齡化研究, 2022, 9(3), 26-34\nPublished Online September 2022 in Hans. http://www.hanspub.org/journal/ar \nhttps://doi.org/10.12677/ar.2022.93004 '

透過列印出node,可以看出這種結構包含了原始文字中的元資訊,包含文字的座標、大小、是否加粗、是否斜體等。

識別表格內容

  • Pymupdf
  • Unitable
  • Table Transformer

openparse提供了三個方法來識別和提取表格中的內容,方法1是直接使用Pymupdf這個庫的表格識別模組,因此準確率最差,但對硬體要求不高;其他的2個都是100mb左右的模型,如果用cpu來推理會比較耗時。

# defining the parser (table_args is a dict)
parser = openparse.DocumentParser(
    table_args={
        "parsing_algorithm": "table-transformers", # 或者其他兩個方法
        "table_output_format": "html" # 以html格式返回表格內容,也可以選擇md
    }
)

與前面直接識別文字類似,只需要加入table_args引數即可。

可以看到表格中的內容被很好的還原了

使用表格提取除了返回表格內容外,還會把正常的文字返回,這與Pymupdf等庫只能選擇返回文字還是隻返回已有的表格不同。因此在不確定文字中含有什麼內容時用這個方法會更加保險一點,對硬體的計算要求也不高。

語義相似

from openparse import processing, DocumentParser

semantic_pipeline = processing.SemanticIngestionPipeline(
    openai_api_key=OPEN_AI_KEY,
    model="text-embedding-3-large",
    min_tokens=64,
    max_tokens=1024,
)

parser = DocumentParser(
    processing_pipeline=semantic_pipeline,
)

openparse還支援端到端的方式對node資料進行向量化並聚類,只需要指定processing_pipeline為相應的embedding模型即可。但是目前僅支援OpenAI的模型,需要OPEN_AI_KEY才可以使用。雖然後續會更新其他模型,但目前想用的話需要自己修改這段程式碼的實現。

combine_parser = DocumentParser(
    processing_pipeline=semantic_pipeline,
    table_args={
        "parsing_algorithm": "table-transformers",
        "table_output_format": "html"
    }
    
)

同時,還能把語義相似和表格內容提取組合到一起使用,實現對錶格內容提取的同時還能融合相似的片段。

總結

openparse這個庫算是目前開源社群中比較優秀的文件分割處理庫了,功能雖然全面,還是還有不少可以最佳化的地方,後續也會支援其他向量化模型,並且可以跟LlamaindexLangchain等框架無縫銜接,應該值得持續關注。

相關文章