Giới thiệu
Trong quá trình làm việc với dữ liệu, việc trích xuất thông tin từ file PDF luôn là một thách thức, đặc biệt là với các tài liệu có cấu trúc phức tạp như chứa nhiều bảng biểu. Thư viện docling
ra đời như một giải pháp mạnh mẽ và linh hoạt, giúp chúng ta phân tích và chuyển đổi tài liệu một cách nhanh chóng và dễ dàng.
Các tính năng nổi bật của Docling:
- Hỗ trợ đa dạng định dạng: Đọc và xuất ra Markdown, JSON từ nhiều định dạng phổ biến như PDF, DOCX, PPTX, XLSX, Hình ảnh, HTML, v.v.
- Hiểu sâu cấu trúc PDF: Có khả năng nhận diện cấu trúc bảng, thứ tự đọc (reading order) và bố cục trang một cách thông minh.
- Định dạng
DoclingDocument
thống nhất: Cung cấp một cấu trúc dữ liệu chung, dễ dàng thao tác. - Tích hợp dễ dàng: Tương thích tốt với các hệ sinh thái RAG/QA mạnh mẽ như LlamaIndex và LangChain.
- Hỗ trợ OCR: Xử lý được cả các file PDF dạng scan (ảnh) nhờ các engine OCR tích hợp.
- Giao diện dòng lệnh (CLI) tiện lợi.
Trong bài viết này, chúng ta sẽ không chỉ dừng lại ở các ví dụ cơ bản mà sẽ đi sâu vào cách tùy chỉnh docling
để đạt được kết quả chuyển đổi tốt nhất, đặc biệt là trong việc giữ lại cấu trúc của bảng biểu từ file PDF.
Tình huống: Chuyển đổi PDF với cấu trúc bảng phức tạp
Hãy tưởng tượng bạn có một file PDF chứa các báo cáo tài chính hoặc thông số kỹ thuật, nơi các bảng biểu là nguồn thông tin quan trọng nhất. Một công cụ chuyển đổi thông thường có thể sẽ làm "vỡ" cấu trúc bảng, biến chúng thành một mớ văn bản hỗn độn. Đây là lúc các tùy chọn nâng cao của docling
phát huy tác dụng.
Đoạn mã dưới đây trình bày cách thiết lập một DocumentConverter
được tùy chỉnh để ưu tiên việc nhận dạng bảng một cách chính xác.
import os
from io import BytesIO
from pathlib import Path from docling.datamodel.base_models import InputFormat, DocumentStream
from docling.datamodel.pdf_models import TableFormerMode
from docling.datamodel.pipeline_options import PdfPipelineOptions
from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.pdf.pdf_backend import PyPdfiumDocumentBackend
from docling.pipeline.pdf_pipeline import StandardPdfPipeline # Giả sử bạn có hàm get_object để lấy file từ S3 hoặc một nguồn lưu trữ khác
# from my_s3_utils import get_object def doc_converter(): """ Tạo một document converter với các tùy chọn được tùy chỉnh. """ # Tải các model cần thiết từ Hugging Face về máy, ví dụ như model cho việc nhận dạng bảng. # Việc này chỉ cần làm một lần. tmp_path = StandardPdfPipeline.download_models_hf(local_dir=Path("/tmp/docling_models")) # Bắt đầu cấu hình pipeline cho file PDF pdf_options = PdfPipelineOptions(artifacts_path=tmp_path) # Tùy chỉnh các lựa chọn: pdf_options.do_ocr = False # Giả sử đây là file PDF gốc (native), không phải file scan. pdf_options.do_table_structure = True # BẬT tính năng nhận dạng cấu trúc bảng. pdf_options.table_structure_options.do_cell_matching = True # Bật tính năng khớp ô trong bảng. pdf_options.ocr_options.use_gpu = False # Không dùng GPU cho OCR (vì đã tắt OCR) # Đây là tùy chọn quan trọng nhất! # Sử dụng chế độ 'ACCURATE' của TableFormer để có độ chính xác cao nhất khi nhận dạng bảng. pdf_options.table_structure_options.mode = TableFormerMode.ACCURATE doc_converter = ( DocumentConverter( # Áp dụng các tùy chọn đã cấu hình cho định dạng PDF format_options={ InputFormat.PDF: PdfFormatOption( pipeline_options=pdf_options, backend=PyPdfiumDocumentBackend, # Sử dụng backend PyPdfium ), }, ) ) return doc_converter # --- Luồng xử lý chính --- # 1. Khởi tạo converter đã được tùy chỉnh
converter = doc_converter() # 2. Lấy file PDF từ một nguồn (ví dụ: S3)
# source_bucket = "my-bucket"
# file_key = "reports/financial_report.pdf"
# body = get_object(bucket=source_bucket, key=file_key)
# file_name = os.path.basename(file_key) # Để demo, ta đọc file từ local
file_path = "docs/sample_table.pdf" # Thay bằng đường dẫn file PDF của bạn
file_name = os.path.basename(file_path)
with open(file_path, "rb") as f: body_stream = BytesIO(f.read()) # 3. Chuẩn bị đầu vào cho converter
source = DocumentStream(name=file_name, stream=body_stream) # 4. Thực hiện chuyển đổi
result = converter.convert(source=source) # 5. Xuất kết quả ra định dạng Markdown
md_text = result.document.export_to_markdown() # 6. In kết quả
print(md_text)
Phân tích chi tiết đoạn mã
StandardPdfPipeline.download_models_hf()
:docling
sử dụng các mô hình AI tiên tiến (cụ thể làTableFormer
từ Microsoft) để nhận dạng bảng. Lệnh này sẽ tải các mô hình cần thiết từ Hugging Face về máy của bạn.PdfPipelineOptions()
: Đây là "trung tâm điều khiển" nơi bạn có thể bật/tắt và tinh chỉnh các tính năng của pipeline xử lý PDF.do_table_structure = True
: Đây là công tắc chính để kích hoạt module nhận dạng bảng.mode = TableFormerMode.ACCURATE
: Đây là điểm "ăn tiền". Thay vì chế độ nhanh (FAST
), chúng ta chọnACCURATE
để ưu tiên độ chính xác. Điều này đặc biệt hữu ích cho các bảng có cấu trúc phức tạp, ô bị gộp (merged cells), hoặc không có đường kẻ rõ ràng.DocumentStream
:docling
có thể xử lý file trực tiếp từ stream (luồng byte) trong bộ nhớ thay vì chỉ đọc từ đường dẫn file trên đĩa. Điều này rất linh hoạt khi bạn làm việc với các hệ thống lưu trữ đám mây như S3, Google Cloud Storage, hoặc nhận file từ một API request.result.document.export_to_markdown()
: Cuối cùng, đối tượngdocument
sau khi xử lý có thể được xuất ra nhiều định dạng, và ở đây chúng ta chọn Markdown. Các bảng sẽ được chuyển đổi thành cú pháp Markdown table một cách hoàn hảo.
So sánh với cách tiếp cận đơn giản
Để thấy rõ sự khác biệt, hãy xem cách chuyển đổi đơn giản nhất:
from docling.document_converter import DocumentConverter source = "docs/sample_table.pdf" converter = DocumentConverter() # Không có tùy chọn gì cả
result = converter.convert(source) # to markdown
print(result.document.export_to_markdown())
Cách này nhanh và tiện lợi cho các tài liệu văn bản đơn giản. Tuy nhiên, với các file PDF phức tạp, việc không chỉ định rõ các tùy chọn như TableFormerMode.ACCURATE
có thể dẫn đến kết quả nhận dạng bảng không như ý.
Mở rộng: Trích xuất riêng từng bảng ra DataFrame
Sau khi đã nhận dạng được các bảng, docling
cho phép bạn truy cập và xử lý riêng từng bảng một cách dễ dàng.
import pandas as pd
from pathlib import Path # Giả sử bạn đã có đối tượng `conv_res` từ bước chuyển đổi ở trên
conv_res = result output_dir = Path("output_tables")
output_dir.mkdir(parents=True, exist_ok=True)
doc_filename = Path(conv_res.input.name).stem # Lặp qua tất cả các bảng đã được nhận dạng trong tài liệu
for table_ix, table in enumerate(conv_res.document.tables): # Xuất bảng ra pandas DataFrame table_df: pd.DataFrame = table.export_to_dataframe() print(f"--- Bảng {table_ix + 1} ---") print(table_df.to_markdown(index=False)) # Lưu bảng thành file CSV csv_filename = output_dir / f"{doc_filename}-table-{table_ix+1}.csv" table_df.to_csv(csv_filename, index=False) print(f"Đã lưu bảng vào: {csv_filename}\n")
Đoạn mã này cực kỳ hữu ích cho các tác vụ phân tích dữ liệu, nơi bạn cần trích xuất các bảng từ hàng loạt file PDF và đưa vào một quy trình xử lý dữ liệu (data pipeline) sử dụng Pandas.
Kết luận
Thư viện docling
không chỉ là một công cụ chuyển đổi định dạng đơn thuần. Nó cung cấp một bộ công cụ mạnh mẽ và có khả năng tùy biến cao, cho phép các nhà phát triển kiểm soát sâu vào quá trình phân tích tài liệu. Bằng cách sử dụng các tùy chọn nâng cao như TableFormerMode.ACCURATE
, chúng ta có thể giải quyết hiệu quả bài toán trích xuất dữ liệu từ các file PDF có cấu trúc phức tạp, đặc biệt là các bảng biểu, với độ chính xác cao.
Đây là một công cụ không thể thiếu trong bộ công cụ của bất kỳ ai làm việc trong lĩnh vực xử lý ngôn ngữ tự nhiên (NLP), xây dựng hệ thống RAG, hay tự động hóa quy trình trích xuất thông tin.