Giriş
Semantik arama ve RAG (Retrieval-Augmented Generation) uygulamaları, yalnızca bir metnin kelimelerine değil, anlamına göre sonuç döndürerek daha isabetli yanıtlar verebiliyor. Bu yaklaşımı uygulamak için vektör veritabanı şart. Pek çok ekip, halihazırda kullandıkları PostgreSQL üzerinde pgvector eklentisiyle bu ihtiyacı karşılıyor. Bu yazıda, PostgreSQL + pgvector kombinasyonuyla semantik arama altyapısını nasıl kuracağınızı, indekslemeyi nasıl yapacağınızı ve performansı nasıl optimize edeceğinizi adım adım anlatıyorum.
Neden pgvector?
Pgvector, PostgreSQL’e vektör veri tipi (vector) ve benzerlik aramaları (cosine, L2, inner product) kazandırır. Ayrı bir veritabanı yönetmek yerine tek bir Postgres kümesi üzerinde hem ilişkisel verilerinizi hem de embedding’lerinizi saklayabilirsiniz. Bu, devops maliyetini azaltırken güçlü ACID garantileri ve yedekleme stratejilerinden de yararlanmanızı sağlar.
Önkoşullar
PostgreSQL 14+ önerilir; performans ve özellikler için 15/16 daha iyi. Sunucuda en az 4 CPU, 8 GB RAM başlamak için konfor sağlar. Ayrıca embedding üretmek için bir model (örneğin OpenAI text-embedding-3-small, Instructor, E5-large veya yerel bir model) gereklidir.
Kurulum (Docker ve Yerel)
Docker ile hızlı kurulum: Resmi Postgres imajı yerine pgvector içeren bir imaj kullanabilirsiniz. Örnek:
docker run -d --name pg -e POSTGRES_PASSWORD=secret -p 5432:5432 ankane/pgvector
Yerel kurulum (Ubuntu/Debian): Paket yöneticinizde pgvector olmayabilir. Kaynaktan kurulum tipik akış:
sudo apt-get update && sudo apt-get install -y postgresql postgresql-server-dev-all git make gcc
git clone https://github.com/pgvector/pgvector.git && cd pgvector && make && sudo make install
Veritabanını Hazırlama
Postgres’e bağlandıktan sonra eklentiyi etkinleştirin ve şemanızı oluşturun:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE documents (id bigserial PRIMARY KEY, title text, body text, embedding vector(1536));
Burada vector(1536) embedding boyutunu temsil ediyor. Kullanacağınız modele göre bu değeri değiştirin (örn. 768, 1024, 1536).
Embedding Üretme ve Veri Ekleme
Embedding’leri uygulama katmanında üretip Postgres’e yazmak en yaygın yaklaşım. Basit akış: metni temizle, cümlelere/segmentlere böl, embedding modeline gönder, sonuç vektörünü tabloya ekle.
Örnek bir ekleme akışı:
INSERT INTO documents (title, body, embedding) VALUES ('KVKK Özeti', 'Kişisel verilerin korunması...', '[0.012, -0.034, ...]');
Not: pgvector, köşeli parantezle vektör alır. Uygulama dilinizde (Python/Node/Go) embedding dizisini string’e çevirip eklemek pratik bir yöntemdir.
Benzerlik İndeksleri: IVFFlat ve HNSW
Büyük veri kümelerinde ham tarama yavaştır. Bu nedenle IVFFlat veya HNSW indeksleri kullanılır. IVFFlat için önce tabloyu kabaca küme merkezlerine göre “eğitmek” gerekir.
-- Koşul: önce yeterince satır eklenmiş olmalı
CREATE INDEX ON documents USING ivfflat (embedding vector_cosine) WITH (lists = 100);
HNSW, eğitime gerek duymaz ve bazı veri setlerinde daha iyi gecikme/kalite dengesi sunabilir:
CREATE INDEX ON documents USING hnsw (embedding vector_cosine) WITH (m = 16, ef_construction = 128);
Metrik seçimi kritiktir: embedding modeliniz cosine ile eğitildiyse vector_cosine seçin. Performans için lists (IVFFlat) ve ef_search (HNSW) değerlerini iş yükünüze göre ayarlayın.
Semantik Arama Sorguları
Arama anında, sorgu metnini embedding’e çevirin ve en yakın komşuları çekin:
-- sorgu_embedding uygulama katmanından parametre olarak gelir
SELECT id, title, body FROM documents ORDER BY embedding <#> :sorgu_embedding LIMIT 5;
<#> operatörü cosine distance’dır. En iyi sonuçları almak için LIMIT’i ve filtre koşullarını (ör. kategori, tarih aralığı) birlikte kullanın.
RAG İçin Basit Bir Akış
- Kullanıcı sorusunu alın ve embedding’e dönüştürün.
- PostgreSQL’den en alakalı 5–10 dokümanı semantik aramayla çekin.
- Cevaplayıcı LLM’e, bu parçaları bağlamsal ek metin (context) olarak verin.
- Kaynakları (title ve id) cevapla birlikte kullanıcıya gösterin. Bu yaklaşım, halüsinasyonları azaltır ve izlenebilirlik sağlar.
Performans ve Ölçek İpuçları
1) İndeks ısınması: Sık aranan sorgu türleri için sistem başladığında birkaç “ısınma” araması yapın. Bu, sayfa önbelleğini doldurur.
2) Paralelleştirme: Toplu embedding üretiminde çoklu iş parçacığı ya da job queue kullanın. Veritabanına batch insert (ör. 100–1000 satır) performans sağlar.
3) Tablo tasarımı: Metin gövdeleri büyükse, embedding’leri ayrı bir tabloda (documents_vec) tutup body’yi object storage’a koymayı değerlendirin; Postgres’te sadece referans saklayın.
4) Bakım: Yoğun yazma/indeks güncellemelerinde VACUUM (ANALYZE) planlayın. Autovacuum ayarlarını (naptime, cost_limit) iş yükünüze göre iyileştirin.
5) IVFFlat ayarları: lists değerini veri büyüklüğüne göre artırmak hatırlama oranını iyileştirir; sorgu anında SET ivfflat.probes = X; ile daha fazla liste tarayıp isabet oranını yükseltebilirsiniz (gecikme artar).
6) HNSW ayarları: SET hnsw.ef_search = 64/128/256 gibi değerlerle kalite/gecikmeyi dengeleyin. Daha yüksek ef_search, daha iyi sonuç ama daha fazla CPU demektir.
7) Sharding/Partitioning: Konu veya müşteri bazlı PARTITION BY LIST ile arama alanını daraltmak ciddi kazanç sağlar.
Güvenlik ve Versiyonlama
Embedding uzayı model güncellemeleriyle değişebilir. Model versiyonunu tabloda saklayın (örn. model_version text) ve farklı versiyonlar için ayrı indeks tutun. Erişim tarafında Row Level Security (RLS) ile müşteri/veri bölümlendirmesini zorunlu kılın.
Hata Ayıklama ve Sık Karşılaşılan Sorunlar
- ERROR: type "vector" does not exist: CREATE EXTENSION vector; komutunun ilgili veritabanında çalıştığından ve eklentinin kurulu olduğundan emin olun.
- IVFFlat “not enough tuples”: İndeksi kurmadan önce yeterli sayıda satır eklenmiş olmalı; aksi halde eğitim yapılamaz.
- Yüksek gecikme: İndeks kullanılmıyor olabilir; EXPLAIN (ANALYZE, BUFFERS) ile planı inceleyin. probes veya ef_search değerlerini ayarlayın.
Sonuç
Pgvector, PostgreSQL’i güçlü bir vektör arama motoruna dönüştürüyor. Doğru indeks ve ayarlarla milyonlarca embedding üzerinde milisaniyeler içinde semantik arama yapılabiliyor. RAG senaryolarında ise hem kaynak yönetimini sadeleştiriyor hem de mevcut Postgres ekosisteminin güvenilirliğinden yararlanmanızı sağlıyor. Küçük bir POC ile başlayıp indeks parametrelerini kademeli ayarlayarak en iyi maliyet/performans noktasını yakalayabilirsiniz.
Hiç yorum yok:
Yorum Gönder