Belajar ChromaDB - Data Modeling & Chunking Strategy
Episode 10 of 23

Belajar ChromaDB - Data Modeling & Chunking Strategy

Episode ini membahas perancangan skema metadata untuk RAG: konvensi id, timestamp, source, tenant dan namespace, lalu strategi chunking yang menentukan akurasi retrieval: ukuran chunk, overlap, dan pemilihan granularity yang tepat.

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

Pendahuluan

Sejauh ini kita fokus pada bagaimana ChromaDB bekerja. Episode 10 membalik fokus ke apa yang kalian masukkandata modeling dan chunking strategy. Satu kebenaran yang sering diabaikan: kualitas retrieval tidak ditentukan oleh vector database, melainkan oleh kualitas data yang masuk ke dalamnya. Embedding function terbaik pun tidak bisa menyelamatkan chunk yang buruk.

Kita akan membahas skema metadata yang disarankan untuk RAG, konvensi id yang terstruktur, lalu strategi chunking: ukuran, overlap, dan granularity. Anggap episode ini sebagai desain arsitektur data sebelum kalian membangun production.

Merancang Skema Metadata

Metadata yang Harus Ada untuk RAG

Metadata adalah konteks yang menemani setiap dokumen. Untuk aplikasi RAG yang sehat, setidaknya simpan:

  • source: asal dokumen (URL, nama file, atau pipeline).
  • timestamp: kapan dokumen dibuat atau diambil.
  • title: judul untuk menampilkan hasil yang lebih ramah.
  • category atau topik: untuk filter di episode 7.
  • tenant atau namespace: pemisah kepemilikan data.
PythonContoh metadata yang kaya
metadata = {
    "source": "https://blog.example.com/docker-intro",
    "timestamp": "2026-07-15T08:30:00Z",
    "title": "Pengenalan Docker untuk Pemula",
    "category": "devops",
    "tenant": "tutorial",
}

Contoh metadata di atas memungkinkan filter seperti where={"category": "devops"} sekaligus menampilkan judul di hasil retrieval tanpa membuka dokumen asli.

Menghindari Metadata yang Tidak Terpakai

Godaan terbesar: menyimpan semua atribut sumber. Metadata yang tidak pernah dipakai query hanya memboroskan storage dan memperlambat serialisasi. Aturan sederhana: simpan hanya yang akan kalian filter, tampilkan di UI, atau jadikan konteks tambahan untuk LLM.

Info

Skema metadata bukan keputusan yang bisa diubah seenaknya. Ubah skema setelah data banyak berarti migrasi seluruh collection. Rancang dengan hati-hati di awal — episode 11 akan membahas alat untuk migrasi jika terlanjur.

Konvensi ID yang Terstruktur

ID sebagai Sumber Informasi

ID di ChromaDB tidak harus numerik sekuensial — ia bebas string. Manfaatkan ini untuk membuat ID yang self-describing, terutama untuk deduplikasi saat pipeline dijalankan ulang:

PythonKonvensi id berbasis hash
import hashlib
 
def buat_id(source, chunk_index):
    hash_teks = hashlib.md5(source.encode()).hexdigest()[:8]
    return f"chunk-{hash_teks}-{chunk_index:04d}"
 
ids = [buat_id("docker-intro", i) for i in range(5)]

buat_id(source, chunk_index) menghasilkan id deterministik: pipeline yang sama dijalankan ulang menghasilkan id yang sama, sehingga upsert dari episode 4 otomatis memperbarui alih-alih menduplikasi. Ini pola penting untuk ingestion berulang.

Hubungan ID dengan Source

Tambahkan prefix yang menandai tipe data atau tenant:

PythonPrefix tenant pada id
id_dok = f"{tenant}:{source}:{chunk_index}"

id_dok = f"{tenant}:{source}:{chunk_index}" membuat ID seperti tutorial:docker-intro:0003. Saat troubleshooting atau audit, ID langsung menceritakan asal usul dokumen tanpa perlu membuka isinya.

Chunking Strategy: Fondasi RAG

Mengapa Dokumen Harus Dipecah

Model embedding punya batas panjang konteks — teks yang terlalu panjang di-embed sebagai satu vektor akan kehilangan detail makna. Selain itu, retrieval bekerja paling baik jika tiap vektor mewakili satu ide yang fokus. Karena itu dokumen panjang harus dipecah menjadi chunk yang lebih kecil.

PythonChunking sederhana per paragraf
def chunk_paragraf(teks):
    return [p.strip() for p in teks.split("\n\n") if p.strip()]
 
chunks = chunk_paragraf(dokumen)

Fungsi chunk_paragraf(teks) memecah dokumen per paragraf — pendekatan paling sederhana yang sudah jauh lebih baik daripada menyimpan dokumen utuh.

Ukuran Chunk yang Tepat

Tidak ada angka ajaib, tapi pedoman yang umum dipakai: 250-500 token per chunk untuk konten umum, dan lebih kecil (100-200 token) untuk konten teknis yang padat. Ukuran terlalu besar membuat satu vektor mencampur banyak topik; terlalu kecil membuat konteks terpotong.

Pertimbangan utama: embedding model kalian. Periksa batas token model — chunk harus berada di bawah batas tersebut dengan ruang untuk overlap.

Overlap dan Granularity

Overlap: Menyambung Konteks yang Terpotong

Saat dokumen dipecah, kalimat yang berkaitan bisa terpisah ke chunk berbeda. Overlap — menyertakan beberapa kalimat terakhir dari chunk sebelumnya — menjaga kontinuitas:

PythonChunking dengan overlap
def chunk_overlap(teks, ukuran=300, overlap=50):
    tokens = teks.split()
    hasil = []
    for i in range(0, len(tokens), ukuran - overlap):
        potongan = tokens[i : i + ukuran]
        hasil.append(" ".join(potongan))
        if i + ukuran >= len(tokens):
            break
    return hasil

chunk_overlap(teks, ukuran=300, overlap=50) maju 250 kata per iterasi dengan 50 kata overlap. Nilai overlap umum: 10-20 persen dari ukuran chunk.

Granularity: Seberapa Kecil Idealnya

Granularity bergantung pada jenis pertanyaan yang akan dijawab:

  • FAQ dan knowledge base: chunk per tanya-jawab atau per topik kecil.
  • Dokumen teknis: chunk per seksi atau subseksi.
  • Berita: chunk per paragraf utama.
  • Manual legal: chunk per pasal atau klausa.

Cara terbaik memilih: jangan menebak. Ambil sampel 50-100 pertanyaan nyata, jalankan retrieval untuk beberapa granularity, dan ukur akurasi mana yang terbaik. Eksperimen berbiaya rendah ini membayar jauh lebih besar daripada memilih angka dari tutorial orang lain.

Pola Ingestion Lengkap

Merangkum episode ini menjadi satu pola ingestion yang sehat:

PythonPipeline ingestion dengan metadata
for idx, chunk in enumerate(chunk_overlap(dokumen)):
    collection.upsert(
        ids=[f"{tenant}:{source}:{idx:04d}"],
        documents=[chunk],
        metadatas=[{
            "source": source,
            "timestamp": timestamp,
            "title": judul,
            "tenant": tenant,
            "chunk_index": idx,
        }],
    )

Pola di atas — id deterministik, metadata lengkap, dan collection.upsert(...) — menghasilkan collection yang bersih, deduplikasi otomatis saat dijalankan ulang, dan mudah difilter. Inilah template yang akan kita gunakan untuk sisa series.

Penutup

Episode 10 menutup fase data: skema metadata yang menunjang filter, konvensi id yang self-describing dan deterministik, serta strategi chunking dengan ukuran, overlap, dan granularity yang disesuaikan dengan jenis pertanyaan. Kualitas retrieval RAG kalian sekarang bergantung pada kualitas data yang kalian rancang — dan kalian sudah tahu cara merancangnya.

Inti yang harus dibawa pulang:

  • Simpan metadata yang dipakai: source, timestamp, title, category, tenant.
  • ID deterministik membuat upsert tidak menduplikasi.
  • Chunk 250-500 token dengan overlap 10-20 persen adalah titik awal yang sehat.
  • Granularity disesuaikan dengan jenis pertanyaan, bukan asumsi.
  • Metadata di atas menentukan kecepatan filter di bawah.
  • Ingestion yang baik bisa dijalankan ulang tanpa efek samping.

Di episode 11 selanjutnya kita akan membahas persistence, import dan export — cara kerja PersistentClient dan lokasi storage, strategi backup dan restore, snapshot, hingga import-export data memakai parquet dan dump-load collection untuk migrasi antar environment. Data kalian mulai bernilai; saatnya menjaganya.

Belajar ChromaDB - Data Modeling & Chunking Strategy | Belajar ChromaDB