3 puan yazan GN⁺ 2024-05-04 | 1 yorum | WhatsApp'ta paylaş
  • Mevcut sqlite-vss sınırlamalarını azaltmak için sqlite-vec, saf C tabanlı bir gömülü vektör arama eklentisi olarak geliştiriliyor ve SQLite’ın çalıştığı tüm ortamları hedefliyor
  • SQL kullanım akışı CREATE VIRTUAL TABLE, INSERT INTO, SELECT etrafında sadeleştiriliyor ve KNN tarzı arama ile JSON ve compact binary vektör girdilerini destekliyor
  • Faiss bağımlılığı kaldırılarak yalnızca Linux ve macOS değil, Windows, WebAssembly, mobil ve Raspberry Pi de hedefleniyor; ikili boyutun da mevcut 3MB~5MB yerine birkaç yüz KB seviyesinde olması bekleniyor
  • Vektörler shadow table içindeki chunk birimleri halinde saklanarak tamamını RAM’e yükleme ihtiyacı azaltılıyor ve PRAGMA mmap_size ile bellek tabanlı arama hızı artırılabiliyor
  • İlk sürüm yalnızca exhaustive full-scan sunacak ve ANN içermeyecek; sqlite-vec.c içindeki 246 TODO tamamlandıktan sonra v0.1.0 sürümünün çıkması planlanıyor

sqlite-vec ile değişmesi amaçlanan SQLite vektör araması

  • sqlite-vec, saf C ile yazılan yeni bir SQLite eklentisi ve Şubat 2023’te duyurulan sqlite-vss yerine geçmesi hedeflenen bir proje
  • Hedef kapsam; hızlı vektör araması için kullanıcı tanımlı SQL fonksiyonları, sanal tablolar (virtual table), vektör işlemleri için araçlar ve yardımcı programları da içeriyor
    • nicemleme
    • JSON/BLOB/numpy dönüşümleri
    • vektör aritmetiği
  • Kullanıcılar yalnızca saf SQL ile bir vektör deposu oluşturup arama yapabiliyor
    • CREATE VIRTUAL TABLE ile vektörler için sanal tablo oluşturma
    • INSERT INTO ile vektör ekleme
    • SELECT ... WHERE sample_embedding MATCH ... ORDER BY distance LIMIT ... biçiminde KNN tarzı arama
  • Vektör girdisi olarak JSON dizgesi veya compact binary biçimi kullanılabiliyor

Saf C ve bağımlılıksız yapının açtığı çalışma ortamları

  • sqlite-vec, bağımlılıksız saf C eklentisi olmayı hedefliyor ve bu tercih, desteklenen platformları genişletmenin temel koşulu olarak görülüyor
  • Mevcut sqlite-vss, C++ bağımlılığı nedeniyle yalnızca Linux ve macOS’ta istikrarlı çalışıyordu ve ikili boyutu 3MB~5MB aralığındaydı
  • Yeni eklenti şu ortamlarda çalışmayı hedefliyor
    • Linux
    • macOS
    • Windows
    • tarayıcıdaki WebAssembly
    • mobil cihazlar
    • Raspberry Pi gibi küçük cihazlar
  • Beklenen ikili boyutu birkaç yüz KB aralığında

Bellek kullanımı ve arama hızını ayarlama

  • sqlite-vec, vektörleri shadow table içindeki chunk’lara bölerek saklama yöntemiyle bellek kullanımını kontrol ediyor
    • KNN araması sırasında tüm vektörler bir anda RAM’e yüklenmiyor, chunk bazında okunuyor
    • Böylece tüm vektörlerin bellekte sürekli tutulması gerekmiyor
  • Bellek tabanlı hız gerektiğinde SQLite’ın PRAGMA mmap_size özelliği kullanılarak KNN araması hızlandırılabiliyor

Yeni vektör özellikleri ve ilk kısıtlar

  • sqlite-vec, güncel vektör arama araçları ve araştırma eğilimlerini yansıtacak şekilde şu özellikleri daha iyi desteklemeyi amaçlıyor
  • Bu özellikler, vektörlerin hız, doğruluk ve disk kullanımı üzerinde daha ince ayar yapabilmek için temel oluşturuyor
  • İlk sqlite-vec sürümü yalnızca exhaustive full-scan vektör aramasını destekleyecek
    • “approximate nearest neighbors” seçeneği başlangıçta olmayacak
    • IVF ve HNSW ise gelecekte eklenmesi umulan özellikler

Tarayıcı demosunun yapısı

  • Demo, tarayıcıda çalışan sqlite-vec kullanıyor
  • Geliştirici araçlarında görülebilen yapı şu bileşenlerden oluşuyor
    • optimize edilmemiş 5.9MB sqlite3.wasm
    • sqlite-vec derlenmiş resmî SQLite WASM derlemesi
    • 2.6MB boyutunda movies.bit.db SQLite veritabanı
  • movies.bit.db, TMDB film meta verileri temel alınarak hazırlanmış 4.800 film overview kaydını articles tablosunda içeriyor
  • Ayrı vec_movies sanal tablosu ise bu overview embedding’lerinin vektör indeksini oluşturuyor

Demo verisi ve KNN arama akışı

  • articles tablosunda title, release_date, overview gibi sütunlar bulunuyor
  • overview sütunu, film özetlerini kısa cümlelerle içeriyor ve demoda embedding hedefi olarak kullanılıyor
  • vec_movies sanal tablosu, articles.overview embedding’lerini overview_embeddings sütununda saklıyor
    • vektörler 768 boyutlu binary vector
    • saklama boyutu 768 / 8 = 96, yani 96 bayt
  • Kullanıcı radyo düğmesiyle bir film seçtiğinde, seçilen film kimliği KNN SQL sorgusundaki :selected_movie parametresine yerleştiriliyor
  • Arama sonucu, seçilen filme en yakın 10 filmden oluşuyor
    • binary vector kullanıldığı için uzaklık hesabında hamming distance kullanılıyor
    • en yakın sonuç her zaman aynı film oluyor ve uzaklığı 0 çıkıyor
  • Kısa tek cümlelik özetlerin ve küçük bir film veri kümesinin embedding’e dönüştürülmesi en yüksek kaliteyi vermiyor; binary quantization da kaliteyi daha da düşürüyor, ancak odak noktası tarayıcı içinde hızlı ve “yeterince iyi” vektör aramasını göstermek
  • İç işleyişi görmek için SELECT önüne EXPLAIN QUERY PLAN eklenebilir; burada vec_movies tarafından kullanılan 0:knn “index” görülebilir

sqlite-vss sınırlamaları ve Faiss bağımlılığı

  • sqlite-vss geliştirme ve benimsenme sürecinde çeşitli engeller vardı
    • yalnızca Linux ve macOS’ta çalışıyor, Windows, WASM, mobil cihazlar gibi ortamları desteklemiyor
    • tüm vektörleri bellekte tutuyor
    • transaction ile ilgili hata ve sorunlar barındırıyor
    • derlenmesi çok zor ve çok zaman alıyor
    • scalar/binary quantization gibi yaygın vektör işlemleri eksik
  • Bu sorunların neredeyse tamamı Faiss bağımlılığından kaynaklanıyor
  • Bazı sorunlar çok zaman ve emekle çözülebilir olsa da, önemli bir kısmı Faiss nedeniyle tıkanabiliyor
  • Bağımlılıksız düşük seviyeli bir çözüm cazip bir seçenek haline geldi ve vektör aramasının aslında o kadar da karmaşık olmadığı değerlendirmesiyle sqlite-vec ortaya çıktı

Sürüm durumu ve sponsorluk çağrısı

  • sqlite-vec çekirdek işlevleri çalışıyor, ancak hata işleme ve testler hâlâ çok yetersiz
  • sqlite-vec.c dosyasında 246 TODO kalmış durumda
    • todo_assert() 191 adet
    • // TODO yorumu 41 adet
    • todo panic 14 adet
    • toplam ilerleme sqlite-vec v0 için 0/246, yani %0 olarak gösteriliyor
  • 246 TODO tamamlandığında ilk v0.1.0 sürümü yayımlanacak
    • belgeler
    • demo
    • binding’ler
    • diğer bileşenler birlikte sunulacak
  • Hedef süre yaklaşık bir ay olsa da kesinleşmiş bir takvim yok
  • sqlite-vec başarısıyla ilgilenen şirketlerden sponsorluk aranıyor ve e-posta ile iletişime geçilebiliyor

1 yorum

 
GN⁺ 2024-05-04
Hacker News yorumları
  • Yazarıyım — sorunuz varsa yanıtlarım. Bu, resmi bir sürümden çok “yeni bir proje üzerinde çalışıyorum” niteliğinde; uzantının kendisi de hâlâ geliştirme aşamasında. Proje bağlantısı: https://github.com/asg017/sqlite-vec
    Bu uzantının v0.1.0 sürümünün nasıl görüneceğine dair oldukça net bir resmim var, ama oraya varmak birkaç hafta daha sürecek gibi. Bu yazının amacı daha çok daha önce yaptığım SQLite vektör arama uzantısı sqlite-vss kullanıcılarına sırada ne olduğunu duyurmaktı; hazır olduğunda daha büyük bir sürüm duyurusu olacak
    Genel olarak kolayca gömülebilen bir vektör arama alternatifine sahip olacağımız için çok heyecanlıyım. Tüm işletim sistemlerinde, WASM’de, mobil cihazlarda, Raspberry Pi’de vb. çalışması özellikle güzel; kişisel olarak da Beepy üzerinde küçük bir anlamsal arama uygulaması çalıştırmayı deniyorum, bu da eğlenceli
    [0] https://beepy.sqfmi.com/

    • Hangi uzaklık fonksiyonlarını desteklediğini merak ediyorum. İkili vektörleri zaten destekliyor gibi görünüyor; Hamming uzaklığının da desteklenip desteklenmediğini merak ediyorum
      sqlite-vss ile karşılaştırmalı performansı da bilmek isterim. Hem sorgu hızı hem de bellek kullanımı için profil çıkarma rakamlarını merak ediyorum
      Genel olarak gerçekten harika görünüyor ve bu yönü seviyorum
      Başta sqlite-vec’in yalnızca tam kapsamlı brute-force vektör aramasını destekleyip yaklaşık en yakın komşu (ANN) seçeneği sunmaması, ama daha sonra IVF ve HNSW eklemek istemesi yaklaşımının %1000 doğru olduğunu düşünüyorum. En baştan aşırı karmaşık hâle getirmemesi hoşuma gidiyor
      Daha önce cihaz üzerinde vektör aramayı yayına almıştım; 128 bit ikili vektörler ve Hamming uzaklığı kombinasyonunda, veritabanı 200 binden fazla öğe içerse bile her kamera karesinde tam brute-force uzaklık araması çalıştıracak kadar hızlıydı. Düşük seviye telefonlarda bile 10 fps’nin üzerinde çıkıyordu, iyi telefonlarda ise çok akıcıydı. Brute force’un yeterli olduğu durumlar şaşırtıcı derecede fazla
      Ancak HNSW gibi ANN algoritmalarını uygularken bunu tablo indeksi paradigmasıyla ele alabilmek harika olurdu. Böylece brute-force aramadan ANN’e geçmek, tabloya indeks oluşturmak kadar basit olur; farklı ANN algoritmaları ve parametreleriyle denemeler yapmak da indeks oluşturma parametrelerini ayarlayarak mümkün olur. Belki zaten bu yöndedir, ama yine de belirtmek istedim
    • HNSW gibi indeksleme stratejilerini de uygulamayı planlayıp planlamadığınızı merak ediyorum. Doğrusal tarama başlangıç noktası olarak elbette iyi; veri makul bir sırayla sıralanmışsa ve örneğin 10 MB’tan küçükse yeterince hızlı olabilir, bu yüzden beta sürümü engelleyecek bir neden gibi görünmüyor
      sqlite-httpvfs ile birlikte derleyip derlemediğinizi de merak ediyorum. Bu projeyle iyi uyum sağlayacak gibi: https://github.com/phiresky/sql.js-httpvfs
    • Wasm’ın dahil olması gerçekten güzel. Normalde tarayıcıda SQLite içindeki vektör aramayı kullanmak zordu
      Ortak bir SQL vektör DSL’i için pgvector ile sözdizimi uyumlu hâle getirmeyi de düşündünüz mü merak ediyorum. Eksilerinin artılarından çok daha küçük olmayabileceğini düşünüyorum, ama mümkün mü merak ediyorum
    • Bunu Rust ile uygulamak mümkün mü? sqlite-loadable-rs projesinin WASM’i destekleyip desteklemediğini de merak ediyorum
      https://observablehq.com/@asg017/introducing-sqlite-loadable...
    • Daha önce sqlite-vss’i Langchain’e vektör deposu olarak eklemiştim. Bu yeni projenin de Langchain’e eklenecek kadar olgun olduğunu düşünüyor musunuz, yoksa biraz daha beklemek mi daha iyi olur?
      sqlite-vss birkaç projede zaten iyi şekilde kullanılıyor
  • “768 boyutlu ikili vektör olduğu için 96 bayt yer kaplıyor (768 / 8 = 96)” kısmı kafamı karıştırdı. Çoğu vektör deposunun yaşadığı sorun olan boyutluluğun laneti tam da bu kısım ve bunun indekslemeden önce gelen bir problem olduğunu düşünüyorum
    Muhtemelen 768 boyut * 8 bayt (f64), yani 6144 bayt demek istenmiştir diye düşündüm. Genelde biraz kaybı göze alarak f32’ye, f16’ya ya da daha küçük bir gösterime indirgenir
    Sıkıştırma veya trie benzeri amortize yöntemlerle 768 boyutu 96 bayta sığdırmanın bir yolu varsa bunu ayrı bir yazıda daha fazla duymak isterim. Her boyutu 1 bit olarak ele alıyorsanız bunu anlarım, ama o zaman arama kalitesi konusunda hâlâ merak ettiğim noktalar var

    • Yazarıyım — burada ikili vektör, her boyutun 1 bit’e kuantize edildiği anlamına geliyor. Normalde vektör başına 4 * boyut sayısı bayt gerekir. Buradaki 4, sizeof(float)
      nomic v1.5[0] veya mixedbread’in yeni modeli[1] gibi bazı gömme modelleri, ikili kuantizasyondan sonra da kaliteyi koruyacak şekilde özel olarak eğitiliyor. Her model için böyle değil, dolayısıyla sonuçlar değişebilir. Genel olarak OpenAI’nin 3072 boyutlu büyük gömme modeli gibi çok büyük vektörlerde, bunun için özel olarak eğitilmemiş olsa bile bir ölçüde işe yarıyor gibi görünüyor
      [0] https://twitter.com/nomic_ai/status/1769837800793243687
      [1] https://www.mixedbread.ai/blog/binary-mrl
    • İkili demek, her boyutun +1 veya -1 olarak kuantize edilmesi demek
      Verilerde FAISS indeksi kullanıp Ürün Kuantizasyonu (Product Quantization) uygularsanız, ikili özellikler için PQ768x1 gibi bir yöntemle ikili vektörleri deneyebilir; ayrıca her vektör çifti için dört değerden birine kuantize etme gibi yaklaşımları da karşılaştırabilirsiniz: https://github.com/facebookresearch/faiss/wiki/The-index-fac...
    • Not olarak, boyutluluğun laneti teknik olarak yüksek boyutlu uzayın görece seyrekleşmesi ve o uzayı doldurmak için verinin üstel olarak artması gerektiği anlamına gelir. Depolama kapasitesiyle ilgisi yoktur
      Vektör veritabanlarında genellikle veriler depolanmadan önce daha düşük boyutlu bir uzaya sıkıştırıldığı veya projekte edildiği için bu durum aksine iyileşir
  • sqlite-vss sayesinde RAG’in nasıl çalıştığını öğrenip bir oyuncak projede uygulayabildim. Hata ayıklaması biraz zordu ama doğru ayarlayınca Ubuntu’da kusursuz çalıştı ve hâlâ kullanıyorum
    Sınırlayıcı bağımlılıklar olmadan daha iyi yeni bir sürüm yapılıyor olması sevindirici

  • Yalnızca herkese açık SQLite API’lerini mi kullanmayı planladığınızı, yoksa SQLite amalgamation’a eklenen bir biçim mi öngördüğünüzü merak ediyorum
    Bu tür bir özelliğe kesinlikle ilgim var, ancak Wasm tabanlı Go binding’lerinde SQLite’tan ayrı olarak nasıl dağıtacağımı düşünmem gerekiyor. Şimdiye kadar Wasm “dinamik linkleme”den çok daha basit olduğu için tüm C kodunu paketleyip dağıtıyordum
    Ayrıca artımlı BLOB giriş/çıkışından bahsetmişsiniz; muhtemelen biliyorsunuzdur ama büyük BLOB’ların sayfaların bağlı listesi olarak saklandığını, bu yüzden BLOB giriş/çıkışının asla rastgele erişim olmadığını akılda tutmak gerekir

    • Yalnızca herkese açık SQLite API’lerini kullanmayı planlıyoruz. Bu yüzden amalgamation’a eklemeye gerek yok
      wazero SQLite binding’lerini gerçekten seviyorum. Aslında 1) sqlite-vec için CGO binding’leri ve 2) go-sqlite3’te doğrudan kullanılabilecek özel bir WASI derlemesi sqlite-vec sunmayı planlıyorum. Başta o depodaki build script’lerini kullanarak sqlite3.wasm dosyasını oluşturmayı düşünüyordum. Projede doğrudan desteklemek isterseniz sqlite-vec.c/h dosyasını go-sqlite3/sqlite3 içine koymak yeterli olabilir
      Artımlı BLOB giriş/çıkışını zor yoldan öğrendim. sqlite-vec’in sorgu hızında kesinlikle sınırlayıcı bir etken. Parça boyutunu nispeten küçük, düşük MB seviyelerinde tutup page_size’ı artırınca denge fena olmuyordu; ama özellikle page_size’ın yan etkileri var. PRAGMA mmap_size da sayfaları bellekte tutarak overflow okumalarını hızlandırıyor gibi göründüğü için çok yardımcı oluyor, ama doğal olarak bellek kullanımı çok daha fazla artıyor. Zor bir denge
    • Bu özellik Wasm Go binding’lerine girerse gerçekten ilgilenirim
  • DuckDB bugün “Vector Similarity Search in DuckDB” eklentisini duyurdu
    https://duckdb.org/2024/05/03/vector-similarity-search-vss.h...

    • Bu heyecan verici. Daha önce yaptığım küçük CDN tabanlı HNSW projesini büyük ölçüde basitleştirebilir gibi: https://github.com/jasonjmcghee/portable-hnsw
      DuckDB VSS kullanınca embedding üretip DuckDB formatında sakladıktan sonra CDN içinde SQL çalıştırarak halledilebilecek gibi görünüyor
  • Bu tarzdaki projeleri seviyorum. Çok belirli bir problemi hedefleyen bir açık kaynak proje olması hoşuma gidiyor
    TypeScript/Next.js/React ekosisteminde de teknik bir nişte çok faydalı bir şey yapabilir miyim diye sürekli düşünüyorum ama henüz ilham gelmedi

  • Yapay zeka RAG uygulaması olan https://github.com/rnadigital/agentcloud içinde uçtan uca otomasyon için Qdrant vektör DB kullandık; bir devam projesi yaptığınızı duyduğuma sevindim. Ne zaman kullanıma hazır olacağını ve hızlı başlangıç kılavuzu olup olmadığını merak ediyorum
    Blog yazımına da yardımcı olabilirim

    • v0.1.0 için hedef yaklaşık bir ay sonrası. Bolca dokümantasyon ve hızlı başlangıç kılavuzu eklemeyi planlıyorum
      Dokümante edilmemiş bir sqlite-vec pip paketi var; Python’daki “Agent Backend” üzerinden doğrudan çağırmak isterseniz şimdiden deneyebilirsiniz
  • Bu, “README odaklı geliştirme”nin nasıl görüneceğini hayal ettiğime oldukça benziyor. Yazarın önce dokümantasyonla başlayıp başlamadığını merak ediyorum

    • Önce kodla başladım. Eklentinin kendisi zaten büyük ölçüde yazılmış durumda[0]
      Ancak “%20 çabayla %80’ini yapmış” haldeyim; kalan %20 olan hata işleme, fuzz testleri ve doğruluk testleri zamanın %80’ini alacak gibi. Yine de insanlar mevcut sqlite-vss durumu hakkında zaten sorular soruyor, bu yüzden bu “devam eden çalışma” blog yazısının bazı sorulara yanıt verebileceğini düşündüm
      Önce dokümantasyonla başlama fikrini de seviyorum. Özellikle SQLite eklentilerinde SQL API’sinin nasıl göründüğü, yani skaler fonksiyonlar ve sanal tablolar vb. gerçekten önemli. Kodun çoğunu yazmadan önce sqlite-vec’in SQL tarafının nasıl görünmesi gerektiğini epeyce taslak olarak çıkardım
      [0] https://github.com/asg017/sqlite-vec/blob/main/sqlite-vec.c
  • Birkaç ay önce SQLite-vss’e açtığım GitHub issue’suna verilmiş bir yanıta yakın gibi. Teknik olarak o issue’ya bir yanıt olmasa da
    https://github.com/asg017/sqlite-vss/issues/124

    • Evet. Oraya takip yanıtı veremediğim için üzgünüm
      Aslında o bileti ilk okuduğumda “sqlite-vss’i nasıl daha iyi hale getirebilirim” tavşan deliğine girdim ve sonunda “sqlite-vec’i yapmalıyım” noktasına geldim. Bu yola girmeme yardımcı olduğunuz için teşekkürler
      sqlite-vec’in yerleşik ikili kuantalamasını kullanırsanız kabaca şöyle yapabilirsiniz:
      CREATE VIRTUAL TABLE vec_files USING vec0 ( contents_embedding bit[1536] );
      INSERT INTO vec_files(rowid,contents_embedding) VALUES ((1, vec_quantize_binary( /* 1536-dimension float vector here*/)))
  • Tarayıcı içinde çalışırken sqlite-vec’in verileri tarayıcının yerel IndexedDB’sinde kalıcı hale getirip getiremeyeceğini merak ediyorum. Yoksa bu kısmı kullanıcının kendisinin mi yönetmesi gerektiğini bilmek istiyorum
    Henüz üzerine düşünmedim şeklinde bir yanıt olsa bile, bu yöndeki düşüncelerinizi paylaşırsanız memnun olurum

    • Mümkün olabilir. Resmî SQLite WASM derlemesini temel aldığı için, onun sunduğu aynı kalıcılık seçenekleri[0] kullanılabilir
      IndexedDB’nin özel olarak desteklenip desteklenmediğinden emin değilim, ancak localStorage/OPFS VFS kullanılabilir
      [0] https://sqlite.org/wasm/doc/trunk/persistence.md#kvvfs