कुछ महीनों पहले, मैंने बात की थी कि यह अच्छी तरह से प्राप्त किया गया था और एक बातचीत करने में सक्षम होने के लिए ताजा था जहां मोबाइल ऐप्स भाषा मॉडल उपयोग में वृद्धि से लाभ प्राप्त कर सकते हैं। ऐप्स में डिवाइस SLMs पर चलाने के लिए बातचीत के बाद, मेरे पास "RAG द्वारा समर्थित SLM का उपयोग करने वाले ऐप का एक उदाहरण देखने के लिए अच्छा होगा" के लाइनों के साथ उपस्थित लोगों से कुछ प्रतिक्रियाएं थीं। ये उचित टिप्पणियाँ हैं. यहां मुश्किल बात यह है कि एक मॉडल को स्थापित करने और सीमित समय में डेवलपर्स को कुछ मायने रखने वाला दिखाने के लिए यह समय लेता है. सौभाग्य से, यह एक महान ब्लॉग पोस्ट के लिए काम करता है! तो, यहां यह है! यदि आप अपने एंड्रॉइड ऐप में एक आरएजी-आधारित भाषा मॉडल जोड़ने के चरणों की तलाश कर रहे हैं, तो यह आपके लिए पोस्ट है! RAG क्या है? यदि आप शब्द के साथ परिचित नहीं हैं, तो RAG का अर्थ है यह भाषा मॉडल के लिए एक तकनीक है जो प्रशिक्षण के बाद बाहरी जानकारी तक पहुंचती है जो उनके डेटासेट में उपलब्ध नहीं है. यह मॉडल को वर्तमान जानकारी के बारे में जानने की अनुमति देता है जिसे वे सुझावों के लिए अधिक सटीक जवाब प्रदान करने के लिए उपयोग कर सकते हैं. Retrieval Augmented Generation आइए एक त्वरित उदाहरण देखें. कल्पना करें कि आपके पास दो भाषा मॉडल हैं, एक मॉडल यूरोप की राजधानीों के बारे में बाहरी जानकारी प्राप्त करने के लिए आरएजी का उपयोग कर रहा है, जबकि दूसरा केवल अपने ज्ञान पर भरोसा कर रहा है. आप दोनों मॉडल को निम्नलिखित निर्देश देते हैं: You are an expert on the geography of Europe. Give me the name of 3 capital cities. Also give me an interesting fact for each of them. परिणाम कुछ इस तरह दिख सकता है: जैसा कि चार्ट दिखाता है, आप अपने ज्ञान पर निर्भर मॉडल के बजाय RAG का उपयोग करके भाषा मॉडल से एक उपयोगी उत्तर प्राप्त करने की अधिक संभावना रखते हैं। यह वास्तव में सब कुछ है जिसे आपको उच्च स्तर पर आरएजी के बारे में जानने की आवश्यकता है. अगला, चलो गहराई से जाते हैं और अपने ऐप के भीतर अपने स्वयं के आरएजी संचालित भाषा मॉडल को सक्षम करने के लिए कुछ कोड लिखते हैं! अपने एंड्रॉयड ऐप सेट करें मान लीजिए कि आप साइमन कहता है के खेल को खेलने के लिए एक भाषा मॉडल का उपयोग करके एक ऐप बनाना चाहते हैं. आप मॉडल साइमन होना चाहते हैं, और कार्यों के एक डेटा स्रोत तक पहुंचने के लिए आरएजी का उपयोग करना चाहते हैं ताकि यह तय किया जा सके कि उपयोगकर्ता को क्या पूछना है. आप ऐसा कैसे करेंगे? Android पर ऐसा करने का सबसे आसान तरीका है , आपके ऐप को एआई और मशीन लर्निंग तकनीकों का उपयोग करने में मदद करने के लिए उपकरणों का एक संग्रह। : मीडिया build.gradle dependencies { implementation("com.google.mediapipe:tasks-genai:0.10.27") implementation("com.google.ai.edge.localagents:localagents-rag:0.3.0") } इसके बाद, आपको अपने कंप्यूटर के माध्यम से अपने परीक्षण डिवाइस में एक भाषा मॉडल जोड़ने की आवश्यकता है. इस उदाहरण के लिए, हम Google के , एक हल्के भाषा मॉडल जिसमें 1 अरब पैरामीटर मूल्य की जानकारी होती है। जीएमएमए 3-1B साइड नोट: मॉडल को डाउनलोड करने से पहले, आपको Kaggle पर साइन अप करने और Google के एआई नियमों और शर्तों से सहमत होने की आवश्यकता हो सकती है। Side Note: Before downloading the model, you may have to sign upto Kaggle and agree to Google’s AI Terms and Conditions. एक बार मॉडल डाउनलोड किया गया है, यह अपने डिवाइस में मॉडल जोड़ने का समय है. आप इसे adb के माध्यम से कर सकते हैं: $ adb shell mkdir -p /data/local/tmp/slm/ # Create a folder to store the model $ adb push output_path /data/local/tmp/slm/gemma3-1B-it-int4.task # Copy the model over to the file वैकल्पिक रूप से, आप उपयोग कर सकते हैं Android स्टूडियो का उपयोग करके आप स्वयं फ़ोल्डर बना सकते हैं और मॉडल को अपने डिवाइस पर खींच सकते हैं। फ़ाइल Explorer मॉडल जोड़ने के साथ, आप Gemma को जानकारी के साथ खिलाने के लिए RAG पाइपलाइन का निर्माण करना जारी रख सकते हैं। Embeddings बनाने के लिए सूचना भाषा मॉडल RAG को करने के लिए भरोसा करते हैं, यह उसी जानकारी नहीं है जिसे आप उसमें स्थानांतरित करते हैं. Models require information to be in a specific format called . Embeddings ये गणितीय श्रृंखलाएं हैं जो पाठ की सेमेंटिक अर्थ का प्रतिनिधित्व करती हैं. जब मॉडल को एक परामर्श प्राप्त होता है, तो यह इसे सबसे प्रासंगिक जानकारी के लिए खोजने के लिए उपयोग करेगा जो उससे मेल खाती है और जवाब देने के लिए अपनी जानकारी के साथ इसका उपयोग करेगा. ये गणितीय श्रृंखलाएं एक उपकरण द्वारा बनाई जाती हैं जिसे एक . Embedder Embeddings अपने आप में एक पूरा विषय है; आप उनके बारे में पढ़ने के लिए प्रोत्साहित कर रहे हैं. इस पोस्ट के लिए, आपको केवल यह जानने की जरूरत है कि उन्हें कैसे बनाया जाए. आप उपकरण के माध्यम से ऐसा कर सकते हैं . गेंदबाजी में शामिल सबसे पहले, डाउनलोड करें Tokenizer और अपने कंप्यूटर पर मॉडल फ़ाइलों को एम्बेडर्ड करें. फिर उन्हें अपने डिवाइस पर दबाएं: sentencepiece.model Gecko_256_f32.tflite $ adb push sentencepiece.model /data/local/tmp/slm/sentencepiece.model # Push the tokenizer to the device $ adb push Gecko_256_f32.tflite /data/local/tmp/slm/Gecko_256_f32.tflite # Push the embedder model to the device अपने डिवाइस पर एम्बेडर स्थापित होने के साथ, एंड्रॉइड स्टूडियो में, अपने ऐप मॉड्यूल में एम्बेड्स बनाने के लिए एक नमूना फ़ाइल प्रदान करने का समय है फ़ोल्डर, एक फ़ाइल बनाएं जिसका नाम है फिर, फ़ाइल में, निम्नलिखित पाठ जोड़ें: assets simon_says_responses.txt <chunk_splitter> Go for a walk <chunk_splitter> Jump and down 10 times <chunk_splitter> Sing your favourite song! <chunk_splitter> Text your best friend a funny meme <chunk_splitter> Do 10 press ups! <chunk_splitter> फ़ाइल में कुछ अलग-अलग जवाब होते हैं जिन्हें आप सिमोन कहता है के खेल में दे सकते हैं, प्रत्येक एक के साथ विभाजित होता है यह एम्बेडर को एक सिग्नल देता है कि जब पाठ को एम्बेडर्स में विभाजित किया जाता है तो प्रत्येक प्रतिक्रिया को अलग करने का तरीका जानने के लिए। <chunk_splitter> इस प्रक्रिया को कहा जाता है और भाषा मॉडल के माध्यम से RAG कितनी अच्छी तरह से प्रदर्शन करता है पर एक बड़ा प्रभाव हो सकता है. विभिन्न आकार के टुकड़ों और प्रतिक्रियाओं के साथ प्रयोग आपके जरूरतों के लिए सही संयोजन खोजने के लिए प्रोत्साहित किया जाता है! chunking एक बात पर विचार करने के लिए ऐप स्टोरेज है. याद रखें, आप पहले से ही अपने डिवाइस पर एक भाषा मॉडल और एक एम्बेडर स्थापित कर चुके हैं. ये gigabytes की जगह लेते हैं, इसलिए एक टेक्स्ट फ़ाइल का उपयोग करके एक डिवाइस को और अधिक उड़ाने के लिए सुनिश्चित न करें जो बहुत बड़ा है! आप भंडारण के साथ समस्याओं को कम करने के लिए नेटवर्क के माध्यम से नमूना फ़ाइल को क्लाउड में संग्रहीत करने और डाउनलोड करने पर विचार करना चाहते हैं। टेक्स्ट फ़ाइल के साथ, यह एम्बेडर को प्रारंभ करने का समय है: private const val GeckoEmbedderPath = "/data/local/tmp/slm/gecko_256_f32.tflite" private const val TokenizerModelPath = "/data/local/tmp/slm/sentencepiece.model" private const val UseGpuForEmbeddings = true val embedder: Embedder<String> = GeckoEmbeddingModel( GeckoEmbedderPath, TokenizerModelPath, UseGpuForEmbeddings, ) एम्बेडर तीन पैरामीटर लेता है: एम्बेडर के मार्ग और डिवाइस पर टोकनेज़र, एक अंतिम पैरामीटर से यह निर्धारित करने के लिए कि एम्बेडर एम्बेड्स बनाने पर डिवाइस जीपीयू का उपयोग कर सकता है या नहीं। यदि यह सच है, तो एक GPU उपलब्ध है, तो इनपुट का निर्माण तेजी से होगा. इस मूल्य को सक्षम करने का निर्णय लेने से पहले डिवाइस की क्षमताओं की जाँच करें। इसके बाद, भाषा मॉडल का एक उदाहरण बनाएं: private const val GemmaModelPath = "/data/local/tmp/slm/gemma3-1B-it-int4.task" val llmInferenceOptions = LlmInferenceOptions.builder() .setModelPath(GemmaModelPath) .setPreferredBackend(LlmInference.Backend.CPU) // Change to GPU if you have a GPU powered device. .setMaxTokens(1200) .build() val llmInferenceSessionOptions = LlmInferenceSessionOptions.builder() .setTemperature(0.6f) .setTopK(5000) .setTopP(1f) .build() val languageModel = MediaPipeLlmBackend( context, // This is the application context languageModelOptions, languageModelSessionOptions) languageModel.initialize().get() ऊपर शामिल कई पैरामीटर हैं; अब इनके बारे में चिंता न करें. हम बाद में उन पर वापस आ जाएंगे. भाषा मॉडल के साथ बनाया गया है, आप इनपुट पर वापस ध्यान केंद्रित कर सकते हैं. मॉडल को प्रत्येक बार जब यह एक परामर्श प्राप्त करता है तो इनपुट को प्राप्त करने के लिए एक जगह की आवश्यकता होती है. MediaPipe एक SQLite प्रदान करता है , जो एम्बेडमेंट को संग्रहीत करने के लिए एक आम उपकरण है. चलो एक बनाते हैं: Vector Store private const val PromptTemplate: String = """ You are Simon in a game of Simon Says. Your task is to ask the player to perform a task from the following list: {0}. Your response must only contain the task that the player must do. Your response must be based on the players request: {1}. Do not ask the player to do the same thing twice. You must not ask the player to do anything that is dangerous, unethical or unlawful. """ val chainConfig = ChainConfig.create( languageModel, PromptBuilder(PromptTemplate), DefaultSemanticTextMemory( SqliteVectorStore(768), embedder ) ) यहां, सब कुछ एक साथ जुड़ना शुरू होता है क्योंकि भाषा मॉडल और इनबेडर दोनों ChainConfig में पारित होते हैं। यह प्रत्येक "वेक्टर" का आकार है जिसे डेटाबेस संग्रहीत कर सकता है। RAG प्रक्रिया को चलाने में मदद करने के लिए एक प्रिंट प्रदान करने के लिए उपयोग किया जाता है। 786 PromptBuilder अंत में, हम संसाधन फ़ोल्डर में पहले बनाए गए पाठ फ़ाइल को एम्बेडर में लोड करें. सबसे पहले, डिवाइस से फ़ाइल लोड करें और पाठ को श्रृंखलाओं की एक सूची में विभाजित करें: // This is an extension function to read the file from disk. val gameResponses: List<String> = context.getTextFromFile("simon_says_responses.txt") अगला, पहले बनाई गई chainConfig में उत्तरों को लोड करें। chainConfig.semanticMemory.getOrNull() ?.recordBatchedMemoryItems(ImmutableList.copyOf(gameResponses)) ?.get() आपके डिवाइस और टेक्स्ट फ़ाइल के आकार के आधार पर, यह पूरा करने में कुछ सेकंड से कुछ मिनट लग सकते हैं. एक अच्छा उंगली का नियम है कि जब यह होता है तो भाषा मॉडल का उपयोग नहीं किया जाता है. आप मुख्य थ्रेड को अवरुद्ध करने से बचने के लिए आईओ थ्रेड पर भी इस ऑपरेशन को चला सकते हैं. ऐसा करने के बाद, आपने अपने टेक्स्ट फ़ाइल को एक वेक्टर स्टोर में रखे गए एक सेट के एम्बेडमेंट में रूपांतरित किया है. आपने अपनी भाषा मॉडल को स्टोर से भी जोड़ा है ताकि वह अब जानकारी प्राप्त कर सके! अगला अनुभाग आपको दिखाएगा कि भाषा मॉडल को अपने निर्देशों को पारित करके इन एम्बेडमेंट का उपयोग कैसे करें। अपने RAG Powered मॉडल के लिए Prompts Passing अधिकांश जटिल सेटिंग्स पूरा होने के साथ, भाषा मॉडल में एक परामर्श स्थानांतरित करना आश्चर्यजनक रूप से आसान है। चेन config का उपयोग करें और इसे कॉल करें। RetrievalAndInferenceChain val retrievalAndInferenceChain = RetrievalAndInferenceChain(chainConfig) इसके बाद, एक अनुरोध बनाएं और इसे चेन में स्थानांतरित करें। val prompt = "Tell me something to do Simon involving jumping!" val retrievalRequest = RetrievalRequest.create( prompt, RetrievalConfig.create( 50, // topK 0.1f, // minSimilarityScore RetrievalConfig.TaskType.RETRIEVAL_QUERY ) ) val response = retrievalAndInferenceChain!!.invoke(retrievalRequest).get().text प्रोसेसिंग के दौरान, यह आपके वेक्टर स्टोर में एम्बेडमेंट्स को संदर्भित करेगा ताकि वह जो सोचता है वह सबसे सटीक जवाब दे। जैसा कि आप उम्मीद कर सकते हैं, जो आप मॉडल से पूछते हैं वह अलग-अलग प्रतिक्रियाओं का परिणाम देगा. चूंकि एम्बेडमेंट में सिमॉन कहते हैं कि प्रतिक्रियाओं की एक श्रृंखला होती है, इसलिए आपको अच्छी प्रतिक्रिया मिलने की संभावना है! उन मामलों के बारे में क्या है जहां आप एक अप्रत्याशित परिणाम प्राप्त करते हैं? इस बिंदु पर, आपको पिछली अनुभाग से अपने वस्तुओं के पैरामीटरों को वापस जाना और अच्छी तरह से समायोजित करना होगा। हम अगले अनुभाग में ऐसा करेंगे। अपने RAG Powered Language Model को ठीक से ट्यूनिंग करें यदि हमने Generative AI से वर्षों से सीखा है, तो यह एक सटीक विज्ञान नहीं है। आपने निस्संदेह ऐसी कहानियां देखी हैं जहां भाषा मॉडल "बुरा व्यवहार" करते हैं और वांछित परिणामों से कम उत्पादन करते हैं, जो कंपनियों को शर्म और प्रतिष्ठा क्षति का कारण बनते हैं। यह एक मॉडल से प्रतिक्रियाओं की उम्मीद सुनिश्चित करने के लिए पर्याप्त परीक्षण किए जाने का परिणाम नहीं है. परीक्षण न केवल शर्म से बचने में मदद करता है, यह आपके भाषा मॉडल आउटपुट के साथ प्रयोग करने में भी मदद कर सकता है ताकि यह और भी बेहतर काम करे! आइए एक नज़र डालें कि हम हमारे आरएजी पावर भाषा मॉडल को अच्छी तरह से टोन करने के लिए कौन से लेवर्स को समायोजित कर सकते हैं। : LLmInferenceOptions.Builder LlmInferenceOptions.builder() .setModelPath(GemmaModelPath) .setPreferredBackend(LlmInference.Backend.CPU) // Change to GPU if you have a GPU powered device. .setMaxTokens(1200) .build() पहला मापदंड जो बदला जा सकता है वह है यह भाषा मॉडल द्वारा संभालने योग्य "आउट" या "आउट" की मात्रा है. मूल्य जितना बड़ा है, उतना ही भाषा मॉडल एक बार में अधिक डेटा संभाल सकता है. बेहतर उत्तरों का परिणाम। setMaxTokens() हमारे उदाहरण में, इसका मतलब है कि मॉडल एक टेक्स्ट इनपुट को संभाल सकता है और एक आउटपुट उत्पन्न कर सकता है जिसमें 1200 टोकन होते हैं. यदि हम कम टेक्स्ट को संभालना चाहते हैं और एक छोटी प्रतिक्रिया भी उत्पन्न करना चाहते हैं, तो हम सेट कर सकते हैं एक छोटा सा मूल्य। MaxTokens इस मूल्य के साथ सावधान रहें, क्योंकि आप पा सकते हैं कि आपका मॉडल अप्रत्याशित रूप से अधिक टोकन संभालता है कि यह उम्मीद करता है। चलो आगे बढ़ते हैं : LlmInferenceSessionOptions.Builder() llmInferenceSessionOptions = LlmInferenceSessionOptions.builder() .setTemperature(0.6f) .setTopK(5000) .setTopP(1f) .build() यहां, आप कुछ अलग-अलग पैरामीटर सेट कर सकते हैं। , और चलो उन्हें उनमें से प्रत्येक में डुबोते हैं। .setTemperature() .setTopK() .setTopP() आप सोच सकते हैं कि भाषा मॉडल से प्रतिक्रियाएं कितनी "स्वाभाविक" हो सकती हैं. मूल्य जितना कम हो जाता है, मॉडल से प्रतिक्रियाएं जितनी अधिक "संभव" हो सकती हैं. मूल्य जितनी अधिक हो सकती है, प्रतिक्रियाएं जितनी अधिक "स्वाभाविक" होंगी, इससे अधिक अप्रत्याशित प्रतिक्रियाएं उत्पन्न होंगी. .setTemperature() इस उदाहरण के लिए, यह निर्धारित है कि , जिसका अर्थ है कि मॉडल आधा रचनात्मक, लेकिन अविश्वसनीय प्रतिक्रियाएं नहीं देगा। 0.6 तापमान के साथ प्रयोग करने के लिए एक अच्छा मूल्य है, क्योंकि आप विभिन्न मूल्यों को आपके उपयोग के मामले के आधार पर बेहतर प्रतिक्रिया प्रदान कर सकते हैं। यह कहने का एक तरीका है कि "केवल शीर्ष K परिणामों को उपयोगकर्ता को वापस करने के लिए विचार करें." भाषा मॉडल, एक प्रिंट को संसाधित करते समय, प्रतिक्रियाओं की एक संख्या उत्पन्न करते हैं, संभावित रूप से हजारों! .setTopK() इनमें से प्रत्येक को सही जवाब होने की संभावना के बारे में एक संभावना दी जाती है. विचार करने वाले उत्तरों की संख्या को सीमित करने के लिए, यदि आप कम संभावना प्रतिक्रियाओं पर विचार किए जाने के साथ खुश हैं, तो आप इस मूल्य को उच्च सेट करना चाहते हैं। topK तापमान संपत्ति के समान, यह प्रयोग करने के लिए एक अच्छा संपत्ति है. आप पा सकते हैं कि मॉडल आपकी जरूरतों के आधार पर विचार करने के लिए कम या अधिक प्रतिक्रियाओं के साथ बेहतर काम करता है। एक खेल के लिए साइमन कहते हैं, हम चाहते हैं कि मॉडल खेल को ताजा रखने के लिए कई अलग-अलग प्रतिक्रियाओं के बारे में सोच रहा हो। एक अच्छा मूल्य लगता है। 5000 निर्धारित सीमा पर निर्धारित यह कहकर कि "केवल उन परिणामों पर विचार करें जिनके पास P की संभावना है" जैसा कि पहले उल्लेख किया गया था, भाषा मॉडल प्रत्येक प्रतिक्रिया को एक संभावना निर्धारित करते हैं जो यह उत्पन्न करता है कि यह कितनी संभावना हो सकती है। इसका मतलब है कि मॉडल आसानी से किसी भी प्रतिक्रिया को खारिज कर सकता है जिसमें न्यूनतम संभावना नहीं है। .setTopP() topK topP एक उदाहरण के लिए, यदि मॉडल एक सेट करें उन्होंने निम्नलिखित जवाबों पर विचार किया: topP 0.4 Simons Says clap 5 times! = 0.7 // This response has a probablility of 0.7 of being correct Simons Says jump up and down! = 0.5 Find a car and drive it. = 0.3 पहले दो जवाबों पर विचार किया जाएगा क्योंकि संभावना अधिक है कार के बारे में जवाब फेंक दिया जाएगा, क्योंकि यह केवल एक संभावना है . 0.4 0.3 इसी तरह और , आपको यह परिभाषित करने की अनुमति देता है कि आपका भाषा मॉडल कितना रचनात्मक हो सकता है. यदि आप प्रोत्साहनों के लिए कम संभावना प्रतिक्रियाओं पर विचार करना चाहते हैं, तो एक कम P मूल्य सेट करना मदद करेगा. temperature topK topP उदाहरण के लिए, यह निर्धारित है कि ऐसा इसलिए है क्योंकि हम चाहते हैं कि मॉडल अपनी प्रतिक्रियाओं के बारे में पूरी तरह से यकीन रखे. आखिरकार, यह एक बच्चों का खेल खेल रहा है! 1.0 इन मूल्यों के साथ प्रयोग करना आपके भाषा मॉडल से बहुत अलग परिणाम उत्पन्न करेगा. उन्हें आज़माएं और देखें कि क्या होता है! अगला कहां जाना है? मुझे उम्मीद है कि आपने अपने एंड्रॉइड ऐप में एक आरएजी समर्थित भाषा मॉडल को कैसे जोड़ना है! यदि आप आरएजी और एंड्रॉइड के बारे में अधिक जानना चाहते हैं, तो यहां कुछ लिंक हैं जो मैं अनुशंसा करता हूं: Clone and run the for this blog post to see it in action. It shows how to setup the RAG pipeline with Gemma using Android architecture best practices. Simons Says App: sample code : Check out the RAG section on the MediaPipe - Highly recommended reading. MediaPipe RAG Google Developer docs : Learn more about how setting the Temperature, TopK, and TopP values can the results from language models. Another highly recommended article. Setting Temperature, TopK, and TopP in LLMs help control