SQL Server 2025 ile Vector Search: RAG Mimarisi, Güvenlik ve Production Checklist


1. Başlıyoruz

Vector Search serisinin üçüncü ve son bölümüne hoş geldin. İlk bölümde VECTOR veri tipini, embedding’leri ve ilk benzerlik sorgusunu yapmıştık. İkinci bölümde 200 PDF’lik bir koleksiyonu chunk’lara bölüp toplu embedding üretmiş, DiskANN indeksini kurup brute force ile arasındaki 28 kat hız farkını gözlemlemiştik.

Bu bölümde ise test ortamından çıkıp gerçek dünyaya geçiyoruz:

(1) RAG mimarisini kurup kullanıcı sorusuna nihai cevabı üreten “IT dokümantasyon asistanı”nı tamamlayacağız
(2) API key’leri güvenli saklamayı ve private network üzerinden Azure OpenAI’a nasıl ulaşılacağını göstereceğim
(3) production’a alırken sorulacak kritik soruların cevaplarını — rate limit, embedding versiyonlama, maliyet — bir checklist olarak bırakacağım.

2. RAG’ın Büyük Resmi

RAG (Retrieval-Augmented Generation) üç adımdan oluşan basit ama güçlü bir mimari:

  1. Retrieve — Kullanıcının sorusunu embedding’e çevir, tablodaki en ilgili K doküman parçasını vector search ile bul.
  2. Augment — Bu parçaları, orijinal soruyla birlikte bir prompt’un içine göm. LLM’e “yalnızca bu kaynaklarda yazanı kullan” talimatı ver.
  3. Generate — LLM’e bu prompt’u gönder, kullanıcıya dönecek nihai cevabı al.

Neden önemli? Çünkü LLM’in tek başına cevap vermesi durumunda (halisyünasyon riski) veya güncel olmayan bilgi vermesi durumunda sorun yaşıyordunuz. RAG ile LLM’in cevabı, senin zaten yönettiğin SQL Server’daki güncel dokümanlara dayanıyor. Fark büyük: bir kullanıcı “bizim incident playbook’unda Redis cluster için ne yazıyor?” sorduğunda, gerçek playbook’undan alıntıyla cevap geliyor.

3. Retrieve — En İlgili Chunk’ları Çekmek

Bölüm 2’nin pipeline’ıyla elinde dbo.DocumentChunks tablosu ve DiskANN indeksi var. Soruyu embedding’e çevirip (aynı Azure OpenAI embeddings endpoint’i), top-5 chunk’ı çekiyorsun. Bunu bir stored procedure içine toparlamak pratik:

CREATE OR ALTER PROCEDURE dbo.GetRelevantChunks
@QueryEmbedding VECTOR(1536),
@TopK INT = 5
AS
BEGIN
SET NOCOUNT ON;
SELECT TOP (@TopK)
c.ChunkId,
d.FileName,
c.PageNumber,
c.ChunkText,
VECTOR_DISTANCE('cosine', c.Embedding, @QueryEmbedding) AS Distance
FROM dbo.DocumentChunks c
JOIN dbo.Documents d ON d.DocumentId = c.DocumentId
WITH (INDEX = IX_Chunks_Embedding)
ORDER BY VECTOR_DISTANCE('cosine', c.Embedding, @QueryEmbedding) ASC;
END
GO

Top-K’yi 5 olarak başlatıyorum. Daha fazla sonuç = LLM’e daha çok bağlam = daha doğru cevap, ama maliyet ve hız pazarlığı var. Tipik doküman QA için 5-10 arası pratik bir seçim olur.

4. Augment — Prompt’u Kurmak

Retrieve’den dönen chunk’ları, sistem talimatı ve kullanıcı sorusuyla birlikte LLM’in anlayacağı formata çeviriyoruz. Sistem talimatı şu üç şeyi söylemek zorunda:

  • Sadece verilen kaynaklardan cevap ver, tahmin üretme.
  • Kaynakta olmayan bilgi sorulursa “bu soruya cevap verecek bilgim yok” de.
  • Her iddia için hangi dosya ve sayfa’dan geldiğini belirt.

Python tarafında prompt üretimi:

def build_prompt(question, chunks):
sources = "\n\n".join(
f"[Kaynak: {c['FileName']}, sayfa {c['PageNumber']}]\n{c['ChunkText']}"
for c in chunks
)
system = (
"Sen bir şirket içi IT asistanısın. Yalnızca aşağıda verilen kaynaklardan "
"cevap ver. Kaynakta yazmayan bilgi sorulursa 'bu konuda elimde kaynak yok' "
"de. Her iddia için parantez içinde [Kaynak: dosya, sayfa] formatında "
"atıf ver."
)
user = f"Kaynaklar:\n\n{sources}\n\nSoru: {question}"
return [
{"role": "system", "content": system},
{"role": "user", "content": user},
]

Sistem talimatını yazarken şu iki tuzak var, dikkat: “kaynağa sadık kal” talimatı yetersiz — LLM yine de yan bilgilerle cevabı “süsleyebiliyor.” Explicit olarak “verilmeyen her bilgiyi reddet” demek gerekiyor. İkincisi, atıf talimatı yoksa LLM hangi kaynağa baktığını söylemiyor, kullanıcı da doğrulayamıyor.

5. Generate — LLM Çağrısı

Bu aşamada tercih ettiğiniz LLM’i çağırıyorsunuz. Azure OpenAI’ın gpt-4o-mini modelini kullanıyorum — maliyet/kalite oranı iyi ve Türkçe’yi de makul düzeyde konuşuyor.

def answer_question(question):
# 1. Soruyu embedding'e çevir
q_embedding = client.embeddings.create(
model="embed-small",
input=,
).data[0].embedding
# 2. SQL Server'dan top-5 chunk'ı çek
cur.execute(
"EXEC dbo.GetRelevantChunks @QueryEmbedding = CAST(? AS VECTOR(1536)), @TopK = 5",
str(q_embedding),
)
chunks = [
{"FileName": r[1], "PageNumber": r[2], "ChunkText": r[3]}
for r in cur.fetchall()
]
# 3. Prompt'u kur
messages = build_prompt(question, chunks)
# 4. LLM'e sor
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
temperature=0.1,
)
return response.choices[0].message.content

Bu fonksiyonu bir REST endpoint’in arkasına koyup Slack bot’undan, intranet portal’ından veya doğrudan DBA araçlarından çağırabilirsin. “Son backup’ım başarısız oldu, ne yapmalıyım?” → asistanın backup_recovery_runbook.pdf‘in sayfa 12’sinden alıntı yaparak talimat verir.

6. Güvenlik: Database Scoped Credential

Yukarıdaki kod Azure OpenAI API key’ini bir ortam değişkeninde tutuyor. Production’da bu yetmez — özellikle SQL Server’ın kendisi de LLM çağrıları yapacaksa. Database Scoped Credential bu iş için tasarlandı:

-- Master key (yoksa) bir kereye mahsus
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Str0ngPass!2026';
-- Azure OpenAI için credential
CREATE DATABASE SCOPED CREDENTIAL [AzureOpenAICredential]
WITH IDENTITY = 'HTTPEndpointHeaders',
SECRET = '{"api-key": "<AZURE_OPENAI_KEY>"}';

Bu credential’ı kullanarak T-SQL içinden doğrudan embedding üretebilirsin:

DECLARE @payload NVARCHAR(MAX) =
N'{"input": "SQL Server 2025 Vector Search nedir?"}';
DECLARE @response NVARCHAR(MAX);
EXEC sp_invoke_external_rest_endpoint
@url = N'https://<resource>.openai.azure.com/openai/deployments/embed-small/embeddings?api-version=2024-10-21',
@method = 'POST',
@headers = N'{"Content-Type":"application/json"}',
@payload = @payload,
@credential = [AzureOpenAICredential],
@response = @response OUTPUT;
-- response.result.data[0].embedding JSON array'i VECTOR'a cast edilebilir

Bu yaklaşımın güzel tarafı: API key asla uygulamada görünmüyor, SQL Server içinde şifreli duruyor, audit loglanabiliyor. DBA olarak kontrol edebileceğin, yönlendirebileceğin tek nokta haline geliyor.

7. Private Endpoint ile Trafik İzolasyonu

API key güvenli saklansa bile, default durumda SQL Server’dan Azure OpenAI’a giden çağrı public internet üzerinden gidiyor. Regülasyona tabi olan sektörlerde (finans, sağlık, kamu) bu kabul edilmiyor. Çözüm: Azure OpenAI’ı Private Endpoint ile SQL Server’ın olduğu VNet’e bağlamak. Kısa checklist:

  • Azure OpenAI kaynağında Private Endpoint oluştur, SQL Server’ın subnet’ine yerleştir.
  • Azure OpenAI’ın public network access ayarını Disabled yap.
  • Private DNS Zone ile *.openai.azure.com adreslerinin private IP’ye çözülmesini sağla.
  • Firewall kuralları: SQL Server subnet’inden 443 çıkışı Private Endpoint IP’ye izinli olsun.

Kurulum tamam olduğunda sp_invoke_external_rest_endpoint çağrısı aynı kalıyor — endpoint URL’i yine *.openai.azure.com. Fark şu: trafik artık public internet’e hiç çıkmıyor, tamamen Azure backbone içinde ilerliyor.

8. Production Checklist

Sistemi kullanıma açmadan önce kafanda netleşmesi gereken üç konu var.

Rate limit yönetimi. Azure OpenAI deployment’ınızın TPM (tokens per minute) limiti var. Pik saatte 100 eşzamanlı kullanıcı soru sorarsa patlar. İki korunma: (a) her LLM çağrısını retry-with-backoff içine alın (429 Too Many Requests geldiğinde 1s, 2s, 4s bekleyerek tekrar deneyin), (b) bir kuyruk sistemi (Azure Service Bus, Redis queue) arkasına alın, pik yükü dağıtın.

Embedding versiyonlama. Bugün text-embedding-3-small ile embedding ürettin. 18 ay sonra model güncellendi, sonuçlar daha iyi. Tüm tabloyu yeniden embed etmen gerekecek — 200 PDF için 30 dakika, 2 milyon chunk için üç gün. Çözüm: tabloya EmbeddingModel kolonu ekle (örn. text-embedding-3-small, text-embedding-3-large-v2) ve sorgularda versiyon filtresi kullan. Yeni model devreye alınırken iki model bir süre paralel çalışır, sonra eski versiyonlar temizlenir.

Maliyet takibi. Embedding üretimi ucuz (1M token yaklaşık 0.02 USD), ama LLM çağrıları pahalıdır (gpt-4o-mini ile 1M input token yaklaşık 0.15 USD).

Maliyeti tahmin edilebilir yapmak için:

– Her soru-cevap döngüsünün kaç token harcadığını logla
– Günlük veya haftalık kullanıcı başı limiti belirle
– Azure Cost Management’ta budget alert kur. Kurumsal kullanımda “bu sistemi açtığımız zaman aylık maliyet ne olacak?” sorusu kaçınılmaz geliyor, önceden cevaplamak işi kolaylaştırır.

9. Bitiriyoruz

Üç bölümde şunları yaptık: VECTOR veri tipini öğrendik, Azure OpenAI ile embedding üretip SQL Server’a yazdık, PDF koleksiyonundan uçtan uca bir pipeline kurduk, DiskANN ile performansı optimize ettik ve en sonunda gerçek bir IT dokümantasyon asistanı inşa ettik.

Önceki makalelerimden alışkınsınız, kendi ortamınızda bunu deneyen, sorun yaşayan ya da ilginç bir kullanım senaryosu bulan herkese duyurum: yorumlara yazın. Özellikle “kendi şirketimde şu senaryoya uyarladım, şu sonucu aldım” gibi pratik notlar, bu seriyi hep güncel tutmam için en değerli geri bildirim.

Sıradaki seride SQL Server 2025’in diğer öne çıkan özelliklerini derinlemesine ele alacağız.


Yavuz Filizlibay sitesinden daha fazla şey keşfedin

Son gönderilerin e-postanıza gönderilmesi için abone olun.


Bir yanıt yazın

Bu site istenmeyenleri azaltmak için Akismet kullanır. Yorum verilerinizin nasıl işlendiğini öğrenin.

Yavuz Filizlibay sitesinden daha fazla şey keşfedin

Okumaya devam etmek ve tüm arşive erişim kazanmak için hemen abone olun.

Okumaya Devam Edin