Apache Tika thực tế: Đọc PDF, Office và xây pipeline ingest cho RAG
Apache Tika giúp chuẩn hóa việc trích xuất text và metadata từ PDF, Word, Excel, PowerPoint trước khi chunking, embedding và lập chỉ mục. Playbook này đi từ chạy Docker, gọi API đến tách nhánh OCR và thiết kế ingest bất đồng bộ.
Một hệ thống RAG có thể đã có embedding model và vector database, nhưng vẫn trả lời kém nếu tài liệu đầu vào chưa được đọc đúng.
Hợp đồng là PDF, quy trình là DOCX, báo cáo nằm trong XLSX, slide ở PPTX; còn nhiều PDF scan thực chất chỉ là ảnh. Nếu tự duy trì parser riêng cho từng định dạng, pipeline ingest sẽ nhanh chóng phức tạp.
Trong các hệ thống quản lý tài liệu và RAG nội bộ, tôi dùng Apache Tika như một lớp dịch vụ trích xuất tài liệu: nhận file, phát hiện định dạng, trả về text và metadata cho các bước phía sau.
Apache Tika làm gì trong pipeline?
Apache Tika không phải vector database, OCR model hay RAG framework.
Vai trò cốt lõi của nó là:
text
File → phát hiện định dạng → parse → text + metadata
Tika có thể xử lý nhiều định dạng như PDF, DOC/DOCX, XLS/XLSX, PPT/PPTX, TXT, HTML, CSV, RTF, email và nhiều loại file khác.
Thay vì ứng dụng phải biết cách đọc từng định dạng, chỉ cần gửi file sang Tika:
text
┌─────────────┐
PDF ───────────►│ │
DOCX ──────────►│ Apache Tika │────► Text
XLSX ──────────►│ │────► Metadata
PPTX ──────────►│ │
└─────────────┘
Điểm có giá trị nhất là chuẩn hóa tầng ingest. Các service phía sau không còn phải quan tâm file gốc là PDF, Word hay PowerPoint.
Trong một pipeline RAG thực tế, Tika nằm ở bước Document Extraction:
text
Document
↓
Document Extraction
↓
Cleaning / Normalization
↓
Document Structure Analysis
↓
Chunking
↓
Embedding
↓
Index
Tika không tạo embedding, không chạy retrieval và không tham gia ở bước trả lời câu hỏi của người dùng.
Chạy Apache Tika bằng Docker
Tôi thường chạy Tika như một service riêng thay vì nhúng trực tiếp vào ứng dụng.
Ví dụ Docker Compose:
yaml
services:
tika:
image: apache/tika:latest-full
containername: tika
restart: unless-stopped
ports:
"9998:9998"
Khởi động container:
bash
docker compose up -d
Kiểm tra:
bash
docker ps
Sau đó có thể gọi Tika Server tại:
text
http://localhost:9998
Với môi trường production, tôi không expose cổng 9998 ra Internet. Backend và Tika nên nằm trong cùng Docker network để backend gọi service nội bộ:
text
Backend
│
│ HTTP
▼
http://tika:9998
Theo cách này, Tika chỉ làm nhiệm vụ service trích xuất tài liệu trong tầng ingest.
Test nhanh: gửi file và lấy text
Giả sử có file hopdong.pdf, có thể trích xuất text bằng:
bash
curl -T hopdong.pdf \
http://localhost:9998/tika \
-H "Accept: text/plain"
Hoặc dùng PUT với nội dung nhị phân:
bash
curl -X PUT \
--data-binary @hopdong.pdf \
-H "Accept: text/plain" \
http://localhost:9998/tika
Tika sẽ trả về phần text đã đọc được, ví dụ:
text
CÔNG TY ABC
HỢP ĐỒNG DỊCH VỤ
Điều 1. Phạm vi dịch vụ
Bên A đồng ý sử dụng...
Cách gọi gần như không đổi với các định dạng Office:
bash
curl -T quytrinh.docx \
http://localhost:9998/tika \
-H "Accept: text/plain"
bash
curl -T baocao.xlsx \
http://localhost:9998/tika \
-H "Accept: text/plain"
bash
curl -T presentation.pptx \
http://localhost:9998/tika \
-H "Accept: text/plain"
Đây là lợi ích vận hành rõ ràng: API gần như thống nhất, dù tài liệu gốc là Word, Excel hay PowerPoint.
Lấy metadata để truy vết tài liệu
Ngoài text, metadata cũng hữu ích cho RAG và hệ thống quản lý tài liệu.
Ví dụ gọi endpoint /meta:
bash
curl -T hopdong.pdf \
http://localhost:9998/meta \
-H "Accept: application/json"
Kết quả có thể gồm content type, kích thước, phiên bản PDF, công cụ tạo file, tác giả hoặc thời điểm tạo:
json
{
"Content-Type": "application/pdf",
"Content-Length": "...",
"pdf:PDFVersion": "1.7",
"xmp:CreatorTool": "...",
"dc:creator": "...",
"dcterms:created": "..."
}
Khi ingest, có thể chuẩn hóa record theo dạng:
json
{
"documentid": "DOC-000123",
"filename": "quydinh2026.pdf",
"contenttype": "application/pdf",
"text": "...",
"metadata": {
"author": "...",
"created": "...",
"source": "internal"
}
}
Sau đó mới thực hiện chunking và embedding.
PDF có text layer khác PDF scan
Không phải PDF nào cũng được xử lý giống nhau.
PDF có text layer
Đây thường là file được export trực tiếp từ Word hoặc ứng dụng văn phòng:
text
Word
↓
Export PDF
↓
PDF có text
Tika thường đọc loại này tốt và nhanh:
text
PDF
↓
Tika
↓
Text
Không cần OCR.
PDF scan
Với tài liệu giấy được scan, PDF có thể chỉ chứa ảnh theo từng trang:
text
Giấy
↓
Scanner
↓
PDF chứa ảnh
Người dùng vẫn nhìn thấy chữ, nhưng parser có thể chỉ nhận được rất ít text hoặc gần như rỗng:
text
Page 1 → Image
Page 2 → Image
Page 3 → Image
Đây là lúc cần cân nhắc OCR.
Tika và Tesseract OCR
Bản Docker full phù hợp khi pipeline cần thêm khả năng OCR.
Có thể thử với PDF scan:
bash
curl -X PUT \
--data-binary @scan.pdf \
-H "Accept: text/plain" \
http://localhost:9998/tika
Tùy cấu hình parser và OCR của Tika Server, Tika có thể phối hợp với Tesseract để đọc nội dung ảnh.
Về logic, luồng xử lý là:
text
PDF Scan
↓
Tika
↓
Image
↓
Tesseract
↓
Text
Cách này tiện khi yêu cầu OCR không quá cao. Tuy nhiên, tôi không xem Tika là giải pháp OCR cuối cùng cho mọi loại tài liệu.
Với scan chất lượng thấp, bảng biểu phức tạp, chữ viết tay hoặc tài liệu tiếng Việt khó, chất lượng OCR có thể không đạt kỳ vọng. Khi đó, nên tách pipeline:
text
┌── Text PDF ──► Tika
│
Document ─► Detect ─┤
│
└── Scan PDF ──► OCR Engine
OCR engine có thể là PaddleOCR, Gemma vision model, Mistral OCR, Google Cloud OCR hoặc một model OCR chuyên dụng, tùy yêu cầu triển khai.
Điểm quan trọng: không nên mặc định cho mọi tài liệu chạy OCR. OCR PDF scan nhiều trang có thể tốn tài nguyên hơn đáng kể so với trích xuất text trực tiếp từ PDF có text layer.
Một điều kiện minh họa là kiểm tra lượng text trả về:
text
if len(text.strip()) < threshold:
sendtoocr()
Trong production, nên kết hợp thêm tín hiệu khác thay vì chỉ dựa vào độ dài text.