Tutorial Lengkap Qdrant: Vector Database untuk Aplikasi AI
Qdrant adalah vector database performa tinggi yang dirancang untuk similarity search dan aplikasi AI. Library ini menyediakan penyimpanan dan retrieval vector embeddings yang efisien, menjadikannya ideal untuk membangun sistem rekomendasi, semantic search, dan aplikasi RAG.
Mengapa Qdrant?
Keunggulan Qdrant:- Performa tinggi: Engine berbasis Rust untuk kecepatan
- Rich filtering: Kombinasikan vector search dengan filter metadata
- Scalable: Mode terdistribusi untuk dataset besar
- Mudah digunakan: REST dan gRPC APIs
- Cloud native: Siap Docker dan Kubernetes
- Semantic search
- Sistem rekomendasi
- RAG (Retrieval-Augmented Generation)
- Image similarity search
- Anomaly detection
Instalasi
# Python client
pip install qdrant-client
Jalankan Qdrant dengan Docker
docker run -p 6333:6333 -p 6334:6334 \
-v $(pwd)/qdrantstorage:/qdrant/storage:z \
qdrant/qdrant
Verify
python -c "from qdrantclient import QdrantClient; print('Qdrant client ready')"
Quick Start
1. Koneksi ke Qdrant
from qdrantclient import QdrantClient
Instance lokal
client = QdrantClient("localhost", port=6333)
In-memory (untuk testing)
client = QdrantClient(":memory:")
Qdrant Cloud
client = QdrantClient(
url="https://xxx-xxx.us-east-1-0.aws.cloud.qdrant.io",
api
key="your-api-key"
)
Cek koneksi
print(client.getcollections())
2. Buat Collection
from qdrantclient import QdrantClient
from qdrantclient.models import Distance, VectorParams
client = QdrantClient("localhost", port=6333)
Buat collection
client.createcollection(
collectionname="mycollection",
vectorsconfig=VectorParams(size=384, distance=Distance.COSINE)
)
List collections
collections = client.getcollections()
print(collections)
3. Insert Vectors
from qdrantclient.models import PointStruct
Insert points
client.upsert(
collection
name="mycollection",
points=[
PointStruct(
id=1,
vector=[0.1, 0.2, 0.3, ...], # vektor 384-dim
payload={"title": "Dokumen 1", "category": "tech"}
),
PointStruct(
id=2,
vector=[0.4, 0.5, 0.6, ...],
payload={"title": "Dokumen 2", "category": "science"}
)
]
)
4. Search Vectors
# Search
results = client.search(
collectionname="mycollection",
queryvector=[0.1, 0.2, 0.3, ...],
limit=5
)
for result in results:
print(f"ID: {result.id}, Score: {result.score}")
print(f"Payload: {result.payload}")
Bekerja dengan Embeddings
1. Menggunakan Sentence Transformers
from qdrantclient import QdrantClient
from qdrant
client.models import Distance, VectorParams, PointStruct
from sentencetransformers import SentenceTransformer
Initialize
client = QdrantClient("localhost", port=6333)
model = SentenceTransformer("all-MiniLM-L6-v2")
Buat collection
client.recreatecollection(
collectionname="documents",
vectorsconfig=VectorParams(size=384, distance=Distance.COSINE)
)
Siapkan dokumen
documents = [
{"id": 1, "text": "Machine learning sangat menarik", "category": "tech"},
{"id": 2, "text": "Natural language processing", "category": "tech"},
{"id": 3, "text": "Resep masakan untuk pemula", "category": "food"},
]
Generate embeddings dan insert
points = []
for doc in documents:
embedding = model.encode(doc["text"]).tolist()
points.append(PointStruct(
id=doc["id"],
vector=embedding,
payload={"text": doc["text"], "category": doc["category"]}
))
client.upsert(collectionname="documents", points=points)
Search
query = "AI dan deep learning"
queryvector = model.encode(query).tolist()
results = client.search(
collectionname="documents",
queryvector=queryvector,
limit=3
)
for result in results:
print(f"Score: {result.score:.4f} - {result.payload['text']}")
2. Menggunakan OpenAI Embeddings
from qdrantclient import QdrantClient
from qdrantclient.models import Distance, VectorParams, PointStruct
import openai
client = QdrantClient("localhost", port=6333)
openai.apikey = "your-api-key"
def getembedding(text):
response = openai.embeddings.create(
model="text-embedding-3-small",
input=text
)
return response.data[0].embedding
Buat collection (1536 dimensi untuk text-embedding-3-small)
client.recreatecollection(
collectionname="openaidocs",
vectorsconfig=VectorParams(size=1536, distance=Distance.COSINE)
)
Insert dokumen
documents = ["Teks dokumen 1", "Teks dokumen 2", "Teks dokumen 3"]
points = []
for i, doc in enumerate(documents):
embedding = getembedding(doc)
points.append(PointStruct(
id=i,
vector=embedding,
payload={"text": doc}
))
client.upsert(collectionname="openaidocs", points=points)
Search
queryembedding = getembedding("Query pencarian")
results = client.search(
collectionname="openaidocs",
queryvector=queryembedding,
limit=5
)
Filtering
1. Filter Dasar
from qdrantclient.models import Filter, FieldCondition, MatchValue
Filter dengan exact match
results = client.search(
collection
name="documents",
queryvector=queryvector,
queryfilter=Filter(
must=[
FieldCondition(
key="category",
match=MatchValue(value="tech")
)
]
),
limit=5
)
2. Filter Kompleks
from qdrantclient.models import (
Filter, FieldCondition, MatchValue, Range,
MatchAny, MatchExcept
)
Range filter
results = client.search(
collectionname="products",
queryvector=queryvector,
queryfilter=Filter(
must=[
FieldCondition(
key="price",
range=Range(gte=10.0, lte=100.0)
)
]
),
limit=5
)
Match any
results = client.search(
collectionname="documents",
queryvector=queryvector,
queryfilter=Filter(
must=[
FieldCondition(
key="category",
match=MatchAny(any=["tech", "science"])
)
]
),
limit=5
)
Exclude values
results = client.search(
collectionname="documents",
queryvector=queryvector,
queryfilter=Filter(
mustnot=[
FieldCondition(
key="status",
match=MatchValue(value="archived")
)
]
),
limit=5
)
Combined filters (AND/OR)
results = client.search(
collectionname="products",
queryvector=queryvector,
queryfilter=Filter(
must=[
FieldCondition(key="category", match=MatchValue(value="electronics"))
],
should=[
FieldCondition(key="brand", match=MatchValue(value="Apple")),
FieldCondition(key="brand", match=MatchValue(value="Samsung"))
],
mustnot=[
FieldCondition(key="outofstock", match=MatchValue(value=True))
]
),
limit=5
)
3. Nested Filters
from qdrantclient.models import Filter, FieldCondition, MatchValue, NestedCondition
Filter pada nested objects
results = client.search(
collection
name="products",
queryvector=queryvector,
queryfilter=Filter(
must=[
FieldCondition(
key="metadata.author",
match=MatchValue(value="John Doe")
)
]
),
limit=5
)
Manajemen Collection
1. Operasi Collection
from qdrantclient.models import Distance, VectorParams, OptimizersConfigDiff
Buat dengan optimizer config
client.createcollection(
collectionname="optimizedcollection",
vectorsconfig=VectorParams(size=384, distance=Distance.COSINE),
optimizersconfig=OptimizersConfigDiff(
indexingthreshold=20000,
memmapthreshold=50000
)
)
Get info collection
info = client.getcollection("mycollection")
print(f"Points count: {info.pointscount}")
print(f"Vectors count: {info.vectorscount}")
Update collection
client.updatecollection(
collectionname="mycollection",
optimizersconfig=OptimizersConfigDiff(
indexingthreshold=10000
)
)
Hapus collection
client.deletecollection("mycollection")
2. Named Vectors
from qdrantclient.models import VectorParams, Distance
Buat collection dengan multiple tipe vektor
client.create
collection(
collectionname="multivector",
vectorsconfig={
"text": VectorParams(size=384, distance=Distance.COSINE),
"image": VectorParams(size=512, distance=Distance.COSINE)
}
)
Insert dengan named vectors
client.upsert(
collectionname="multivector",
points=[
PointStruct(
id=1,
vector={
"text": [0.1, 0.2, ...],
"image": [0.3, 0.4, ...]
},
payload={"title": "Produk 1"}
)
]
)
Search vektor spesifik
results = client.search(
collectionname="multivector",
queryvector=("text", [0.1, 0.2, ...]),
limit=5
)
Operasi Batch
1. Batch Upsert
from qdrantclient.models import PointStruct, Batch
Method 1: List of points
points = [
PointStruct(id=i, vector=vectors[i], payload=payloads[i])
for i in range(len(vectors))
]
client.upsert(collection
name="mycollection", points=points)
Method 2: Batch object (lebih efisien)
client.upsert(
collection
name="mycollection",
points=Batch(
ids=list(range(len(vectors))),
vectors=vectors,
payloads=payloads
)
)
2. Batch Search
from qdrantclient.models import SearchRequest
Multiple searches dalam satu request
results = client.searchbatch(
collectionname="mycollection",
requests=[
SearchRequest(vector=queryvector1, limit=5),
SearchRequest(vector=queryvector2, limit=5),
SearchRequest(vector=queryvector3, limit=5)
]
)
for i, result in enumerate(results):
print(f"Query {i}: {len(result)} results")
Manajemen Payload
1. Update Payload
from qdrantclient.models import PointIdsList
Set payload
client.setpayload(
collectionname="mycollection",
payload={"newfield": "newvalue"},
points=[1, 2, 3]
)
Overwrite payload
client.overwritepayload(
collectionname="mycollection",
payload={"completely": "new"},
points=[1]
)
Hapus payload keys
client.deletepayload(
collectionname="mycollection",
keys=["oldfield"],
points=[1, 2, 3]
)
2. Payload Indexing
from qdrantclient.models import PayloadSchemaType
Buat payload index untuk filtering lebih cepat
client.create
payloadindex(
collection
name="mycollection",
field
name="category",
fieldschema=PayloadSchemaType.KEYWORD
)
Buat index untuk field numerik
client.createpayloadindex(
collectionname="mycollection",
fieldname="price",
fieldschema=PayloadSchemaType.FLOAT
)
Integrasi RAG
1. Dengan LangChain
from langchaincommunity.vectorstores import Qdrant
from langchainopenai import OpenAIEmbeddings
from langchain.textsplitter import CharacterTextSplitter
Initialize embeddings
embeddings = OpenAIEmbeddings()
Buat vector store
qdrant = Qdrant.fromdocuments(
documents,
embeddings,
url="http://localhost:6333",
collectionname="langchaindocs"
)
Search
results = qdrant.similaritysearch("query text", k=5)
Sebagai retriever
retriever = qdrant.asretriever(searchkwargs={"k": 5})
docs = retriever.getrelevantdocuments("query text")
2. Dengan LlamaIndex
from llamaindex.core import VectorStoreIndex, StorageContext
from llama
index.vectorstores.qdrant import QdrantVectorStore
from qdrant
client import QdrantClient
Initialize Qdrant
client = QdrantClient("localhost", port=6333)
Buat vector store
vectorstore = QdrantVectorStore(
client=client,
collectionname="llamaindexdocs"
)
Bangun index
storagecontext = StorageContext.fromdefaults(vectorstore=vectorstore)
index = VectorStoreIndex.fromdocuments(
documents,
storagecontext=storagecontext
)
Query
queryengine = index.asqueryengine()
response = queryengine.query("Ini tentang apa?")
Snapshots dan Backup
1. Buat Snapshot
# Buat snapshot
snapshotinfo = client.createsnapshot(collectionname="mycollection")
print(f"Snapshot dibuat: {snapshotinfo.name}")
List snapshots
snapshots = client.listsnapshots(collectionname="mycollection")
for snapshot in snapshots:
print(f"Snapshot: {snapshot.name}, Size: {snapshot.size}")
2. Recovery dari Snapshot
# Recover collection dari snapshot
client.recoversnapshot(
collectionname="mycollection",
location=f"http://localhost:6333/collections/mycollection/snapshots/{snapshotname}"
)
Atau dari file lokal
client.recoversnapshot(
collectionname="mycollection",
location="file:///path/to/snapshot.snapshot"
)
Optimasi Performa
1. Konfigurasi HNSW
from qdrantclient.models import HnswConfigDiff
Optimasi untuk recall
client.update
collection(
collectionname="mycollection",
hnswconfig=HnswConfigDiff(
m=32, # Lebih banyak koneksi = recall lebih baik
efconstruct=200 # Lebih tinggi = kualitas index lebih baik
)
)
Optimasi untuk kecepatan
client.updatecollection(
collectionname="mycollection",
hnswconfig=HnswConfigDiff(
m=16,
efconstruct=100
)
)
2. Search Parameters
from qdrantclient.models import SearchParams
High precision search
results = client.search(
collectionname="mycollection",
queryvector=queryvector,
searchparams=SearchParams(
hnswef=128, # Lebih tinggi = lebih akurat
exact=False
),
limit=10
)
Exact search (lebih lambat tapi presisi)
results = client.search(
collectionname="mycollection",
queryvector=queryvector,
searchparams=SearchParams(exact=True),
limit=10
)
Best Practices
1. Batch Processing Efisien
import numpy as np
from tqdm import tqdm
def batchupsert(client, collectionname, vectors, payloads, batchsize=100):
"""Batch upsert efisien dengan progress bar."""
total = len(vectors)
for i in tqdm(range(0, total, batchsize)):
batchvectors = vectors[i:i+batchsize]
batchpayloads = payloads[i:i+batchsize]
batchids = list(range(i, min(i+batchsize, total)))
points = [
PointStruct(id=id, vector=vec.tolist(), payload=pay)
for id, vec, pay in zip(batchids, batchvectors, batchpayloads)
]
client.upsert(collectionname=collectionname, points=points)
Penggunaan
batchupsert(client, "mycollection", allvectors, allpayloads)
2. Connection Pooling
from qdrantclient import QdrantClient
Gunakan connection pooling untuk production
client = QdrantClient(
url="http://localhost:6333",
prefer
grpc=True, # gRPC lebih cepat untuk payload besar
timeout=30
)
Kesimpulan
Qdrant adalah essential untuk aplikasi AI dengan:
Key takeaways:
- Gunakan distance metrics yang sesuai untuk use case Anda
- Buat payload indexes untuk filtered searches
- Batch operations untuk performa lebih baik
- Konfigurasi HNSW parameters berdasarkan kebutuhan recall/speed
- Gunakan named vectors untuk aplikasi multi-modal