輕松解析本地PDF表格,基于LlamaIndex和UnstructuredIO打造RAG
1 使用 LlamaIndex 和 UnstructuredIO 檢索數據
在數據檢索領域,LlamaIndex 以其強大的工具和技術,為用戶帶來了全新的檢索體驗。這個框架的亮點在于索引系統的靈活性,用戶可以根據文檔的具體內容,量身定制索引策略,以適應不同的文檔結構。每種索引都設計得獨具匠心,能夠精準匹配各種文檔結構,確保信息檢索的準確性和高效性。
對于包含大量表格的 PDF 文件,建議使用 LlamaIndex 推薦的 RecursiveRetriever。這種遞歸檢索技術的精髓在于,它不僅深入挖掘與信息直接相關的節點,還會追溯這些節點與其它檢索器或查詢引擎之間的關聯,進而執行相應的檢索操作。
例如,某個節點精煉地總結了某個結構化表格的關鍵信息,并鏈接到該表格的 SQL 或 Pandas 查詢引擎。那么在檢索到這個節點之后,我們就能夠利用這些底層的查詢工具深入挖掘,從而獲取更詳盡的數據。這種深入的檢索方法,大大增強了我們從復雜數據集中提取有價值信息的能力。
為了有效實施這一策略,分步驟進行:
a. 首先,將 PDF 文件轉換成 HTML 格式,這一步已經完成。
b. 接著,利用 UnstructuredIO 讀取轉換后的 HTML 文件。
c. 對于 UnstructuredIO 從 HTML 中識別出的每個元素,無論是文本還是表格,都將其存儲到 LlamaIndex 的節點中。
d. 這樣一來,就構建了一個包含文本和表格的節點列表。
e. (可選步驟)可以專門篩選出包含表格的節點,并將這些表格發送到語言模型(LLM)以生成摘要。
f. 然后,借助 LlamaIndex,LLM 代理將遞歸地檢索與問題相關的信息。
g. 最后,將這些檢索到的數據發送回 LLM,以生成最終的響應。
雖然這個過程聽起來頗為復雜,但得益于 LlamaIndex 提供的封裝良好的函數,我們執行這些步驟更加容易些。
1.1 讀取和處理數據
from llama_index.readers.file.flat_reader import FlatReader
from llama_index.node_parser import UnstructuredElementNodeParser
import os
import pickle
from pathlib import Path
os.environ["OPENAI_API_KEY"] = "<your openai api key>"
# 讀取數據
reader = FlatReader()
data = reader.load_data(Path('./The_Worlds_Billionaires.html'))
# 初始化 NodeParser
node_parser = UnstructuredElementNodeParser()
# 如果稍后想重用它
if not os.path.exists("qr_2023_nodes.pkl"):
raw_nodes = node_parser.get_nodes_from_documents(data)
pickle.dump(raw_nodes, open("the_world_billionaires_raw_nodes.pkl", "wb"))
# 基礎節點和節點映射
base_nodes, node_mappings = node_parser.get_base_nodes_and_mappings(
raw_nodes
)
1.2 構建索引
from llama_index.retrievers import RecursiveRetriever
from llama_index.query_engine import RetrieverQueryEngine
from llama_index import VectorStoreIndex
vector_index = VectorStoreIndex(base_nodes_qr_2023)
vector_retriever = vector_index.as_retriever(similarity_top_k=3)
vector_query_engine = vector_index.as_query_engine(similarity_top_k=3)
recursive_retriever = RecursiveRetriever(
"vector",
retriever_dict={"vector": vector_retriever},
node_dict=node_mappings_qr_2023,
)
query_engine = RetrieverQueryEngine.from_args(recursive_retriever)
query_engine.query("Who is the richest billionaire in 2020?")
1.3 其他類型的查詢索引
前面的例子已經展示了 UnstructuredElementNodeParser 如何無縫集成到 LlamaIndex + UnstructuredIO 的數據處理流程中,體現了其在提升數據處理效率和便捷性方面的強大能力。它采用了一種簡化的方法論,讓原本復雜的數據提取工作變得更加易于掌握。
鑒于 LlamaIndex 提供了多種索引類型和檢索技術,探索不同的選項以找到最適合你特定場景的解決方案是非常有價值的。不妨嘗試包括自動合并檢索器、結果重排序以及混合搜索在內的多種策略。
每種策略都有其獨到之處,而最終的效果也會隨著數據的復雜性而有所不同。通過實際測試和評估,你可以優化檢索流程,確保采用最合適的方法從數據集中提取關鍵信息。
2 如何從 PDF/HTML 中提取表格
這部分內容提供了一個可選的功能,它通過較低級別的 API 支持從 PDF 或 HTML 中提取表格,這可能對特定需求非常有用。雖然前面提到的方法在大多數情況下已經足夠有效,但如果需要更精細的控制,比如直接操作底層數據,那么可能需要在數據處理流程中加入額外的步驟,例如利用語言模型(LLM)來生成數據摘要。這一環節值得你進一步探索。
2.1 從 PDF 中提取表格
完成從 PDF 中提取表格的任務,可以依賴多種光學字符識別(OCR)技術和庫,同時也可以考慮使用云服務,但這涉及較高的成本。UnstructuredIO 提供了一個功能強大的 ??partition_pdf?
? 方法,它通過多個參數讓你能夠靈活地在處理速度和識別準確性之間做出權衡,并且可以指定特定的深度學習模型來優化表格的提取效果。
from unstructured.partition.pdf import partition_pdf
from unstructured.staging.base import elements_to_json
import json
file_path = 'The_Worlds_Billionaires.pdf'
raw_pdf_elements = partition_pdf(
filename=file_path,
extract_images_in_pdf=False,
infer_table_structure=True,
chunking_strategy='by_title',
max_characters=4000,
new_after_n_chars=3800,
combine_text_under_n_chars=2000,
strategy = "hi_res"
)
# 將結果存儲在 json 中
elements_to_json(raw_pdf_elements, filename=f"./The_Worlds_Billionaires_Converted.json")
no_tables = 0
def process_json_file(input_filename):
# 讀取 JSON 文件
with open(f'./{input_filename}.json', 'r') as file:
data = json.load(file)
# 遍歷 JSON 數據并提取所需的表格元素
extracted_elements = []
for entry in data:
if entry['type'] == 'CompositeElement':
extracted_elements.append(entry['text'])
if entry["type"] == "Table":
no_tables += 1
extracted_elements.append(entry["metadata"]["text_as_html"])
# 將提取的元素寫入輸出文件
with open(f"{input_filename}.txt", 'w') as output_file:
for element in extracted_elements:
output_file.write(element + "\n\n") # 添加兩個換行符以分隔
process_json_file(f"The_Worlds_Billionaires_Converted") # ## with new_file_name 是上面的 JSON 文件
print(f"Number of tables: {no_tables}")
### 加載數據
```python
# documents = SimpleDirectoryReader("./<folder_name>",
# input_files=['./<new_file_name.txt>']).load_data()
該方法能夠讀取 PDF 文件,并提取出其中的元素,如文本和表格。表格元素會以 JSON 格式保存為“text_as_html”。你可以逐一讀取和處理 JSON 文件中的每個元素,并將處理后的數據存儲為 TXT 文件,以便后續的 RAG 讀取。
需要注意的是,直接解析 PDF 的性能可能不盡如人意。目前,UnstructuredIO 提供了多種模型,例如 YOLOx,來幫助將 PDF 轉換為可操作的元素。然而,這些深度神經網絡模型在低配置計算機上表現不佳,建議在配備高性能 GPU 的機器上運行。唯一需要關注的問題是,當同時處理千份文檔時,系統的性能表現如何。
3 總結
開源項目和云服務提供商在應對 PDF 處理復雜性方面展現了行業的協同努力。
在這個不斷變化的環境中,沒有一種通用的方法能夠有效管理復雜的 PDF 文件。經驗表明,結合使用 LlamaIndex、UnstructuredIO 以及 PDF 到 HTML 的轉換,是一種簡單而高效的解決方案,能夠產生優異的結果。
此外,提高 RAG 準確性的關鍵策略之一是靈活地結合不同的索引和檢索器。這種多元化的方法認識到沒有一套固定的索引規則適用于所有情況,強調需要根據每種文檔的具體特性和處理細節來定制策略。通過接受這種靈活性,并使用量身定制的索引和檢索器組合,你可以構建一個更準確、更復雜的檢索系統,以應對數據的復雜性。
本文轉載自 ??AI科技論談??,作者: AI科技論談
