- 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
- Son haber olarak batch processing uygulanmış ve görüntü kodlama hızı yaklaşık 3 kata kadar iyileşmiştir
- Llama 3.2 1B, yazarın 16 çekirdekli makinesinde 50 tok/s hızda çalışmaktadır
- Hazır modeller ve tokenizer’lar Hugging Face’ten indirilebilir
- Hız ölçümü 16 çekirdekli AMD Epyc üzerinde yapılmıştır
- README Q8_0 kullanımını önerir; Q4_0 quantization’ın ise hâlâ iyileştirilmekte olduğunu belirtir
-
Hazır model tablosu
- Gemma 2 2B IT Q4_0: 1.39G, 20 tok/s
- Gemma 2 2B IT Q8_0: 2.66GB, 24 tok/s
- Gemma 2 9B IT Q4_0: 4.91GB, 7 tok/s
- Gemma 2 9B IT Q8_0: 9.53GB, 8 tok/s
- Llama 3.2 1B IT: 4.94GB, 21 tok/s
- Llama 3.2 1B IT Q8_0: 1.27GB, 50 tok/s
- Llama 3.2 3B IT Q4_0: 1.71GB, 17 tok/s
- Llama 3.2 3B IT Q8_0: 3.31GB, 19 tok/s
- PHI 3.5 IT Vision Q8_0: 4.28GB, 17 tok/s
- PHI 3.5 IT Mini Q8_0: 3.94GB, 18 tok/s
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
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ş/tmpiçinelm.rsklonlanıpRUSTFLAGS="-C target-cpu=native" cargo build --release --bin chatile derlendikten sonra, Hugging Face’tentokenizer.binvellama3.2-1b-it-q80.lmrsindirilerek./target/release/chat --model llama3.2-1b-it-q80.lmrskomutuyla çalıştırılmış./target/release/chat --model llama3.2-1b-it-q80.lmrs --show-metricsile çalıştırıp saniyedeki token sayısının ne kadar çıktığını kontrol edip edemeyeceği sorulmuşBiçimlendirme nedeniyle yalnızca bir kısmı bırakılmış, ama uzun rastgele kelime dizileri sürekli devam eden bir yapıdaymış
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üzdenlm.rsnesnesine bağlı bir logging örneğinin string buffer’ına yazması daha iyi olurAyrıca model reader’da veri hizalamasını zorlamak için
unsafekullanılan bir kısım görülüyor; çok zorlamadanunsafeolmadan mümkün olup olmadığı da merak ediliyorBö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.cppdesteği için, ama bu da oldukça ilginç. Grammar kısıtlaması (grammar) desteği planlanıp planlanmadığı da merak ediliyorhttps://github.com/ShelbyJenkins/llm_client
Başlıktaki no dependency ifadesi pek net değil
İlk bakışta
no_stdolabilir diye düşünülmüş, ama aslındano_stddeğil ve birkaç bağımlılık da var gibi görünüyor. Belki hepsinin Rust bağımlılığı olduğu kastedilmiş olabilirŞeffaf olmak gerekirse 5 temel Rust bağımlılığı var; bunlardan
chronoveclapchat ö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ıranrayon, SIMD’ye yardımcı olanwide, model dosyasını bellek eşlemek içinmemmap2requirements.txtiç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
Ne yazık ki HN başlıklardan kelimeleri çoğu zaman pek gerekçe veya şeffaflık olmadan silebiliyor
cargosu da artık neredeysenpmgibi mi oldu diye düşündürüyor16 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
https://github.com/crabml/crabml
Bazı SIMD komutlarını doğrudan kullandım ve performansın
llama.cppile 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üyorAncak 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
https://github.com/maedoc/rwkv.js
Emscripten ile derlenmiş
Rwkv.cppkullandı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üyorGenel sohbet için kapasitesi yetersiz, ama RAG gibi kullanım alanları için gayet yeterli olabilir
Zorunlu bağımlılıklar olan
rayonvewideWASM’ı doğrudan destekliyor;transformer.rsiçindekiMmaptipini&[u8]ile değiştirirsenizmemmap2de kaldırılabilirAncak 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
GPU destekleyen bir Rust framework’ü denemek istiyorsanız Candle’a https://github.com/huggingface/candle/tree/main bakmaya değer
Amacınız gerçekten çalıştırmaksa, yalnızca CPU kullansanız bile alternatif olarak
llama.cppkullanmak 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ınLLM’ler etki açısından sihir gibi görünse de kod açısından oldukça basit
Rust tarafında benim
llm_clientgibillama.cppsarmalayıcıları var; Candle tabanlı projeler olarak damistral.rsve Kalosm bulunuyorBenim projem de
mistral.rsuygulaması sunmayı hedefliyor, ama henüzllama.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Ö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
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.cppile karşılaştırıldığında ne tür bir değer sunduğunu merak ediyorumGü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
Ancak ana yazar olmasam da katkıcı olarak
wgpuile 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 bilmiyorumRust topluluğunun neredeyse her şeyi yeniden yazma konusundaki tutkusu ilginç ve takdire değer geliyor