Dizinleme: Parçaları Gömme ve Depolama
Her parçayı OpenAI gömme API'sini kullanarak gömün ve ortaya çıkan vektörleri üst verilerle birlikte bir vektör deposuna ekleyip güncelleyin; böylece belgeleriniz için aranabilir bir dizin oluşturun.
Dizinleme: Parçaları Gömme ve Depolama, CoddyKit'te ücretsiz bir AI Engineering Academy dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, AI Engineering Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. AI Engineering Academy kursu toplamda 4 dersten oluşur.
Dizine Ekleme Aşaması: Genel Bakış
Belgelerinizi yükleyip parçalara ayırdıktan sonra dizine ekleme aşamasına ulaşırsınız: metin parçalarını vektör embedding'lerine dönüştürür ve aranabilir bir vektör veritabanında depolarsınız. Bu, sorgular yanıtlanmadan önceki son çevrimdışı adımdır. Embedding'lerinizin kalitesi ile depolama ve dizine ekleme stratejinizin verimliliği, RAG sisteminizin sorgu zamanındaki hızını ve doğruluğunu doğrudan belirler.
OpenAI API'si Üzerinden Embedding Oluşturma
En yaygın yaklaşım, parça metninizle OpenAI'nin embedding API'sini çağırmaktır. text-embedding-3-small modeli 1536 boyutlu vektörler üretir ve milyon belirteç başına 0,02 ABD doları maliyetle çalışır; bu, çoğu iş yükü için son derece ucuzdur. Verimliliği en üst düzeye çıkarmak için tek bir API çağrısında birden fazla metin gönderin (en fazla 2048 girdi). Yanıt, girdi metinleriyle aynı sırada, her girdi metni için bir embedding vektörü içerir.
from openai import OpenAI
client = OpenAI()
def embed_batch(texts, model='text-embedding-3-small'):
response = client.embeddings.create(
model=model,
input=texts # up to 2048 texts per call
)
return [item.embedding for item in response.data]
# Embed one batch of 100 chunk texts
texts = [chunk['text'] for chunk in chunks[:100]]
vectors = embed_batch(texts)
print(f'Embedding dimension: {len(vectors[0])}')
print(f'Embedded {len(vectors)} chunks')Verimlilik İçin Toplu İşleme
Binlerce parçayı dizine eklerken verimlilik önemlidir. Aktarım hızı ile bellek kullanımını dengelemek için parçaları 100-500'lük gruplar hâlinde işleyin. Bir hata sonrasında, daha önce işlenmiş parçalara yeniden embedding uygulamadan devam edebilmek için konumunuzu izleyin. İlerlemeyi düzenli olarak günlüğe kaydedin. 500'lük gruplar hâlinde işlenen 100.000 parça için 200 API çağrısı yaparsınız; bu işlem genellikle birkaç dakika içinde tamamlanır.
def embed_all_chunks(chunks, batch_size=200):
embedded = []
total = len(chunks)
for i in range(0, total, batch_size):
batch = chunks[i:i+batch_size]
texts = [c['text'] for c in batch]
vectors = embed_batch(texts)
for chunk, vector in zip(batch, vectors):
embedded.append({
**chunk,
'embedding': vector
})
if (i // batch_size) % 10 == 0:
print(f'Progress: {min(i+batch_size, total)}/{total}')
return embeddedDizine Ekleme Sırasında Hız Sınırı İşleme
OpenAI embedding API'sinin hız sınırları, dakika başına belirteç (TPM) cinsinden ölçülür. Büyük dizine ekleme işleri bu sınırlara ulaşır ve RateLimitError alır. Jitter içeren üstel geri çekilme uygulayın: bir hız sınırı hatası oluştuğunda yeniden denemeden önce kısa ve rastgele bir süre bekleyin; sonraki her başarısızlıkta bekleme süresini iki katına çıkarın. Bu, yeniden denemeleri zamana yayar ve tüm paralel çalışanların aynı anda API'yi aşırı yüklemesini önler.
import time
import random
from openai import RateLimitError
def embed_batch_with_retry(texts, max_retries=5):
for attempt in range(max_retries):
try:
return embed_batch(texts)
except RateLimitError:
if attempt == max_retries - 1:
raise
wait = (2 ** attempt) + random.uniform(0, 1)
print(f'Rate limited. Waiting {wait:.1f}s...')
time.sleep(wait)
return []Vektörleri Pinecone'a Upsert Etme
Embedding'leri oluşturduktan sonra bunları vektör deposuna upsert edin. Upsert etme, yeni vektörleri eklemek veya aynı ID zaten varsa mevcut vektörleri güncellemek anlamına gelir; bu işlem tasarımı gereği idempotenttir. Pinecone'da upsert edilen her kayıt, vektör ID'sini, embedding değerlerini ve daha sonra filtrelemek veya görüntülemek istediğiniz alanlardan oluşan bir üst veri sözlüğünü içerir. En iyi aktarım hızı için her çağrıda en fazla 100 kayıtlık gruplar halinde upsert edin.
import pinecone
pc = pinecone.Pinecone(api_key='YOUR_KEY')
index = pc.Index('rag-index')
def upsert_to_pinecone(embedded_chunks, batch_size=100):
for i in range(0, len(embedded_chunks), batch_size):
batch = embedded_chunks[i:i+batch_size]
vectors = [
(
chunk['id'],
chunk['embedding'],
{
'text': chunk['text'],
'source': chunk['metadata']['source'],
'page': chunk['metadata'].get('page', 0)
}
)
for chunk in batch
]
index.upsert(vectors=vectors)
print(f'Upserted {min(i+batch_size, len(embedded_chunks))}/{len(embedded_chunks)}')pgvector'da Depolama
pgvector ile embedding'leri standart SQL kullanarak doğrudan bir PostgreSQL tablosuna eklersiniz. vector veri türü, dize olarak serileştirilmiş bir Python kayan nokta listesini kabul eder. Tüm satırları ekledikten sonra yaklaşık en yakın komşu sorgularını hızlandırmak için bir HNSW Index oluşturun. Milyonlarca satır içeren mevcut bir tabloyu Index'lemek birkaç dakika sürebilir; bu nedenle Index'i toplu eklemeden önce değil, sonra oluşturun.
import psycopg2
from psycopg2.extras import execute_values
def upsert_to_pgvector(conn, embedded_chunks):
with conn.cursor() as cur:
records = [
(
chunk['id'],
chunk['text'],
chunk['metadata']['source'],
chunk['metadata'].get('page', 0),
chunk['embedding'] # list of floats
)
for chunk in embedded_chunks
]
execute_values(cur, '''
INSERT INTO document_chunks (id, text, source, page, embedding)
VALUES %s
ON CONFLICT (id) DO UPDATE
SET text = EXCLUDED.text, embedding = EXCLUDED.embedding
''', records)
conn.commit()HNSW Index Oluşturma
HNSW (Hiyerarşik Gezinilebilir Küçük Dünya), yaklaşık en yakın komşu aramasını hızlandıran Index türüdür. Sorgu vektörünü depolanan her vektörle karşılaştıran kaba kuvvet aramasının aksine HNSW, arama alanını daraltan çok katmanlı bir grafik yapısı oluşturur. m parametresi her düğümün kaç bağlantısı olduğunu belirler (daha yüksek değer, daha iyi geri çağırma ancak daha fazla bellek kullanımı demektir); ef_construction ise oluşturma sırasında Index kalitesini denetler.
-- Build HNSW index after bulk insertion
CREATE INDEX CONCURRENTLY ON document_chunks
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- Set ef_search at query time to trade recall vs speed
SET hnsw.ef_search = 100;
-- Verify index was created
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'document_chunks';Üst Veri Şeması Tasarımı
Her vektörün yanında depolanan üst veriler, güçlü filtrelenmiş erişim olanağı sağlar. Index'leme işleminden önce üst veri şemanızı tasarlayın; daha sonra yeni alanlar eklemek yeniden Index'leme gerektirir. Filtrelemede kullanacağınız alanları (departman, belge türü, tarih aralığı), alıntılarda görüntüleyeceğiniz alanları (başlık, sayfa, yazar) ve hata ayıklama için yararlı alanları (parça Index'i, toplam parça sayısı, Index'lenme zamanı) ekleyin. Üst veri değerlerini basit tutun: dizeler, sayılar ve Boole değerleri verimli şekilde Index'lenir ve filtrelenir; iç içe nesneler ise verimli değildir.
# Well-designed metadata schema
METADATA_SCHEMA = {
# For filtering at retrieval time
'department': 'HR', # string
'doc_type': 'policy', # string
'year': 2025, # integer
'is_active': True, # boolean
# For display in citations
'title': 'Employee Handbook 2025',
'author': 'HR Team',
'page': 12,
'source': 's3://docs/handbook_2025.pdf',
# For debugging and updates
'chunk_index': 3,
'total_chunks': 24,
'indexed_at': '2025-09-01T10:00:00Z'
}Uzun Index'leme İşlerinde Denetim Noktaları
Büyük bir derlemi Index'lemek saatler sürebilir. İşlemin ortasında yaşanan bir çökme, tüm ilerlemeyi boşa çıkarır. Başarıyla Index'lenen parçaları kaydeden bir denetim noktası dosyası uygulayın. Yeniden başlatıldığında, daha önce Index'lenmiş parçaları atlayıp kaldığınız yerden devam edin. Bu, Index'leme işini idempotent ve sürdürmeye güvenli hale getirir. Denetim noktasını, işlenmiş parça kimliklerinden oluşan bir küme olarak JSON dosyasında veya veritabanı tablosunda saklayın.
import json
from pathlib import Path
CHECKPOINT_FILE = '/tmp/index_checkpoint.json'
def load_checkpoint():
if Path(CHECKPOINT_FILE).exists():
return set(json.loads(Path(CHECKPOINT_FILE).read_text()))
return set()
def save_checkpoint(indexed_ids):
Path(CHECKPOINT_FILE).write_text(json.dumps(list(indexed_ids)))
def index_with_checkpoint(chunks, index):
done = load_checkpoint()
remaining = [c for c in chunks if c['id'] not in done]
print(f'Resuming: {len(done)} done, {len(remaining)} remaining')
for chunk in remaining:
upsert_to_pinecone([chunk], index)
done.add(chunk['id'])
save_checkpoint(done)Index Eksiksizliğini Doğrulama
Index'leme işleminden sonra tüm parçaların vektör deposuna ulaştığını doğrulayın. Parçalayıcınızın ürettiği parça sayısını, Index'in bildirdiği vektör sayısıyla karşılaştırın. Bilinen bir belgenin metniyle Index'i sorgulayın ve beklenen sonucun ilk 5 sonuç arasında göründüğünü doğrulayın. Altın test kümenizden bilinen birkaç sorguyu çalıştırın ve kesinliğin beklenen düzeyde olup olmadığını kontrol edin. Doğrulamadan Index'in eksiksiz olduğunu asla varsaymayın.
def verify_index(index, chunks, sample_size=10):
index_stats = index.describe_index_stats()
total_vectors = index_stats.total_vector_count
expected = len(chunks)
print(f'Index vectors: {total_vectors}, Expected: {expected}')
if total_vectors != expected:
print('WARNING: mismatch — some chunks may not have been indexed')
# Spot-check retrieval
import random
sample = random.sample(chunks, sample_size)
for chunk in sample:
vec = embed_batch([chunk['text']])[0]
results = index.query(vector=vec, top_k=1, include_metadata=True)
top_id = results.matches[0].id if results.matches else None
if top_id != chunk['id']:
print(f'WARNING: expected {chunk["id"]}, got {top_id}')Yerel Embedding Alternatifleri
Altyapınızın dışına çıkarılamayacak gizlilik açısından hassas veriler için yerel olarak barındırılan embedding modellerini kullanın. sentence-transformers kütüphanesi, all-MiniLM-L6-v2 (384 boyutlu, 22 MB, çok hızlı) ve bge-large-en-v1.5 (1024 boyutlu, daha kaliteli) gibi yüksek kaliteli modeller sağlar. Orta ölçekli iş yüklerinde bunları CPU üzerinde, büyük Index'leme işlerinde ise GPU üzerinde çalıştırın. Yerel modeller API maliyetlerini ve veri çıkışını ortadan kaldırır; ancak model dosyalarını ve işlem kaynaklarını yönetmenizi gerektirir.
from sentence_transformers import SentenceTransformer
# Load once at startup
model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
def embed_locally(texts, batch_size=64):
# encode() handles batching internally
embeddings = model.encode(
texts,
batch_size=batch_size,
show_progress_bar=True,
convert_to_numpy=True
)
return embeddings.tolist() # convert numpy array to Python list
vectors = embed_locally([c['text'] for c in chunks])Kısa Kontrol
Bu dersteki yapay zekâ mühendisliği kavramlarını anlayıp anlamadığınızı test edin.
Ders Özeti
Bu derste şunları öğrendiniz: OpenAI API ile embedding'leri gruplar halinde oluşturmayı ve üstel geri çekilmeyle hız sınırlarını yönetmeyi, üst verilerle vektörleri Pinecone ve pgvector'a upsert etmeyi, hızlı yaklaşık en yakın komşu araması için HNSW Index'leri oluşturmayı ve denetim noktası tabanlı sürdürme, üst veri şeması tasarımı ve Index eksiksizliğini doğrulama gibi üretim ortamı en iyi uygulamalarını. Sırada, parçaları alan ve temellendirilmiş yanıtlar oluşturan sorgu hattını kuracağız.
Sıkça Sorulan Sorular
“Dizinleme: Parçaları Gömme ve Depolama” dersi ücretsiz mi?
Evet — “Dizinleme: Parçaları Gömme ve Depolama” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve AI Engineering Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. AI Engineering Academy kursu toplamda 4 dersten oluşur.
“Dizinleme: Parçaları Gömme ve Depolama” dersinde ne öğreneceğim?
Her parçayı OpenAI gömme API'sini kullanarak gömün ve ortaya çıkan vektörleri üst verilerle birlikte bir vektör deposuna ekleyip güncelleyin; böylece belgeleriniz için aranabilir bir dizin oluşturun. AI Engineering Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
AI Engineering Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te AI Engineering Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“Dizinleme: Parçaları Gömme ve Depolama” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu AI Engineering Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her AI Engineering Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Belge Yükleme ve Metin Çıkarma
- Parçalama Stratejileri: Sabit, Cümle Tabanlı ve Özyinelemeli
- Dizinleme: Parçaları Gömme ve Depolama
- Sorgulama, Geri Getirme ve Oluşturma