0

Thiết kế pipeline dịch PDF bằng AI: Từ OCR đến khôi phục bố cục

Dịch một đoạn văn bằng AI tương đối đơn giản: gửi nội dung đến mô hình, nhận kết quả và hiển thị lại cho người dùng.

Dịch một tệp PDF hoàn chỉnh lại là một bài toán khác.

PDF có thể chứa văn bản nhiều cột, bảng dữ liệu, công thức toán học, hình ảnh, chú thích, header, footer, font nhúng và các trang được scan dưới dạng ảnh. Nếu chỉ trích xuất toàn bộ văn bản rồi gửi đến mô hình dịch, kết quả thường mất thứ tự đọc và không thể đặt chính xác trở lại tài liệu.

Một hệ thống dịch PDF đáng tin cậy cần xử lý đồng thời ba vấn đề:

  1. Hiểu cấu trúc của tài liệu.
  2. Dịch nội dung mà không phá hỏng dữ liệu đặc biệt.
  3. Tái tạo PDF với bố cục dễ đọc.

Bài viết này phân tích cách thiết kế một pipeline dịch PDF bằng AI, từ lúc người dùng tải tệp lên đến khi hệ thống xuất bản PDF đã dịch.


1. Vì sao PDF khó xử lý hơn văn bản thuần?

PDF là định dạng trình bày cố định. Nó mô tả vị trí của từng thành phần trên trang thay vì lưu nội dung theo cấu trúc tuyến tính như HTML.

Một trang PDF có thể chứa:

  • Đoạn văn ở nhiều cột
  • Text box đặt tại tọa độ tuyệt đối
  • Bảng được tạo từ nhiều khối văn bản rời rạc
  • Hình ảnh và caption
  • Công thức toán học
  • Header và footer lặp lại
  • Font nhúng
  • Văn bản xoay hoặc viết dọc
  • Trang scan không có text layer

Khi sử dụng thư viện PDF thông thường để extract text, kết quả có thể giống như sau:

Title
Left column paragraph 1
Right column paragraph 1
Left column paragraph 2
Table heading
Footer
Right column paragraph 2

Thứ tự này không phản ánh cách con người đọc tài liệu.

Vì vậy, pipeline không nên bắt đầu bằng câu hỏi:

Làm thế nào để lấy toàn bộ text khỏi PDF?

Câu hỏi đúng hơn là:

Làm thế nào để xác định từng khối nội dung, vai trò của chúng và thứ tự đọc trên mỗi trang?


2. Kiến trúc tổng thể

Một pipeline cơ bản có thể được chia thành các bước sau:

Upload PDF
    ↓
Validate file
    ↓
Parse pages
    ↓
Detect digital text or scanned pages
    ↓
OCR when required
    ↓
Layout analysis
    ↓
Reading-order reconstruction
    ↓
Content classification
    ↓
Translation
    ↓
Text fitting and font selection
    ↓
PDF reconstruction
    ↓
Quality checks
    ↓
Download translated PDF

Không nhất thiết mọi tài liệu đều đi qua toàn bộ các bước.

PDF có text layer tốt có thể bỏ qua OCR. Một tài liệu chỉ có đoạn văn đơn giản có thể không cần phân tích bảng phức tạp. Tuy nhiên, hệ thống vẫn nên chuẩn bị cho các trường hợp hỗn hợp.

Một PDF có thể chứa 20 trang kỹ thuật số và 5 trang scan ở phần phụ lục. Do đó, quyết định sử dụng OCR nên được thực hiện theo từng trang, không chỉ theo toàn bộ tệp.


3. Bước đầu tiên: kiểm tra và chuẩn hóa tệp

Trước khi xử lý nội dung, hệ thống nên kiểm tra:

  • Định dạng tệp có thực sự là PDF hay không
  • Tệp có bị hỏng không
  • PDF có được mã hóa hoặc đặt mật khẩu không
  • Số trang
  • Kích thước tệp
  • Kích thước từng trang
  • Trang có bị xoay không
  • Có font nhúng hay không
  • Có text layer hay chỉ chứa ảnh

Ngoài ra cần áp dụng giới hạn tài nguyên.

Ví dụ:

Maximum file size: 100 MB
Maximum pages per task: 500
Maximum page dimensions: 20,000 × 20,000 px
Task timeout: 30 minutes

Các giới hạn này giúp tránh một tệp bất thường chiếm toàn bộ RAM, CPU hoặc GPU của worker.

Tệp gốc nên được lưu trong object storage, còn database chỉ lưu metadata và trạng thái task.

Một record đơn giản có thể gồm:

{
  "task_id": "tr_01JXYZ",
  "status": "uploaded",
  "source_language": "de",
  "target_language": "en",
  "page_count": 84,
  "source_file_key": "uploads/tr_01JXYZ/source.pdf"
}

4. Phân biệt text PDF và scanned PDF

Không thể chỉ dựa vào việc PDF có chứa một vài ký tự để kết luận rằng toàn bộ trang là text-based.

Một trang có thể chứa:

  • Ảnh scan chiếm toàn bộ trang
  • Một text layer OCR chất lượng thấp nằm phía sau ảnh
  • Header kỹ thuật số nhưng nội dung chính là ảnh
  • Text layer bị lỗi hoặc không khớp với hình ảnh

Có thể sử dụng một số tín hiệu để đánh giá:

  • Số lượng ký tự extract được
  • Diện tích bounding box của text
  • Tỷ lệ diện tích ảnh trên trang
  • Mật độ ký tự
  • Mức độ trùng khớp giữa text layer và hình ảnh
  • Font và encoding có hợp lệ không

Ví dụ về logic đơn giản:

if extracted_characters < threshold:
    use_ocr = True
elif image_coverage > 0.85 and text_coverage < 0.10:
    use_ocr = True
else:
    use_ocr = False

Trong hệ thống thực tế, quyết định này nên dựa trên nhiều tín hiệu hơn và được thực hiện cho từng trang.


5. OCR không chỉ cần nhận dạng ký tự

OCR truyền thống thường trả về text và bounding box:

{
  "text": "Safety instructions",
  "x": 120,
  "y": 84,
  "width": 360,
  "height": 42,
  "confidence": 0.97
}

Đối với dịch PDF, kết quả này chưa đủ.

Hệ thống còn cần biết:

  • Đây là tiêu đề hay đoạn văn?
  • Nó thuộc cột nào?
  • Nó có nằm trong bảng không?
  • Nó có phải caption của hình ảnh không?
  • Các dòng nào thuộc cùng một đoạn?
  • Khối nào nên đọc trước?
  • Nội dung có bị xoay không?
  • Ngôn ngữ của khối là gì?

OCR nên được kết hợp với document layout analysis.

Một output tốt hơn có thể là:

{
  "page": 3,
  "type": "paragraph",
  "reading_order": 7,
  "language": "de",
  "bbox": [120, 210, 620, 410],
  "lines": [
    {
      "text": "Vor der Installation...",
      "bbox": [120, 210, 610, 246]
    }
  ]
}

Confidence thấp cũng nên được giữ lại để hệ thống ưu tiên kiểm tra sau khi dịch.


6. Phân tích layout và xác định thứ tự đọc

Layout analysis là phần quan trọng nhất của pipeline.

Hệ thống cần phân loại các vùng trên trang thành:

  • Title
  • Heading
  • Paragraph
  • List
  • Table
  • Figure
  • Caption
  • Formula
  • Header
  • Footer
  • Footnote
  • Page number

Sau đó, các vùng phải được sắp xếp theo reading order.

Với trang một cột, thứ tự từ trên xuống thường đủ. Với trang hai cột, cần xác định ranh giới cột trước khi sắp xếp.

Một chiến lược cơ bản:

  1. Loại bỏ header, footer và page number khỏi luồng chính.
  2. Nhóm các block theo cột.
  3. Sắp xếp block trong từng cột theo tọa độ Y.
  4. Ghép các cột theo hướng đọc của ngôn ngữ.
  5. Gắn caption với figure gần nhất.
  6. Gắn footnote với marker tương ứng.
  7. Giữ bảng như một đơn vị có cấu trúc.

Đối với ngôn ngữ viết từ phải sang trái, logic cột cũng cần đảo chiều.

Không nên gửi từng dòng OCR riêng biệt đến mô hình dịch. Các dòng thuộc cùng một đoạn cần được ghép lại để mô hình có đủ ngữ cảnh.


7. Biểu diễn trung gian của tài liệu

Thay vì xử lý trực tiếp trên PDF ở mọi bước, nên chuyển tài liệu thành một biểu diễn trung gian.

Ví dụ:

{
  "document_id": "doc_123",
  "pages": [
    {
      "page_number": 1,
      "width": 595,
      "height": 842,
      "blocks": [
        {
          "id": "b1",
          "type": "heading",
          "text": "Installation Guide",
          "bbox": [70, 80, 520, 130],
          "style": {
            "font_size": 22,
            "font_weight": 700
          }
        }
      ]
    }
  ]
}

Biểu diễn trung gian giúp:

  • Retry từng bước mà không parse lại toàn bộ PDF
  • Thay đổi translation engine
  • So sánh text gốc và bản dịch
  • Hỗ trợ bilingual output
  • Debug lỗi layout
  • Lưu confidence từ OCR
  • Chạy quality checks
  • Tái tạo nhiều định dạng đầu ra

Nó cũng giúp tách pipeline thành các worker độc lập.


8. Phân đoạn nội dung trước khi dịch

Nếu gửi toàn bộ tài liệu dài vào một request, hệ thống sẽ gặp giới hạn token và khó retry khi lỗi.

Nếu chia quá nhỏ, bản dịch mất ngữ cảnh.

Một chunk tốt nên:

  • Không cắt giữa câu
  • Không tách heading khỏi đoạn liên quan
  • Giữ các item trong cùng một list
  • Giữ nội dung của một table cell
  • Mang theo glossary và context
  • Không vượt giới hạn token của model

Có thể nhóm theo section:

Heading
Paragraph 1
Paragraph 2
List
Caption

Mỗi request nên chứa:

  • Loại tài liệu
  • Ngôn ngữ nguồn và đích
  • Nội dung chunk
  • Heading của section
  • Glossary
  • Các quy tắc bảo vệ
  • Một phần context trước và sau

Ví dụ:

{
  "document_type": "technical_manual",
  "source_language": "German",
  "target_language": "English",
  "section_title": "Electrical Installation",
  "protected_terms": [
    "AX-500",
    "RESET_MODE",
    "IEC 60204-1"
  ],
  "content": [
    {
      "id": "b43",
      "type": "paragraph",
      "text": "..."
    }
  ]
}

Model phải trả lại id tương ứng để kết quả có thể đặt đúng vào block ban đầu.


9. Bảo vệ nội dung không được dịch

Không phải mọi chuỗi ký tự đều nên được gửi đi như văn bản tự nhiên.

Cần bảo vệ:

  • URL
  • Email
  • Model number
  • Product code
  • File path
  • Source code
  • Equation
  • Variable
  • Citation number
  • Standard identifier
  • Placeholder

Có thể thay thế tạm thời bằng token:

Connect the {{PRODUCT_CODE_1}} device to {{PORT_2}}.

Sau khi dịch:

Kết nối thiết bị {{PRODUCT_CODE_1}} với {{PORT_2}}.

Cuối cùng restore:

Kết nối thiết bị AX-500 với COM3.

Token phải đủ đặc biệt để model không tự ý sửa.

Cũng nên validate rằng mọi placeholder đầu vào đều xuất hiện trong đầu ra. Nếu thiếu, request cần được retry hoặc đưa vào hàng đợi kiểm tra.


10. Quản lý thuật ngữ nhất quán

Trong tài liệu dài, cùng một thuật ngữ có thể xuất hiện hàng trăm lần.

Nếu dịch từng chunk độc lập, model có thể sử dụng nhiều cách dịch khác nhau.

Một glossary có thể được biểu diễn như sau:

{
  "control unit": "bộ điều khiển",
  "safety valve": "van an toàn",
  "maintenance interval": "chu kỳ bảo trì"
}

Có ba cách áp dụng glossary:

Cách 1: Đưa glossary vào prompt

Dễ triển khai nhưng model có thể không tuân thủ hoàn toàn.

Cách 2: Thay thế thuật ngữ bằng placeholder

Chặt chẽ hơn nhưng khó xử lý biến thể ngữ pháp.

Cách 3: Kiểm tra sau dịch

Tìm các thuật ngữ không nhất quán và sửa bằng rule hoặc một model thứ hai.

Trong hệ thống thực tế, có thể kết hợp cả ba.

Glossary nên được lưu ở cấp:

  • Người dùng
  • Workspace
  • Project
  • Document

Project glossary hữu ích khi một nhóm thường xuyên dịch tài liệu cùng ngành.


11. Dịch bảng như dữ liệu có cấu trúc

Không nên flatten toàn bộ bảng thành một đoạn text.

Một bảng nên được biểu diễn theo hàng và cột:

{
  "type": "table",
  "rows": [
    ["Model", "Voltage", "Maximum pressure"],
    ["AX-100", "220 V", "10 bar"],
    ["AX-200", "380 V", "16 bar"]
  ]
}

Chỉ các cell có nội dung ngôn ngữ mới cần dịch.

Các giá trị sau thường nên giữ nguyên:

  • Số
  • Đơn vị
  • Mã sản phẩm
  • Công thức
  • Ký hiệu
  • URL

Sau khi dịch, cần kiểm tra:

  • Số hàng và cột không thay đổi
  • Không mất cell
  • Không di chuyển giá trị
  • Header vẫn thuộc đúng cột
  • Colspan và rowspan được giữ lại
  • Dữ liệu số không bị thay đổi

Table rendering là một vấn đề riêng vì bản dịch thường dài hơn bản gốc.

Có thể cần:

  • Giảm font size trong giới hạn
  • Tăng chiều cao hàng
  • Điều chỉnh chiều rộng cột
  • Cho phép wrap text
  • Chuyển bảng sang trang mới

12. Công thức và ký hiệu khoa học

Công thức nên được phát hiện và loại khỏi luồng dịch thông thường.

Có thể nhận diện bằng:

  • Font đặc biệt
  • Mật độ ký hiệu
  • Superscript và subscript
  • Math operators
  • LaTeX hoặc MathML nếu có
  • Vùng hình ảnh chứa công thức

Ví dụ:

E = mc²

không cần dịch, nhưng caption hoặc phần giải thích xung quanh thì có.

Sau khi tái tạo, cần kiểm tra:

  • Dấu trừ
  • Số mũ
  • Chỉ số dưới
  • Dấu ngoặc
  • Phân số
  • Ký tự Hy Lạp
  • Số thứ tự phương trình

Một dấu trừ bị mất có thể nghiêm trọng hơn một đoạn văn dịch chưa tự nhiên.


13. Tái tạo layout sau khi dịch

Đây là giai đoạn khó vì độ dài văn bản thay đổi theo ngôn ngữ.

Một câu tiếng Anh ngắn có thể dài hơn nhiều khi dịch sang tiếng Đức. Một đoạn tiếng Trung có thể cần font và spacing khác hoàn toàn.

Có thể áp dụng thứ tự điều chỉnh:

  1. Giữ nguyên kích thước font nếu text vẫn vừa.
  2. Wrap text trong bounding box.
  3. Tăng chiều cao block nếu còn khoảng trống.
  4. Di chuyển các block phía dưới.
  5. Giảm font size trong giới hạn cho phép.
  6. Tạo thêm trang nếu không thể fit.
  7. Đánh dấu block cần review nếu vẫn overflow.

Không nên giảm font vô hạn chỉ để giữ nguyên một trang.

Một tài liệu có bố cục giống hệt nhưng chữ quá nhỏ không phải là kết quả tốt.

Một PDF translator hướng đến trải nghiệm người dùng cuối cần cân bằng giữa độ trung thực của layout và khả năng đọc thực tế.


14. Lựa chọn font cho ngôn ngữ đích

Font gốc có thể không chứa glyph cho ngôn ngữ mới.

Ví dụ, font Latin không nhất thiết hỗ trợ:

  • Tiếng Việt đầy đủ dấu
  • Tiếng Nhật
  • Tiếng Hàn
  • Tiếng Trung
  • Tiếng Ả Rập
  • Tiếng Thái

Pipeline nên có font fallback theo script.

Ví dụ:

Latin → font gốc hoặc Noto Sans
CJK → Noto Sans CJK
Arabic → Noto Sans Arabic
Thai → Noto Sans Thai

Cần chú ý:

  • Font embedding
  • License của font
  • Font weight
  • Italic
  • Line height
  • Right-to-left shaping
  • Ligature
  • Vertical writing

Nếu font thay đổi, kích thước text cũng thay đổi và ảnh hưởng đến layout fitting.


15. Bản dịch một ngôn ngữ và bản song ngữ

Hệ thống nên lưu text gốc và text dịch riêng biệt để có thể tạo nhiều output.

Translated-only PDF

Phù hợp cho:

  • Đọc cuối cùng
  • Phân phối cho khách hàng
  • In ấn
  • Trình bày

Bilingual PDF

Phù hợp cho:

  • Proofreading
  • Kiểm tra thuật ngữ
  • So sánh số liệu
  • Review hợp đồng
  • Học tập
  • Duyệt nội bộ

Bản song ngữ có thể được trình bày:

  • Hai cột
  • Trang gốc và trang dịch xen kẽ
  • Original block phía trên, translation phía dưới
  • Hai tệp đồng bộ theo page number

Việc lựa chọn phụ thuộc vào cấu trúc tài liệu và kích thước màn hình.

Một hướng dẫn về PDF translation bằng AI có thể giúp người dùng hiểu sự khác biệt giữa OCR, layout analysis, translation engine và các định dạng đầu ra trước khi xử lý tài liệu phức tạp.


16. Thiết kế worker và hàng đợi

Dịch PDF là tác vụ dài, không phù hợp với một HTTP request đồng bộ.

Kiến trúc nên sử dụng task queue:

API Server
    ↓
Task Queue
    ↓
Parser Worker
    ↓
OCR Worker
    ↓
Translation Worker
    ↓
Rendering Worker
    ↓
QA Worker

Mỗi bước cập nhật trạng thái:

uploaded
parsing
running_ocr
analyzing_layout
translating
rendering
validating
completed
failed

Lợi ích:

  • Retry từng bước
  • Scale worker độc lập
  • Giới hạn concurrency
  • Theo dõi tiến độ
  • Xử lý timeout
  • Tránh mất toàn bộ task khi một worker lỗi

OCR có thể cần GPU hoặc CPU mạnh, trong khi translation worker chủ yếu gọi API. Hai loại worker nên scale riêng.


17. Cache và tránh dịch lại

Chi phí có thể giảm đáng kể nếu cache theo nội dung block.

Một cache key có thể gồm:

hash(
  source_text
  + source_language
  + target_language
  + glossary_version
  + prompt_version
  + translation_engine
)

Nếu cùng một đoạn xuất hiện ở nhiều trang hoặc nhiều phiên bản tài liệu, hệ thống có thể tái sử dụng kết quả.

Tuy nhiên, cần cẩn thận vì cùng một câu có thể cần bản dịch khác khi context thay đổi.

Có thể cache ở hai cấp:

  • Exact cache cho chuỗi và context giống nhau
  • Translation memory cho người dùng lựa chọn lại kết quả trước đó

18. Quality assurance tự động

Không thể đánh giá chất lượng chỉ bằng việc API trả về trạng thái thành công.

Các kiểm tra tự động nên bao gồm:

Kiểm tra cấu trúc

  • Số trang hợp lệ
  • Mọi block đều có translation hoặc được đánh dấu không cần dịch
  • Không mất table cell
  • Không mất hình ảnh
  • Reading order không rỗng

Kiểm tra nội dung

  • Số không bị thay đổi
  • Placeholder được restore đầy đủ
  • URL và email còn nguyên
  • Product code không bị sửa
  • Không xuất hiện đoạn dịch trống bất thường

Kiểm tra layout

  • Không có text overflow lớn
  • Không có block nằm ngoài trang
  • Không chồng lấn nghiêm trọng
  • Font hỗ trợ đầy đủ glyph
  • Table không vượt quá page width

Kiểm tra ngôn ngữ

  • Output chủ yếu thuộc ngôn ngữ đích
  • Không còn nhiều đoạn ngôn ngữ nguồn ngoài các vùng được bảo vệ
  • Thuật ngữ quan trọng nhất quán

Mỗi trang có thể nhận một QA score. Các trang có điểm thấp được đưa vào danh sách cần review.


19. Các lỗi thường gặp

Chỉ extract text rồi dịch

Kết quả mất bảng, hình ảnh, thứ tự đọc và vị trí nội dung.

OCR toàn bộ mọi PDF

Tốn tài nguyên và có thể làm kết quả tệ hơn so với text layer gốc.

Dịch từng dòng riêng lẻ

Model thiếu context và tạo câu rời rạc.

Không bảo vệ mã và số

Product code, số liệu hoặc công thức có thể bị thay đổi.

Cố giữ đúng số trang bằng mọi giá

Text bị thu nhỏ đến mức khó đọc.

Không version glossary và prompt

Cache trả lại kết quả cũ dù quy tắc dịch đã thay đổi.

Không có intermediate representation

Khó retry, debug, tạo bản song ngữ hoặc đổi translation engine.

Chỉ kiểm tra ngôn ngữ

Bản dịch có thể đúng nhưng bảng, caption hoặc cảnh báo nằm sai vị trí.


20. Một MVP nên bắt đầu từ đâu?

Không nên cố giải quyết mọi loại PDF ngay trong phiên bản đầu tiên.

Một MVP thực tế có thể giới hạn:

  • PDF có text layer
  • Một hoặc hai cột
  • Không hỗ trợ form tương tác
  • Table đơn giản
  • Một số ngôn ngữ phổ biến
  • Output translated-only
  • Giới hạn số trang
  • Manual review cho trang lỗi

Sau đó mở rộng theo thứ tự:

  1. Scanned PDF và OCR
  2. Bilingual output
  3. Table phức tạp
  4. Formula protection
  5. Glossary
  6. Custom translation instructions
  7. Right-to-left languages
  8. Vertical text
  9. Human-in-the-loop editor

Điều quan trọng là đo tỷ lệ tài liệu xử lý tốt trong phạm vi đã định nghĩa, thay vì tuyên bố hỗ trợ mọi PDF nhưng tạo ra kết quả không ổn định.


Kết luận

Dịch PDF bằng AI là một bài toán document intelligence, không chỉ là một lời gọi đến translation API.

Một pipeline hoàn chỉnh cần:

  • Phân tích loại PDF
  • OCR theo từng trang
  • Hiểu layout
  • Khôi phục reading order
  • Phân đoạn nội dung hợp lý
  • Bảo vệ công thức, mã và số
  • Quản lý thuật ngữ
  • Dịch có ngữ cảnh
  • Tái tạo bố cục
  • Kiểm tra chất lượng tự động
  • Hỗ trợ review song ngữ

Chất lượng cuối cùng không chỉ được đánh giá bằng câu hỏi:

Bản dịch có đúng ngữ pháp không?

Mà còn phải trả lời:

Người dùng có thể đọc, kiểm tra và sử dụng tài liệu đã dịch như một PDF hoàn chỉnh hay không?

Khi xem đây là một pipeline xử lý tài liệu có cấu trúc, chúng ta có thể thiết kế hệ thống dễ mở rộng, dễ debug và đáng tin cậy hơn nhiều so với cách extract toàn bộ text rồi gửi thẳng đến mô hình.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí