Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

SQL Server 2025 – Vector Search

Merhaba,

SQL Server 2025, yapay zekâ çağının dinamiklerine uyum sağlamak adına kapsamlı bir dönüşüm geçirerek, veritabanı motoruna yerleşik vektör arama (native vector search) yeteneği kazandırmıştır. Bu stratejik adım SQL Server’ı geleneksel veri yönteminin ötesine taşıyarak, yapay zekâya özgü semantik arama (semantic search) altyapısını doğal bir bileşen haline getirmiştir. Böylece metin, görsel ve ses gibi yapılandırılmamış veri türlerinde, yalnızca anahtar kelime eşleşmesine dayalı sorgularla sınırlı kalmaksızın, anlamsal benzerlik temelinde daha derinlikli ve bağlamsal sorgulamalar mümkün hale gelmiştir.

Anlayacağınız bu yenilik, yalnızca teknik bir güncelleme değil, aynı zamanda bilgi erişiminin, aramanın ve analiz süreçlerinin temel doğasını yeniden şekillendiren ve yapay zekâ destekli uygulamalar geliştirirken ilişkisel veritabanı olan SQL Server’ı bir vektör depolama katmanı olarak da kullanmamıza olanak tanıyan dönüşümsel sürecin ta kendisidir.

Şimdi gelin SQL Server’ın vector search ile ilgili bizlere sağladığı olanakları inceleyelim ve bir yandan da pratiksel olarak Python dili eşliğinde bu olanakları nasıl kullanabileceğimizi hep birlikte tecrübe edelim…

Vektör Veri Türü – Vector(n)

SQL Server 2025, artık Vector(n) adında yeni bir veri türü sunmaktadır. Bu tür sayesinde metin, görsel, ses veya diğer yapılandırılmamış verilerden elde edilen embedding vektörler doğrudan tablolar içerisinde sakalanabilmektedir.

Vektörler, tipik olarak float öğelerden oluşan sıralı dizilerdir. SQL Server, vector veri türü sayesinde bu dizileri optimize edilmiş ikili (binary) formatta saklamaktadır.

Semantik Arama Fonksiyonları

SQL Server 2025, klasik anahtar kelime tabanlı sorgulamanın ötesine geçerek, anlamsal yakınlığa dayalı (semantic similarity search) yapma olanağı tanımaktadır. Bu doğrultuda aşağıdaki algoritmaları benimseyen fonksiyonlar sunmaktadır;

  • Exact k-NN Araması – VECTOR_DISTANCE('cosine' | 'euclidean' | 'dot', v1, v2)

    İki vektör arasındaki benzerliği ölçer.

    Exact k-NN, verilen bir sorgu örneği için veri kümesindeki tüm noktaları tarar ve gerçek anlamda en yakın n adet komşuyu bularak getirir. Bu işlem için SQL Server, exact nearest neighbor (ENN) ya da k-NN aramasını/algoritmasını kullanmaktadır. Bu yöntem sayesinde tam doğruluk sağlanabilir ancak her vektörle mesafe hesaplandığı için büyük veri setlerinde ister istemez ciddi maliyet söz konusu olabilmektedir.

    Örnek kullanım;

    DECLARE @v1 VECTOR(2) = '[1,1]';
    DECLARE @v2 VECTOR(2) = '[-1,-1]';
    SELECT 
        VECTOR_DISTANCE('euclidean', @v1, @v2) AS euclidean,
        VECTOR_DISTANCE('cosine', @v1, @v2) AS cosine,
        VECTOR_DISTANCE('dot', @v1, @v2) AS negative_dot_product;
    

    Yukarıdaki kod bloğunu incelersek eğer iki boyutlu @v1 ve @v2 vektörleri üzerinden VECTOR_DISTANCE fonksiyonu ile öklid(euclidean) mesafesi, kosinüs(cosine) mesafesi ve nokta(dot) çarpımı mesafesi hesaplanmakta ve her bir metriğe göre hesaplanan mesafe aşağıdaki görselde olduğu gibi float olarak döndürülmektedir.SQL Server 2025 - Vector SearchBu hesaplamalar ne anlama geliyor? diye sorarsanız olayın pekte matematiksel tekniğine girmeksizin şöyle özetlemekte fayda görmekteyim;

    Öklid mesafesi, iki vektör arasındaki ‘düz çizgi’ mesafesini hesaplar. Haliyle çıktı olarak elde edilen sayısal değer vektörlerin uzayda birbirlerine ne kadar uzakta olduğunu ifade eder. Böylece, bu değer büyüdükçe vektörlerin daha farklı olduğu yorumunda bulunulabilir.

    Kosinüs mesafesi, iki vektör arasındaki açısal farkı ölçmekte ve bu ölçüm neticesinde 0 ile 2 arasında bir değer üretilerek benzerlik analizinde bulunulabilmektedir. 2 değeri, vektörlerin tamamen zıt yönlerde (aralarındaki açı 180 derece) olduğunu göstermektedir. Haliyle örnekte verdiğimiz [1,1] ve [-1,-1] vektörlerinin de birbirine tamamen ters yönlü olduğu zahiren aşikar olsa da kosinüs ölçümü neticesinde de bu doğrulanmaktadır. Uzun lafın kısası kosinüs mesafesinde ölçün neticesi 0’a yaklaştıkça benzerlik artmakta, bilakis 2’ye yaklaştıkça azalmaktadır.

    Nokta çarpımı ise vektörlerin yönelimine ve büyüklüğüne bağlı bir benzerlik ölçüsüdür. Esasında iki vektörün elemanlarının karşılıklı çarpımlarının toplamlıdır. Elde edilen netice ne kadar büyük ve pozitifse, vektörler o kadar benzerdir. Ancak SQL Server’da nokta çarpımının negatifi alındığı için bu mantığın tam tersi geçerlidir. Yani düşük veya negatif değer benzerlik gösterirken, yüksek ve pozitif değer ise farkı gösterecektir.

    Ayrıca aşağıdaki örnek vektör tabanlı benzerlik aramasını da inceleyelim;

    DECLARE @v AS VECTOR(512);
    SELECT TOP 1 @v = embedding FROM embeddings 
    
    SELECT TOP(10) 
        VECTOR_DISTANCE('cosine', @v, embedding) AS distance 
    FROM embeddings ORDER BY distance
    

    Yukarıdaki sorguyu çalıştırdığımızdaSQL Server 2025 - Vector Searchdeğerinin üretildiğini gözlemlemekteyiz. Bu da yaklaşık 0.0000000596 değerine yani 0 (sıfır)’a yakın diyebiliriz. Ee haliyle kosinüs ölçümüne göre bu vektörler aynı vektörlerdir diyebiliriz.

    Tavsiye odur ki, k-NN araması 50.000 (elli bin) vektörden az veriye uygulanmalıdır. Daha büyük verilerde ise tabloda arama yapılacak verinin kapsamının önceden daraltılması gerekmektedir. Evet, k-NN araması, doğruluk açısından en yüksek garantiyi sağlamaktadır sağlamasına ancak yapay zekâ sistemlerinde, embedded edilmiş veriler bir tür soyutlama olduğundan %100 doğruluğa da ihtiyaç duyulmamaktadır. Bundan kaynaklı küçük veri setlerinde bu yaklaşım etkiliyken, büyük kurumsal çalışmalarda ise daha verimli yaklaşımlar hesaba katılmalıdır.

  • Approximate k-NN | ANN Algoritması – VECTOR_SEARCH(...)

    ANN indekslerini kullanarak yüksek hacimli veri içinde en benzer kayıtları getirir.

    Yukarıdaki satırlarda k-NN araması için, tüm veri noktalarıyla mesafe hesapladığından ve kesin sonuçlar verdiğinden ancak bunun büyük veri setleri için yavaş olabileceğinden bahsetmiştik. ANN araması ise kesin sonuçlar yerine yaklaşık (approximate) en yakın komşuları bulmak için optimizasyonlar sunmakta ve böylece sorgulama hızını artırmaktadır.

    SQL Server 2025’te VECTOR_SEARCH fonksiyonu ile ANN aramaları gerçekleştirilebilmektedir. Bu fonksiyon, vektör indekslerini kullanarak yaklaşık en yakın komşuları bulmaktadır. Bu davranışı sayesinde özellikle milyonlarca vektör içeren veri setlerinde k-NN aramasına kıyasla çok daha hızlı arama gerçekleştirebilmektedir.

    Bunun için, ANN algoritmasını yukarıdaki k-NN algoritmasında kullandığımız sorguyla ilişkilendirerek örneklendirirsek eğer;

    DECLARE @v AS VECTOR(512);
    SELECT TOP 1 @v = embedding FROM embeddings 
     
    SELECT TOP(10) 
        VECTOR_DISTANCE('cosine', @v, embedding) AS distance 
    FROM embeddings ORDER BY distance
    

    Bu sorguda, tam olarak k-NN araması yapılmaktadır ve tüm vektörlerle kosinüs mesafesi hesaplanmaktadır. Bundan kaynaklı da önceki satırlarda konuştuğumuz gibi büyük veri setlerinde yavaşlık ve yüksek maliyet söz konusu olabilmektedir.

    DECLARE @v AS VECTOR(512);
    SELECT TOP 1 @v = embedding FROM embeddings 
     
    SELECT TOP(10) 
        VECTOR_DISTANCE('cosine', @v, embedding) AS distance 
    FROM embeddings WHERE VECTOR_SEARCH(@v, embedding, 'cosine', 10)
    

    Bu sorguda ise vektör indeksleri kullanılarak yaklaşık en yakın 10 vektör bulunmakta ve ardından k-NN araması yapılmaktadır. Böylece tüm tabloyu taramak yerine indeks tabanlı bir arama yapılmakta ve böylece çok daha hızlı davranış sergilenmektedir.

    ANN araması, vektörler arasındaki yakınlık hesaplarını grafik tabanlı veriler üzerinden gezerek yapmaktadırlar. Bu sayede; işlemci ve bellek kullanımını düşürür, yüksek sorgu başına işlem (QPS) ve düşük gecikme sağlar.

AI İle Entegrasyon: Embedding Üretimi

SQL Server 2025, Azure OpenAI, OpenAI API ve Ollama gibi yerel LLM çözümleriyle doğrudan entegre olarak vektör verisi oluşturabilmektedir. Bu entegrasyon sayesinde, T-SQL üzerinden AI_GENERATE_EMBEDDINGS fonksiyonu kullanılarak kullanıcıdan gelen metinler otomatik olarak vektör temsillerine (embeddings) dönüştürülebilir.

Bunun dışında tabi ki de AI_GENERATE_EMBEDDINGS fonksiyonu yerine özel embedding çalışmaları gerçekleştirmek de mümkündür. Ancak bu, SQL Server’ın doğrudan sağladığı entegrasyonlar dışında ek geliştirme ve yapılandırma gerektirebilmektedir. Özellikle içeriğimizin devamında pratiksel olarak sunacağımız SentenceTransformer('all-MiniLM-L6-v2') gibi bir model eşliğinde bu durumu örneklendiriyor olacağız.

Yazılımcı Bakış Açısı

Vektör indeksleri, ilişkisel indekslerden farklıdırlar. Biliyorsunuz ki biz yazılımcılar, hız ve doğruluk arasında bir denge kurmak mecburiyetindeyiz. Eğer sorgular düşük gecikme gerektiriyorsa Yaklaşık En Yakın Komşu (ANN) indeksleri ideal bir seçim olacaktır. Ancak kesinlik kritik önem taşıyorsa ve vektör sayısı makul bir seviyedeyse, Tam En Yakın Komşu (ENN) daha uygun bir tercih olacaktır. Yani gerektiği yerde maliyet gözden çıkarılmalıdır.

SQL Server’ın vektör arama yetenekleri, ilişkisel veritabanı sorgularıyla entegre çalışabildiği için güçlü bir avantaj sağlamaktadır. Bu sayede, hem embedded edilmiş vektörleri hem de yapısal verileri aynı anda işleyen çok boyutlu sorgular oluşturulabilir. Bu özellik, Retrieval-Augmented Generation (RAG) mimarilerinde yalnızca anlamsal benzerliklere dayalı sonuçlar değil, aynı zamanda bağlamsal filtrelerle (örneğin; tarih, kullanıcı grubu veya erişim düzeyi) zenginleştirilmiş, hedef odaklı bilgi getirimi sağlamaktadır. Böylece RAG sistemleri, daha anlamlı, kontrollü ve alana özgü yanıtlar üretebilme kapasitesine erişebilir.

Pratiksel Olarak Vector Embedding ve Vector Search Çalışması

Evet… Artık sıra, vector embedding ve vector search davranışlarını pratiksel olarak uygulamaya geldi diyebiliriz. Tabi tüm bu çalışmada veritabanı olarak SQL Server 2025’i tercih edeceğiz. Ancak süreçte SQL Server’ın yapay zekâ ile ilgili getirisi olan AI ile bir entegrasyon gerçekleştirmeyecek ve tüm embedding ve search çalışmasını özelleştirilmiş bir vaziyette yürüteceğiz. Ee haliyle AI_GENERATE_EMBEDDINGS fonksiyonunu bu makalede deneyimlemeyecek, o konuyu belki başka bir içeriğe yahut sizlere bırakmış olacağız.

Şimdi aşağıdaki talimatlar eşliğinde önergeleri sıralı bir şekilde seyrederek pratik çalışmaya eşlik edebilirsiniz:

  1. Temel Kurulumlar

    İlk olarak SQL Server 2025 ile birlikte uygulamalarla SQL Server veritabanı arasında iletişim kurmamızı sağlayacak olan ODBC Driver gibi temel kurulumların gerçekleştirilmesi gerekmektedir. Bunun için aşağıdaki talimatlar eşliğinde ilgili altyapıyı sağlayabilirsiniz.

  2. Proje Dosyalarının ve Ortamının Hazırlanması

    Ardından proje dosyalarının ve ortamının hazırlanması gerekmektedir.

    • Proje Klasörünün Oluşturulması
      Uygun bir yerde istediğiniz isimde bir klasör oluşturun. (Benim tercih ettiğim isim : SQL_Server_2025_Vector_Embedding_And_Vector_Search)
    • requirements.txt’nin Oluşturulması
      Oluşturulan klasörde requirements.txt adında bir dosya oluşturun ve içeriğine aşağıdaki kütüphane isimlerini yazın:

      flask
      pyodbc
      sentence-transformers
      Pillow
      torch
      numpy 
      

      ‘Nedir bu kütüphanelerin işlevselliği?’ diye sorarsanız hızlıca özetleyelim;

      • flask : Hafif bir Python web framework’üdür. Web uygulamaları geliştirmek için kullanılır.
      • pyodbc : Python’dan ODBC veritabanlarına bağlanmak ve veri sorgulamak için kullanılan bir kütüphanedir.
      • sentence-transformers : Cümle ve metinleri vektör temsillerine dönüştürmek için kullanılan bir NLP kütüphanesidir.
      • Pillow : Python’da görüntü işleme ve manipülasyonu için kullanılan bir kütüphanedir.
      • torch : Derin öğrenme modelleri oluşturmak ve eğitmek için kullanılan bir makine öğrenimi kütüphanesidir.
      • numpy : Bilimsel hesaplamalar için çok boyutlu diziler ve matematiksel işlemler sağlayan bir kütüphanedir.
    • Python Bağımlılıklarının Kurulumu
      İlgili dizinde requirements.txt içerisinde belirtilen Python kütüphanelerini aşağıdaki talimat eşliğinde kurun:

      pip install -r requirements.txt
      
    • app.py Dosyasının Oluşturulması
      Vector embedding ve vector search işlemlerinin Python ile yürütüleceği app.py isimli dosyayı oluşturun.
  3. Uygulamanın Geliştirilmesi

    Artık uygulamayı geliştirebiliriz. Bunun için app.py dosyasında, hem vector embedding hem de vector search çalışmalarının yanında bir yandan da bu çalışmaları test edebilmemizi sağlayacak olan API çalışmalarını da Python’da yürütmemiz gerekecektir. Buradaki ilerleme mutlak sıralı takip gerektireceği için her bir önergenin başına koyduğum adım numarasını ardışık takip etmeye özen göstermenize dikkatinizi çekerim.

    • 1-) Gerekli Kütüphanelerin Import Edilmesi
      # Gerekli kütüphaneler import ediliyor
      from flask import Flask, request, jsonify
      from sentence_transformers import SentenceTransformer
      from PIL import Image
      import io
      import base64
      import pyodbc
      import numpy as np
      import torch
      import os
      
    • 2-) Temel Flask Nesnesinin Oluşturulması
      # Flask uygulaması başlatılıyor
      app = Flask(__name__)
      
    • 3-) Metin ve Görsel Veriler İçin Modellerin Yüklenmesi
      # Metin verileri için embedding modeli yükleniyor
      text_model = SentenceTransformer('all-MiniLM-L6-v2')
      
      # Görsel veriler için CLIP tabanlı embedding modeli yükleniyor
      clip_model = SentenceTransformer('clip-ViT-B-32')
      
    • 4-) SQL Server Veritabanına Bağlantı Kurulması
      # SQL Server veritabanına bağlantı kuruluyor
      try:
          # Direkt Example veritabanına bağlan
          conn = pyodbc.connect(
              'DRIVER={ODBC Driver 17 for SQL Server};'
              'SERVER=localhost,1433;'
              'DATABASE=Example;'
              'UID=sa;'
              'PWD=Test123!;'
              'TrustServerCertificate=yes;'
          )
          cursor = conn.cursor()
          print("Example veritabanına bağlantı başarılı!")
          
      except Exception as e:
          print(f"SQL Server bağlantısı hatası: {e}")
          print("Lütfen SQL Server'ın çalıştığından ve Example veritabanının mevcut olduğundan emin olun!")
          raise
      
    • 5-) Embeddings Tablosunun Oluşturulması
      # Embeddings tablosu oluşturuluyor
      def create_table():
          try:
              # Tablo var mı kontrol et
              cursor.execute("""
              IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='embeddings' and xtype='U')
              BEGIN
                  CREATE TABLE embeddings (
                      id INT IDENTITY(1,1) PRIMARY KEY,
                      data_type NVARCHAR(10),
                      original_data NVARCHAR(MAX),
                      embedding VECTOR(512),  -- SQL Server 2025 VECTOR türü - CLIP modeli 512 boyutlu
                      original_data_type NVARCHAR(20),
                      file_path NVARCHAR(255),
                      label NVARCHAR(100)
                  )
                  PRINT 'VECTOR embeddings tablosu oluşturuldu!'
              END
              ELSE
              BEGIN
                  PRINT 'Embeddings tablosu zaten mevcut!'
              END
              """)
              
              conn.commit()
          except Exception as e:
              print(f"Tablo oluşturulurken hata: {e}")
              raise
      
      # Tabloyu oluştur
      create_table()
      

      Vector embedding sürecinde verileri tutacağımız tablo ‘Example’ isimli veritabanı içerisine var mı yok mu kontrol edilmekte, yoksa eğer oluşturulmaktadır.

      Ayrıca burada embedding kolonunun VECTOR(512) türünden olduğuna dikkatinizi çekerim. İşte bu, SQL Server 2025 ile hayatımıza girmiş olan vector türünü ilk deneyimlememiz 🙂 Günün sonunda bu kolonSQL Server 2025 - Vector Searchgörselde de görüldüğü üzere vector türünden oluşturulacaktır.

    • 6-) embed Endpoint’inin Hazırlanması
      # /embed endpoint'i
      @app.route('/embed', methods=['POST'])
      def embed():
          try:
              data_type = request.form.get('type')
              file_path = None
              original_data_type = data_type
              label = request.form.get('label')
      
              if data_type == 'text':
                  text = request.form.get('data')
                  if not text:
                      return jsonify({'error': 'Metin verisi eksik!'}), 400
      
                  try:
                      embedding = text_model.encode(text)
                  except Exception as e:
                      return jsonify({'error': f'Embedding alınırken hata: {e}'}), 500
      
                  original_data = text
                  file_path = None
      
              elif data_type == 'image':
                  if 'data' not in request.files:
                      return jsonify({'error': 'Görsel dosyası eksik!'}), 400
      
                  image_file = request.files['data']
                  try:
                      image = Image.open(image_file.stream).convert('RGB')
                  except Exception as e:
                      return jsonify({'error': f'Görsel okunamadı: {e}'}), 400
      
                  save_dir = 'uploaded_images'
                  os.makedirs(save_dir, exist_ok=True)
                  image_filename = image_file.filename
                  save_path = os.path.join(save_dir, image_filename)
                  try:
                      image.save(save_path)
                  except Exception as e:
                      return jsonify({'error': f'Görsel kaydedilemedi: {e}'}), 500
      
                  file_path = save_path
      
                  try:
                      embedding = clip_model.encode(image)
                  except Exception as e:
                      return jsonify({'error': f'Embedding alınırken hata: {e}'}), 500
      
                  try:
                      buffered = io.BytesIO()
                      image.save(buffered, format="PNG")
                      original_data = base64.b64encode(buffered.getvalue()).decode()
                  except Exception as e:
                      return jsonify({'error': f'Base64 dönüştürme hatası: {e}'}), 500
      
              else:
                  return jsonify({'error': 'type must be text or image'}), 400
      
              # Embedding'i hazırla
              try:
                  embedding_array = embedding.astype(np.float32)
                  embedding_str = f"[{','.join(map(str, embedding_array))}]"
              except Exception as e:
                  return jsonify({'error': f'Embedding vectore dönüştürülürken hata: {e}'}), 500
      
              # Veritabanına ekle
              try:
                  # Önce tablo türünü kontrol et
                  cursor.execute("SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'embeddings' AND COLUMN_NAME = 'embedding'")
                  column_type = cursor.fetchone()[0]
                  
                  if column_type == 'vector':
                      # Vector türü için doğrudan SQL kullan
                      embedding_values = ','.join(map(str, embedding.astype(np.float32)))
                      sql = f"INSERT INTO embeddings (data_type, original_data, embedding, original_data_type, file_path, label) VALUES (?, ?, CAST('[{embedding_values}]' AS VECTOR(512)), ?, ?, ?)"
                      cursor.execute(sql, data_type, original_data, original_data_type, file_path, label)
                  else:
                      # VARBINARY kullan
                      embedding_bytes = embedding.astype(np.float32).tobytes()
                      cursor.execute(
                          "INSERT INTO embeddings (data_type, original_data, embedding, original_data_type, file_path, label) VALUES (?, ?, ?, ?, ?, ?)",
                          data_type, original_data, embedding_bytes, original_data_type, file_path, label
                      )
              except Exception as e:
                  return jsonify({'error': f'Veritabanına ekleme hatası: {e}'}), 500
              
              conn.commit()
              return jsonify({'status': 'success'})
      
          except Exception as e:
              return jsonify({'error': f'Bilinmeyen hata: {e}'}), 500
      

      Burada dikkat ederseniz kullanıcıdan POST request’i ile gelecek olan verinin içeriğine bakılmakta ve yapılacak davranış bu içeriğe göre belirlenmektedir. 10 ile 21. satır aralığında gelen metinsel veriler analiz edilerek, embedding edilmektedir. 23 ile 54. satır aralığında ise görsel veriler analiz edilmekte, embedding edilebilmesi için önce RGB’ye dönüştürülmekte ve öylece embedding edilmektedir. Ayrıca fiziksel olarak hangi görselin olduğunu da takip edebilmemiz için ‘uploaded_images’ isimli klasöre görselin orjinal hali de eklenmektedir.

      60 ile 64. satır aralığında embedding edilmiş olan veriler vektöre dönüştürülmekte ve 67 ile 83. satır aralığında ise elde edilen vektör veritabanına eklenmektedir.

    • 7-) Vector Search Endpoint’inin Hazırlanması
      # /vector_search endpoint'i
      @app.route('/vector_search', methods=['POST'])
      def vector_search():
          try:
              data_type = request.form.get('type')
              
              if data_type == 'text':
                  text = request.form.get('data')
                  if not text:
                      return jsonify({'error': 'Metin verisi eksik!'}), 400
                  query_embedding = text_model.encode(text)
              elif data_type == 'image':
                  if 'data' not in request.files:
                      return jsonify({'error': 'Görsel dosyası eksik!'}), 400
                  image_file = request.files['data']
                  image = Image.open(image_file.stream).convert('RGB')
                  query_embedding = clip_model.encode(image)
              else:
                  return jsonify({'error': 'type must be text or image'}), 400
      
              # Tüm embedding'leri çek
              cursor.execute("SELECT id, data_type, original_data, embedding, original_data_type, file_path, label FROM embeddings")
              results = cursor.fetchall()
      
              if not results:
                  return jsonify({'error': 'Hiç embedding bulunamadı.'}), 404
      
              # Tablo türünü kontrol et
              cursor.execute("SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'embeddings' AND COLUMN_NAME = 'embedding'")
              column_type = cursor.fetchone()[0]
      
              # En benzer sonucu bul
              best_match = None
              best_similarity = -1
      
              print(f"Toplam {len(results)} embedding bulundu")
              print(f"Tablo türü: {column_type}")
      
              for row in results:
                  db_id, db_data_type, db_original_data, db_embedding, db_original_data_type, db_file_path, db_label = row
                  
                  try:
                      if column_type == 'vector':
                          # Vector türü için Python'da cosine similarity kullan
                          # Vector'ü string'den parse et
                          vector_str = str(db_embedding)
                          # [1.0,2.0,3.0] formatından array'e çevir
                          vector_values = vector_str.strip('[]').split(',')
                          db_embedding_array = np.array([float(x.strip()) for x in vector_values], dtype=np.float32)
                          
                          # Cosine similarity hesapla
                          similarity = np.dot(query_embedding, db_embedding_array) / (np.linalg.norm(query_embedding) * np.linalg.norm(db_embedding_array))
                          print(f"ID {db_id} vector cosine similarity: {similarity}")
                      else:
                          # VARBINARY için cosine similarity
                          db_embedding_array = np.frombuffer(db_embedding, dtype=np.float32)
                          similarity = np.dot(query_embedding, db_embedding_array) / (np.linalg.norm(query_embedding) * np.linalg.norm(db_embedding_array))
                          print(f"ID {db_id} varbinary cosine similarity: {similarity}")
                      
                      # Threshold'u düşür - 0.1'den büyük olanları kabul et
                      if similarity > 0.1 and similarity > best_similarity:
                          best_similarity = similarity
                          best_match = {
                              'id': db_id,
                              #'data_type': db_data_type,
                              #'original_data': db_original_data,
                              #'original_data_type': db_original_data_type,
                              'file_path': db_file_path,
                              'label': db_label,
                              'similarity': float(similarity)
                          }
                  except Exception as e:
                      print(f"Similarity hesaplama hatası ID {db_id}: {e}")
                      continue
      
              print(f"En iyi similarity: {best_similarity}")
              print(f"En iyi match: {best_match}")
      
              if best_match:
                  return jsonify(best_match)
              else:
                  return jsonify({'error': 'Benzer sonuç bulunamadı.'}), 404
      
          except Exception as e:
              return jsonify({'error': f'Hata: {e}'}), 500
      
      

      Yine POST edilerek gelen request üzerindeki verilere göre vector search’ün nasıl yapılacağı kararlaştırılmakta ve davranış ona göre oluşturulmaktadır. 22 ile 23. satır aralığında embeddings tablosundaki tüm veriler elde edilmekte ve 43 ile 53. satır aralığında vector türüne göre kosinüs ölçeği eşliğinde vector search gerçekleştirilmektedir. Ayrıca 56 ile 58. satır aralığında ise kolonun türü vector yerine ‘VARBINARY’ olma ihtimaline karşın, bu duruma uygun vector search işlemi gerçekleştirilmektedir.

      61 ile 71. satır aralığında ise yapılan vector search neticesinde elde edilen vektörlerden benzerlik (similarity) değeri 0.1’in üstü olanlar ayrılmakta ve böylece istenen verideki hassasiyet eşiği manuel olarak tarafımızca biraz daha optimize edilerek, verinin aranana yakınlık ihtimali daha da artırılmaktadır.

    • 8 -) Debug Endpoint’inin Oluşturulması
      # Debug endpoint'i - embedding sayısını kontrol et
      @app.route('/debug', methods=['GET'])
      def debug():
          try:
              cursor.execute("SELECT COUNT(*) FROM embeddings")
              count = cursor.fetchone()[0]
              
              cursor.execute("SELECT id, data_type, label FROM embeddings")
              embeddings = cursor.fetchall()
              
              return jsonify({
                  'total_embeddings': count,
                  'embeddings': [{'id': row[0], 'type': row[1], 'label': row[2]} for row in embeddings]
              })
          except Exception as e:
              return jsonify({'error': f'Debug hatası: {e}'}), 500
      
      

      Kaç verinin embedded edildiğine dair istatistiği hızlıca edinebilmek için bu endpoint geliştirilmiştir.

    • 9-) Flask Uygulamasının Başlatılması
      # Flask uygulaması başlatılıyor
      if __name__ == '__main__':
          app.run(debug=True) 
      

    İşte bu kadar 🙂 Uygulamayı artık olması gerektiği gibi geliştirmiş bulunuyoruz. Şimdi teste geçebiliriz.

  4. Test Edilmesi

    Hem vector embedding hem de vector search için testlerin gerçekleştirilmesi gerekmektedir.

    • Uygulamanın Ayağa Kaldırılması
      python app.py
      
    • Vector Embedding Testi
      Görsel veriler için;

      curl -X POST -F "type=image" -F "data=@görsel.path.jpg" -F "label=görsel veri ismi" http://localhost:5000/embed
      

      Birkaç görsel veri üzerinden örnek embedding talebinin çıktısı aşağıdaki görseldeki gibi olacaktır;SQL Server 2025 - Vector SearchMetinsel veriler için;

      curl -X POST -F "type=text" -F "data=metinsel veri" -F "label=metinsel veri ismi" http://localhost:5000/embed
      
    • Vector Search Testi
      Görsel veriler için;

      curl -X POST -F "type=image" -F "data=@görsel.path.jpg" http://localhost:5000/vector_search
      

      Görsel veriler üzerinden örnek vector search ise aşağıdaki gibi olacaktır;SQL Server 2025 - Vector SearchMetinsel veriler için;

      curl -X POST -F "type=text" -F "data=metinsel veri" http://localhost:5000/vector_search
      

      Tüm çalışmalar neticesinde veritabanının son halide aşağıdaki gibi olacaktır;SQL Server 2025 - Vector Search

    • Debug Testi
      http://localhost:5000/debug
      

      SQL Server 2025 - Vector Search

Ve böylece pratiksel çalışmamızı da tamamlamış ve SQL Server 2025 eşliğinde hem vector embedding’i, hem vector search’ü hem de bir yandan SQL Server 2025’in vector türünü hep birlikte deneyimlemiş olduk. Artık teoride kalan son dokunuşlara dönebilir ve azar azar içeriğimizi nihayete erdirebiliriz.

Teknik Avantajlar ve Fark Yaratan Özellikler

SQL Server’ın vektör arama yetenekleri, vektörel arama ile ilişsek veriler arasında köprü kuran güçlü bir altyapıya sahiptir. Şöyle ki; vector veri türünü kullanarak, örnekte de deneyimlediğimiz gibi embedding edilmiş verilerle yapılandırılmış verileri aynı tabloda saklama olanağı söz konusudur. Böylece tek bir veritabanı ile AI destekli uygulama geliştirme biz yazılımcılar açısından oldukça kolaylaşabilmektedir.

Ayrıca bu teknolojinin sunduğu avantajlar, özellikle veri mahremiyetine duyarlı projeler için dikkat çekicidir. Ek bir araca gerek kalmaksızın yapay zekâ yeteneklerini doğrudan T-SQL komutları ile yönetebilir, geleneksel SQL uzmanlığına gerek olmaksızın semantic search yapabilir ve tüm süreçler tamamen on-prem ortamında gerçekleşebilir.

Nihai olarak;

SQL Server 2025’in vektör arama özelliği, yapay zekâ çağının ihtiyaç duyduğu semantik düzeyde sorgulama yeteneklerini kurumsal veritabanlarına entegre ederek devrimsel bir sıçrama sunmaktadır. Bu özellik, yalnızca teknolojik olarak değil, aynı zamanda veriye erişim, yorumlama ve karar verme biçimimiz üzerinde de köklü değişiklikler yaratma potansiyeline sahiptir.

Farkındaysanız, geleceği inşa eden sistemler artık sadece veriye değil, verinin anlamına da erişmek mecburiyetindedir. İşte SQL Server, tam da bu noktada 2025 ile varlık göstermektedir.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek çalışmaya aşağıdaki GitHub adresinden erişebilirsiniz.
https://github.com/gncyyldz/SQL_Server_2025_Vector_Embedding_And_Vector_Search

Bunlar da hoşunuza gidebilir...

4 Cevaplar

  1. Hakan Angın dedi ki:

    Gençay hocam selamlar. Buradaki çıktılarda yer alan similarity değeri, “embeddings” tablosuna daha önce kaydedilmiş olan diğer veriler ile olan benzerlik derecesini ifade ediyor diye düşünüyorum doğru mu?

    Eğer böyle ise, burada bir sorun var gibi görünüyor. Birbirine çok benzeyen görseller ile çok alakasız farklı bir görsel üzerinde testlerimi gerçekleştirdiğimde similarity değeri için benzer sonuçlar aldım.

    Olayı ben de çok yanlış anlamış olabilirim. Bu konu da cevap verirseniz memnun olurum. Emeğinize sağlık. Teşekkür ederim.

  2. İlhan Bulut dedi ki:

    Harika bir yazı. Kalemine sağlık. Çok teşekkürler

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir