कुछ हफ़्ते पहले मैंने गूगल के जेम्मा डेवलपर डे में भाग लिया था। यह दिन गूगल द्वारा जेम्मा नामक अपने नवीनतम एलएलएम मॉडल की क्षमताओं, पोर्टेबिलिटी और खुलेपन को प्रस्तुत करने के लिए समर्पित था।
ये मॉडल जनरेटिव एआई के लिए एक रोमांचक नया चरण प्रस्तुत करते हैं। मॉडल इतने छोटे हैं कि उन्हें स्थानीय डिवाइस पर इस्तेमाल किया जा सकता है और फिर भी वे एक आकर्षक और मददगार अनुभव प्रदान कर सकते हैं।
मोबाइल एआई को देखे हुए मुझे काफी समय हो गया है और मैं दिन भर प्रेरित महसूस करता रहा हूं। मैंने यह देखने का फैसला किया कि जब मैं इन मॉडलों को एंड्रॉइड ऐप में आज़माता हूं तो क्या होता है।
मैं जेम्मा को एक आसान लेकिन अनोखी चुनौती देना चाहता था। साइमन सेज़ नामक गेम खेलना।
नियम सरल हैं। एक खिलाड़ी साइमन बन जाता है। उनकी भूमिका दूसरे खिलाड़ियों को कार्य करने के लिए देना है। साइमन के रूप में खेलने वाले खिलाड़ी को कार्य देने से पहले "साइमन कहते हैं" कहना होता है।
मैंने तीन स्क्रीन वाला एक ऐप बनाया। एक एंट्री स्क्रीन, एक निर्देश स्क्रीन और एक चैट स्क्रीन, जहाँ जेम्मा संवाद कर सकती है और कार्य दे सकती है।
चैट स्क्रीन के निर्माण में तेजी लाने के लिए मुझे मेयता तलिति का यह ब्लॉग पोस्ट अत्यंत उपयोगी लगा।
स्क्रीन बनाने के बाद मेरा अगला काम जेम्मा को एकीकृत करना था। इसके लिए मैंने मीडियापाइप नामक टूल के सेट का इस्तेमाल किया, जिसके बारे में मैंने सीखा था।
मीडियापाइप उपकरणों का एक संग्रह है जिसका लक्ष्य Android, iOS और वेब पर ऐप्स में AI मॉडल को एकीकृत करना आसान बनाना है। मीडियापाइप के साथ आपके पास अपनी ज़रूरतों के हिसाब से बहुत सारे विकल्प हैं।
यदि आप जल्दी से शुरुआत करना चाहते हैं तो मीडियापाइप आपको एआई मॉडल को कॉल करने के लिए टास्क नामक एक एपीआई प्रदान करता है। ये एपीआई विज़न, टेक्स्ट और ऑडियो जैसे विभिन्न क्षेत्रों में विभाजित हैं।
मीडियापाइप आपके ऐप्स में एम्बेड करने के लिए प्रीट्रेन्ड मॉडल का संग्रह भी प्रदान करता है। फिर से, जल्दी से शुरू करने के लिए उपयोगी है।
अगर आपको कुछ ज़्यादा कस्टम चाहिए और आप स्क्रैच से मॉडल नहीं बनाना चाहते हैं, तो MediaPipe मॉडल मेकर नामक एक टूल प्रदान करता है। मॉडल मेकर मौजूदा मशीन लर्निंग मॉडल को फिर से प्रशिक्षित करने और उसे नया डेटा प्रदान करने के लिए ट्रांसफर लर्निंग नामक प्रक्रिया का उपयोग करता है। इस दृष्टिकोण का लाभ यह है कि यह समय बचाता है और नया मॉडल बनाने के लिए कम प्रशिक्षण डेटा की आवश्यकता होती है।
मॉडल मेकर इस प्रक्रिया के ज़रिए बनाए गए मॉडल का आकार भी कम कर सकता है। ध्यान दें कि इस प्रक्रिया के कारण मॉडल अपने मौजूदा ज्ञान में से कुछ को "भूल" जाता है।
मीडियापाइप का अंतिम टूल मीडियापाइप स्टूडियो है, जो आपके कस्टम मॉडल का मूल्यांकन और उसमें बदलाव करने के लिए एक वेब एप्लीकेशन है। यदि आप अपने मॉडल का बेंचमार्क करना चाहते हैं और यह समझना चाहते हैं कि तैनाती से पहले वे कितनी अच्छी तरह काम करते हैं, तो यह उपयोगी है।
अपनी ज़रूरतों के लिए हम LLM इंटरफ़ेंस API का लाभ उठाने जा रहे हैं, जो मीडियापाइप के लिए एक नया API है। यह हमें जेम्मा के साथ संवाद करने और प्रतिक्रिया प्राप्त करने की अनुमति देता है।
मीडियापाइप का उपयोग करने के लिए आपको सबसे पहले इसे ऐप में ग्रेडेल निर्भरता के रूप में जोड़ना होगा:
implementation ("com.google.mediapipe:tasks-genai:0.10.11")
इसके बाद, आप LlmInference
का एक इंस्टेंस बनाते हैं। यह वह ऑब्जेक्ट है जिसका उपयोग आप Gemma के साथ संचार करने के लिए करते हैं:
val llmInference = LlmInference.createFromOptions( context, LlmInference.LlmInferenceOptions.builder() .setModelPath("/data/local/tmp/llm/gemma-2b-it-cpu-int8.bin") .build() )
.setModelPath
का उपयोग करके सेट किए गए पथ को नोट करना महत्वपूर्ण है। यह वह स्थान है जहाँ डिवाइस पर जेम्मा मॉडल रहता है। यह भी महत्वपूर्ण है कि इस्तेमाल किया गया जेम्मा मॉडल gemma-2b
संस्करण है। 7b
संस्करण अभी तक मीडियापाइप द्वारा समर्थित नहीं हैं, इस बारे में बाद में और अधिक जानकारी दी जाएगी। अभी के लिए आइए मॉडल डाउनलोड करें।
आप जेम्मा को कागल से डाउनलोड कर सकते हैं। यह डेटा वैज्ञानिकों और मशीन लर्निंग को समर्पित एक वेबसाइट है। मॉडल डाउनलोड करने से पहले आपको एक खाता बनाना होगा और उपयोग की शर्तों और नियमों को स्वीकार करना होगा। आप जेम्मा पेज यहाँ पा सकते हैं।
यदि आप इस पोस्ट को पढ़ रहे हैं तो याद रखें कि TensorFlow Lite
टैब के अंतर्गत मॉडल के केवल gemma-2b-it-cpu
संस्करण ही डाउनलोड करें। यदि आप gemma-2b-it-gpu
संस्करण आज़माते हैं तो आप अपने आप ही इसे आज़मा सकते हैं।
एक बार मॉडल डाउनलोड हो जाने के बाद, .setModelPath
में सेट किए गए पथ पर मॉडल को आयात करने के लिए Android Studio में डिवाइस एक्सप्लोरर का उपयोग करें। यदि आपने पथ या मॉडल का नाम बदल दिया है, तो पथ नाम को अपडेट करना सुनिश्चित करें।
एक बार मॉडल आयात हो जाने के बाद आप .generateResponse
विधि का उपयोग करके जेम्मा में प्रॉम्प्ट पास करना शुरू कर सकते हैं। साइमन सेज़ खेलने के लिए मैं जेम्मा को जो प्रॉम्प्ट देता हूँ उसका एक उदाहरण यहाँ दिया गया है:
private const val SimonSaysPrompt = """ You are a Simon in a game of Simon Says. Your objective is to ask the player to perform tasks. For every task you give, you must prefix it with the words "Simon says". You must not ask the player to do anything that is dangerous, unethical or unlawful. Do not try to communicate with the player. Only ask the player to perform tasks. """ val gemmaResponse = llmInference.generateResponse(SimonSaysPrompt)
यदि आपने पहले LLM का उपयोग किया है और प्रॉम्प्ट इंजीनियरिंग की बुनियादी समझ है, तो यह आपको परिचित लग सकता है। सावधानी बरतने के लिए मैंने प्रॉम्प्ट में एहतियाती निर्देश शामिल किए हैं। हम नहीं चाहते कि साइमन उपयोगकर्ता से कुछ भी संदिग्ध करने के लिए कहे!
यदि आप इसे किसी डिवाइस पर चलाने का प्रयास करते हैं तो कुछ चीजें हो सकती हैं:
ऐप को प्रतिक्रिया देने में थोड़ा समय लग सकता है और अंततः वह प्रतिक्रिया प्रदान कर सकता है।
ऐप क्रैश हो सकता है। Logcat में देखने पर आपको MediaPipe के मॉडल को खोजने में असमर्थ होने के बारे में संदेश दिखाई देंगे। क्या आपने सही मॉडल पथ सेट किया है?
ऐप क्रैश हो सकता है। अगर आप Logcat में देखें तो आपको बहुत सारे नेटिव कोड लॉगिंग और मेमोरी के रीसाइकिल होने के बारे में जानकारी मिलेगी।
मेरा अनुभव दूसरी और तीसरी श्रेणी में आता है। यदि आपने सब कुछ सही तरीके से सेटअप किया है और उच्च स्पेक भौतिक डिवाइस का उपयोग कर रहे हैं तो आपके अपने अनुभव भिन्न हो सकते हैं।
यदि आपके पास इनमें से कोई भी चीज़ नहीं है, तो एक और विकल्प है, एम्यूलेटर के माध्यम से उपलब्ध RAM की मात्रा बढ़ाना।
उपलब्ध RAM की मात्रा बढ़ाने से आम तौर पर मेमोरी की अधिक खपत वाले वातावरण में मदद मिलती है, तो मेमोरी की अधिक खपत वाले LLM में इससे क्या फर्क पड़ेगा? ऐसा करने के लिए मैंने अपने Android एमुलेटर द्वारा उपयोग की जाने वाली RAM की मात्रा को अनुकूलित किया।
यदि आपके पास कोई मौजूदा एमुलेटर है तो आप देख सकते हैं कि RAM फ़ील्ड अक्षम है। आप डिवाइस मैनेजर में इसके दाईं ओर तीन बिंदुओं पर क्लिक करके अभी भी इसमें उपलब्ध RAM की मात्रा को अपडेट कर सकते हैं।
डिस्क पर दिखाएँ पर क्लिक करें और फिर टेक्स्ट एडिटर में config.ini और hardware-qemu.ini फ़ाइलें खोलें। प्रत्येक फ़ाइल में hw.ramSize
के मान बदलें। मुझे यह कैसे करना है, इसका उत्तर देने के लिए इस स्टैक ओवरफ़्लो प्रश्न का धन्यवाद।
वैकल्पिक रूप से आप एंड्रॉइड स्टूडियो में डिवाइस मैनेजर पर जाकर, क्रिएट वर्चुअल डिवाइस और फिर न्यू हार्डवेयर प्रोफाइल पर क्लिक करके एक कस्टम एमुलेटर बना सकते हैं। कस्टमाइज़ करने के विकल्पों के हिस्से के रूप में आप RAM की मात्रा का चयन कर सकते हैं।
मुझे 8GB RAM अपेक्षाकृत अच्छी लगी। मैंने 22GB RAM के साथ भी अपनी किस्मत आजमाई। यह गति के मामले में थोड़ा बेहतर प्रदर्शन करता है, हालाँकि उतना नहीं जितना मैंने उम्मीद की थी।
मुझे संदेह है कि जब जेम्मा को मेमोरी में लोड किया जाता है तो कहीं कोई बाधा होती है, क्योंकि एमुलेटर का बाकी हिस्सा सुचारू रूप से चलता है। शायद कहीं कोई सुधार किया जा सकता है।
मीडियापाइप के साथ संगत जेम्मा मॉडल gemma-2b
संस्करण हैं। 2b
का मतलब है 2 बिलियन पैरामीटर। मॉडल को काम करने के लिए एक साथ काम करने वाले पैरामीटर की मात्रा।
ये वे मान हैं जो प्रशिक्षण के दौरान मॉडल में निर्धारित किए जाते हैं ताकि जब आप जेम्मा से कोई प्रश्न पूछें तो एक दूसरे के बीच संबंध और निष्कर्ष प्रदान किए जा सकें।
इसके अलावा एक gemma-7b
संग्रह भी है, जो 7 बिलियन पैरामीटर का उपयोग करता है। हालाँकि, ये मीडियापाइप द्वारा समर्थित नहीं हैं। शायद एक दिन!
यदि आप एलएलएम के मापदंडों के बारे में अधिक समझने में रुचि रखते हैं तो मैं इस पृष्ठ की अनुशंसा करता हूं।
2 बिलियन पैरामीटर मॉडल को मोबाइल डिवाइस पर लोड करके चलाना एक प्रभावशाली उपलब्धि है। लेकिन यह कितना कारगर है? आइए जानें।
gemma-2b-it-cpu-int4
एक 4 बिट एलएलएम है। इसका मतलब है कि मॉडल द्वारा उपयोग किए जाने वाले प्रत्येक पैरामीटर का मेमोरी आकार 4 बिट है। यहाँ लाभ यह है कि मॉडल का कुल आकार छोटा है, हालाँकि प्रत्येक पैरामीटर के लिए कम मेमोरी आकार का मतलब है कि मॉडल की सटीकता और गुणवत्ता भी प्रभावित होती है।
तो gemma-2b-it-cpu-int4
कैसा प्रदर्शन करता है? ईमानदारी से कहूं तो यह इतना बढ़िया नहीं है। ऊपर दिए गए प्रॉम्प्ट का उपयोग करके साइमन सेज़ को चलाने और उससे सामान्य प्रश्न पूछने के मेरे प्रयासों के कुछ स्क्रीनशॉट यहां दिए गए हैं।
जवाब अप्रत्याशित थे और मॉडल से साइमन सेज़ के खेल जैसा कुछ भी करवाना निराशाजनक था। यह किसी दूसरे विषय पर चला जाता और गलत जानकारी का भ्रम पैदा करता।
मतिभ्रम एक ऐसी घटना है जिसमें एलएलएम झूठ और असत्य बातें बोलते हैं जैसे कि वे तथ्य हों। ऊपर दिए गए उदाहरण को लें, यह सच नहीं है कि आप 60 मिनट में 60 मील प्रति घंटे की रफ़्तार से मंगल ग्रह तक जा सकते हैं। वैसे भी अभी तक नहीं। 😃
संदर्भ जागरूकता की भी कमी थी। इसका मतलब है कि यह किसी बातचीत में पहले बताई गई किसी बात को याद नहीं रख सका। यह संभवतः मॉडल के सीमित आकार के कारण है।
कुछ समय बाद मैंने इस मॉडल को छोड़ दिया और बड़े 8 बिट आकार वाले मॉडल को आजमाने का निर्णय लिया।
gemma-2b-it-cpu-int8
एक 8 बिट एलएलएम है। यह अपने 4 बिट भाई से आकार में बड़ा है। इसका मतलब है कि यह अधिक सटीक हो सकता है और बेहतर गुणवत्ता वाले उत्तर प्रदान कर सकता है। तो यहाँ परिणाम क्या था?
यह मॉडल साइमन सेज़ के विचार को समझने में सक्षम था, और तुरंत साइमन की भूमिका ग्रहण कर ली। दुर्भाग्य से यह भी संदर्भ जागरूकता की कमी से ग्रस्त था।
इसका मुकाबला करने के लिए मुझे हर बार साइमन सेज़ के नियमों के साथ मॉडल को पुनः संकेत देना पड़ता था और इसे किसी अन्य संकेत के साथ संयोजित करके उसे कार्य प्रदान करने के लिए कहना पड़ता था।
कार्य संकेत को सूची से यादृच्छिक रूप से चुना जाता है और जेम्मा को भेजा जाता है, जिससे पूछे जाने वाले कार्यों में कुछ विविधता आ जाती है।
नीचे क्या हो रहा है इसका एक उदाहरण दिया गया है:
private const val SimonSaysPrompt = """ You are a Simon in a game of Simon Says. Your objective is to ask the player to perform tasks. For every task you give, you must prefix it with the words "Simon says". You must not ask the player to do anything that is dangerous, unethical or unlawful. Do not try to communicate with the player. Only ask the player to perform tasks. """ private const val MovePrompt = SimonSaysPrompt + """ Give the player a task related to moving to a different position. """ private const val SingASongPrompt = SimonSaysPrompt + """ Ask the player to sing a song of their choice. """ private const val TakePhotoPrompt = SimonSaysPrompt + """ Give the player a task to take a photo of an object. """ private val prompts = listOf( MovePrompt, SingASongPrompt, TakePhotoPrompt ) val prompt = prompts.random() val response = llmInference.generateResponse(prompt)
यह कभी-कभी एक कर्व बॉल प्रतिक्रिया देता है जो चरित्र से बाहर लगती है। मैं इसे मॉडल के आकार के कारण मान रहा हूँ। यह भी ध्यान देने योग्य है कि यह केवल v1 है।
एक बार जब संकेत तय हो गए तो मैंने पाया कि केवल संकेतों पर भरोसा करना और उपयोगकर्ता इनपुट को ध्यान में न रखना उपयोगी था। क्योंकि मॉडल में संदर्भ जागरूकता की कमी है, इसलिए उपयोगकर्ता इनपुट के कारण यह साइमन सेज़ को बजाना बंद कर देता है और इसके बजाय इनपुट पर प्रतिक्रिया करता है।
इस प्रकार की चालाकी को जोड़ने से कोई संतोषजनक परिणाम नहीं निकला, लेकिन जेम्मा को साइमन सेज़ की भूमिका में बनाए रखना आवश्यक था।
तो क्या जेम्मा एंड्रॉयड डिवाइस पर साइमन सेज़ खेल सकती है? मैं कहूंगा कि "कुछ हद तक, मदद से"।
मैं जेम्मा 2बी के 4 बिट संस्करण को अधिक सहजता से प्रतिक्रिया करते देखना चाहूंगा। जेम्मा 2बी संदर्भ को जागरूक बनाना ताकि हर अनुरोध के लिए इसे फिर से संकेत देने की आवश्यकता न पड़े और उपयोगकर्ता इनपुट के साथ सावधान रहना भी मददगार होगा।
सरल अनुरोधों के लिए केवल एक ही संकेत की आवश्यकता होती है। मैं देख सकता हूँ कि जेम्मा 2 बी इन कार्यों को आराम से संभालने में सक्षम है।
यह भी ध्यान में रखना चाहिए कि ये मॉडल v1 हैं। तथ्य यह है कि वे मोबाइल ऑपरेटिंग सिस्टम पर चलते हैं और काम करते हैं, यह एक प्रभावशाली उपलब्धि है!
मोबाइल डिवाइस पर LLM के भविष्य के बारे में क्या? मुझे दो बाधाएं नज़र आती हैं। हार्डवेयर सीमाएँ और व्यावहारिक उपयोग के मामले।
मुझे लगता है कि हम ऐसे मुकाम पर पहुंच गए हैं जहां केवल हाई एंड डिवाइस ही इन मॉडलों को प्रभावी ढंग से चला सकते हैं। मेरे दिमाग में आने वाले डिवाइस में पिक्सल 7 या पिक्सल 8 सीरीज के फोन शामिल हैं जिनमें टेंसर जी चिप है और एप्पल का आईफोन जिसमें न्यूरल इंजन चिप है।
हमें इस तरह की विशिष्टताओं को मध्य-श्रेणी के फोनों में भी देखने की जरूरत है।
डिवाइस LLMs द्वारा रिट्रीवल ऑगमेंटेड जेनरेशन का उपयोग करने से दिलचस्प विचार सामने आ सकते हैं। उत्तर प्रदान करते समय अतिरिक्त संदर्भ प्राप्त करने के लिए LLMs के लिए बाहरी डेटा स्रोतों के साथ संचार करने की एक तकनीक। यह प्रदर्शन को बढ़ावा देने का एक प्रभावी तरीका हो सकता है।
दूसरी बाधा व्यावहारिक उपयोग के मामले ढूँढना है। मुझे लगता है कि ये सीमित हैं जबकि डिवाइस इंटरनेट पर अधिक शक्तिशाली एलएलएम के साथ संचार कर सकते हैं। उदाहरण के लिए OpenAI से GPT-4 एक ट्रिलियन से अधिक मापदंडों का समर्थन करने की अफवाह है!
हालांकि, ऐसा समय भी आ सकता है जब इन मॉडलों को मोबाइल डिवाइस पर तैनात करने की लागत उन्हें क्लाउड में होस्ट करने की तुलना में सस्ती हो जाए। चूंकि इन दिनों लागत में कटौती का चलन है, इसलिए मैं इसे एक व्यवहार्य उपयोग मामला मान सकता हूँ।
इसके अलावा, आपके पास अपना खुद का निजी एलएलएम होने से गोपनीयता के लाभ भी हैं, जिससे कोई भी जानकारी आपके डिवाइस की सीमा से बाहर नहीं जाएगी। एक उपयोगी लाभ जो गोपनीयता के प्रति जागरूक ऐप उपयोगकर्ताओं को आकर्षित करेगा।
मेरा अनुमान है कि एलएलएम को नियमित रूप से डिवाइस पर तैनात करने में हमें अभी भी कुछ वर्ष लगेंगे।
यदि आप जेम्मा को मोबाइल डिवाइस पर स्वयं आजमाने के इच्छुक हैं तो यहां कुछ संसाधन दिए गए हैं जो आपकी सहायता करेंगे:
जेम्मा : आधिकारिक जेम्मा वेबसाइट में बेंचमार्क, त्वरित आरंभ मार्गदर्शिका और जिम्मेदार जनरेटिव एआई विकास के लिए गूगल के दृष्टिकोण पर जानकारी सहित बहुत सारी जानकारी शामिल है।
मीडियापाइप : मीडियापाइप का अपना Google डेवलपर अनुभाग है जहाँ आप इसके बारे में और इसे उपयोग करने के तरीके के बारे में अधिक जान सकते हैं। पढ़ने के लिए अत्यधिक अनुशंसित।
Google डेवलपर ग्रुप डिस्कॉर्ड : Google डेवलपर ग्रुप डिस्कॉर्ड में जेनरेटिव AI को समर्पित चैनल हैं। समान विचारधारा वाले लोगों से चैट करने के लिए #gemma, #gemini और #ml चैनल देखें।
सिमंस सेज़ ऐप: इस ब्लॉग पोस्ट के लिए सैंपल कोड को क्लोन करें और चलाएँ ताकि इसे क्रियान्वित होते हुए देखा जा सके। इसमें मीडियापाइप से इमेज क्लासिफिकेशन टास्क का उपयोग भी शामिल है। सेटअप निर्देश README में हैं।
23/03/24 को अपडेट किया गया, जिसमें IO थ्रेड से LLM अनुमान को कॉल करने का उल्लेख किया गया
इस पोस्ट को लिखने के बाद मुझे लगा कि जेम्मा को कॉल करना एक फ़ाइल पर रीड/राइट ऑपरेशन है। .generateResponse()
विधि को IO थ्रेड पर ले जाने से जेम्मा को मेमोरी में लोड करने पर होने वाली अत्यधिक जंक से बचा जा सकेगा:
suspend fun sendMessage(): String { return withContext(Dispatchers.IO) { val prompt = prompts.random() llmInference.generateResponse(prompt) } }
यहां भी दिखाई देता है.