4 điểm bởi GN⁺ 2025-05-15 | 1 bình luận | Chia sẻ qua WhatsApp
  • Trích xuất văn bản từ tệp PDF khó hơn rất nhiều so với dự đoán, và PDF về bản chất là một định dạng tệp dựa trên đồ họa
  • Trong PDF chỉ tồn tại thông tin vị trí của glyph, gần như không có tín hiệu ngữ nghĩa nên việc nhận diện và tái cấu trúc văn bản trở nên phức tạp
  • Các công cụ tìm kiếm cần đầu vào HTML sạch sẽ, nhưng những công cụ mã nguồn mở hiện có có giới hạn trong việc trích xuất thông tin cấu trúc như tiêu đề hay đoạn văn
  • Cách tiếp cận thị giác dựa trên machine learning cho độ chính xác cao nhất, nhưng khó áp dụng ở quy mô lớn do vấn đề tài nguyên và hiệu năng
  • Biện pháp cải thiện chính là đưa vào thuật toán nhận diện tiêu đề và đoạn văn dựa trên cỡ chữ và thống kê để nâng độ chính xác trích xuất

Thách thức của việc trích xuất văn bản từ PDF

  • Các công cụ tìm kiếm hiện đại đã có khả năng lập chỉ mục định dạng tệp PDF
  • Việc trích xuất thông tin từ PDF không hề dễ, vì PDF vốn là định dạng đồ họa chứ không phải định dạng văn bản
  • Thay vì văn bản thực sự, PDF chứa các glyph được đặt tại những tọa độ nhất định, dẫn tới các vấn đề như xoay, chồng lấp, thứ tự lộn xộn và thiếu thông tin ngữ nghĩa
  • Thông tin dưới dạng văn bản như chúng ta thường hình dung thực ra không tồn tại trực tiếp trong tệp
  • Việc có thể tìm kiếm văn bản bằng ctrl+f trong trình xem PDF thực ra là điều khá đáng kinh ngạc

Yêu cầu của công cụ tìm kiếm và giới hạn của cách tiếp cận cơ bản

  • Loại đầu vào mà công cụ tìm kiếm ưa thích nhất là định dạng HTML sạch
  • Các mô hình computer vision hiện đại dựa trên machine learning cho hiệu năng tốt nhất, nhưng
    • việc xử lý các tệp PDF dung lượng lớn (hàng trăm GB) trên một máy chủ không có GPU là không hiệu quả
  • May mắn là lĩnh vực này không hoàn toàn là vùng đất chưa được khám phá, nên
    • có thể dùng lớp PDFTextStripper của PDFBox làm điểm khởi đầu
    • tuy nhiên gần như không thể nắm bắt cấu trúc ngữ nghĩa như tiêu đề — chỉ trích xuất được chuỗi ký tự

Thuật toán nhận diện tiêu đề

Nguyên lý cơ bản của nhận diện tiêu đề

  • Thông thường có thể tận dụng việc tiêu đề thường là chữ semi-bold hoặc đậm hơn và đứng tách biệt
    • nhưng tiêu đề không in đậm cũng rất phổ biến, nên chỉ dựa vào cách này thì có giới hạn
  • Trong nhiều trường hợp, cỡ chữ là tiêu chí để phân biệt tiêu đề
    • tuy nhiên cỡ chữ khác nhau hoàn toàn giữa các tài liệu, nên không thể dùng ngưỡng toàn cục

Tận dụng thống kê cỡ chữ

  • Mỗi trang nhìn chung đều có một cỡ chữ chi phối (phần thân bài)
  • Trang 1 (bìa) có nội dung mô tả và thông tin tác giả nên phân bố cỡ chữ khác biệt
  • phân bố cỡ chữ khác nhau theo từng trang, nên dùng thống kê theo trang thay vì toàn bộ tài liệu sẽ hiệu quả hơn
  • Có thể nhận diện tiêu đề khá chính xác bằng cách áp dụng mức tăng khoảng 20% so với cỡ chữ trung vị của từng trang

Vấn đề gộp các tiêu đề nhiều dòng

  • Vì lý do trình bày, tiêu đề đôi khi được tách thành nhiều dòng
    • việc quyết định thời điểm gộp tiêu đề không đơn giản, vì có thể lẫn các tiêu đề từ hai dòng trở lên, tên tác giả hoặc văn bản nhấn mạnh riêng biệt
  • Quy tắc gộp:
    • gộp các dòng liên tiếp có cùng cỡ chữ và độ đậm hoạt động khá tốt
    • nhưng vẫn có rất nhiều ngoại lệ — gộp bừa bãi có thể dẫn tới kết quả sai lệch

Cải thiện nhận diện đoạn văn

  • PDFTextStripper nhận diện đoạn văn dựa trên khoảng cách giữa các dòng và thụt lề
    • vì dùng ngưỡng phân tách theo từng dòng là giá trị cố định, nên có giới hạn khi áp dụng cho các tài liệu có giãn dòng khác nhau
    • đặc biệt trong bản nháp bài báo hay bản preprint, giãn dòng 1.5~2 lần là điều phổ biến
  • Nếu ngưỡng quá lớn, sẽ phát sinh lỗi gộp tiêu đề vào phần thân bài

Phân tách đoạn văn dựa trên thống kê

  • Tương tự cỡ chữ, có thể áp dụng xử lý thống kê cho khoảng cách giữa các dòng
    • tận dụng giá trị giữa (trung vị) của khoảng cách giữa các dòng để phân tách đoạn văn ổn định với mọi kiểu giãn dòng

Kết luận

  • Việc trích xuất văn bản từ PDF về bản chất không thể hoàn hảo
    • vì bản thân định dạng PDF không được thiết kế cho mục đích đó
  • Trong triển khai thực tế, thỏa hiệp là điều bắt buộc, và chiến lược quan trọng là đạt được kết quả ở mức “đủ tốt”
  • Với công cụ tìm kiếm, việc tập trung trích xuất những tín hiệu có ý nghĩa như tiêu đề, tóm tắt và các manh mối cấu trúc chính sẽ hiệu quả hơn

Mẫu văn bản tham khảo

  • Can Education be Standardized? Evidence from Kenya (2022) - Working Paper
    : Guthrie Gray-Lobe, Anthony Keats, Michael Kremer, Isaac Mbiti, Owen W. Ozier
  • The theory of ideas and Plato’s philosophy of mathematics (2019)
    : Dembiński, B.
  • The role of phronesis in Knowledge-Based Economy (2024)
    : Anna Ceglarska, Cymbranowicz Katarzyna

1 bình luận

 
GN⁺ 2025-05-15
Ý kiến trên Hacker News
  • Đã bao giờ bạn thấy điều gì đó mới mẻ và thú vị trong đời, rồi mơ hồ nhớ ra rằng trước đây mình từng là chuyên gia về đúng việc đó trong nhiều tháng hoặc nhiều năm chưa? Thậm chí cảm giác như cả những lúc mình từng làm được những thứ rất ngầu cũng đã biến mất khỏi đầu, khiến bạn phải bắt đầu lại từ đầu. Tôi có ký ức mơ hồ rằng khoảng 6~7 năm trước mình từng làm một thứ rất ghê với PDF và OCR. Tìm trên Google thì cái tên “tesseract” nghe rất quen

    • Khoảng năm 2006, tôi bực mình vì trên iRex, một máy đọc sách điện tử đời đầu có thể hack được, không thể sao chép văn bản từ các bài báo khoa học nhiều cột. Khi đó trình xem PDF dùng poppler, nên tôi đã sửa poppler để suy luận thứ tự đọc trong tài liệu nhiều cột. Để làm vậy, tôi tham khảo thuật toán OCR của Thomas Breuel, tác giả của tesseract. Đây là kiểu vá víu theo heuristic, và nó không khớp lắm với API trợ năng. Tính năng chọn văn bản đa cột đã được thêm vào nhưng tôi gặp khó khi thuyết phục người bảo trì. Dù sao thì nhờ vậy kpdf đã có tính năng chọn văn bản đa cột. Gần đây tôi nghĩ dùng trực tiếp tesseract cho mục đích này hợp lý hơn nhiều

    • Không thể lấy lại hàng chục năm thời gian của nhân loại đã bị lãng phí vì định dạng PDF. Không biết bao giờ hiện tượng điên rồ này mới kết thúc

    • Có một thời Tesseract là OCR mã nguồn mở tốt nhất. Nhưng giờ tôi thấy docTR vượt trội hơn về độ chính xác và tăng tốc GPU. docTR có kiến trúc pipeline cho phép kết hợp nhiều mô hình phát hiện và nhận dạng văn bản khác nhau. Cũng có thể huấn luyện và tinh chỉnh bằng PyTorch hoặc TensorFlow nên có thể kéo hiệu năng phù hợp với từng miền cụ thể tốt hơn nhiều

    • Cuộc đời là thế đấy. Mỗi khi kết thúc một dự án, tôi lại nghĩ “giờ mình đã là chuyên gia trong lĩnh vực này. Nhưng chắc sẽ không bao giờ làm lại việc này nữa”. Vì lần sau lại bắt đầu một chủ đề hoàn toàn mới từ con số không

    • Cách đây không lâu có người hỏi tôi về C++ và tôi đã nói “chưa từng làm nghiêm túc”. Rồi sau đó mới nhớ ra là khoảng 20 năm trước tôi từng viết mã client cho một ứng dụng nhắn tin riêng bằng Borland C++, và đã có hàng nghìn người dùng. Chuyện này xảy ra khá thường xuyên

    • Tôi không thể biết hết trong đầu bạn có gì, nhưng có lẽ thật sự là tesseract đấy. Tôi cũng có trải nghiệm tương tự, trường hợp của tôi là khoảng 12 năm trước

    • Hồi HQ nổi lên, tôi từng làm một bộ giải đố HQ tự động bằng tesseract. Nó chụp màn hình câu hỏi trong app, gửi qua một API nhỏ, rồi tìm câu hỏi đó trên Google và đếm số lần mỗi đáp án xuất hiện để xếp hạng theo xác suất. Không chính xác lắm và khá đơn giản, nhưng làm rất vui

    • Hiện tượng này chẳng khác gì con kiến lửa khi chiếc lá bị gió thổi bay thì nó chỉ đi tìm chiếc lá khác thôi

    • Chuyện này là khi tôi 20 mấy tuổi, khoảng 7~8 năm trước, nên tôi vẫn nhớ rất rõ. Không biết có phải chênh lệch tuổi tác kha khá không. Hoặc cũng khuyên bạn nên đi kiểm tra sức khỏe

  • Tôi ước có một công cụ kiểu như bộ công cụ nhà phát triển của trình duyệt (“inspect element”) nhưng dành cho content stream của PDF — như BT…ET bao quanh văn bản, các operator chỉ định font và tọa độ, v.v. — để có thể “xem” ở mức mã nguồn và so sánh, phân tích song song với kết quả render. Nó khác với luồng xử lý mà mô hình thị giác “nhìn” PDF để đọc văn bản, mà là mong muốn hiểu thật sâu xem bên trong PDF thực sự chứa những thông tin gì. Có vài công cụ rồi, nhưng chúng chỉ hiển thị đến mức object chứ không đào vào bên trong content stream. Tôi muốn có môi trường cho phép so sánh và phân tích song song như HTML giữa source stream thực tế của một PDF ví dụ và kết quả render để xem phần nào được biểu diễn theo cách nào

    • Tôi nghĩ nếu dùng PDF.js của Mozilla để render PDF thành DOM thì có thể có được trải nghiệm gần giống vậy. Ví dụ các toán tử như Tj hay TJ sẽ được chuyển thành các <span> hoặc tập hợp của chúng. Có lẽ là vì cần bám sát tài liệu gốc

    • Tôi khuyên bạn thử công cụ cpdf (do tôi tự làm). Với các tùy chọn -output-json-output-json-parse-content-streams của cpdf, bạn có thể chuyển PDF thành JSON để thử đủ thứ. Cũng có thể chuyển ngược từ JSON về PDF. Tuy nhiên nó không cung cấp tương tác thời gian thực

    • Có vẻ bạn đang tìm công cụ miễn phí hoặc mã nguồn mở, nhưng hồi trước khi tôi dùng Acrobat Pro thì nó từng cung cấp gần giống chức năng đó. Tuy nhiên nó theo kiểu duyệt cây nội dung hơn là inspect từng trang, và chỉ hiện tới mức object/stream chứ không xuống đến từng lệnh riêng lẻ

    • “Bọn tôi đang làm đúng kiểu kết hợp giữa ‘mô hình thị giác nhìn PDF như con người’ và ‘biết thực sự trong PDF có dữ liệu gì’ tại Tensorlake (tôi làm ở đó). Không chỉ đọc văn bản, mà còn thực sự hiểu bảng, ảnh, công thức, chữ viết tay, v.v. để có thể trích xuất dữ liệu sang markdown/JSON, rồi áp dụng cho các ứng dụng AI, LLM, v.v.” https://tensorlake.ai

    • Chưa hẳn đạt đúng mức bạn muốn, nhưng có một notebook cung cấp inspector hiển thị ‘live’ các phép toán vẽ khác nhau bên trong PDF, bạn có thể tham khảo https://observablehq.com/@player1537/pdf-utilities

  • Tôi đã tập trung vào vấn đề này nhiều năm ở Apple. Cốt lõi là chấp nhận rằng “mọi thứ đều là hình học”, và dùng thuật toán phân cụm để phân biệt khoảng cách giữa từ với khoảng cách giữa chữ cái. Nó hiệu quả với phần lớn PDF, nhưng nhìn kỹ thì biến thể quá đa dạng nên có những trường hợp khá thất vọng. Nếu làm lại bây giờ, tôi sẽ bỏ hẳn OCR, vẫn đi theo hướng dựa trên thông tin hình học nhưng kết hợp machine learning. Nếu tạo PDF từ văn bản đã biết trước rồi dùng cho machine learning thì còn có thể tự động hóa việc xây dựng dữ liệu huấn luyện. (Có video bài trình bày của Bertrand Serlet tại WWDC 2009)

  • Tôi không nghĩ đây là một bài toán duy nhất tên là ‘PDF to Text’, mà thực ra chia thành 3 nhóm: (1) OCR đáng tin cậy (cho tìm kiếm, nạp vào vector DB, v.v.), (2) trích xuất dữ liệu có cấu trúc (chỉ lấy ra các giá trị cụ thể), (3) tự động hóa toàn bộ pipeline tài liệu (ví dụ: tự động hóa thế chấp). Marginalia nhắm tới (1), và gần đây nhờ Gemini Flash các thứ mà OCR đã trở nên rẻ và phổ dụng hơn. Nhưng (2) và (3) khó hơn nhiều, và để tự động hóa hoàn toàn thì vẫn cần rất nhiều công sức của con người như xây dựng dataset, thiết kế pipeline, phát hiện bất định và can thiệp thủ công, fine-tuning, v.v. Tương lai nằm ở hướng này. (Tôi đang vận hành một công ty xử lý tài liệu bằng LLM) https://extend.ai

    • Tôi nghĩ còn cần cả (4): OCR và trích xuất ngữ nghĩa đáng tin cậy trên các loại tài liệu đa dạng, tức giải pháp cho trợ năng. Lý do việc này khó là vì khác với workflow thông thường, loại tài liệu của người dùng là không thể dự đoán; phải trích xuất cả các thành phần ngoài văn bản như bảng, header/footer/chú thích/công thức; yêu cầu giảm lỗi tối đa nên không thể dùng OCR quá mức cần thiết; văn bản nhúng và nội dung render có thể không khớp nhau (văn bản ẩn hoặc tổ hợp phi chuẩn, v.v.); chủ yếu chạy trong app cục bộ nên khó tận dụng server; còn cần hỗ trợ form cho các tài liệu dùng theo kiểu in đóng dấu. Hiện chưa có giải pháp nào giải quyết hoàn toàn tất cả các điểm này

    • Dù người ta nói đã đơn giản hóa pipeline OCR bằng VLM, tôi muốn cảnh báo rằng với tài liệu phức tạp thực tế thì cực kỳ khó. Nó rất giỏi ở nhãn ảnh đơn giản, và dùng được với tài liệu rất đơn giản, nhưng với tài liệu có bảng, header, phần tóm tắt được sắp xếp, v.v. thì bị hallucinate rất nặng. Vì vậy trên thực tế gần như không dùng được

    • Tôi đang gặp đủ kiểu vấn đề như phát hiện header trong lúc chuyển sang Markdown. OCR ngày nay rất tốt, nhưng giữ được cấu trúc tổng thể của tài liệu còn khó hơn nhiều. Tôi đang có kết quả tạm ổn bằng cách cho qua LLM nhiều lần để trích xuất cấu trúc, rồi đưa thêm ngữ cảnh theo từng trang

  • Giải pháp tốt hơn là đính kèm tài liệu nguồn có thể chỉnh sửa vào bên trong PDF. Làm việc này khá dễ bằng LibreOffice. Thông thường cũng không tốn thêm nhiều dung lượng, và có thể biết rõ ý nghĩa văn bản. Các trình đọc PDF hiện có cũng dùng bình thường không vấn đề gì

    • Khi vấn đề là trích xuất văn bản từ các PDF hiện có, tôi tự hỏi lời khuyên về cách tạo PDF thì thực sự giúp được gì đến đâu. Không biết bao giờ kiểu giải pháp này mới thật sự phát huy tác dụng rộng rãi

    • Đúng là vậy, nhưng nó tạo ra rủi ro là tài liệu nguồn và PDF đã render có thể hoàn toàn khác nội dung

    • Ý kiến đúng, nhưng chỉ có tác dụng khi lợi ích của người tạo PDF và người sử dụng PDF trùng nhau. Trong lĩnh vực e-Discovery, việc luật sư phía đối phương cố tình chuyển tài liệu sang PDF để khiến tài liệu khó sử dụng là chuyện rất phổ biến. Kết quả là các luật sư bào chữa công với ít nguồn lực hơn phải tốn nhiều thời gian xử lý tài liệu và chịu bất lợi thực chất. Để ngăn điều đó, tôi nghĩ nên luật hóa việc bắt buộc nộp các loại dữ liệu dưới định dạng máy có thể đọc theo chuẩn

    • Nếu có thể truy cập tài liệu nguồn thì việc đính kèm nó vào PDF là rất hay. Nhưng trong phần lớn trường hợp thì ta không có quyền kiểm soát đó

    • Phần lớn vấn đề thực sự nằm ở PDF legacy. Công ty tôi cũng có hàng nghìn cái chất đống, trong đó có những bản scan rất tệ. Một số có Adobe OCR nhúng sẵn nhưng đa số thì hoàn toàn không có

  • File PDF bên dưới thực ra là một file .txt. Chỉ cần đổi phần mở rộng sang .pdf là có thể mở bằng trình xem PDF, và cũng có thể sửa trực tiếp bằng trình soạn thảo văn bản để điều khiển nội dung hiển thị trên màn hình, font, cỡ font, giãn dòng, số ký tự mỗi trang, số dòng, khổ giấy cùng nhiều thứ khác. (Có kèm ví dụ PDF dạng văn bản tự viết)

    • PDF cũng có thể nhúng stream nhị phân. PDF không phải là văn bản, mà là định dạng được tạo ra cho layout và đồ họa. Như ví dụ thì mỗi dòng có thể xuất hiện một lần, nhưng thực tế nó có thể được biểu diễn theo từng ký tự, từng từ hoặc thậm chí không theo thứ tự nào cả

    • PDF là viết tắt của “Portable Document Format”. Nó được mã hóa dưới dạng tệp ASCII 7-bit nên có tính di động cao trên nhiều thiết bị và hệ điều hành khác nhau. (Tham khảo: liên kết tài liệu chính thức của Adobe)

    • Ví dụ này là kiểu ‘Hello World’ của PDF. PDF gần đây đa số nén các object bằng deflate, rồi nhóm các object đó vào bên trong stream nên phức tạp hơn nhiều. Vì thế việc chỉ tìm kiếm chuỗi văn bản như 6 0 Obj để phân tích trở nên rất khó

  • Trích xuất văn bản từ PDF, đặc biệt là văn bản có cấu trúc, tuyệt đối không hề dễ. Bảng trong HTML thì thường vẫn còn tương đối dễ lấy ra, còn PDF chỉ trông giống bảng nhờ các tọa độ render, trong khi thực chất văn bản và đồ họa nằm rải rác. Bản thân tôi cũng đang dùng cách chuyển PDF sang HTML bằng Poppler PDF utils, rồi tìm header của bảng, xác định cột dựa trên tọa độ x của từng giá trị và trích xuất dữ liệu theo từng hàng. Trông hơi thô, nhưng vẫn cho kết quả đáng tin hơn làm trên txt đã căn lề

    • Tôi bực vì không thể trích xuất dữ liệu từ PDF như dùng BeautifulSoup với trang web, nên đã tự làm một thư viện có kiểu giao diện như vậy. (Ví dụ dạng 'page.find') Từng PDF có vô số trường hợp địa ngục khác nhau, nên tôi đang gom các mẹo trích xuất cùng những ví dụ PDF quái dị thành thư viện https://jsoma.github.io/natural-pdf/ , https://badpdfs.com/

    • Một ngày nào đó tôi muốn trích xuất dữ liệu bảng từ PDF vào phần mềm xử lý dữ liệu của mình. Nếu ai biết thư viện miễn phí hoặc rất rẻ, có thể tích hợp vào ứng dụng C++, xin hãy chia sẻ

    • Có những tài liệu mà văn bản có thể in ra được và văn bản thực sự trích xuất được là hoàn toàn khác nhau, như kiểu tài liệu của cơ quan nhà nước. Những trường hợp như vậy xảy ra khá thường xuyên

    • PDF về bản chất là một định dạng markup/XML. Cùng một PDF nhưng có thể được tạo ra theo vô số cách khác nhau. Nếu xuất từ công cụ đồ họa thì sẽ ra PDF trộn giữa đồ họa và văn bản, còn xuất từ trình xử lý văn bản thì thường là PDF thiên về văn bản, tức kết quả rất đa chiều. Cách ứng dụng tạo tài liệu xử lý thông tin ảnh hưởng lớn đến cách PDF được xuất ra. Với các tiện ích off-the-shelf, nhiều dòng sản phẩm như cisdem cũng dùng được phần nào để lấy dữ liệu có cấu trúc. Nhưng tùy từng công việc mà cần công cụ phù hợp

  • Một trong những ví dụ tôi thích là file PDF của bài báo này (có đính kèm link). Trang đầu có đủ thứ: văn bản 2 cột điển hình, header ở giữa, văn bản chen vào khoảng giữa hai cột, các yếu tố làm thay đổi độ dài dòng và thụt đầu dòng. Header trang cũng khác nhau giữa trang chẵn và lẻ, quy tắc header của section cũng không đồng nhất. Đoạn văn cũng không phải lúc nào cũng thụt đầu dòng và khoảng cách dòng có biến động. Nó là một bộ sưu tập tổng hợp của nhiều loại vấn đề

    • API CoreGraphics của macOS cung cấp văn bản trong PDF theo từng trang, theo đúng thứ tự được encoding trong dictionary. Trong 95% trường hợp, cách này hoạt động khá tốt và PDFKit cùng Preview cũng không gặp vấn đề lớn trong nhiều năm. Văn bản 2 cột cũng thường được đưa vào PDF theo đúng thứ tự buffer của trình xử lý văn bản gốc nên luồng nội dung vẫn đúng. Chỉ có header/footer và các thứ tương tự thì mỗi ứng dụng nội bộ xử lý rất khác nhau nên không thể đoán trước
  • Khi tự viết một parser PDF đơn giản, tôi đã rất ngạc nhiên với cách định dạng này vận hành. Vì thế tôi luôn thấy lạ là vì sao nó lại được dùng nhiều cho các mục đích lấy văn bản. Ví dụ như hóa đơn, hệ thống số thì nên dễ trích xuất dữ liệu, còn con người thì nên nhận được cách trình bày đã được định dạng sẵn. Vì vậy tôi hy vọng giới công nghệ sẽ dần dần chuyển sang những định dạng tốt hơn

    • Ngày xưa XML+XSLT từng gần đạt được vai trò đó, nhưng tiếc là giờ các trình duyệt không còn hỗ trợ nữa cho file XML cục bộ. Chúng chỉ hỗ trợ XML qua server từ xa
  • Công việc của Tensorlake là trích xuất ‘thông tin hữu ích’ từ PDF (https://tensorlake.ai). PDF chứa không chỉ văn bản mà còn cả bảng, hình ảnh, công thức, chữ viết tay, gạch xóa, v.v., nên với tư cách nhà phát triển chúng ta không chỉ cần “đọc” văn bản mà còn phải “hiểu” được nó. (Xin nói rõ là tôi là nhân viên)