Menü

Dil Seçimi
Blog Listesine Dön

SQL Server 2025 ve Yerel Yapay Zeka ile Tam Otonom "Anlamsal Arama" Mimarisi (Vektör)

4 Ekim 2026
Ahmet Bektaş

Yıllardır yaşanan sorunlar arasında en büyük kabuslardan biri kirli veridir. Özellikle kullanıcıların serbest metin olarak girdiği "Adres" gibi alanlarda standart klasik T-SQL LIKE '%...%' sorguları tamamen çaresiz kalır. Kullanıcı "Çatalca" yerine "Katalca", "Mahallesi" yerine "Mhl." yazdığında o kaydı bulmak neredeyse imkansızdır.

SQL Server 2025 ile hayatımıza giren Vektör veri tipi ve VECTOR_DISTANCE fonksiyonu bu sorunu kökünden çözüyor. Ancak verilerimizi vektöre (matematiksel anlama) çevirmek için veritabanımızdaki milyonlarca adresi dış dünyadaki (OpenAI, Google vb.) bulut API'lerine mi göndereceğiz?

Modern DevSecOps kültüründe veriyi dışarı sızdırmamak en katı kurallardan biridir. Bu makalede, SQL Server içine Python gömmek yerine, tamamen kendi sunucumuzda, internete kapalı olarak çalışan yerel bir Yapay Zeka (Ollama) kurarak kusursuz bir "Bulanık Arama" mimarisini sıfırdan nasıl inşa edeceğimizi inceleyeceğiz.

Örnek olarak kullanacağımız veritabanı tamamen random veriler ile doldurulmuş bir adres veritabanıdır. İçerisinde 20.000 adet veri vardır ve testler bu veritabanı üzerinde yapılmıştır. Bu makalemde sizlere kurulum aşamasında yaşadığım bütün sorunları ve dipnotları şeffaf bir şekilde paylaşacağım. Ancak kodlara geçmeden önce, bu sistemin arka planında yatan matematiğe kısaca göz atalım.

Geleneksel Aramanın Ötesi: Vektör Uzayı ve Kosinüs Benzerliği (Cosine Similarity) Nasıl Çalışır?

Geleneksel ilişkisel veritabanı dünyasında arama işlemleri kelimelerin dizilimine ve harf eşleşmelerine dayanır. Bir VARCHAR sütununda B-Tree indeks kullanarak arama yaptığınızda, SQL Server sadece o karakterlerin yan yana gelip gelmediğine bakar. Metnin "anlamı" veritabanı motoru için koca bir hiçtir.

Peki yapay zeka bu körlüğü nasıl aşıyor? Cevap: Vektörler ve Kosinüs Benzerliği.

1. Kelimeleri Matematiğe Çevirmek (Embeddings)

Yapay zeka modelleri, kendisine verilen bir metni okuduğunda onu devasa bir çok boyutlu uzayda matematiksel bir vektöre (koordinata) dönüştürür. Bunu daha iyi kavramak için yukarıdaki görselde yer alan 2 boyutlu uzay örneğine bakalım:

Şekil 1'de görebileceğiniz gibi; "Coffee" (Kahve) ve "Tea" (Çay) kelimeleri anlamsal olarak birbirine çok benzediği için (ikisi de içecek kategorisindedir), uzayda birbirine çok yakın yönleri gösterirler ve aralarındaki açı ($\theta$) oldukça dardır. Ancak sağ taraftaki "Ball" (Top) ve "Crocodile" (Timsah) kelimelerinin birbiriyle anlamsal hiçbir alakası yoktur; bu yüzden vektörleri uzayda bambaşka yönlere bakar ve aralarındaki açı çok geniştir.

Makale içeriği

İşte bu makalede kullanacağımız gelişmiş dil modeli (bge-m3), adres metinlerimizi sadece 2 boyutta değil, tam 1024 farklı boyutta (eksende) bu şekilde konumlandırır! Ortaya çıkan bu 1024 adet sayılık koordinat dizisine Vektör denir. Anlamca birbirine benzeyen ("Katalca" ve "Çatalca" gibi) kelimeler, bu devasa uzayda birbirine çok yakın noktalara yerleşir.


2. Kosinüs Benzerliği ile "Anlamı" Ölçmek

Kullanıcı arama kutusuna eksik veya bozuk bir adres yazdığında, yapay zeka bu metni de bir vektör olarak uzaya gönderir. Veritabanı bu yeni noktanın hangi adrese ait olduğunu bulmak için, tıpkı Şekil 1'deki formülde olduğu gibi merkezden bu noktalara çizilen iki vektör arasındaki açıya bakar. Veri biliminde buna Kosinüs Benzerliği denir.

  • Açı daraldıkça (0°'ye yaklaştıkça): Kelimeler veya harfler farklı bile olsa, cümlelerin "anlamı" birbiriyle eşleşir.
  • Açı genişledikçe (90°'ye yaklaştıkça): Cümlelerin birbiriyle hiçbir anlamsal bağı olmadığı (Top ve Timsah gibi) anlaşılır.

SQL Server 2025'teki VECTOR_DISTANCE fonksiyonu bu karmaşık açıyı milisaniyeler içinde hesaplar ve formülü gereği sonucu bir "mesafe" olarak döndürür. Skor 0'a (sıfıra) ne kadar yakınsa, anlamsal eşleşme o kadar kusursuzdur! Şimdi bu mimariyi SQL Server üzerinde nasıl ayağa kaldıracağımıza adım adım bakalım.


1. Mimari Karar: Yerel Yapay Zeka (Ollama) ve Dil Sorunu

Sürecin ilk adımı, metinleri sayısal dizilere (vektörlere) çevirecek motoru sunucuya kurmaktır. Bunun için ücretsiz ve açık kaynaklı Ollama'yı sunucumuza kurarak işe başlıyoruz (Arka planda http://localhost:11434 üzerinden REST API olarak ayağa kalkar).

Ollama'yı sunucumuza kurmak çok basitti. Ancak 20.000 satırlık veritabanımızda ilk denemelerimizi yaparken şok edici bir şeyle karşılaştım: Farklı şehirlerdeki adresler aramalarda birebir aynı skorla (Mesafe = 0) geliyordu! Trabzon ile Erzurum, yapay zeka için aynı yerdi.

Bunun sebebi internette sıkça önerilen İngilizce odaklı modellerin (örn: nomic-embed-text) Türkçe sorunlarıydı. Türkçe adres şablonunu görünce coğrafyayı anlayamıyor ve hepsini aynı matematiksel noktaya fırlatıyordu (Bu duruma Embedding Collapse denir).

Bu cehaleti aşmak için 100'den fazla dili ana dili gibi anlayan, endüstri standardı bge-m3 modelini kullanacağız. Sunucumuzun komut satırından (CMD) modeli indiriyoruz:

ollama pull bge-m3


2. SQL Server Hazırlığı ve Tablo Güncellemesi

Modelimiz metinleri 1024 boyutlu matematiksel dizilere çeviriyor. Öncelikle tablomuzda bu veriyi tutacak sütunu oluşturmalıyız.

Ayrıca SQL Server'ın kendi içindeki REST API bileşeni sadece şifreli (HTTPS) bağlantı kabul ettiği için, yerel ağımızdaki Ollama'ya (HTTP) ulaşmak adına güvenilir OLE Automation prosedürlerini aktif ediyoruz.

-- 1. OLE Automation'ı Aktif Etme
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'Ole Automation Procedures', 1; RECONFIGURE;

-- 2. Tabloya 1024 Boyutlu Vektör Sütununu Ekleme
ALTER TABLE dbo.SALES_Vektor ADD AdresVektoru VECTOR(1024);


3. Eski Verileri Toplu Güncelleme

İçerideki 20.000 adet random adresi bir defaya mahsus vektörlemek için bir CURSOR (döngü) yazdım. Burada T-SQL Sorununa dikkat etmeliyiz: Döngü (Cursor) çok hızlı çalıştığı için, Ollama'ya arka arkaya binlerce kez istek atarken, servis saniyelik bir tıkanma yaşadığında T-SQL değişkenleri boşaltmaz. Hafızasında kalan bir önceki başarılı kaydın vektörünü tutar ve sonraki 10-15 kayda yanlışlıkla aynı vektörü kopyalar.

Tecrübe Notu: Bunu önlemek için döngünün hemen başında SET @ResponseText = NULL; diyerek değişkenleri zorla sıfırlamak hayati önem taşır. İşte o toplu güncelleme kodumuz:

SET NOCOUNT ON;
DECLARE @KayitID INT, @AdresMetni VARCHAR(500);
DECLARE @BasariliKayit INT = 0;
DECLARE @Url NVARCHAR(4000) = N'http://localhost:11434/api/embeddings';
DECLARE @Payload NVARCHAR(MAX), @ResponseText NVARCHAR(MAX), @VektorString NVARCHAR(MAX);
DECLARE @Object INT, @HResult INT;
DECLARE @ResponseTable TABLE (JsonVerisi NVARCHAR(MAX));

DECLARE AdresCursor CURSOR FOR
SELECT ID, ADDRESSTEXT FROM dbo.SALES_Vektor WHERE ADDRESSTEXT IS NOT NULL AND AdresVektoru IS NULL;

OPEN AdresCursor;
FETCH NEXT FROM AdresCursor INTO @KayitID, @AdresMetni;

WHILE @@FETCH_STATUS = 0
BEGIN
    -- Klonlanmayı önlemek için her satırda hafızayı temizle!
    SET @ResponseText = NULL;
    SET @VektorString = NULL;
    DELETE FROM @ResponseTable;

    SET @Payload = N'{"model": "bge-m3", "prompt": "' + STRING_ESCAPE(@AdresMetni, 'json') + '"}';
    
    EXEC @HResult = sp_OACreate 'MSXML2.ServerXMLHTTP', @Object OUT;
    IF @HResult = 0
    BEGIN
        EXEC sp_OAMethod @Object, 'open', NULL, 'POST', @Url, 'false';
        EXEC sp_OAMethod @Object, 'setRequestHeader', NULL, 'Content-Type', 'application/json';
        EXEC sp_OAMethod @Object, 'send', NULL, @Payload;
        
        INSERT INTO @ResponseTable (JsonVerisi)
        EXEC sp_OAGetProperty @Object, 'responseText';
        EXEC sp_OADestroy @Object;
        
        SELECT TOP 1 @ResponseText = JsonVerisi FROM @ResponseTable;
        IF @ResponseText IS NOT NULL
        BEGIN
            SET @VektorString = JSON_QUERY(@ResponseText, '$.embedding');
            IF @VektorString IS NOT NULL
            BEGIN
                UPDATE dbo.SALES_Vektor
                SET AdresVektoru = CAST(@VektorString AS VECTOR(1024))
                WHERE ID = @KayitID;
                SET @BasariliKayit = @BasariliKayit + 1;
            END
        END
    END
    FETCH NEXT FROM AdresCursor INTO @KayitID, @AdresMetni;
END
CLOSE AdresCursor; DEALLOCATE AdresCursor;
SELECT CAST(@BasariliKayit AS VARCHAR) + ' Kayıt Başarıyla Vektörlendi!' AS Sonuc;


4. Sistemi Otonom Hale Getirmek (Gelecek Veriler İçin)

Eski verilerimizi temizledik. Peki ya yeni eklenecek veriler? Yeni bir müşteri eklendiğinde veya mevcut adres güncellendiğinde, veritabanı yöneticisinin manuel müdahalesine gerek kalmadan sistemin otonom çalışması gerekir. Bunun için adres sütunu her değiştiğinde arka planda Ollama'ya gidip 1024 boyutlu vektörü çeken ve tabloya yazan bir Trigger kullanıyoruz.

CREATE OR ALTER TRIGGER trg_SALES_Vektor_OtomatikAdres
ON dbo.SALES_Vektor
AFTER INSERT, UPDATE
AS
BEGIN
    SET NOCOUNT ON;
    IF NOT UPDATE(ADDRESSTEXT) RETURN;

    DECLARE @KayitID INT, @AdresMetni VARCHAR(500);
    DECLARE @Url NVARCHAR(4000) = N'http://localhost:11434/api/embeddings';
    DECLARE @Payload NVARCHAR(MAX), @ResponseText NVARCHAR(MAX), @VektorString NVARCHAR(MAX);
    DECLARE @Object INT, @HResult INT;
    DECLARE @ResponseTable TABLE (JsonVerisi NVARCHAR(MAX));

    DECLARE TriggerCursor CURSOR FOR
    SELECT i.ID, i.ADDRESSTEXT FROM inserted i
    WHERE i.ADDRESSTEXT IS NOT NULL AND LTRIM(RTRIM(i.ADDRESSTEXT)) <> '';

    OPEN TriggerCursor;
    FETCH NEXT FROM TriggerCursor INTO @KayitID, @AdresMetni;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @Payload = N'{"model": "bge-m3", "prompt": "' + STRING_ESCAPE(@AdresMetni, 'json') + '"}';
        DELETE FROM @ResponseTable;

        EXEC @HResult = sp_OACreate 'MSXML2.ServerXMLHTTP', @Object OUT;
        IF @HResult = 0
        BEGIN
            EXEC sp_OAMethod @Object, 'open', NULL, 'POST', @Url, 'false';
            EXEC sp_OAMethod @Object, 'setRequestHeader', NULL, 'Content-Type', 'application/json';
            EXEC sp_OAMethod @Object, 'send', NULL, @Payload;
            
            INSERT INTO @ResponseTable (JsonVerisi)
            EXEC sp_OAGetProperty @Object, 'responseText';
            EXEC sp_OADestroy @Object;
            
            SELECT TOP 1 @ResponseText = JsonVerisi FROM @ResponseTable;
            SET @VektorString = JSON_QUERY(@ResponseText, '$.embedding');
            
            IF @VektorString IS NOT NULL
            BEGIN
                UPDATE dbo.SALES_Vektor
                SET AdresVektoru = CAST(@VektorString AS VECTOR(1024))
                WHERE ID = @KayitID;
            END
        END
        FETCH NEXT FROM TriggerCursor INTO @KayitID, @AdresMetni;
    END
    CLOSE TriggerCursor;
    DEALLOCATE TriggerCursor;
END;


5. Sistemin Test Edilmesi: VECTOR_DISTANCE ile Anlamsal Eşleştirme (Semantic Search)

Tüm altyapı hazırlıklarını tamamlayıp 20.000 kaydı vektör uzayına taşıdıktan sonra, mimarimizin asıl gücünü test etme aşamasına geldik. Geleneksel ilişkisel veritabanı mimarilerinde TRABZON ŞALPAZAR CİVARI KİREÇ MAHALLESİ SARAYBOSNA EVLERİ gibi eksik, sırası karışık ve yazım hataları içeren bir metni LIKE operatörü ile arattığınızda sonuç kümesi her zaman boş dönecektir.

Ancak kurduğumuz bu yerel yapay zeka entegrasyonunda, arama işlemine yaklaşımımız tamamen değişiyor. SQL Server 2025'in VECTOR_DISTANCE fonksiyonunu kullanarak, aranan kusurlu metnin vektör karşılığını alıp tablomuzdaki 20.000 adresin vektörüyle "Kosinüs Benzerliği" (Cosine Similarity) üzerinden karşılaştırıyoruz. Sistem harf dizilimine değil, metnin bağlamsal ve matematiksel yakınlığına odaklandığı için, geleneksel yöntemlerle bulunması imkansız olan o doğru kaydı saniyeler içinde eşleştirerek en yüksek skorla karşımıza çıkarıyor.

SET NOCOUNT ON;

-- Bilerek hatalı, eksik veya bozuk yazılmış bir metin
DECLARE @AramaMetni NVARCHAR(MAX) = N'TRABZON ŞALPAZAR CİVARI KİREÇ MAHALLESİ SARAYBOSNA EVLERİ'; 
DECLARE @Url NVARCHAR(4000) = N'http://localhost:11434/api/embeddings';
DECLARE @Payload NVARCHAR(MAX) = N'{"model": "bge-m3", "prompt": "' + STRING_ESCAPE(@AramaMetni, 'json') + '"}';
DECLARE @Object INT, @HResult INT;
DECLARE @ResponseTable TABLE (JsonVerisi NVARCHAR(MAX));
DECLARE @ResponseText NVARCHAR(MAX), @AramaVektoru NVARCHAR(MAX);

EXEC @HResult = sp_OACreate 'MSXML2.ServerXMLHTTP', @Object OUT;
IF @HResult = 0
BEGIN
    EXEC sp_OAMethod @Object, 'open', NULL, 'POST', @Url, 'false';
    EXEC sp_OAMethod @Object, 'setRequestHeader', NULL, 'Content-Type', 'application/json';
    EXEC sp_OAMethod @Object, 'send', NULL, @Payload;
    
    INSERT INTO @ResponseTable (JsonVerisi)
    EXEC sp_OAGetProperty @Object, 'responseText';
    EXEC sp_OADestroy @Object;
    
    SELECT TOP 1 @ResponseText = JsonVerisi FROM @ResponseTable;
    SET @AramaVektoru = JSON_QUERY(@ResponseText, '$.embedding');
    
    IF @AramaVektoru IS NOT NULL
    BEGIN
        SELECT TOP 5
            ID,
            ADDRESSTEXT,
            -- İki vektör arasındaki mesafeyi ölçüyoruz. Sıfıra (0) ne kadar yakınsa, anlamsal olarak o kadar aynıdır!
            VECTOR_DISTANCE('cosine', AdresVektoru, CAST(@AramaVektoru AS VECTOR(1024))) AS MesafeSkoru
        FROM dbo.SALES_Vektor
        WHERE AdresVektoru IS NOT NULL
        ORDER BY MesafeSkoru ASC;
    END
END


6. Sonuç

Bu makalede, geleneksel yöntemlerin tıkandığı o noktada SQL Server 2025'in Vektör (Vector) yeteneklerinin ve yerel yapay zekanın nasıl devrim yarattığını adım adım gördük.

En önemli başarımız ise veri güvenliğinden taviz vermemek oldu. Şirketimizin en değerli hazinesi olan verilerimizi hiçbir dış bulut API'sine (OpenAI, Google vb.) sızdırmadan; internete tamamen kapalı, KVKK ve DevSecOps standartlarına %100 uyumlu bir On-Premise mimari inşa ettik.

Bu süreçte T-SQL döngülerindeki hafıza tuzaklarını ve yabancı dil modellerinin yarattığı "dil sorunlarını" (bge-m3 modeliyle) aşarak sahada yaşanabilecek kritik zorlukları tecrübe ettik. Geldiğimiz noktada; eklenen her adresi otonom olarak (Trigger ile) vektörleyen, harf hatalarına takılmadan "anlamsal" eşleşmeyi milisaniyeler içinde bulan kusursuz bir arama motoruna sahibiz.


İçerik kimlik bilgilerine bakın

Makale içeriği


SQL Server artık sadece veriyi depolayan pasif bir ambar değil; verinin bağlamını "anlayan" aktif bir zeka merkezidir. Umarım 20.000 kayıtlık bu saha tecrübesi, sistemlerini modernleştirmek isteyen tüm meslektaşlarıma ışık tutar.

Bu yazıyı beğendiniz mi?