1 puan yazan GN⁺ 2024-10-12 | 1 yorum | WhatsApp'ta paylaş
  • lm.rs, Rust ile CPU üzerinde yerel dil modeli çıkarımı çalıştıran bir projedir ve ML kütüphanesi olmadan tüm çıkarımı yapan minimal bir kod uygulaması hedefler
  • Karpathy’nin llama2.c ve llm.c projelerinden ilham aldı; başlangıçta yalnızca Google Gemma 2’yi desteklerken Llama 3.2 ve PHI-3.5 ile görüntü girişi desteğine kadar genişledi
  • Son değişiklikle batch processing uygulanarak görüntü kodlama hızı yaklaşık 3 kata kadar artırıldı; Llama 3.2 1B, yazarın 16 çekirdekli makinesinde 50 tok/s hızda çalışıyor
  • Hazır modeller Hugging Face’ten indirilebiliyor; README Q8_0 kullanımını öneriyor ve Q4_0 quantization’ın hâlâ iyileştirilmekte olduğunu belirtiyor
  • Kullanıcılar LMRS formatındaki modeli ve tokenizer’ı indirip doğrudan derleyebilir veya Hugging Face’teki özgün model dosyalarını export.py ve tokenizer.py ile dönüştürerek çalıştırabilir

lm.rs’nin hedefi

  • lm.rs, Rust ile yazılmış yerel CPU tabanlı bir dil modeli çıkarım uygulamasıdır
  • Amaç, ML kütüphanesi olmadan CPU üzerinde dil modelinin tüm çıkarımını yapan minimal bir kod uygulamasıdır
  • Karpathy’nin llama2.c ve llm.c projelerinden ilham almıştır
  • README, mevcut kodun “o kadar da minimal olmadığını” ve bazı kodların optimizasyon ve iyileştirmeye açık olduğunu belirtir
  • Proje aynı zamanda yazarın Rust’ı ilk kez denemesi için bir vesile olmuştur

Desteklenen modeller ve multimodal genişleme

  • Başlangıçta yalnızca Google Gemma 2 modellerini destekliyordu; daha sonra Llama 3.2 model desteği eklendi
  • Yakın zamanda PHI-3.5 üzerinden görüntü kullanma seçeneği eklendi
  • Şu anda öne çıkan destek kalemleri
    • PHI-3.5-vision modeli üzerinden multimodal destek
    • PHI-3.5-mini yalnızca metin modeli desteği
  • İlgili kaynaklar

Performans ve hazır modeller

Model dönüştürme akışı

  • Hazır quantized modelleri ve tokenizer’ları Hugging Face’ten indirirseniz dönüştürme sürecini atlayabilirsiniz
  • Google veya Meta’nın Hugging Face’te yayımladığı modelleri doğrudan dönüştürmek için ek Python bağımlılıklarının kurulması gerekir
pip install -r requirements.txt
  • Özgün model sayfasından .safetensors ve config.json dosyaları indirilip kullanılır
  • PHI3.5 Vision gibi multimodal modeller için CLIP config dosyası da gerekir
  • export.py, bfloat16 ağırlıklarını LMRS formatına dönüştürür
python export.py --files [ordered .safetensor files] --config [model config.json] --save-path [name and path to save] --type [model type (GEMMA/LLAMA/PHI)]
  • Quantized sürüm dışa aktarmak için --quantize ve --quantize-type bayrakları kullanılır
  • int8 quantization model boyutu, grup boyutuna bağlı olarak yaklaşık 9.8G’den yaklaşık 2.5G’ye düşebilir
  • Multimodal modeller --vision-config argümanını içermelidir
  • tokenizer.py, tokenizer modelini LMRS tokenizer formatına dönüştürür
python tokenizer.py --model-id [huggingface model_id] --tokenizer-type [type of the tokenizer (GEMMA/LLAMA/PHI)]

Derleme ve çalıştırma

  • Rust kodu cargo ile derlenir; README target-cpu bayrağının iletilmesini belirtir
RUSTFLAGS="-C target-cpu=native" cargo build --release --bin chat
  • Multimodal işlevleri etkinleştirmek için --features multimodal argümanı eklenir
  • Temel çalıştırma, model ağırlıkları dosyası belirtilerek yapılır
./target/release/chat --model [model weights file]
  • Ek argüman olarak tokenizer, temperature, top-p, show-metrics vb. kullanılabilir
  • Kullanılabilir argümanlar --help ile kontrol edilir
  • Multimodal modellerde görüntü yolunu belirtmek için --image argümanı kullanılır
  • PHI3.5-vision kullanırken README temperature değerinin 0 olmasını önerir

WebUI backend çalıştırma

  • WebUI için backend çalıştırmak üzere backend özelliğiyle derlenir
RUSTFLAGS="-C target-cpu=native" cargo build --release --features backend --bin backend
  • Multimodal backend için backend-multimodal özelliği etkinleştirilir
  • Backend, model ağırlıkları dosyası belirtilerek çalıştırılır
./target/release/backend --model [model weights file]
  • IP ve port --ip ve --port ile değiştirilebilir
  • temperature gibi ek bayraklar da kullanılabilir
  • Multimodal uyumluluk için --multimodal bayrağı kullanılır
  • Çalıştırdıktan sonra web arayüzüne bağlanılabilir

TODO durumu ve lisans

  • Tamamlanan kalemler
    • Başka sampling yöntemleri ekleme
    • 9B ve 27B model test kalemlerinden 9B testi tamamlandı; 27B’nin çok yavaş olacağı belirtildi
    • Multi-head attention döngüsünün paralelleştirilmesi
    • Performans metrikleri ekleme
    • int8, int4 quantization desteği
  • Kalan kalemler
    • Sistem prompt’u sağlama işlevi
  • Lisans MIT’dir

1 yorum

 
GN⁺ 2024-10-12
Hacker News görüşleri
  • M2 64GB MacBook üzerinde 1,2 GB’lık llama3.2-1b-it-q80.lmrs çalıştırıldığında oldukça hızlı hissettirdiği ve Activity Monitor’a göre 13 iş parçacığında CPU’nun %1000 kullanıldığı belirtilmiş
    /tmp içine lm.rs klonlanıp RUSTFLAGS="-C target-cpu=native" cargo build --release --bin chat ile derlendikten sonra, Hugging Face’ten tokenizer.bin ve llama3.2-1b-it-q80.lmrs indirilerek ./target/release/chat --model llama3.2-1b-it-q80.lmrs komutuyla çalıştırılmış

    • ./target/release/chat --model llama3.2-1b-it-q80.lmrs --show-metrics ile çalıştırıp saniyedeki token sayısının ne kadar çıktığını kontrol edip edemeyeceği sorulmuş
    • Basit bir Fransızca sohbet istemi girildiğinde başta yanıt veriyor gibi görünmüş, ancak kısa süre sonra sonsuz ve anlaşılmaz çöp çıktıya çökmüş
      Biçimlendirme nedeniyle yalnızca bir kısmı bırakılmış, ama uzun rastgele kelime dizileri sürekli devam eden bir yapıdaymış
    • Bunun en yeni ChatGPT ile karşılaştırıldığında ne kadar akıllı olduğunu nasıl anlamak gerektiği merak edilmiş
  • Yazı çok iyi yazılmış; derste transformer’ların gerçekte nasıl çalıştığını anlatırken kaynak kodun bir kısmı kullanılabilir gibi görünüyor
    Kod, attention head çizimlerinden daha somut ve ayrıntılı. Ancak kütüphane doğrudan stdout’a çıktı verirse, metin düzenleyicide stil denetimi sunmak gibi uygulama çıktılarını bozabilir; bu yüzden lm.rs nesnesine bağlı bir logging örneğinin string buffer’ına yazması daha iyi olur
    Ayrıca model reader’da veri hizalamasını zorlamak için unsafe kullanılan bir kısım görülüyor; çok zorlamadan unsafe olmadan mümkün olup olmadığı da merak ediliyor

    • String buffer yerine kullanıcı callback’i çağırmak daha iyi olur
      Böylece logları GUI’de göstermek gibi şekillerde işlenebilir
  • Model yükleme ve çeşitli LLM işleri için Rust araçları epeyce hazırlanmış
    Kullanılabilir belleğe göre en büyük quantized modeli otomatik seçme, gguf’tan tokenizer çıkarma, prompt verme gibi özellikleri var. Bunlar kullanılırsa bazı Python bağımlılıkları kaldırılabilir gibi görünüyor
    Şu anda llama.cpp desteği için, ama bu da oldukça ilginç. Grammar kısıtlaması (grammar) desteği planlanıp planlanmadığı da merak ediliyor
    https://github.com/ShelbyJenkins/llm_client

  • Başlıktaki no dependency ifadesi pek net değil
    İlk bakışta no_std olabilir diye düşünülmüş, ama aslında no_std değil ve birkaç bağımlılık da var gibi görünüyor. Belki hepsinin Rust bağımlılığı olduğu kastedilmiş olabilir

    • Başlık koymak zor. Söylenmek istenen, PyTorch, CUDA, ONNX gibi derin öğrenme bağımlılıklarının olmadığı ve tüm mantığın kendi içinde bulunduğuydu
      Şeffaf olmak gerekirse 5 temel Rust bağımlılığı var; bunlardan chrono ve clap chat özelliği için feature flag ile ele alınmalı. Kalan 3’ü donanım performansından biraz daha fazla yararlanmak için kullanılan yardımcı crate’ler: paralelleştirmeyi kolaylaştıran rayon, SIMD’ye yardımcı olan wide, model dosyasını bellek eşlemek için memmap2
    • README’ye bakınca requirements.txt içinde PyTorch ve çeşitli Python bağımlılıkları gerekiyor gibi görünüyor; sayfada “dependency” kelimesinin göründüğü tek yer de orası olduğundan başlıktaki ifade epey kafa karıştırıcı
      Projenin kendisi yalnızca “Minimal LLM inference in Rust” alt başlığını kullanıyor gibi. Git geçmişine bakılırsa bu yazıyı paylaşan hesap katkıda bulunan biri, ama ana yazar değil gibi; zero dependencies ifadesinin tam olarak ne anlama geldiğini açıklarsa faydalı olur
    • Aslında başlık “donanım bağımlılığı yok” veya “GPU bağımlılığı yok” gibi olsaydı anlamlı olabilirdi
      Ne yazık ki HN başlıklardan kelimeleri çoğu zaman pek gerekçe veya şeffaflık olmadan silebiliyor
    • Rust’ın cargosu da artık neredeyse npm gibi mi oldu diye düşündürüyor
      16 bağımlılık varken nasıl bağımlılık yok denebildiği anlaşılmıyor
  • Daha önce benzer bir şey yapılmış, ancak CPU’da çalışan C/C++ kodla karşılaştırıldığında performansı yetersiz kalmış
    Bu, Rust’ı hızlı hale getirmenin yolunu doğru bilmediği anlamına da geliyor. Çeşitli Rust implementasyonlarının benchmark’ları olsa iyi olurdu
    LLM inference implementasyonu, ciddi programcılar için yeni bir “Hello, world!” haline gelebilir gibi görünüyor
    https://github.com/gip/yllama.rs

    • Benim de eskiden benzer bir “Hello, world” deneyimi olarak yaptığım bir şey var
      https://github.com/crabml/crabml
      Bazı SIMD komutlarını doğrudan kullandım ve performansın llama.cpp ile eşleşebileceği görülüyordu. Kilit nokta quantized matris çarpımında SIMD kullanımı ve iş parçacıkları arasında iş bölümü yaparken condition variable yerine busy-wait döngüsü kullanmak gibi görünüyor
      Ancak GPU’da Vulkan ile quantized model inference üzerinde çalışmaya devam edecek zamanım olmadığından bir süredir güncelleyemedim
  • Zaten Dioxus kullanılıyor olması ilginç; yol haritasına WASM’ın da girip giremeyeceğini merak ediyorum
    Tarayıcıda RWKV gibi hafif bir LLM çalıştırılabilirse, SaaS API çağırmadan da tarayıcı yeni bir işlev kategorisinin önünü açabilir

    • Bu tarafla biraz uğraşmıştım
      https://github.com/maedoc/rwkv.js
      Emscripten ile derlenmiş Rwkv.cpp kullandım, ama tokenizer kısmını henüz düzgün çözememiştim. Yine de 1.6B RWKV6 yalnızca çevrimdışı tarayıcı kullanımı için yeterince işe yarar görünüyor
      Genel sohbet için kapasitesi yetersiz, ama RAG gibi kullanım alanları için gayet yeterli olabilir
    • Kütüphanenin kendisi çok az değişiklikle WASM derlemesine uygun görünüyor
      Zorunlu bağımlılıklar olan rayon ve wide WASM’ı doğrudan destekliyor; transformer.rs içindeki Mmap tipini &[u8] ile değiştirirseniz memmap2 de kaldırılabilir
      Ancak RWKV tamamen farklı bir mimari olduğundan her şeyin baştan uygulanması gerekir; yol haritasına girme ihtimali de çok düşük görünüyor
  • Bu uygulamaların hepsinin yalnızca CPU ile sınırlı olup olmadığını merak ediyorum
    İyi bir GPU varsa başka alternatiflere bakmak mı gerekir diye soruyor

    • Evet. Bu proje CPU’da çalıştığı için GPU’yu hesaplamada kullanmıyor
      GPU destekleyen bir Rust framework’ü denemek istiyorsanız Candle’a https://github.com/huggingface/candle/tree/main bakmaya değer
    • Hepsi CPU üzerinde uygulanmış ve en azından şu anda hiç GPU hızlandırması yok
      Amacınız gerçekten çalıştırmaksa, yalnızca CPU kullansanız bile alternatif olarak llama.cpp kullanmak daha iyi olur. Bu proje, ekosistemdeki karmaşık katmanlar kaldırıldığında içeride nelerin nasıl çalıştığını gösteren eğitim materyaline daha yakın
      LLM’ler etki açısından sihir gibi görünse de kod açısından oldukça basit
    • GPU’ya bağlı olarak 10~20 kat fark olabilir
      Rust tarafında benim llm_client gibi llama.cpp sarmalayıcıları var; Candle tabanlı projeler olarak da mistral.rs ve Kalosm bulunuyor
      Benim projem de mistral.rs uygulaması sunmayı hedefliyor, ama henüz llama.cpp’den tamamen geçiş yapamadım. Tam Rust uygulamasının kurulum süresini hızlandırmak gibi büyük avantajları var. Şu an benim crate’imin klonlanıp derlenmesi gerekiyor; macOS, Windows ve Linux’ta otomasyon var, ama derleme süresi yaklaşık 1 dakika uzuyor
    • CPU da doğru, ama daha önemli olan bellek bant genişliği
      Örneğin RTX 3090 neredeyse 1TB/s bellek bant genişliğine sahip. Bunu yakalamak için dünyadaki en hızlı kavram kanıtı düzeyindeki DDR5’ten en az 12 kanal gerekir
      Harici GPU’nuz varsa onu kullanan bir uygulama seçmek bambaşka bir dünya. Apple Silicon’daki LLM çıkarım değerlerinin etkileyici olmasının nedeni de CPU-GPU birleşik yüksek bant genişlikli bellek mimarisi; hatırladığım kadarıyla yaklaşık 400GB/s idi
    • Duruma göre değişir. İyi modeller büyük olur ve bellek gereksinimleri de yüksektir
      4090 bile LLM ölçütlerine göre o kadar fazla belleğe sahip değil. GPU daha hızlı olacaktır, ama büyük modelleri yükleyememe ihtimali yüksek
  • Bunun llama.cpp ile karşılaştırıldığında ne tür bir değer sunduğunu merak ediyorum

    • Diğer Rust projeleriyle entegre etmek daha kolay olabilir
    • Özellikleri daha az olduğu için kod tabanı daha temiz
  • Güzel bir iş ve ilk Rust kütüphanesini yapmış olman da tebrik edilesi, ama ciddi yerel kullanım için Metal/CUDA desteği şart

    • CUDA kullanmak bu projenin amacıyla çeliştiği için en baştan uygun değil
      Ancak ana yazar olmasam da katkıcı olarak wgpu ile bir miktar GPU hızlandırması elde etmeyi deniyorum. Ana yazar karmaşıklığı kontrol altında tutmak istiyor, bu yüzden pratikte nereye kadar gideceğini bilmiyorum
  • Rust topluluğunun neredeyse her şeyi yeniden yazma konusundaki tutkusu ilginç ve takdire değer geliyor