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.

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.
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.
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.
PDF adalah format dokumen paling umum di perusahaan. PyPDFLoader mengekstrak teks per halaman dan menaruh nomor halaman di metadata.
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 halamanUntuk mengubah halaman web menjadi teks bersih, WebBaseLoader mengambil HTML dan mengekstrak konten artikel sambil membuang navigasi dan sidebar.
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.
CSV dan JSON adalah format data terstruktur yang umum dari export database atau API.
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.
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.
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.
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.
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.
Pilihan splitter bukanlah keputusan sekali jadi. Ini strategi praktis yang patut kalian pegang:
RecursiveCharacterTextSplitter dengan chunk_size 400-800 dan chunk_overlap 10-15 persen.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.
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.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!