1 पॉइंट द्वारा GN⁺ 2024-10-12 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • lm.rs Rust में CPU पर local language model inference चलाने वाला project है, और इसका लक्ष्य ML libraries के बिना पूरा inference करने वाला न्यूनतम code implementation बनाना है
  • यह Karpathy के llama2.c और llm.c से प्रेरित है; शुरुआत में यह केवल Google Gemma 2 को support करता था, लेकिन अब Llama 3.2 और PHI-3.5 image input support तक विस्तारित हो चुका है
  • हालिया बदलावों में batch processing implement की गई है, जिससे image encoding speed लगभग 3 गुना तक तेज हुई है, और Llama 3.2 1B लेखक की 16-core machine पर 50 tok/s पर चलता है
  • तैयार models Hugging Face से लिए जा सकते हैं; README Q8_0 इस्तेमाल करने की सलाह देता है और बताता है कि Q4_0 quantization अभी सुधार के दौर में है
  • users LMRS format model और tokenizer डाउनलोड करके सीधे build कर सकते हैं, या Hugging Face की original model files को export.py और tokenizer.py से convert करके चला सकते हैं

lm.rs का लक्ष्य

  • lm.rs Rust में लिखा गया local CPU-based language model inference implementation है
  • लक्ष्य है ML libraries के बिना CPU पर language model का पूरा inference करने वाला न्यूनतम code implementation
  • Karpathy के llama2.c और llm.c से प्रेरित है
  • README बताता है कि मौजूदा code “इतना minimal नहीं है”, और कुछ code में optimization और सुधार की गुंजाइश है
  • यह project लेखक के लिए पहली बार Rust आज़माने का एक कारण भी है

supported models और multimodal विस्तार

  • शुरुआत में केवल Google Gemma 2 models support थे, लेकिन बाद में Llama 3.2 model support जोड़ा गया
  • हाल में PHI-3.5 के ज़रिए image इस्तेमाल करने का option जोड़ा गया
  • वर्तमान में प्रमुख supported items
    • PHI-3.5-vision model के ज़रिए multimodal support
    • PHI-3.5-mini text-only model support
  • संबंधित resources

performance और तैयार models

  • ताज़ा खबर के रूप में batch processing implement हुई है, जिससे image encoding speed लगभग 3 गुना तक बेहतर हुई है
  • Llama 3.2 1B लेखक की 16-core machine पर 50 tok/s पर चलता है
  • तैयार models और tokenizers Hugging Face से मिल सकते हैं
  • speed measurements 16-core AMD Epyc पर किए गए
  • README Q8_0 इस्तेमाल करने की सलाह देता है, और बताता है कि Q4_0 quantization अभी सुधार के दौर में है
  • तैयार models की तालिका

model conversion flow

  • Hugging Face से तैयार quantized models और tokenizers लेने पर conversion process skip किया जा सकता है
  • Google या Meta द्वारा Hugging Face पर जारी models को खुद convert करने के लिए अतिरिक्त Python dependencies install करनी होंगी
pip install -r requirements.txt
  • original model page से .safetensors और config.json files डाउनलोड करके इस्तेमाल की जाती हैं
  • PHI3.5 Vision जैसे multimodal models के लिए CLIP config file भी चाहिए
  • export.py bfloat16 weights को LMRS format में convert करता है
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 version export करने के लिए --quantize और --quantize-type flags इस्तेमाल करें
  • int8 quantized model size group size के आधार पर लगभग 9.8G से घटकर लगभग 2.5G हो सकता है
  • multimodal models में --vision-config argument शामिल करना होगा
  • tokenizer.py tokenizer model को LMRS tokenizer format में convert करता है
python tokenizer.py --model-id [huggingface model_id] --tokenizer-type [type of the tokenizer (GEMMA/LLAMA/PHI)]

build और run

  • Rust code cargo से compile होता है, और README target-cpu flag pass करने का उल्लेख करता है
RUSTFLAGS="-C target-cpu=native" cargo build --release --bin chat
  • multimodal feature enable करने के लिए --features multimodal argument जोड़ें
  • basic run model weights file specify करके किया जाता है
./target/release/chat --model [model weights file]
  • additional arguments के रूप में tokenizer, temperature, top-p, show-metrics आदि इस्तेमाल किए जा सकते हैं
  • available arguments --help से देखे जा सकते हैं
  • multimodal models में --image argument से image path specify किया जाता है
  • PHI3.5-vision इस्तेमाल करते समय README temperature 0 की सलाह देता है

WebUI backend run करना

  • WebUI के लिए backend run करने हेतु backend feature के साथ compile करें
RUSTFLAGS="-C target-cpu=native" cargo build --release --features backend --bin backend
  • multimodal backend के लिए backend-multimodal feature enable करें
  • backend model weights file specify करके run होता है
./target/release/backend --model [model weights file]
  • --ip और --port से IP और port बदले जा सकते हैं
  • temperature जैसे additional flags भी इस्तेमाल किए जा सकते हैं
  • multimodal compatibility के लिए --multimodal flag इस्तेमाल करें
  • run करने के बाद web interface से connect किया जा सकता है

TODO status और license

  • पूरे हुए items
    • अन्य sampling methods जोड़ना
    • 9B और 27B model test items में से 9B test पूरा, 27B को बहुत धीमा होने की संभावना के रूप में चिह्नित किया गया
    • multi-head attention loop parallelization
    • performance metrics जोड़ना
    • int8, int4 quantization support
  • बाकी items
    • system prompt देने की functionality
  • license MIT है

1 टिप्पणियां

 
GN⁺ 2024-10-12
Hacker News की राय
  • M2 64GB MacBook पर 1.2GB वाले llama3.2-1b-it-q80.lmrs को चलाकर देखा, तो यह काफी तेज लगा, और Activity Monitor के हिसाब से 13 threads पर CPU 1000% इस्तेमाल कर रहा था
    /tmp में lm.rs क्लोन किया और RUSTFLAGS="-C target-cpu=native" cargo build --release --bin chat से build करने के बाद, Hugging Face से tokenizer.bin और llama3.2-1b-it-q80.lmrs डाउनलोड किए और ./target/release/chat --model llama3.2-1b-it-q80.lmrs से चलाया

    • पूछा कि क्या ./target/release/chat --model llama3.2-1b-it-q80.lmrs --show-metrics से चलाकर देखा जा सकता है कि tokens per second कितने मिलते हैं
    • एक सरल French बातचीत वाला prompt डालने पर पहले लगा कि जवाब दे रहा है, लेकिन जल्द ही बेतहाशा, समझ से परे अंतहीन garbage output में टूट गया
      formatting की वजह से सिर्फ कुछ हिस्सा रखा, लेकिन लंबे random शब्दों की string लगातार चलती रही
    • जानना है कि इसे latest ChatGPT की तुलना में कितना smart समझा जाए, इसे कैसे समझना चाहिए
  • लेख बहुत अच्छी तरह लिखा गया है, और class में transformers असल में कैसे काम करते हैं यह समझाते समय source code के कुछ हिस्से इस्तेमाल किए जा सकते हैं
    attention head वाली diagrams की तुलना में code ज्यादा ठोस और detailed है। हालांकि library अगर सीधे stdout पर output करे, तो text editor में style checking देने जैसी application output खराब हो सकती है, इसलिए lm.rs object से जुड़े logging instance के string buffer में लिखना बेहतर होगा
    साथ ही model reader में data alignment enforce करने के लिए unsafe इस्तेमाल होता दिख रहा है; जानना चाहूंगा कि बहुत जोर लगाए बिना unsafe के बिना यह संभव है या नहीं

    • string buffer के बजाय user callback call करना बेहतर होगा
      तब logs को GUI में दिखाने जैसी handling की जा सकती है
  • model loading और कई LLM tasks के लिए Rust tools काफी बना रखे हैं
    available memory के आधार पर सबसे बड़ा quantized model auto-select करना, gguf से tokenizer निकालना, prompt डालना वगैरह features हैं। इससे कुछ Python dependencies हटाई जा सकती हैं
    फिलहाल यह llama.cpp support के लिए है, लेकिन यह भी काफी interesting है। जानना चाहूंगा कि grammar constraints support करने की योजना है या नहीं
    https://github.com/ShelbyJenkins/llm_client

  • title में no dependency expression कम स्पष्ट है
    पहली बार देखकर लगा था कि शायद यह no_std हो सकता है, लेकिन असल में यह no_std नहीं है और कुछ dependencies भी दिखती हैं। शायद मतलब यह हो कि सब Rust dependencies हैं

    • title रखना मुश्किल है। कहना यह था कि PyTorch, CUDA, ONNX जैसी deep learning dependencies नहीं हैं और सारी logic self-contained है
      साफ-साफ कहें तो default Rust dependencies 5 हैं, जिनमें chrono और clap chat feature के लिए feature flag में रखने लायक हैं। बाकी 3 hardware performance थोड़ा और निकालने के लिए utility crates हैं: parallelization आसान करने वाला rayon, SIMD में मदद करने वाला wide, और model file memory mapping के लिए memmap2
    • README देखने पर requirements.txt में PyTorch और कई Python dependencies जरूरी लगती हैं, और page पर “dependency” शब्द जहां दिखता है वह भी वही है, इसलिए title का wording काफी confusing है
      project खुद तो बस “Minimal LLM inference in Rust” subtitle इस्तेमाल कर रहा लगता है। Git history देखने पर यह पोस्ट करने वाला account contributor है, लेकिन main author नहीं लगता; zero dependencies का ठीक-ठीक मतलब क्या है यह समझा दें तो मदद होगी
    • असल में अगर title “hardware dependency नहीं” या “GPU dependency नहीं” जैसा होता तो शायद बात बनती
      अफसोस, HN अक्सर title से शब्द बिना खास वजह या transparency के हटा देता है
    • लगता है Rust का cargo भी अब लगभग npm जैसा हो गया है
      16 dependencies हैं, फिर इसे dependency-free कैसे कह सकते हैं, समझ नहीं आता
  • पहले कुछ ऐसा ही बनाया था, लेकिन CPU पर चलने वाले C/C++ code की तुलना में performance निराशाजनक थी
    इसका मतलब यह भी है कि मुझे Rust को fast बनाने का तरीका ठीक से नहीं आता था। अलग-अलग Rust implementations के benchmarks हों तो अच्छा होगा
    LLM inference implementation गंभीर programmers के लिए नया “Hello, world!” बन सकता है
    https://github.com/gip/yllama.rs

    • मैंने भी पहले इसी तरह के “Hello, world” experience के तौर पर कुछ बनाया था
      https://github.com/crabml/crabml
      कुछ SIMD instructions सीधे इस्तेमाल किए थे, और performance llama.cpp से match की जा सकती थी। मुख्य बात लगती है quantized matrix multiplication में SIMD का इस्तेमाल और threads के बीच work split करते समय condition variables की जगह busy-wait loop का उपयोग
      हालांकि GPU पर Vulkan के साथ quantized model inference पर काम जारी रखने का समय नहीं मिला, इसलिए कुछ समय से update नहीं कर पाया
  • यह दिलचस्प है कि पहले से ही Dioxus इस्तेमाल हो रहा है, और जिज्ञासा है कि क्या रोडमैप में WASM भी आ सकता है
    अगर ब्राउज़र में RWKV जैसे हल्के LLM चलाए जा सकें, तो SaaS API कॉल किए बिना भी ब्राउज़र नई तरह की क्षमताओं के दरवाज़े खोल सकता है

    • मैंने इस तरफ थोड़ा हाथ आज़माया है
      https://github.com/maedoc/rwkv.js
      Emscripten से compile किया हुआ Rwkv.cpp इस्तेमाल किया था, लेकिन tokenizer वाला हिस्सा अभी ठीक से हल नहीं कर पाया। फिर भी 1.6B RWKV6 offline browser-only उपयोग के लिए काफी काम का लग सकता है
      सामान्य chat के लिए इसकी क्षमता कम है, लेकिन RAG जैसे use cases के लिए यह काफी पर्याप्त हो सकता है
    • library खुद बहुत कम बदलावों के साथ WASM compile हो सकती है
      जरूरी dependencies rayon और wide WASM को सीधे support करती हैं, और transformer.rs के Mmap type को &[u8] में बदल दें तो memmap2 भी हटाया जा सकता है
      हालांकि RWKV की संरचना पूरी तरह अलग है, इसलिए सब कुछ नए सिरे से implement करना होगा, और इसके roadmap में आने की संभावना बहुत कम दिखती है
  • जिज्ञासा है कि क्या ये implementations पूरी तरह CPU-only हैं
    सवाल यह है कि अगर अच्छा GPU है, तो क्या कोई दूसरा विकल्प ढूंढना ही सही होगा

    • हां। यह project CPU पर चलता है, इसलिए GPU को computation में इस्तेमाल नहीं करता
      अगर GPU support वाला Rust framework आज़माना चाहते हैं, तो Candle https://github.com/huggingface/candle/tree/main देखना ठीक रहेगा
    • सब कुछ CPU पर implemented है, और कम से कम अभी GPU acceleration बिल्कुल नहीं है
      अगर मकसद सच में run करना है, तो केवल CPU इस्तेमाल करने पर भी alternative, यानी llama.cpp, इस्तेमाल करना बेहतर होगा। यह project ecosystem की जटिल layers हटाने पर अंदर चीजें कैसे काम करती हैं, यह दिखाने वाली educational सामग्री के ज्यादा करीब है
      LLM असर के लिहाज़ से जादू जैसा लगता है, लेकिन code के नज़रिए से काफी सरल है
    • GPU के हिसाब से 10~20 गुना फर्क पड़ सकता है
      Rust side में मेरे llm_client जैसे llama.cpp wrappers हैं, और Candle-based projects के तौर पर mistral.rs और Kalosm हैं
      मेरा project भी mistral.rs implementation देने की कोशिश कर रहा है, लेकिन अभी llama.cpp से पूरी तरह migrate नहीं कर पाया है। पूरी Rust implementation के बड़े फायदे हैं, जैसे install time तेज़ होना। अभी मेरे crate को clone और build करना पड़ता है, इसलिए macOS, Windows, Linux पर automation तो है, लेकिन build time में लगभग 1 मिनट बढ़ जाता है
    • CPU भी सही है, लेकिन ज्यादा अहम चीज memory bandwidth है
      उदाहरण के लिए RTX 3090 के पास लगभग 1TB/s memory bandwidth है। इसे match करने के लिए धरती पर सबसे तेज़ proof-of-concept स्तर की DDR5 कम से कम 12 channels में लगानी पड़ेगी
      अगर discrete GPU है, तो उसका फायदा उठाने वाली implementation इस्तेमाल करना बिल्कुल अलग दुनिया है। Apple Silicon के LLM inference numbers प्रभावशाली होने की वजह भी CPU-GPU unified high-bandwidth memory architecture है, और याद पड़ता है कि यह लगभग 400GB/s था
    • परिस्थिति पर निर्भर करता है। अच्छे models बड़े होते हैं और उनकी memory requirements भी बड़ी होती हैं
      4090 में भी LLM के हिसाब से इतनी ज्यादा memory नहीं है। GPU तेज़ तो होगा, लेकिन बड़े model को load न कर पाने की संभावना है
  • जिज्ञासा है कि llama.cpp की तुलना में इसकी क्या value है

    • दूसरे Rust projects के साथ integrate करना ज्यादा आसान हो सकता है
    • features कम हैं, इसलिए codebase ज्यादा साफ है
  • बढ़िया है और पहली Rust library बनाने के लिए बधाई भी, लेकिन serious local usage के लिए Metal/CUDA support जरूरी है

    • CUDA इस्तेमाल करना इस project के मकसद के खिलाफ होगा, इसलिए शुरुआत से ही fit नहीं बैठता
      हालांकि मैं मुख्य author नहीं हूं, लेकिन contributor के तौर पर wgpu से कुछ हद तक GPU acceleration पाने का experiment कर रहा हूं। मुख्य author complexity को control में रखना चाहते हैं, इसलिए असल में यह कहां तक जाएगा पता नहीं
  • Rust community का लगभग हर चीज़ को फिर से लिखने का जोश दिलचस्प भी लगता है और सराहनीय भी