Docling: Document Parsing Cerdas untuk Pipeline AI dan RAG

# Docling: Document Parsing Cerdas untuk Pipeline AI dan RAG Dalam era AI generatif, kemampuan untuk mengekstrak informasi dari dokumen secara otomatis menjadi sangat krusial. Baik itu PDF laporan ta...

By Ruby Abdullah · · tutorial
DoclingDocument ParsingPDFRAGPython

Docling: Document Parsing Cerdas untuk Pipeline AI dan RAG

Dalam era AI generatif, kemampuan untuk mengekstrak informasi dari dokumen secara otomatis menjadi sangat krusial. Baik itu PDF laporan tahunan, presentasi PowerPoint, dokumen Word, atau halaman web HTML, kita membutuhkan alat yang mampu mengubah format-format tersebut menjadi data terstruktur yang siap dikonsumsi oleh model AI. Di sinilah Docling hadir sebagai solusi.

Docling adalah library open-source dari IBM Research yang dirancang untuk melakukan parsing dokumen secara cerdas. Library ini mendukung berbagai format input dan mampu menghasilkan output dalam format Markdown atau JSON yang bersih, siap untuk digunakan dalam pipeline AI, khususnya Retrieval-Augmented Generation (RAG).

Dalam tutorial ini, kita akan mempelajari cara menggunakan Docling mulai dari instalasi, konversi dokumen dasar, hingga membangun pipeline ingestion dokumen yang lengkap untuk RAG.

Prasyarat

Sebelum memulai, pastikan Anda memiliki:

  • Python 3.10 atau lebih baru
  • pip package manager
  • Pemahaman dasar tentang Python
  • (Opsional) GPU untuk OCR yang lebih cepat

Instalasi

Instalasi Docling cukup mudah menggunakan pip. Ada beberapa opsi instalasi tergantung kebutuhan Anda.

Instalasi Dasar

pip install docling

Instalasi dengan Dukungan OCR

pip install "docling[ocr]"

Instalasi Lengkap (Semua Fitur)

pip install "docling[all]"

Verifikasi Instalasi

import docling

print(f"Docling version: {docling.version}")

Format yang Didukung

Docling mendukung berbagai format dokumen sebagai input:

| Format | Ekstensi | Keterangan |

|--------|----------|------------|

| PDF | .pdf | Termasuk PDF dengan scan/gambar |

| Microsoft Word | .docx | Format Open XML |

| Microsoft PowerPoint | .pptx | Format Open XML |

| HTML | .html, .htm | Halaman web |

| Gambar | .png, .jpg, .tiff | Melalui OCR |

| AsciiDoc | .adoc | Format dokumentasi |

| Markdown | .md | Format markdown |

Konversi Dokumen Dasar

Mari mulai dengan konversi dokumen sederhana. Docling menyediakan API yang intuitif melalui class DocumentConverter.

Konversi PDF ke Markdown

from docling.documentconverter import DocumentConverter

Inisialisasi converter

converter = DocumentConverter()

Konversi dokumen PDF

result = converter.convert("laporantahunan.pdf")

Dapatkan output dalam format Markdown

markdownoutput = result.document.exporttomarkdown()

print(markdownoutput)

Konversi dari URL

Docling juga mendukung konversi langsung dari URL:

from docling.documentconverter import DocumentConverter

converter = DocumentConverter()

Konversi dari URL

result = converter.convert("https://example.com/dokumen.pdf")

markdownoutput = result.document.exporttomarkdown()

print(markdownoutput)

Konversi DOCX

from docling.documentconverter import DocumentConverter

converter = DocumentConverter()

result = converter.convert("proposalproyek.docx")

markdownoutput = result.document.exporttomarkdown()

Simpan ke file

with open("proposalproyek.md", "w", encoding="utf-8") as f:

f.write(markdownoutput)

print("Konversi selesai!")

Format Output

Docling mendukung beberapa format output yang dapat Anda pilih sesuai kebutuhan.

Export ke Markdown

from docling.documentconverter import DocumentConverter

converter = DocumentConverter()

result = converter.convert("dokumen.pdf")

Export ke Markdown

mdcontent = result.document.exporttomarkdown()

Simpan ke file

with open("output.md", "w", encoding="utf-8") as f:

f.write(mdcontent)

Export ke JSON (Document Format)

import json

from docling.documentconverter import DocumentConverter

converter = DocumentConverter()

result = converter.convert("dokumen.pdf")

Export ke dictionary/JSON

docdict = result.document.exporttodict()

Simpan ke file JSON

with open("output.json", "w", encoding="utf-8") as f:

json.dump(docdict, f, indent=2, ensureascii=False)

Export ke Teks Biasa

from docling.documentconverter import DocumentConverter

converter = DocumentConverter()

result = converter.convert("dokumen.pdf")

Export ke teks biasa

textcontent = result.document.exporttotext()

print(textcontent)

Ekstraksi Tabel

Salah satu fitur unggulan Docling adalah kemampuannya mengekstrak tabel dari dokumen dengan akurat.

from docling.documentconverter import DocumentConverter

converter = DocumentConverter()

result = converter.convert("laporankeuangan.pdf")

Iterasi semua tabel dalam dokumen

for tableix, table in enumerate(result.document.tables):

print(f"\n=== Tabel {tableix + 1} ===")

# Export tabel ke DataFrame pandas

df = table.exporttodataframe()

print(df)

# Simpan ke CSV

df.tocsv(f"tabel{tableix + 1}.csv", index=False)

print(f"Tabel {tableix + 1} disimpan ke CSV")

Konfigurasi Ekstraksi Tabel

from docling.documentconverter import DocumentConverter, PdfFormatOption

from docling.datamodel.pipelineoptions import PdfPipelineOptions

from docling.datamodel.basemodels import InputFormat

Konfigurasi pipeline untuk tabel

pipelineoptions = PdfPipelineOptions()

pipelineoptions.dotablestructure = True

pipelineoptions.tablestructureoptions.docellmatching = True

converter = DocumentConverter(

formatoptions={

InputFormat.PDF: PdfFormatOption(

pipelineoptions=pipelineoptions

)

}

)

result = converter.convert("dokumendengantabel.pdf")

for table in result.document.tables:

df = table.exporttodataframe()

print(df.tostring())

Ekstraksi Gambar

Docling dapat mengekstrak gambar yang terdapat dalam dokumen.

from docling.documentconverter import DocumentConverter, PdfFormatOption

from docling.datamodel.pipelineoptions import PdfPipelineOptions

from docling.datamodel.basemodels import InputFormat

from pathlib import Path

Aktifkan ekstraksi gambar

pipelineoptions = PdfPipelineOptions()

pipelineoptions.imagesscale = 2.0

pipelineoptions.generatepictureimages = True

converter = DocumentConverter(

formatoptions={

InputFormat.PDF: PdfFormatOption(

pipelineoptions=pipelineoptions

)

}

)

result = converter.convert("dokumenbergambar.pdf")

Simpan gambar yang diekstrak

outputdir = Path("extractedimages")

outputdir.mkdir(existok=True)

for idx, picture in enumerate(result.document.pictures):

if picture.image:

imagepath = outputdir / f"gambar{idx + 1}.png"

picture.image.pilimage.save(str(imagepath))

print(f"Gambar {idx + 1} disimpan ke {imagepath}")

Dukungan OCR

Untuk dokumen yang berupa scan atau gambar, Docling menyediakan dukungan OCR (Optical Character Recognition).

from docling.documentconverter import DocumentConverter, PdfFormatOption

from docling.datamodel.pipelineoptions import (

PdfPipelineOptions,

EasyOcrOptions,

TesseractOcrOptions,

)

from docling.datamodel.basemodels import InputFormat

Menggunakan EasyOCR

pipelineoptions = PdfPipelineOptions()

pipelineoptions.doocr = True

pipelineoptions.ocroptions = EasyOcrOptions(

lang=["id", "en"], # Bahasa Indonesia dan Inggris

forcefullpageocr=False,

)

converter = DocumentConverter(

formatoptions={

InputFormat.PDF: PdfFormatOption(

pipelineoptions=pipelineoptions

)

}

)

result = converter.convert("dokumenscan.pdf")

markdownoutput = result.document.exporttomarkdown()

print(markdownoutput)

Menggunakan Tesseract OCR

from docling.datamodel.pipelineoptions import TesseractOcrOptions

Konfigurasi Tesseract

pipelineoptions = PdfPipelineOptions()

pipelineoptions.doocr = True

pipelineoptions.ocroptions = TesseractOcrOptions(

lang=["ind", "eng"], # Kode bahasa Tesseract

)

converter = DocumentConverter(

formatoptions={

InputFormat.PDF: PdfFormatOption(

pipelineoptions=pipelineoptions

)

}

)

result = converter.convert("dokumenscan.pdf")

print(result.document.exporttomarkdown())

Chunking untuk RAG

Fitur chunking sangat penting untuk pipeline RAG. Docling menyediakan beberapa strategi chunking yang cerdas.

Hierarchical Chunking

from docling.documentconverter import DocumentConverter

from docling.chunking import HierarchicalChunker

converter = DocumentConverter()

result = converter.convert("dokumenpanjang.pdf")

Gunakan hierarchical chunker

chunker = HierarchicalChunker()

chunks = list(chunker.chunk(result.document))

for i, chunk in enumerate(chunks):

print(f"\n--- Chunk {i + 1} ---")

print(f"Text: {chunk.text[:200]}...")

print(f"Metadata: {chunk.meta}")

Hybrid Chunking

from docling.chunking import HybridChunker

from tokenizers import Tokenizer

Chunker dengan batasan token

chunker = HybridChunker(

tokenizer=Tokenizer.frompretrained("bert-base-uncased"),

maxtokens=512,

mergepeers=True,

)

converter = DocumentConverter()

result = converter.convert("dokumen.pdf")

chunks = list(chunker.chunk(result.document))

for i, chunk in enumerate(chunks):

print(f"Chunk {i + 1}: {len(chunk.text)} karakter")

print(f"Heading: {chunk.meta.headings}")

print(f"Text preview: {chunk.text[:150]}...")

print()

Batch Processing

Untuk memproses banyak dokumen sekaligus, Docling menyediakan fitur batch processing.

from docling.documentconverter import DocumentConverter

from pathlib import Path

converter = DocumentConverter()

Daftar dokumen yang akan diproses

inputfiles = [

"dokumen1.pdf",

"dokumen2.docx",

"dokumen3.pptx",

"https://example.com/dokumen4.html",

]

Batch convert

results = converter.convertall(inputfiles)

for result in results:

source = result.input.file

print(f"\nMemproses: {source}")

if result.status.value == "success":

md = result.document.exporttomarkdown()

outputfile = Path("output") / f"{Path(str(source)).stem}.md"

outputfile.parent.mkdir(existok=True)

with open(outputfile, "w", encoding="utf-8") as f:

f.write(md)

print(f" -> Berhasil disimpan ke {outputfile}")

else:

print(f" -> Gagal: {result.status}")

Batch Processing dengan Progress Tracking

from docling.documentconverter import DocumentConverter

from pathlib import Path

import time

converter = DocumentConverter()

inputdir = Path("dokumeninput")

pdffiles = list(inputdir.glob(".pdf"))

print(f"Ditemukan {len(pdffiles)} file PDF")

starttime = time.time()

results = converter.convertall(

[str(f) for f in pdffiles],

raisesonerror=False,

)

successcount = 0

errorcount = 0

for result in results:

if result.status.value == "success":

successcount += 1

md = result.document.exporttomarkdown()

outputpath = Path("output") / f"{Path(str(result.input.file)).stem}.md"

outputpath.parent.mkdir(existok=True)

with open(outputpath, "w", encoding="utf-8") as f:

f.write(md)

else:

errorcount += 1

print(f"Error pada {result.input.file}: {result.status}")

elapsed = time.time() - starttime

print(f"\nSelesai dalam {elapsed:.1f} detik")

print(f"Berhasil: {successcount}, Gagal: {errorcount}")

Kustomisasi Pipeline

Docling memungkinkan Anda untuk menyesuaikan pipeline konversi sesuai kebutuhan.

from docling.documentconverter import DocumentConverter, PdfFormatOption

from docling.datamodel.pipelineoptions import PdfPipelineOptions

from docling.datamodel.basemodels import InputFormat

Konfigurasi pipeline kustom

pipelineoptions = PdfPipelineOptions()

pipelineoptions.doocr = True

pipelineoptions.dotablestructure = True

pipelineoptions.tablestructureoptions.docellmatching = True

pipelineoptions.generatepictureimages = True

pipelineoptions.imagesscale = 2.0

converter = DocumentConverter(

allowedformats=[

InputFormat.PDF,

InputFormat.DOCX,

InputFormat.PPTX,

InputFormat.HTML,

InputFormat.IMAGE,

],

formatoptions={

InputFormat.PDF: PdfFormatOption(

pipelineoptions=pipelineoptions

)

}

)

result = converter.convert("dokumenkompleks.pdf")

print(result.document.exporttomarkdown())

Integrasi dengan LlamaIndex

Docling terintegrasi dengan baik dengan LlamaIndex untuk membangun pipeline RAG.

pip install llama-index-readers-docling llama-index

from llamaindex.readers.docling import DoclingReader

from llamaindex.core import VectorStoreIndex

Gunakan DoclingReader

reader = DoclingReader()

documents = reader.loaddata(

filepath=["laporan.pdf", "presentasi.pptx"]

)

Buat index untuk RAG

index = VectorStoreIndex.fromdocuments(documents)

Query engine

queryengine = index.asqueryengine()

response = queryengine.query(

"Apa kesimpulan utama dari laporan tersebut?"

)

print(response)

Integrasi dengan LangChain

Docling juga tersedia sebagai document loader untuk LangChain.

pip install langchain-docling langchain-openai langchain

from langchaindocling import DoclingLoader

from langchain.textsplitter import RecursiveCharacterTextSplitter

from langchainopenai import OpenAIEmbeddings, ChatOpenAI

from langchain.vectorstores import FAISS

from langchain.chains import RetrievalQA

Load dokumen dengan Docling

loader = DoclingLoader(

filepath="laporankeuangan.pdf",

exporttype="markdown",

)

documents = loader.load()

Split dokumen

textsplitter = RecursiveCharacterTextSplitter(

chunksize=1000,

chunkoverlap=200,

)

splits = textsplitter.splitdocuments(documents)

Buat vector store

embeddings = OpenAIEmbeddings()

vectorstore = FAISS.fromdocuments(splits, embeddings)

Buat chain RAG

llm = ChatOpenAI(model="gpt-4o", temperature=0)

qachain = RetrievalQA.fromchaintype(

llm=llm,

chaintype="stuff",

retriever=vectorstore.asretriever(searchkwargs={"k": 5}),

)

Query

result = qachain.invoke(

{"query": "Berapa total pendapatan perusahaan tahun ini?"}

)

print(result["result"])

Contoh Praktis: Pipeline Ingestion Dokumen untuk RAG

Berikut adalah contoh lengkap membangun pipeline ingestion dokumen menggunakan Docling untuk sistem RAG.

"""

Pipeline Ingestion Dokumen untuk RAG menggunakan Docling

"""

import json

import hashlib

from pathlib import Path

from datetime import datetime

from dataclasses import dataclass, field

from docling.documentconverter import DocumentConverter, PdfFormatOption

from docling.datamodel.pipelineoptions import PdfPipelineOptions, EasyOcrOptions

from docling.datamodel.basemodels import InputFormat

from docling.chunking import HybridChunker

from tokenizers import Tokenizer

@dataclass

class ProcessedChunk:

"""Representasi chunk yang sudah diproses."""

chunkid: str

text: str

sourcefile: str

headings: list = field(defaultfactory=list)

pagenumbers: list = field(defaultfactory=list)

chunkindex: int = 0

totalchunks: int = 0

processedat: str = ""

class DocumentIngestionPipeline:

"""Pipeline untuk ingestion dokumen ke sistem RAG."""

def init(

self,

outputdir: str = "ragoutput",

maxtokens: int = 512,

enableocr: bool = True,

ocrlanguages: list = None,

):

self.outputdir = Path(outputdir)

self.outputdir.mkdir(parents=True, existok=True)

# Konfigurasi pipeline

pipelineoptions = PdfPipelineOptions()

pipelineoptions.dotablestructure = True

pipelineoptions.tablestructureoptions.docellmatching = True

if enableocr:

pipelineoptions.doocr = True

pipelineoptions.ocroptions = EasyOcrOptions(

lang=ocrlanguages or ["id", "en"],

forcefullpageocr=False,

)

self.converter = DocumentConverter(

allowedformats=[

InputFormat.PDF,

InputFormat.DOCX,

InputFormat.PPTX,

InputFormat.HTML,

InputFormat.IMAGE,

],

formatoptions={

InputFormat.PDF: PdfFormatOption(

pipelineoptions=pipelineoptions

)

}

)

# Konfigurasi chunker

self.chunker = HybridChunker(

tokenizer=Tokenizer.frompretrained("bert-base-uncased"),

maxtokens=maxtokens,

mergepeers=True,

)

def generatechunkid(self, text: str, source: str, index: int) -> str:

"""Generate ID unik untuk setiap chunk."""

content = f"{source}:{index}:{text[:100]}"

return hashlib.md5(content.encode()).hexdigest()

def processdocument(self, filepath: str) -> list[ProcessedChunk]:

"""Proses satu dokumen dan hasilkan chunks."""

print(f"Memproses: {filepath}")

# Konversi dokumen

result = self.converter.convert(filepath)

if result.status.value != "success":

print(f" Gagal mengkonversi: {result.status}")

return []

# Chunking

chunks = list(self.chunker.chunk(result.document))

processedchunks = []

for i, chunk in enumerate(chunks):

chunkid = self.generatechunkid(

chunk.text, filepath, i

)

processed = ProcessedChunk(

chunkid=chunkid,

text=chunk.text,

sourcefile=str(filepath),

headings=chunk.meta.headings if chunk.meta else [],

chunkindex=i,

totalchunks=len(chunks),

processedat=datetime.now().isoformat(),

)

processedchunks.append(processed)

print(f" Dihasilkan {len(processedchunks)} chunks")

return processedchunks

def processdirectory(self, inputdir: str) -> list[ProcessedChunk]:

"""Proses semua dokumen dalam direktori."""

inputpath = Path(inputdir)

supportedextensions = {

".pdf", ".docx", ".pptx", ".html", ".htm",

".png", ".jpg", ".jpeg", ".tiff",

}

files = [

f for f in inputpath.rglob("")

if f.suffix.lower() in supportedextensions

]

print(f"Ditemukan {len(files)} dokumen untuk diproses")

allchunks = []

for filepath in files:

chunks = self.processdocument(str(filepath))

allchunks.extend(chunks)

return allchunks

def savechunks(self, chunks: list[ProcessedChunk]) -> str:

"""Simpan chunks ke file JSON."""

outputfile = self.outputdir / "chunks.json"

chunksdata = []

for chunk in chunks:

chunksdata.append({

"id": chunk.chunkid,

"text": chunk.text,

"metadata": {

"source": chunk.sourcefile,

"headings": chunk.headings,

"chunkindex": chunk.chunkindex,

"totalchunks": chunk.totalchunks,

"processedat": chunk.processedat,

},

})

with open(outputfile, "w", encoding="utf-8") as f:

json.dump(chunksdata, f, indent=2, ensureascii=False)

print(f"\n{len(chunks)} chunks disimpan ke {outputfile}")

return str(outputfile)

def exportforvectordb(self, chunks: list[ProcessedChunk]) -> dict:

"""Export chunks dalam format siap untuk vector database."""

return {

"documents": [c.text for c in chunks],

"ids": [c.chunkid for c in chunks],

"metadatas": [

{

"source": c.sourcefile,

"headings": ", ".join(c.headings) if c.headings else "",

"chunkindex": c.chunkindex,

}

for c in chunks

],

}

Penggunaan pipeline

if name == "main":

# Inisialisasi pipeline

pipeline = DocumentIngestionPipeline(

outputdir="ragoutput",

maxtokens=512,

enableocr=True,

ocrlanguages=["id", "en"],

)

# Proses satu dokumen

chunks = pipeline.processdocument("laporantahunan2025.pdf")

# Atau proses seluruh direktori

# chunks = pipeline.processdirectory("dokumenperusahaan/")

# Simpan hasil

pipeline.savechunks(chunks)

# Export untuk vector database

vectordbdata = pipeline.exportforvectordb(chunks)

# Contoh: masukkan ke ChromaDB

# import chromadb

# client = chromadb.Client()

# collection = client.createcollection("dokumenperusahaan")

# collection.add(vectordbdata)

print("\nPipeline ingestion selesai!")

print(f"Total chunks: {len(chunks)}")

Tips dan Best Practices

  • Pilih format output yang tepat: Gunakan Markdown untuk pipeline RAG dan JSON untuk analisis terstruktur.
  • Optimalkan OCR: Hanya aktifkan OCR jika dokumen mengandung gambar atau scan. OCR membutuhkan waktu dan resource lebih banyak.
  • Atur ukuran chunk: Untuk RAG, ukuran chunk 256-512 token biasanya memberikan hasil terbaik. Terlalu besar akan mengurangi presisi, terlalu kecil akan kehilangan konteks.
  • Gunakan batch processing: Untuk banyak dokumen, gunakan convertall() untuk memanfaatkan paralelisme bawaan Docling.
  • Perhatikan kualitas dokumen: Hasil konversi sangat bergantung pada kualitas dokumen input. PDF yang di-generate secara digital akan menghasilkan output yang lebih baik dari scan.
  • Cache hasil konversi**: Simpan hasil konversi untuk menghindari pemrosesan ulang dokumen yang sama.
  • Kesimpulan

    Docling menyediakan solusi lengkap untuk parsing dokumen dalam pipeline AI. Dengan dukungan untuk berbagai format input, kemampuan OCR, ekstraksi tabel dan gambar, serta integrasi dengan framework RAG populer seperti LlamaIndex dan LangChain, Docling menjadi alat yang sangat berharga dalam membangun aplikasi AI yang membutuhkan pemahaman dokumen.

    Fitur chunking cerdas yang disediakan Docling juga memudahkan persiapan data untuk pipeline RAG, memastikan bahwa informasi dari dokumen dapat diakses dan dimanfaatkan secara optimal oleh model AI.

    Mulailah bereksperimen dengan Docling pada dokumen-dokumen Anda dan lihat bagaimana library ini dapat meningkatkan kualitas pipeline AI Anda!

    Artikel Terkait

    DSPy: Berhenti Ngoprek Prompt Manual, Biarkan Compiler yang Optimasi

    DSPy: Berhenti Ngoprek Prompt Manual, Biarkan Compiler yang Optimasi Halo temen-temen, kali ini aku mau ngenalin satu li...

    Cognee: Bangun Memory dan Knowledge Graph untuk AI Agent-mu

    Cognee: Bangun Memory dan Knowledge Graph untuk AI Agent-mu Halo temen-temen, di tutorial kali ini aku mau ngajak kalian...

    Tutorial Marker: Mengubah PDF dan Dokumen Menjadi Markdown untuk Pipeline RAG

    Tutorial Marker: Mengubah PDF dan Dokumen Menjadi Markdown untuk Pipeline RAG Dalam dunia AI dan data engineering, kemam...

    Tutorial Lengkap Pinecone: Vector Database untuk AI dan Semantic Search

    Tutorial Lengkap Pinecone: Vector Database untuk AI dan Semantic Search Pinecone adalah managed vector database yang dir...