Belajar ChromaDB - Querying & Semantic Search
Episode 5 of 23

Belajar ChromaDB - Querying & Semantic Search

Episode ini membedah API query ChromaDB: query_texts dan query_embeddings, pengaturan n_results, serta parameter include untuk memilih dokumen, metadatas, distances, atau embeddings yang dikembalikan, lengkap dengan interpretasi distance vs similarity.

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

Pendahuluan

Di episode 4 kalian sudah bisa menyimpan dan mengelola data. Sekarang masuk ke bagian yang membuat ChromaDB istimewa: querying dan semantic search. Di sinilah kalian bertanya dalam bahasa alami dan ChromaDB menemukan dokumen yang bermakna sama, bukan sekadar yang hurufnya sama.

Episode 5 membedah API query secara menyeluruh: dua cara memberikan input (query_texts dan query_embeddings), berapa banyak hasil (n_results), apa saja yang dikembalikan (include), serta cara membaca hasil — terutama perbedaan distance dan similarity yang sering membingungkan.

API query: Dua Cara Memberikan Input

query_texts: Query dari Teks

Cara paling alami: berikan teks dan biarkan ChromaDB men-embed-nya sendiri:

PythonQuery dari teks
hasil = collection.query(
    query_texts=["Bagaimana cara deploy aplikasi?"],
    n_results=3,
)

collection.query(query_texts=["..."], n_results=3) men-embed teks query dengan embedding function collection, mencari 3 vektor terdekat, lalu mengembalikan hasil. Ini adalah pintu utama semantic search.

query_embeddings: Query dari Vektor

Jika embedding query sudah dibangkitkan di luar — misalnya dari model yang sama dengan data — gunakan query_embeddings:

PythonQuery dari vektor
hasil = collection.query(
    query_embeddings=[[0.2, 0.8, 0.4, 0.6]],
    n_results=2,
)

Perbedaan keduanya hanya di proses embed. collection.query(query_embeddings=[[...]]) memakai vektor yang diberikan langsung. Untuk pipeline RAG yang men-embed query dengan model khusus, bentuk ini lebih efisien karena menghemat satu panggilan.

Parameter include: Mengontrol Isi Hasil

Empat Komponen Hasil

Secara default, query mengembalikan ids, documents, metadatas, dan distances. Kalian bisa mengatur apa saja yang dikembalikan lewat include:

PythonMemilih isi hasil
hasil = collection.query(
    query_texts=["Apa itu Kubernetes?"],
    n_results=2,
    include=["documents", "metadatas", "distances"],
)

Opsi yang tersedia untuk include=["documents", "metadatas", "distances"]:

  • documents: teks sumber, wajib untuk RAG.
  • metadatas: atribut seperti sumber dan tanggal.
  • distances: nilai jarak hasil terhadap query.
  • embeddings: vektor hasil, berguna untuk analisis lanjutan.

Semakin banyak yang diminta, semakin besar payload yang dikembalikan. Di production, minta hanya yang dibutuhkan untuk menghemat bandwidth.

Memahami Distance vs Similarity

Dua Skala yang Berbeda

Konsep yang paling sering salah dipahami: ChromaDB mengembalikan distance, bukan similarity. Semakin kecil distance, semakin mirip hasilnya:

PythonMembaca hasil query
hasil = collection.query(query_texts=["deploy aplikasi"], n_results=2)
 
for i, dok in enumerate(hasil["documents"][0]):
    jarak = hasil["distances"][0][i]
    print(f"{dok} -> jarak {jarak:.4f}")

Pada kode di atas, hasil["documents"][0] adalah list hasil untuk query pertama, dan hasil["distances"][0] adalah jarak masing-masing. Hasil diurutkan dari jarak terkecil (paling relevan) ke terbesar.

Menghitung Similarity dari Distance

Distance bergantung pada metrik yang dipakai (episode 9). Untuk cosine distance, similarity dihitung sebagai:

PythonKonversi distance ke similarity
similarity = 1.0 - jarak

Rumus similarity = 1.0 - jarak berlaku untuk cosine. Jadi jarak 0.15 berarti similarity 0.85. Ingat kebalikannya saat membandingkan hasil antar collection dengan metrik berbeda.

Warning

Jangan membandingkan nilai distance antara collection yang memakai metrik berbeda. Cosine, L2, dan inner product menghasilkan skala jarak yang berbeda sama sekali — episode 9 akan menjelaskan kapan memakai yang mana.

Query dengan Beberapa Pertanyaan Sekaligus

query_texts menerima list, sehingga satu panggilan bisa menjawab banyak pertanyaan:

PythonBatch query
hasil = collection.query(
    query_texts=["Apa itu Docker?", "Apa itu Kubernetes?", "Apa itu CI/CD?"],
    n_results=1,
)
 
for i, dok in enumerate(hasil["documents"]):
    print(f"Q{i}: {dok[0]}")

Struktur hasil selalu dua level: hasil["documents"][i] adalah list hasil untuk query ke-i. Batch query collection.query(query_texts=[...]) memangkas latensi karena satu round-trip menangani banyak pertanyaan — pola yang akan kita pakai lagi untuk multi-query di episode 19.

Kesalahan Umum dan Solusinya

Hasil Kosong atau Kurang Relevan

Jika query mengembalikan dokumen yang tidak relevan, beberapa kemungkinan: embedding function collection berbeda dari yang dipakai membangkitkan data, atau ukuran chunk dokumen (episode 10) terlalu besar sehingga makna tercampur. Periksa dulu embedding function, lalu cek strategi chunking.

TypeError: Ukuran List Tidak Sama

Semua argumen list di add, query, dan lainnya harus punya panjang yang sama. Error ini biasanya dari query_texts yang tidak berupa list:

PythonPola yang benar dan salah
hasil = collection.query(query_texts="deploy")
hasil = collection.query(query_texts=["deploy"])

Selalu bungkus query tunggal dalam list. collection.query(query_texts=["deploy"]) adalah bentuk yang benar — kesalahan ini yang paling sering terjadi di forum komunitas.

Penutup

Episode 5 membuka kekuatan inti ChromaDB: querying dan semantic search. Kalian sekarang bisa memberi query dalam bentuk teks atau vektor, mengontrol jumlah dan isi hasil lewat n_results dan include, membaca hasil yang terurut dari jarak terkecil, dan menghindari jebakan distance versus similarity.

Inti yang harus dibawa pulang:

  • query_texts untuk query teks; query_embeddings untuk query vektor.
  • n_results menentukan jumlah hasil; include menentukan isi hasil.
  • ChromaDB mengembalikan distance, bukan similarity: semakin kecil semakin mirip.
  • Cosine similarity dihitung sebagai 1 - distance.
  • Hasil batch selalu dua level: hasil per query.
  • Jarak antar collection dengan metrik berbeda tidak bisa dibandingkan.

Di episode 6 selanjutnya kita akan membahas embeddings dan embedding functions — model bawaan ONNX MiniLM yang berjalan lokal, cara mengganti ke sentence-transformers atau OpenAI, integrasi pre-computed embeddings, dan cara menulis fungsi embedding custom. Ini menentukan kualitas semantic search kalian secara keseluruhan.

Belajar ChromaDB - Querying & Semantic Search | Belajar ChromaDB