Ana sayfa ›
Platform & Altyapı ›
Qdrant Vektör DB
🗄️Qdrant Vektör Veritabanı
📑 Bu sayfada
📺 Daha Fazlası İçin İzleyin
✅ Komtaş Kurumsal Qdrant Ortamı
Komtaş, GCP europe-west3 bölgesinde şirket geneline hizmet veren kurumsal bir Qdrant ortamına sahiptir. Bu ortam; iç bilgi tabanları, doküman arşivleri ve yapay zekâ destekli arama senaryoları için aktif olarak kullanılmaktadır.
Kurumsal bilgilerin bu vektör veritabanına eklenmesi ve mevcut koleksiyonlara erişim için Komtaş TIO (Transformation and Innovation Office) ile iletişime geçiniz. TIO ekibi; koleksiyon tasarımı, embedding pipeline kurulumu ve kiracı yönetimi konularında destek sağlayacaktır.
Qdrant, Komtaş CoPilot'un semantik arama ve RAG altyapısının temelini oluşturmaktadır. europe-west3 bölgesinde çalışan self-hosted kurulum GDPR uyumluluğunu sağlamaktadır.
7.1 Koleksiyon Tasarımı ve HNSW Ayarları
from qdrant_client import QdrantClient
from qdrant_client.models import (
Distance, VectorParams, HnswConfigDiff,
QuantizationConfig, ScalarQuantizationConfig, ScalarType,
OptimizersConfigDiff
)
client = QdrantClient(
url="http://qdrant:6333",
api_key=os.environ["QDRANT_API_KEY"],
timeout=30
)
# Üretim kalitesi koleksiyon oluşturma
def create_production_collection(collection_name: str, vector_size: int = 1536):
client.recreate_collection(
collection_name=collection_name,
vectors_config=VectorParams(
size=vector_size,
distance=Distance.COSINE,
# HNSW parametreleri
hnsw_config=HnswConfigDiff(
m=16, # Her node için bağlantı sayısı (8-64, varsayılan: 16)
ef_construct=200, # Indeks oluşturma kalitesi (yüksek = yavaş build, iyi kalite)
full_scan_threshold=10000 # Bu sayının altında brute-force
)
),
# Scalar quantization: vektör boyutunu 4x küçültür, %5-10 doğruluk kaybı
quantization_config=QuantizationConfig(
scalar=ScalarQuantizationConfig(
type=ScalarType.INT8,
quantile=0.99,
always_ram=True # Hız için RAM'de tut
)
),
# Optimizasyon ayarları
optimizers_config=OptimizersConfigDiff(
default_segment_number=4,
max_segment_size=200000,
memmap_threshold=50000,
indexing_threshold=20000,
flush_interval_sec=5
),
# Varsayılan shard sayısı
shard_number=2,
replication_factor=2 # Yüksek erişilebilirlik
)
print(f"✅ Koleksiyon oluşturuldu: {collection_name}")
📌 Kod Notları
- Koleksiyon stratejisi: Her tenant için ayrı koleksiyon vs. tek koleksiyon + payload filtresi seçimi kritiktir. Küçük tenant sayısında ayrı koleksiyon, büyük sayıda payload bazlı izolasyon tercih edilir.
- Distance.COSINE: Normalize edilmiş embedding'ler için Cosine benzerliği en yaygın metriktir. Normalize edilmemiş vektörler için Dot Product daha hızlı olabilir. Metriği sonradan değiştiremezsiniz; koleksiyon yeniden oluşturulmalıdır.
- HNSW index: Approximate Nearest Neighbor araması için kullanılır.
mveef_constructparametreleri hız/doğruluk/bellek dengesini ayarlar. - on_disk_payload: Vektör boyutu büyük ya da koleksiyon sayısı yüksekse
on_disk=TrueRAM kullanımını azaltır ancak I/O yavaşlar.
7.2 Çoklu Kiracılık (Multi-tenancy)
| Yaklaşım | İzolasyon Seviyesi | Ölçek | Yönetim Karmaşıklığı | Komtaş Kullanımı |
|---|---|---|---|---|
| Payload Tabanlı | Orta (filtre) | Yüksek (tek koleksiyon) | Düşük | İç kullanıcılar, paylaşılan bilgi tabanı |
| Koleksiyon Başına Tenant | Yüksek (tam izolasyon) | Orta (N koleksiyon) | Orta | Premium müşteri verileri |
| Hibrit (Tiered) | Dinamik | Yüksek | Yüksek | Karma kullanım senaryoları |
# Payload tabanlı multi-tenancy
from qdrant_client.models import Filter, FieldCondition, MatchValue
def search_with_tenant_isolation(
collection: str,
query_vector: list[float],
tenant_id: str,
limit: int = 10
):
"""Tenant izolasyonlu arama"""
return client.search(
collection_name=collection,
query_vector=query_vector,
limit=limit,
query_filter=Filter(
must=[
FieldCondition(
key="tenant_id",
match=MatchValue(value=tenant_id)
)
]
),
with_payload=True,
score_threshold=0.7
)
# JWT tabanlı RBAC
def create_qdrant_jwt(user_id: str, tenant_id: str, permissions: list[str]) -> str:
"""Qdrant API key ve JWT ile erişim kontrolü"""
payload = {
"sub": user_id,
"tenant_id": tenant_id,
"permissions": permissions, # ["read", "write"] veya ["read"]
"exp": datetime.utcnow() + timedelta(hours=24)
}
return jwt.encode(payload, settings.JWT_SECRET, algorithm="HS256")
📌 Kod Notları
- FieldCondition: Qdrant'ın vektör aramasını payload değerlerine göre filtreleyen yapısıdır. Her aramaya
filter=Filter(must=[...])eklemek tenant izolasyonunu garanti eder. - Tenant sızıntısı: Filtre eklemeyi unutmak kritik bir güvenlik açığıdır. Her arama fonksiyonunu
tenant_idparametresiyle zorunlu yapın ve iç testlerle doğrulayın. - Performans: Payload filtresi eklemek büyük koleksiyonlarda aramayı yavaşlatabilir. Sık filtrelenen alanlar için
create_payload_index()kullanın.
7.3 Hybrid Search ve Performans
from qdrant_client.models import SparseVector, SparseVectorParams, NamedSparseVector
from fastembed import SparseTextEmbedding
# Sparse embedding modeli (BM25 benzeri)
sparse_model = SparseTextEmbedding("Qdrant/bm25")
def hybrid_search(collection: str, query: str, limit: int = 10):
"""
Dense (semantik) + Sparse (keyword) hibrit arama
Reciprocal Rank Fusion ile birleştirme
"""
# Dense vector (anlamsal)
dense_vector = embed_dense(query)
# Sparse vector (keyword)
sparse_embedding = list(sparse_model.embed([query]))[0]
sparse_vector = SparseVector(
indices=sparse_embedding.indices.tolist(),
values=sparse_embedding.values.tolist()
)
results = client.query_points(
collection_name=collection,
prefetch=[
# Dense search
{"query": dense_vector, "using": "dense", "limit": 20},
# Sparse search
{"query": sparse_vector, "using": "sparse", "limit": 20}
],
# RRF (Reciprocal Rank Fusion) ile birleştir
query={"fusion": "rrf"},
limit=limit,
with_payload=True
)
return results