OCR không phải bước phụ trong RAG
Một playbook giúp tech lead quyết định khi nào dùng OCRmyPDF, khi nào bỏ qua, và cách thử pipeline tài liệu scan trong một buổi.
Bụi WireBạn đang build RAG cho hợp đồng, hồ sơ vận đơn, phiếu bảo hành, biên bản nghiệm thu. Team đã chọn model, đã dựng vector database, đã bàn tới reranking. Rồi tới lúc ingest PDF scan thì mọi thứ lặng đi như đứng ngay trên một đường đứt gãy: file mở được, mắt người đọc được, nhưng hệ thống thì chỉ thấy… ảnh.
Đây là chỗ nhiều team hiểu sai: OCR không phải “tiền xử lý lặt vặt”. Với tài liệu scan, OCR là quyết định kiến trúc. Làm qua loa thì RAG phía sau chỉ đang xây trên lớp trầm tích chữ bị vỡ, thiếu dấu, sai cột, mất trang.
Bài này không bàn “OCRmyPDF hay không” theo kiểu công cụ nào đang được nhắc nhiều. Mình muốn bạn có một khung quyết định rõ hơn: khi nào OCRmyPDF đủ tốt để đưa vào pipeline, khi nào cần engine khác, và thử trong một buổi ra sao để khỏi tự lừa mình bằng demo đẹp.

Sơ đồ tóm tắt ý chính của bài viết.
Mục tiêu: biến PDF scan thành tài sản có thể kiểm tra
OCRmyPDF là công cụ biến PDF dạng ảnh thành PDF có lớp text tìm kiếm được. Nó thường dùng Tesseract bên dưới, có thể xuất PDF/A — định dạng PDF phục vụ lưu trữ lâu dài — và tạo sidecar text, tức file .txt chứa phần chữ OCR tách riêng.
Điểm đáng quan tâm với builder không nằm ở câu “PDF giờ search được”. Điểm đáng quan tâm là bạn có thêm ba artifact để vận hành:
- PDF đầu ra: người dùng vẫn mở như tài liệu gốc.
- Text sidecar: pipeline RAG, search, classification hoặc extraction có thể ăn thẳng.
- Log/validation: team biết file nào OCR ổn, file nào cần xử lý lại.
Nói thẳng ra thì, nếu bạn chỉ upload PDF scan vào hệ thống rồi hy vọng model tự đọc ảnh tốt hơn, bạn đang chuyển rủi ro từ ingestion sang inference. Lúc đó lỗi không còn nằm ở một bước dễ kiểm tra, mà chảy như dung nham sang retrieval, prompt, evaluation và cả support ticket.
Checklist quyết định trước khi cài gì đó
Trước khi mở terminal, hỏi nhanh 5 câu này. Nếu trả lời không rõ, đừng vội chọn tool.
| Câu hỏi | Nếu câu trả lời là “có” | Quyết định nghiêng về |
|---|---|---|
| Tài liệu chủ yếu là PDF scan, không có text layer? | Có nhiều file ảnh hoặc bản scan cũ | OCRmyPDF đáng thử đầu tiên |
| Bạn cần lưu trữ chuẩn, không chỉ extract text? | Có yêu cầu archive, audit, pháp lý | Bật PDF/A |
| Pipeline phía sau cần text riêng? | RAG/search/classifier cần input sạch | Xuất sidecar text |
| File đã OCR sẵn lẫn file chưa OCR? | Có nguồn tài liệu hỗn tạp | Dùng chế độ skip hoặc redo có kiểm soát |
| Scan nhiễu, nghiêng, mờ, nhiều ngôn ngữ? | Có | Cần test kỹ Tesseract config, có thể cần engine khác |
Framework gọn: chọn OCRmyPDF khi bạn cần một pipeline tài liệu scan có thể chạy batch, kiểm tra được, và giữ PDF làm artifact chính. Bỏ qua hoặc thay bằng hướng khác nếu tài liệu là ảnh phức tạp, layout nhiều bảng khó, chữ viết tay, hoặc bạn cần OCR theo vùng với độ chính xác nghiệp vụ rất cao.
Ví dụ cụ thể: một team bảo hiểm ở Việt Nam có 3 loại file: hợp đồng scan, giấy tờ tùy thân, và ảnh chụp biên lai. OCRmyPDF có thể hợp lý cho hợp đồng scan nhiều trang. Nhưng với ảnh chụp biên lai méo góc, ánh sáng xấu, layout thay đổi liên tục, bạn nên tách thành pipeline xử lý ảnh riêng thay vì ép tất cả qua một cửa.
Một buổi thử: dựng pipeline tối thiểu nhưng không hời hợt
Mục tiêu của buổi thử không phải là “chạy được một file”. Mục tiêu là trả lời: đủ tin để đưa vào ingestion staging chưa?
Bước 1: tạo môi trường nhỏ, tránh cài lan man
Trên máy Linux hoặc container thử nghiệm, cài các dependency hệ thống thường gặp:
sudo apt-get update
sudo apt-get install -y \
tesseract-ocr \
ghostscript \
qpdf \
unpaper \
pngquant \
poppler-utils
python -m pip install --upgrade ocrmypdf img2pdf pillow
Nếu cần tiếng Việt, kiểm tra gói ngôn ngữ Tesseract trong môi trường của bạn. Tên package có thể khác theo distro, nên đừng hardcode vào production script trước khi xác minh trên image deploy thật.
tesseract --list-langs
ocrmypdf --version
Bước 2: chạy OCR cơ bản với sidecar
Dùng một file scan thật từ nghiệp vụ, không dùng file mẫu quá sạch.
mkdir -p out
ocrmypdf \
--sidecar out/sample.txt \
input_scan.pdf \
out/sample_ocr.pdf
Kiểm tra nhanh:
pdftotext out/sample_ocr.pdf - | head -n 40
head -n 40 out/sample.txt
ls -lh input_scan.pdf out/sample_ocr.pdf out/sample.txt
Ở đây pdftotext giúp bạn xác nhận PDF đầu ra thật sự có text layer. sidecar giúp bạn nhìn phần chữ mà pipeline sẽ dùng, thay vì chỉ mở PDF bằng mắt rồi tự thấy yên tâm.
Bước 3: bật PDF/A nếu tài liệu cần lưu trữ
PDF/A không phải lúc nào cũng cần. Nhưng nếu tài liệu có vòng đời dài, phải audit, hoặc được dùng như bản số hóa chính thức, hãy test sớm.
ocrmypdf \
--output-type pdfa \
--sidecar out/archive.txt \
input_scan.pdf \
out/archive_pdfa.pdf
Sau đó so kích thước file và mở bằng viewer thường dùng nội bộ. Đừng chỉ kiểm bằng một máy dev. Có những lỗi “nhỏ” như font, nén ảnh, metadata lại thành phiền to khi đi qua hệ thống DMS hoặc ký số.
Bước 4: xử lý file đã có text layer
Một bẫy phổ biến: tài liệu đầu vào không đồng nhất. Có file scan trắng tinh, có file đã OCR từ trước, có file vừa text vừa ảnh.
Bạn cần quyết định chính sách:
# Bỏ qua trang đã có text, giảm nguy cơ làm hỏng lớp text cũ
ocrmypdf --skip-text input_mixed.pdf out/skip_text.pdf
# OCR lại khi bạn không tin lớp text cũ, dùng cẩn thận
ocrmypdf --force-ocr input_old_ocr.pdf out/force_ocr.pdf
Đừng chọn --force-ocr vì “cho chắc”. Nó có thể làm chậm pipeline và thay đổi artifact nhiều hơn mức cần thiết. Với tài liệu pháp lý, thay đổi không kiểm soát là chấn tâm của nhiều vụ debug mệt mỏi.
Bước 5: chạy batch có log riêng
Đừng batch kiểu một lệnh nuốt hết thư mục rồi cầu may. Tối thiểu hãy ghi trạng thái từng file.
mkdir -p out text logs
for f in scans/*.pdf; do
base=$(basename "$f" .pdf)
echo "OCR $f"
ocrmypdf \
--skip-text \
--sidecar "text/${base}.txt" \
"$f" "out/${base}.pdf" \
> "logs/${base}.log" 2>&1 || echo "$f" >> logs/failed.txt
done
Sau batch, đếm file fail, mở vài log, và so text sidecar với kỳ vọng nghiệp vụ. Đừng chỉ nhìn exit code.
Bẫy dễ gặp: demo sạch không đại diện production
Có bốn kiểu tự lừa mình mình thấy khá thường xuyên.
Một là lấy PDF đẹp để test. File mẫu font rõ, trang thẳng, không dấu mộc, không scan lệch thì OCR nào cũng trông ổn. Hãy lấy 20–30 file xấu vừa đủ đại diện: bản fax, scan mờ, trang xoay, dấu đỏ, chữ nhỏ, bảng nhiều cột. Đây là ví dụ minh họa về cỡ mẫu thử nội bộ, không phải chuẩn thống kê.
Hai là chỉ đo “có text hay chưa”. Có text layer không có nghĩa text dùng được. Bạn cần kiểm tra vài trường quan trọng: số hợp đồng, ngày tháng, mã khách hàng, tổng tiền. Nếu các field này sai, retrieval phía sau sẽ trả lời tự tin trên nền dữ liệu lệch.
Ba là nhét OCR vào request path. OCR nhiều trang có thể chậm và tốn CPU. Với hệ thống production, hãy ưu tiên job bất đồng bộ: upload → queue → OCR → validate → index. Queue ở đây là hàng đợi xử lý, giúp request người dùng không phải đứng chờ toàn bộ tài liệu được đọc xong.
Bốn là quên versioning artifact. Khi đổi Tesseract language pack, bật cleaning, đổi DPI hint hoặc đổi chế độ nén, output có thể khác. Lưu lại cấu hình OCR theo batch để sau này biết vì sao cùng một file cho ra text khác.
Khi nào nên đổi quyết định?
OCRmyPDF là lựa chọn thực dụng nếu bạn cần đi từ “đống PDF scan” tới “PDF tìm kiếm được + text để index” nhanh, chạy local được, dễ batch, dễ gắn vào pipeline hiện có.
Nhưng hãy đổi hướng nếu gặp các dấu hiệu này:
- Tài liệu nhiều chữ viết tay hoặc form ảnh chụp ngoài hiện trường.
- Layout bảng phức tạp là phần giá trị chính, không chỉ text tuyến tính.
- Bạn cần trích xuất theo schema nghiêm ngặt ngay từ ảnh gốc.
- Độ chính xác tiếng Việt trong mẫu xấu không đạt ngưỡng nghiệp vụ sau khi đã chỉnh scan và language config.
- Chi phí vận hành CPU cho OCR batch vượt mức chấp nhận được.
Lúc đó, OCRmyPDF vẫn có thể là bước archive, còn extraction chính nên đi bằng OCR/layout model khác hoặc dịch vụ chuyên dụng. Quyết định đúng không phải là “dùng một tool cho mọi file”, mà là phân luồng tài liệu theo rủi ro.
Hình dung thế này: cùng là đá, nhưng đá lát đường, đá xây móng và đá quý không nên đi qua cùng một máy nghiền. Tài liệu cũng vậy. Hợp đồng scan 50 trang và ảnh biên lai chụp vội không nên bị ép vào cùng một pipeline chỉ vì đều là “PDF hoặc ảnh”.
Chốt lại cho tech lead
Sau bài này, điều mình muốn bạn đổi cách nghĩ là: OCR nằm ở lớp quyết định dữ liệu, không phải lớp tiện ích phụ trợ. Nếu bạn làm RAG trên tài liệu scan, hãy đánh giá OCR như một component production: có input class, output artifact, log, batch policy, retry, và tiêu chí đổi tool.
Nếu là mình, mình sẽ bắt đầu bằng OCRmyPDF cho luồng PDF scan nhiều trang, bật sidecar text, giữ log theo file, và chỉ đưa vào index sau khi qua một bước kiểm tra field quan trọng. Phần ảnh chụp, bảng dày, chữ viết tay thì tách nhánh từ đầu.
Đừng để tới lúc model trả lời sai mới đi tìm lỗi ở đáy núi lửa; nhiều khi dung nham đã trào từ bước OCR rồi.
---
Bụi Wire — nghiện đọc release notes lúc 2 giờ sáng
Nguồn tham khảo
- OCRmyPDF Tutorial: Convert Scanned Documents into Searchable PDF/A Files with Sidecar Text Extraction and Batch Processing - MarkTechPost
- How to Use NVIDIA Canary-1B-v2 for ASR, Translation, and Automatic SRT Subtitle Export in Python - MarkTechPost
- How to Build a Forecasting Pipeline with TimeCopilot Using Foundation Models and Automated Anomaly Detection - MarkTechPost
- Using Graphify and NetworkX to Map Python Codebase Structure with God Nodes, Communities, and Architecture Visualizations - MarkTechPost
- Building a Stable Fable 5 Traces Workflow in Colab: Parsing Tool Calls, Auditing Data, and Training Baselines - MarkTechPost