Belajar LangChain - Document Loaders & Text Splitters
Episode 9 of 23

Belajar LangChain - Document Loaders & Text Splitters

Mengubah berbagai sumber dokumen menjadi objek Document lalu memotongnya menjadi chunks: RecursiveCharacterTextSplitter, token-based splitter, chunk size dan overlap, serta strategi chunking yang tepat untuk RAG.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

Di episode 8 agent kalian sudah bisa bertindak lewat tools. Sekarang giliran data. RAG — retrieval-augmented generation — bekerja karena model diberi konteks dari dokumen milik kalian sendiri. Tapi sebelum dokumen bisa di-retrieve, ia harus diubah menjadi bentuk yang bisa dicari: objek Document yang terpotong rapi menjadi potongan kecil yang disebut chunks.

Episode ini membahas dua tahap awal pipeline RAG. Pertama, document loaders: membaca PDF, web/HTML, CSV, dan JSON menjadi Document berisi page_content dan metadata. Kedua, text splitters: memotong dokumen menjadi chunks dengan RecursiveCharacterTextSplitter, splitter berbasis token, serta strategi chunk size dan overlap untuk kualitas retrieval yang baik.

Objek Document: page_content dan metadata

Semua loader mengembalikan objek Document dengan dua field utama: page_content yang memuat teks, dan metadata yang memuat informasi konteks seperti sumber, judul, atau nomor halaman. metadata inilah yang nanti dipakai untuk filter retrieval.

PythonStruktur dasar Document
from langchain_core.documents import Document
 
doc = Document(
    page_content="LangChain adalah framework untuk aplikasi LLM.",
    metadata={"sumber": "docs/langchain.md", "halaman": 1},
)
print(doc.page_content)
print(doc.metadata)

Mental modelnya sederhana: loader apa pun — PDF, web, CSV, JSON — pada akhirnya menghasilkan list Document. Seluruh sisa pipeline (split, embed, retrieve) tidak peduli asal formatnya, karena semua sudah dinormalisasi ke struktur yang sama.

Loader untuk PDF dan Web

PDF

PDF adalah format dokumen paling umum di perusahaan. PyPDFLoader mengekstrak teks per halaman dan menaruh nomor halaman di metadata.

PythonMemuat PDF
from langchain_community.document_loaders import PyPDFLoader
 
loader = PyPDFLoader("laporan-tahunan.pdf")
dokumen = loader.load()
 
print(len(dokumen))          # jumlah halaman
print(dokumen[0].metadata)   # metadata berisi nomor halaman

Web / HTML

Untuk mengubah halaman web menjadi teks bersih, WebBaseLoader mengambil HTML dan mengekstrak konten artikel sambil membuang navigasi dan sidebar.

PythonMemuat halaman web
from langchain_community.document_loaders import WebBaseLoader
 
loader = WebBaseLoader("https://example.com/artikel-langchain")
dokumen = loader.load()
print(dokumen[0].page_content[:200])

Perhatikan bahwa WebBaseLoader menandai halaman yang baru saja diambil agar permintaan berulang tidak mengulang unduhan — berguna saat kalian menguji berkali-kali.

Loader untuk CSV dan JSON

CSV dan JSON adalah format data terstruktur yang umum dari export database atau API.

PythonMemuat CSV dan JSON
from langchain_community.document_loaders import CSVLoader, JSONLoader
 
csv_docs = CSVLoader("data-pengguna.csv").load()
print(csv_docs[0].page_content)
 
# JSONLoader butuh jq-style path untuk menunjuk isi teks
import json
with open("data.json") as f:
    data = json.load(f)
 
json_docs = JSONLoader(
    file_path="data.json",
    jq_schema=".items[]",
    text_content=False,
).load()

Untuk CSV, satu baris menjadi satu Document. Untuk JSON, jq_schema menentukan bagian mana yang diambil sebagai dokumen — misalnya tiap elemen array items. Sebelum memasang, pastikan loader yang kalian butuh memang tersedia di langchain-community versi kalian.

RecursiveCharacterTextSplitter

Splitter paling serbaguna dan rekomendasi default. Ia memotong teks menggunakan daftar separator berjenjang — dari paragraf (baris baru) turun ke kalimat, lalu kata — sehingga potongan tetap berada di batas yang masuk akal, bukan di tengah kalimat.

PythonRecursiveCharacterTextSplitter
from langchain_text_splitters import RecursiveCharacterTextSplitter
 
splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
    separators=["\n\n", "\n", ".", " "],
)
chunks = splitter.split_documents(dokumen)
 
print(len(chunks))
print(chunks[0].page_content)

Dua parameter kunci: chunk_size membatasi panjang tiap chunk, chunk_overlap membuat tiap chunk tumpang tindih sebagian dengan chunk sebelumnya sehingga konteks di batas potongan tidak hilang. splitter.split_documents(...) memproses list Document sekaligus dan mewariskan metadata ke tiap chunk.

Info

Nilai chunk_size yang baik berkisar 300-1000 karakter untuk retrieval umum, tapi optimalnya berbeda per domain dan per model embedder. Selalu uji kombinasi ukuran dan overlap sebelum dipakai produksi.

Splitter Berbasis Token

Karakter dan token tidak selalu selaras — satu kata bisa menghabiskan beberapa token di model tertentu. Jika konteks diukur dalam token (yang memang dihitung provider), TokenTextSplitter memotong berdasarkan jumlah token, memberikan kontrol yang lebih presisi atas biaya dan context window.

PythonTokenTextSplitter untuk kontrol token
from langchain_text_splitters import TokenTextSplitter
 
token_splitter = TokenTextSplitter(
    chunk_size=200,
    chunk_overlap=20,
)
chunks_token = token_splitter.split_documents(dokumen)
print(len(chunks_token))

Satu kekurangan: TokenTextSplitter memotong per token tanpa memperhatikan batas kalimat, sehingga potongan bisa terputus di tengah kalimat. Untuk teks prosa yang rapi, RecursiveCharacterTextSplitter biasanya menghasilkan chunk yang lebih enak dibaca dan lebih mudah dipahami model.

Strategi Chunking untuk RAG

Pilihan splitter bukanlah keputusan sekali jadi. Ini strategi praktis yang patut kalian pegang:

  • Dokumen prosa panjang (artikel, laporan): RecursiveCharacterTextSplitter dengan chunk_size 400-800 dan chunk_overlap 10-15 persen.
  • Kode dan file teknis: pertahankan batas fungsi atau blok — gunakan separator berbasis karakter baris baru, dan pertimbangkan splitter khusus per bahasa.
  • Batas semantik: bila dokumen punya bagian jelas (bab, pasal), potong di batas itu terlebih dahulu sebelum splitter halus bekerja.
  • Ukuran model embedder: sesuaikan chunk_size dengan batas token model embedding yang dipakai; chunk terlalu panjang bisa terpotong saat di-embed.

Verifikasi kualitas chunking: baca beberapa chunk secara acak. Kalau konteks sebuah pertanyaan terpotong di antara dua chunk, naikkan chunk_overlap atau pindahkan batas potong ke separator yang lebih tinggi. Proses ini tidak bisa dimurnikan otomatis — evaluasi manual tetap penting.

Penutup

Pipeline data kalian kini lengkap sampai titik sebelum penyimpanan: format apa pun — PDF, web, CSV, JSON — berhasil dinormalisasi menjadi Document, lalu dipotong menjadi chunks yang terkelola lewat splitter dan strategi chunking yang disesuaikan. Kualitas chunking hari ini menentukan kualitas retrieval di episode 11.

Inti yang harus dibawa pulang:

  • Document punya page_content untuk teks dan metadata untuk konteks sumber — semua loader dinormalisasi ke struktur ini.
  • PyPDFLoader untuk PDF per halaman, WebBaseLoader untuk web, CSVLoader dan JSONLoader untuk data terstruktur.
  • RecursiveCharacterTextSplitter memotong di batas alami paragraf/kalimat/kata — pilihan default yang aman.
  • chunk_size mengontrol panjang chunk, chunk_overlap menjaga konteks di batas potongan.
  • TokenTextSplitter memberi kontrol berbasis token, berguna saat biaya dan context window jadi pertimbangan utama.
  • Evaluasi manual chunking tetap wajib sebelum lanjut ke embedding dan retrieval.

Di episode 10 kita mengubah chunks menjadi vektor: Embeddings & Vector Stores — dari OpenAIEmbeddings dan HuggingFaceEmbeddings hingga penyimpanan index di Chroma, FAISS, pgvector, dan Qdrant. Sampai jumpa!

Belajar LangChain - Document Loaders & Text Splitters | Belajar LangChain