OCR pipeline: chọn hải trình, không chọn cờ

OCR pipeline: chọn hải trình, không chọn cờ

Marker 2 thắng benchmark là tin vui. Nhưng với team build AI, câu hỏi đúng không phải “tool nào mạnh nhất”, mà là tài liệu nào đáng trả GPU.

“Tool mới ra, benchmark cao hơn, mình migrate luôn nhé?”

Nếu câu này vang lên trong Slack team bạn lúc 5 giờ chiều thứ Sáu, mình xin phép đặt nhẹ ly cà phê xuống. Không phải vì Marker 2 không đáng chú ý. Ngược lại, đây là một release khá đáng soi: full rewrite, hỗ trợ nhiều định dạng, có mode GPU lẫn CPU, và benchmark nhìn rất sáng.

Nhưng niềm tin phổ biến cần gỡ ở đây là: OCR pipeline tốt nhất là pipeline có điểm benchmark cao nhất.

Không hẳn. Với team đang xây RAG, search nội bộ, invoice automation, legal review hay knowledge base từ PDF, câu hỏi thực tế hơn là: tài liệu nào cần độ chính xác cao, tài liệu nào chỉ cần đủ sạch, và đoạn nào không nên OCR lại làm gì.

Nói thẳng ra thì: chọn OCR pipeline giống chọn hải trình, không phải chọn lá cờ trên tàu. Cờ đẹp không giúp bạn cập bến nếu gió ngược là chi phí GPU, latency và lỗi format lặt vặt.

Sơ đồ minh họa cho bài OCR pipeline: chọn hải trình, không chọn cờ

Sơ đồ tóm tắt ý chính của bài viết.

Cuộc tranh luận thật: chất lượng hay thông lượng?

Marker 2 của Datalab được viết lại quanh ba mảnh chính: Surya OCR 2, một layout model 20M parameters để đọc bố cục nhanh, và pdftext mới được nói là nhanh hơn bản trước 3 lần. Nó chuyển PDF, ảnh, PPTX, DOCX, XLSX, HTML, EPUB sang markdown, JSON, HTML hoặc chunks.

Điểm gây chú ý nằm ở benchmark olmOCR-bench từ Allen AI. Trong nguồn, Marker 2 ở balanced mode đạt 76.0% overall, 83.5% trên born-digital PDFs, và chạy 2.9 pages/second trên một B200 GPU. So với đó, MinerU pipeline backend được ghi nhận 72.7% ở 0.54 pages/second, còn Docling 50.3% ở 2.1 pages/second trên cùng harness.

Các số này đáng quan tâm. Nhưng nếu bạn bê nguyên kết luận “Marker 2 thắng, vậy đổi hết” vào production, bạn đang bỏ qua phần quan trọng nhất của release: Marker 2 không ép bạn đi một đường duy nhất.

Nó đưa ra ba hải trình khác nhau.

| Lựa chọn | Cách chạy | Điểm đáng dùng | Rủi ro chính |
|---|---|---|---|
| balanced | Surya VLM xử lý layout, OCR lại cả trang khi text nhúng kém | Chất lượng cao nhất, hợp tài liệu phức tạp | Cần GPU, phải quản concurrency |
| fast | Layout detector nhẹ + pdftext, chỉ dùng VLM khi cần | Rẻ hơn, hợp nhiều PDF bình thường | Có thể hụt case bố cục khó |
| --disable_ocr | Chỉ lấy text layer, không gọi VLM | CPU-only, rất nhanh: nguồn ghi 23.7 pg/s | Chất lượng thấp hơn: 43.6% trên benchmark |

VLM ở đây là vision-language model, model đọc cả hình ảnh lẫn chữ. Text layer là lớp chữ đã có sẵn trong PDF, kiểu bạn bôi đen copy được, không cần nhìn ảnh để đoán chữ.

Và đây mới là điểm builder nên giữ lại: release này không chỉ là “model OCR mạnh hơn”, mà là router cho tài liệu.

Biến số 1: tài liệu của bạn có đáng OCR lại không?

Nhiều team Việt Nam có một phản xạ hơi tốn tiền: cứ PDF là đẩy qua OCR. Invoice scan, hợp đồng ký tay, slide export, báo cáo ngân hàng, catalogue sản phẩm — tất cả vào chung một hàng đợi.

Hình dung thế này: bạn có 50.000 file PDF nội bộ. Trong đó, một phần lớn là born-digital PDF, tức được xuất trực tiếp từ Word, Google Docs, ERP hoặc hệ thống kế toán. Những file này thường đã có text layer. Nếu bạn OCR lại toàn bộ bằng VLM, giống như tàu đã có hải đồ mà bạn vẫn bắt thủy thủ leo lên cột buồm nhìn từng mét sóng.

Với Marker 2, --disable_ocr chạy CPU-only và không cần inference server. Inference server là service chuyên nhận request model và trả kết quả dự đoán. Nếu file có text layer ổn, mode này có thể đủ cho indexing, search hoặc chunking sơ bộ.

Nhưng nếu file là scan mờ, bảng bị vỡ, nhiều cột, header/footer lẫn vào nội dung, hoặc hợp đồng có dấu mộc và chữ ký, bạn cần balanced. Ở đó, Surya VLM xử lý layout và OCR lại khi text nhúng bị tệ.

Khung nghĩ mình đề xuất:

Đừng hỏi “mode nào tốt nhất?”. Hỏi: sai ở trang này thì hậu quả là gì?

Biến số 2: bottleneck của bạn nằm ở GPU hay điều phối?

Một chi tiết dễ bị lướt qua: Marker 2 có kiến trúc nhiều CPU workers mỏng cùng chia sẻ một Surya inference server. Parent process quản ngân sách VLM concurrency, tức số lượt model được phép chạy song song.

Đây là thay đổi đáng tiền hơn cả headline benchmark.

Vì trong production, OCR pipeline thường không chết vì thiếu model. Nó chết vì hàng đợi nghẽn: process nào cũng ôm VRAM, job retry lung tung, file lớn làm kẹt file nhỏ, GPU lúc thì rỗng lúc thì nghẹt.

Throughput là số trang xử lý được trong một đơn vị thời gian. Nguồn nói balanced mode đạt khoảng 2.9 pages/second nhờ nhiều worker dùng chung server, trong khi single-stream khoảng 0.3 pages/second trên cùng phần cứng. Con số cụ thể tùy máy và workload, nhưng bài học kiến trúc rất rõ: đừng nhân bản cả con tàu chỉ để chở thêm vài thùng hàng; hãy tách khoang chở hàng khỏi phòng máy.

Với builder, mình sẽ nhìn pipeline thành 4 lớp:

  1. Classifier: phân loại file trước khi xử lý.
  2. Extractor: chọn --disable_ocr, fast, hoặc balanced.
  3. Verifier: kiểm tra output có đủ sạch không.
  4. Escalator: đẩy trang lỗi sang mode đắt hơn.

Marker 2 đưa sẵn mode. Việc còn lại của team bạn là viết luật điều phối.

Khi nào chọn Marker 2, MinerU, Docling hoặc giữ nguyên?

Đây là phần dễ gây tranh cãi, nên mình nói theo quyết định vận hành chứ không theo fan club tool.

Chọn Marker 2 nếu bạn có workload lẫn lộn

Nếu corpus của bạn có đủ loại: PDF export, scan, slide, bảng, ảnh, ebook, HTML, thì Marker 2 đáng thử vì nó không khóa bạn vào một mode. Device-aware default cũng tiện: có GPU thì mặc định balanced, CPU/MPS thì fast, vẫn override được bằng --mode.

Nó hợp với team muốn xây pipeline phân tầng: rẻ trước, đắt sau, có đường nâng cấp chất lượng.

Chưa vội migrate nếu pipeline hiện tại đã ổn định

Nếu Docling hay MinerU trong hệ thống của bạn đang chạy ổn, lỗi đã biết, monitoring đã có, downstream chunker đã quen format output, thì benchmark mới chưa đủ để phá neo.

Đặc biệt, Marker 2 có breaking changes: Python 3.10+ là yêu cầu mới, packaging cũng thay đổi theo nguồn. Với production, “migrate OCR” không chỉ là đổi package. Bạn phải regression test lại layout, bảng, footnote, heading, chunk boundary và metadata.

Dùng CPU path nếu mục tiêu là lọc thô

Có những pipeline không cần output hoàn hảo ngay vòng đầu. Ví dụ cụ thể: team bạn muốn quét kho tài liệu nội bộ để tìm 2.000 file có nhắc đến một điều khoản cụ thể, rồi chỉ đưa file nghi vấn vào xử lý sâu. Lúc này --disable_ocr hoặc fast có thể là lớp sàng đầu.

Độ chính xác thấp hơn không phải lúc nào cũng là vấn đề, nếu nó nằm ở tầng rẻ và có bước kiểm tra sau.

Một buổi chiều để thử mà không tự lừa mình

Đừng benchmark bằng 10 file đẹp nhất trong máy bạn. Làm như vậy thì tool nào cũng thành hải đăng.

Trong một buổi chiều, bạn có thể thử theo khung này:

Bước 1: lấy 30 file đại diện

Chia thành 5 nhóm, mỗi nhóm 6 file:

Bước 2: chạy ba mode trên cùng tập

Ví dụ minh họa lệnh, bạn cần chỉnh theo setup thật:

marker_single input.pdf --output_dir out/balanced --mode balanced
marker_single input.pdf --output_dir out/fast --mode fast
marker_single input.pdf --output_dir out/text --disable_ocr

Nếu command thực tế thay đổi theo phiên bản package, ưu tiên tài liệu chính thức của project bạn đang cài. Ý ở đây là: so cùng file, cùng output expectation, khác mode.

Bước 3: chấm bằng lỗi downstream, không chỉ nhìn markdown đẹp

Tạo bảng review 5 cột:

| File | Mode | Mất heading? | Sai bảng? | Chunk dùng được cho RAG? |
|---|---|---|---|---|
| contract_01.pdf | fast | Không | Có | Không |
| report_02.pdf | disable_ocr | Không | Không | Có |

RAG là retrieval-augmented generation, tức cho model tìm tài liệu liên quan trước khi trả lời. Với RAG, markdown nhìn sạch chưa đủ; chunk sai bảng hoặc lẫn header lặp lại cũng làm câu trả lời lệch.

Bước 4: viết rule router bản đầu

Ví dụ:

def choose_marker_mode(doc):
    if doc.has_clean_text_layer and not doc.has_complex_tables:
        return "disable_ocr"
    if doc.is_born_digital and doc.page_count > 50:
        return "fast"
    if doc.is_scanned or doc.has_financial_tables or doc.is_legal:
        return "balanced"
    return "fast"

Đây không phải production code, chỉ là khung quyết định. Sau đó bạn thêm logging: mode nào được chọn, trang nào fail, output nào bị reviewer đánh dấu.

Điều nên nghĩ khác sau release này

Marker 2 đáng chú ý không chỉ vì nó thắng vài dòng benchmark. Điều đáng học là cách nó biến document conversion thành hệ thống nhiều cấp chi phí, thay vì một cục OCR duy nhất.

Các release gần đây cũng đi theo cùng một hướng: desktop agent nhấn mạnh deliverable thay vì chat, security plugin đưa scan vào terminal có bước duyệt patch, world model nhỏ hơn để chạy on-device, transcription model mở trọng số cho bài toán hẹp. Điểm chung không phải “AI to hơn”, mà là AI được đặt đúng chỗ trong workflow.

Nếu là mình, mình sẽ không migrate toàn bộ sang Marker 2 ngay. Mình sẽ chọn 30 file xấu nhất, chạy ba mode, rồi viết router. Nếu router chứng minh được file rẻ vẫn rẻ, file khó mới dùng GPU, lúc đó hãy tính chuyện kéo neo.

Chốt lại: benchmark là hải đăng, không phải bến cảng. Thấy sáng thì mừng, nhưng cập bến được hay không vẫn do bạn lái pipeline.

---
Bụi Wire — nghiện đọc release notes lúc 2 giờ sáng

Nguồn tham khảo