- 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 की तालिका
- 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 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 टिप्पणियां
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 कितने मिलते हैंformatting की वजह से सिर्फ कुछ हिस्सा रखा, लेकिन लंबे random शब्दों की string लगातार चलती रही
लेख बहुत अच्छी तरह लिखा गया है, और class में transformers असल में कैसे काम करते हैं यह समझाते समय source code के कुछ हिस्से इस्तेमाल किए जा सकते हैं
attention head वाली diagrams की तुलना में code ज्यादा ठोस और detailed है। हालांकि library अगर सीधे
stdoutपर output करे, तो text editor में style checking देने जैसी application output खराब हो सकती है, इसलिएlm.rsobject से जुड़े logging instance के string buffer में लिखना बेहतर होगासाथ ही model reader में data alignment enforce करने के लिए
unsafeइस्तेमाल होता दिख रहा है; जानना चाहूंगा कि बहुत जोर लगाए बिनाunsafeके बिना यह संभव है या नहींतब logs को GUI में दिखाने जैसी handling की जा सकती है
model loading और कई LLM tasks के लिए Rust tools काफी बना रखे हैं
available memory के आधार पर सबसे बड़ा quantized model auto-select करना,
ggufसे tokenizer निकालना, prompt डालना वगैरह features हैं। इससे कुछ Python dependencies हटाई जा सकती हैंफिलहाल यह
llama.cppsupport के लिए है, लेकिन यह भी काफी interesting है। जानना चाहूंगा कि grammar constraints support करने की योजना है या नहींhttps://github.com/ShelbyJenkins/llm_client
title में no dependency expression कम स्पष्ट है
पहली बार देखकर लगा था कि शायद यह
no_stdहो सकता है, लेकिन असल में यहno_stdनहीं है और कुछ dependencies भी दिखती हैं। शायद मतलब यह हो कि सब Rust dependencies हैंसाफ-साफ कहें तो default Rust dependencies 5 हैं, जिनमें
chronoऔरclapchat feature के लिए feature flag में रखने लायक हैं। बाकी 3 hardware performance थोड़ा और निकालने के लिए utility crates हैं: parallelization आसान करने वालाrayon, SIMD में मदद करने वालाwide, और model file memory mapping के लिएmemmap2requirements.txtमें PyTorch और कई Python dependencies जरूरी लगती हैं, और page पर “dependency” शब्द जहां दिखता है वह भी वही है, इसलिए title का wording काफी confusing हैproject खुद तो बस “Minimal LLM inference in Rust” subtitle इस्तेमाल कर रहा लगता है। Git history देखने पर यह पोस्ट करने वाला account contributor है, लेकिन main author नहीं लगता; zero dependencies का ठीक-ठीक मतलब क्या है यह समझा दें तो मदद होगी
अफसोस, HN अक्सर title से शब्द बिना खास वजह या transparency के हटा देता है
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
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 के लिए यह काफी पर्याप्त हो सकता है
जरूरी dependencies
rayonऔरwideWASM को सीधे support करती हैं, औरtransformer.rsकेMmaptype को&[u8]में बदल दें तोmemmap2भी हटाया जा सकता हैहालांकि RWKV की संरचना पूरी तरह अलग है, इसलिए सब कुछ नए सिरे से implement करना होगा, और इसके roadmap में आने की संभावना बहुत कम दिखती है
जिज्ञासा है कि क्या ये implementations पूरी तरह CPU-only हैं
सवाल यह है कि अगर अच्छा GPU है, तो क्या कोई दूसरा विकल्प ढूंढना ही सही होगा
अगर GPU support वाला Rust framework आज़माना चाहते हैं, तो Candle https://github.com/huggingface/candle/tree/main देखना ठीक रहेगा
अगर मकसद सच में run करना है, तो केवल CPU इस्तेमाल करने पर भी alternative, यानी
llama.cpp, इस्तेमाल करना बेहतर होगा। यह project ecosystem की जटिल layers हटाने पर अंदर चीजें कैसे काम करती हैं, यह दिखाने वाली educational सामग्री के ज्यादा करीब हैLLM असर के लिहाज़ से जादू जैसा लगता है, लेकिन code के नज़रिए से काफी सरल है
Rust side में मेरे
llm_clientजैसेllama.cppwrappers हैं, और Candle-based projects के तौर परmistral.rsऔर Kalosm हैंमेरा project भी
mistral.rsimplementation देने की कोशिश कर रहा है, लेकिन अभीllama.cppसे पूरी तरह migrate नहीं कर पाया है। पूरी Rust implementation के बड़े फायदे हैं, जैसे install time तेज़ होना। अभी मेरे crate को clone और build करना पड़ता है, इसलिए macOS, Windows, Linux पर automation तो है, लेकिन build time में लगभग 1 मिनट बढ़ जाता हैउदाहरण के लिए 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 था
4090 में भी LLM के हिसाब से इतनी ज्यादा memory नहीं है। GPU तेज़ तो होगा, लेकिन बड़े model को load न कर पाने की संभावना है
जिज्ञासा है कि
llama.cppकी तुलना में इसकी क्या value हैबढ़िया है और पहली Rust library बनाने के लिए बधाई भी, लेकिन serious local usage के लिए Metal/CUDA support जरूरी है
हालांकि मैं मुख्य author नहीं हूं, लेकिन contributor के तौर पर
wgpuसे कुछ हद तक GPU acceleration पाने का experiment कर रहा हूं। मुख्य author complexity को control में रखना चाहते हैं, इसलिए असल में यह कहां तक जाएगा पता नहींRust community का लगभग हर चीज़ को फिर से लिखने का जोश दिलचस्प भी लगता है और सराहनीय भी