Vector Databases

LanceDB ile Çok Modlu RAG: Görsel-Metin Çiftlerinin Depolanması ve Sorgulanması

Geri Alma Destekli Üretim (RAG) sistemleri son zamanlara kadar büyük ölçüde metin odaklıydı. Ancak modern yapay zeka uygulamaları, görsel ve metinsel verileri eş zamanlı olarak geri alma ve çıkarım yapma yeteneğini giderek daha fazla gerektiriyor. İşte çok modlu RAG burada devreye giriyor. Geleneksel vektör veritabanları, birden fazla veri türünü ve büyük ikili yükleri yönetmenin karmaşıklığıyla başa çıkmakta zorlanırken, LanceDB, özellikle yapay zeka iş yükleri için tasarlanmış sağlam, sütun tabanlı bir depolama çözümü sunar.

Bu kılavuzda, LanceDB'yi kullanarak görsel-metin çiftlerini nasıl verimli bir şekilde depolayacağımızı ve sorgulayacağımızı inceleyeceğiz. Çok modlu bir sistem için gerekli gömme (embedding) üretimi, veri alımı ve geri alma mantığını nasıl ele alacağımızı göstereceğiz.

Çok Modlu Veriler İçin Neden LanceDB?

LanceDB, Lance biçimini kullanan açık kaynaklı ve geliştirici dostu bir vektör veritabanıdır. Satır tabanlı veritabanlarının aksine Lance, rastgele erişim ve büyük ikili dosyalar için optimize edilmiştir; bu da görselleri vektör gömmeleriyle birlikte depolamak için ideal kılar. Temel avantajlar şunlardır:

  • Sıfır İşletim Maliyetli Depolama: Uygulamanızın içinde gömülü olarak çalışarak altyapı karmaşıklığını azaltır.
  • Verimli Filtreleme: Vektör benzerliğinin yanı sıra meta veri filtrelemesini destekler; bu da arama sonuçlarını kategori, tarih veya kaynağa göre daraltmak için kritiktir.
  • Büyük Nesne Desteği: Birçok senaryoda, harici blob depolama bağımlılıkları olmadan büyük ikili verileri (görseller gibi) yerel olarak işler.

Kurulum ve Yükleme

Başlamak için LanceDB'yi ve çok modlu bir gömme modeli yüklemeniz gerekir. Bu örnekte, gömme üretimi için transformers kütüphanesini bir CLIP modeliyle kullanacağız.


# Bağımlılıkları yükle
pip install lancedb transformers torch pillow

Adım 1: Çok Modlu Gömmeleri Üretme

Çok modlu RAG'ın temeli, görselleri ve metni aynı vektör uzayında hizalamaktır. Hem görseller hem de metin sorguları için gömmeleri üretmek için bir CLIP modeli kullanırız. Arama yaparken, ilgili görselleri bulmak için metinle sorgu yapabilir veya bunun tersini yapabilirsiniz.


import torch
from transformers import CLIPProcessor, CLIPModel
from PIL import Image
import base64
import numpy as np

# CLIP modelini yükle
model_name = "openai/clip-vit-base-patch32"
processor = CLIPProcessor.from_pretrained(model_name)
model = CLIPModel.from_pretrained(model_name)

def get_image_embedding(image_path):
    """Bir görsel için gömme üretir."""
    image = Image.open(image_path)
    inputs = processor(images=image, return_tensors="pt")
    with torch.no_grad():
        outputs = model.get_image_features(**inputs)
    return outputs.cpu().numpy().flatten()

def get_text_embedding(text):
    """Bir metin sorgusu için gömme üretir."""
    inputs = processor(text=text, return_tensors="pt", padding=True)
    with torch.no_grad():
        outputs = model.get_text_features(**inputs)
    return outputs.cpu().numpy().flatten()

Adım 2: Görsel-Metin Çiftlerini Alma

Görsel verileri (bu örnekte taşınabilirlik için Base64 olarak kodlanmış, ancak performans için ham baytlar tercih edilir), açıklamayı (caption) ve vektör gömmesini depolayan bir LanceDB tablosu oluşturacağız.


import lancedb
import uuid

# Veritabanını başlat
db = lancedb.connect("./multimodal_db")

# Tablo yoksa oluştur
# Not: Üretim ortamında, görsel baytlarını doğrudan depolayabilir veya URI'ler kullanabilirsiniz
table = db.open_table("images") if db.table_names() else db.create_table("images", mode="create")

# Örnek veri
sample_data = [
    {
        "id": str(uuid.uuid4()),
        "caption": "Bir parkta oynayan altın retriever",
        "image_data": open("dog.jpg", "rb").read(), # Görsel baytlarını oku
        "vector": get_image_embedding("dog.jpg"),
    },
    {
        "id": str(uuid.uuid4()),
        "caption": "Kitap rafları olan rahat bir kütüphane",
        "image_data": open("library.jpg", "rb").read(),
        "vector": get_image_embedding("library.jpg"),
    }
]

# Tabloya veri ekle
table.add(sample_data)

Adım 3: Çok Modlu Arama Yapma

Çok modlu RAG'ın gücü, çapraz modlu geri almada yatar. Bir kullanıcı "Bana köpek fotoğrafları bul" yazabilir ve sistem, metin sorgusuna dayalı olarak en görsel olarak benzer görselleri döndürmelidir.


def search_images(text_query, top_k=5):
    """Bir metin sorgusuna dayalı olarak görselleri arar."""
    # Metin sorgusu için gömme üret
    query_vector = get_text_embedding(text_query)
    
    # Meta veri filtresiyle vektör araması yap
    # Burada sadece vektör benzerliğine göre arama yapıyoruz
    results = table.search(query_vector).limit(top_k).to_pandas()
    
    # Gösterim için görsel verilerini çözümlen (isteğe bağlı)
    for idx, row in results.iterrows():
        print(f"Sonuç {idx}: {row['caption']}")
        # Gerçek bir uygulamada, row['image_data'] çözümlenir ve görüntülenir
        # img = Image.open(io.BytesIO(row['image_data']))
        
    return results

# Aramayı çalıştır
results = search_images("dışarıda oynayan sevimli köpek")
print(results[['id', 'caption', '_distance']])

Sonuç

LanceDB, karmaşık veri türlerinin depolanmasını ve geri alınmasını basitleştirerek çok modlu RAG uygulamaları oluşturma konusunda akıcı bir yol sunar. Metin ve görsel gömmelerini ortak bir vektör uzayında hizalayarak, geliştiriciler bir şeyin nasıl göründüğü ile nasıl tanımlandığı arasındaki ilişkiyi anlayan sezgisel arama deneyimleri yaratabilir. Çok modlu modeller giderek daha yaygınlaştıkça, LanceDB gibi araçlar, alttaki veri altyapısını yönetmek için vazgeçilmez olacaktır.

Share: