इंटेलिजेंट ऐप्लिकेशन

ML Kit GenAI की मदद से, अपने ऐप्लिकेशन में एजेंटिक एआई की सुविधाएं अनलॉक करना

स्पीकर

  • योलांडा फेरहूफ़

    डेवलपर रिलेशंस इंजीनियर

  • विक्टोरिया लेस्तारी

    सॉफ़्टवेयर इंजीनियर

इसके बारे में

बातचीत के बारे में जानकारी

उपयोगकर्ता के डिवाइस पर काम करने वाले ऑटोनॉमस एजेंट बनाकर, Android पर एआई की सुविधाओं को और बेहतर बनाएं. इस सेशन में, हम ML Kit के नए एजेंटिक एपीआई के बारे में जानेंगे. ये एपीआई, डायरेक्ट मॉडल ऐक्सेस एपीआई के ऊपर बनाए गए हैं. इनके बारे में आपको पहले से पता है.

ओपन सोर्स Jetpacker ऐप्लिकेशन का इस्तेमाल करके, आपको स्थानीय डेटा के साथ कई चरणों वाली कार्रवाइयों को चेन करने का तरीका पता चलेगा. साथ ही, अलग-अलग कॉन्टेक्स्ट के साथ स्टेटफ़ुल मल्टी-टर्न सेशन मैनेज करने का तरीका भी पता चलेगा. इसके अलावा, Android एमसीपी को वायर अप करने का तरीका भी पता चलेगा, ताकि एक ही कोड बेस से, ऐप्लिकेशन में मौजूद असिस्टेंट और Android सिस्टम-लेवल की सुविधाओं, दोनों को बेहतर बनाया जा सके.

खास जानकारी

  • Gemini Nano 4 में फ़ंक्शन कॉलिंग की सुविधा पहले से मौजूद है. इससे डिवाइस पर मौजूद मॉडल, नैचुरल लैंग्वेज को कार्रवाइयों में बदल सकते हैं और लोकल एपीआई चला सकते हैं.
  • Jetpack AppFunctions लाइब्रेरी, नैचुरल लैंग्वेज में KDoc ब्यौरे के ज़रिए टूल तय करती है. ऐक्सेस लेवल बदलने से, Gemini जैसे सिस्टम एजेंट को इन फ़ंक्शन का ऐक्सेस मिल सकता है.
  • ML Kit GenAI में नई एजेंटिक फ़्लो लाइब्रेरी (ऐल्फ़ा) की मदद से, एजेंट बनाना आसान हो जाता है. यह लाइब्रेरी, एक्ज़ीक्यूशन लूप और टूल कॉल को मैनेज करती है.
  • AgentRunner, टूल के एक्ज़ीक्यूशन को मैनेज करता है. साथ ही, यह कॉन्टेक्स्ट को खोए बिना, कई बार होने वाली बातचीत के लिए सेशन के तरीके उपलब्ध कराता है.
  • Prompt API के ज़रिए डायरेक्ट ऐक्सेस की सुविधा उपलब्ध रहेगी. इससे इतिहास को आसानी से कंट्रोल किया जा सकता है. इसके अलावा, मल्टी-एजेंट और हाइब्रिड सिस्टम जैसे जटिल सेटअप को भी कंट्रोल किया जा सकता है.

कौशल

संसाधन

Gemini Notebook

विषय

  • ml-kit
  • on-device-ai
  • gemini-nano
  • एआई-एजेंट
  • फ़ंक्शन कॉलिंग
  • app-functions
  • aicore

ट्रांसक्रिप्ट

ट्रांसक्रिप्ट डाउनलोड करें

उपयोगकर्ता के डिवाइस पर मौजूद एआई और Gemini Nano के बारे में जानकारी

  • मेरा नाम योलांडा फेरहूफ़ है.

  • मैं Android में डेवलपर रिलेशंस इंजीनियर हूं. आज मेरे साथ विक्टोरिया लेस्तारी हैं, जो AICore की इंजीनियरिंग टीम का हिस्सा हैं.

  • नमस्ते.

  • आज सुबह के सेशन में शामिल होने के लिए धन्यवाद.

  • इसलिए, हमारी टीम सालों से मिलकर काम कर रही है, ताकि क्लाउड से बेहतरीन एआई मॉडल को सीधे Android डिवाइसों पर चलाया जा सके.

  • इन सभी सुविधाओं को ML Kit GenAI सुइट में शामिल किया गया है.

  • एक तरफ़, ML Kit GenAI Suite में हमारे पास टर्नकी समाधानों के लिए हाई-लेवल एपीआई हैं. जैसे, टेक्स्ट की खास जानकारी, इमेज का ब्यौरा, और बोली की पहचान.

  • इसके अलावा, हमने उपयोगकर्ता के डिवाइस पर मौजूद मॉडल, Gemini Nano का सीधा ऐक्सेस भी दिया है.

  • आज हम एक और कदम आगे बढ़ा रहे हैं.

  • इस डायरेक्ट ऐक्सेस की मदद से, हम आपको इन-ऐप्लिकेशन एजेंट बनाने की सुविधा देंगे. ये एजेंट, कई चरणों में तर्क कर सकते हैं, बातचीत के संदर्भ को सेव कर सकते हैं, और आपके ऐप्लिकेशन में कार्रवाइयां कर सकते हैं.

  • विक्टोरिया, इसका असल में क्या मतलब है?

  • हाँ।

  • अब तक, डिवाइस पर इस्तेमाल किए जाने वाले मामलों के बारे में बात करते समय, हम छोटे, आसान, और अलग-अलग टास्क के बारे में सोचते हैं. जैसे, किसी संभावित धोखाधड़ी का पता लगाना या फ़ोन कॉल की खास जानकारी देना.

  • जब हमें कोई मुश्किल काम करना होता है, जैसे कि आपके फ़ोटो कैटलॉग के बारे में सवाल पूछना या Google Maps से कुछ पूछना, तो हम बड़े क्लाउड मॉडल का इस्तेमाल करते हैं.

  • इसलिए, क्लाउड मॉडल में डेटा को प्रोसेस करने की क्षमता ज़्यादा होती है और रीयल-टाइम डेटा मिलता है. हालांकि, उपयोगकर्ता के डिवाइस पर मौजूद एआई, कम इंतज़ार के समय और रीयल-टाइम और स्थानीय डेटा प्रोसेसिंग के लिए नई संभावनाएं खोलता है.

  • इसलिए, Gemini Nano ने पहले ही आपके डिवाइसों पर किए जा सकने वाले कामों का दायरा बढ़ा दिया है.

  • इसका एक उदाहरण Pixel Screenshots है. इसकी मदद से, डिवाइस पर मौजूद स्क्रीनशॉट खोजे जा सकते हैं और उनसे जुड़े सवाल पूछे जा सकते हैं.

  • इसलिए, जब हम उपयोगकर्ता के डिवाइस पर एजेंट चलाते हैं, तो इसका मतलब है कि हमें मॉडल की क्षमता में काफ़ी सुधार करना होगा. इसलिए, हम Gemini Nano 4 बना रहे हैं. यह अलग-अलग चरणों में तर्क कर सकता है और असल कार्रवाइयां कर सकता है.

  • हालांकि, इस नई सुविधा का फ़ायदा सिर्फ़ तब मिलता है, जब डेवलपर के पास टारगेट करने के लिए असली डिवाइस हों.

  • अच्छी बात यह है कि Gemini Nano 4, चुनिंदा फ़्लैगशिप डिवाइसों पर पहले से ही उपलब्ध है. साथ ही, AICore के डेवलपर के लिए झलक का इस्तेमाल करके, इसे कई अन्य डिवाइसों पर भी टेस्ट किया जा सकता है.

  • साथ ही, हम अगले साल की शुरुआत तक 10 करोड़ डिवाइसों तक पहुंचने की राह पर हैं.

  • इसका क्या मतलब है?

  • इसका मतलब है कि आज से ही इन अनुभवों को बनाना और टेस्ट करना शुरू किया जा सकता है. साथ ही, यह भी पता चल सकता है कि आज जो बनाया जा रहा है वह बड़ी संख्या में लोगों तक पहुंचेगा.

  • हमने Gemini Nano 4 और इसकी संभावित पहुंच के बारे में बात कर ली है. अब बात करते हैं कि एजेंटिक एआई की सुविधाओं का असल में क्या मतलब है.

  • इसलिए, एजेंटिक एआई मुश्किल टास्क के लिए प्लान बना सकता है, उन्हें कई चरणों में बांट सकता है, और फिर आपके ऐप्लिकेशन पर इन चरणों को पूरा कर सकता है.

  • मान लीजिए कि आपके डिवाइस पर Gemini Nano मॉडल मौजूद है. यह आपके लोकल डेटाबेस से क्वेरी कर सकता है, बैक एंड से डेटा वापस पा सकता है, आपके मुश्किल सवालों के जवाब दे सकता है, और आपके डिवाइस पर खास ऐप्लिकेशन वर्कफ़्लो को भी ट्रिगर कर सकता है.

  • हालांकि, एआई किसी प्लान को बनाने से लेकर उसे असल में लागू करने तक का सफ़र कैसे तय करता है?

  • आज का हमारा विषय है, फ़ंक्शन कॉलिंग.

  • यह एजेंटिक एआई की सुविधा का मुख्य इंजन है.

  • यह नैचुरल लैंग्वेज को सिस्टम एक्ज़ीक्यूशन में बदलता है. साथ ही, यह मॉडल को पैसिव रीज़निंग से ऐक्टिव एक्ज़ीक्यूशन में ले जाता है. इसके लिए, यह मुश्किल टास्क को हल करने के लिए ज़रूरी लोकल एपीआई को चुनता है और उन्हें चलाता है.

  • हमें यह बताते हुए भी खुशी हो रही है कि Gemini Nano 4 पर, फ़ंक्शन कॉलिंग की सुविधा नेटिव तौर पर काम करती है.

  • फ़िलहाल, यह AICore के डेवलपर की झलक वाले वर्शन में उपलब्ध है. जल्द ही, इसे Nano 4 के साथ काम करने वाले सभी डिवाइसों पर रोल आउट किया जाएगा.

  • इसलिए, यह बहुत अच्छी बात है कि हमारे पास मॉडल में इस तरह की सुविधाएं हैं. हालांकि, मॉडल में मौजूद सुविधा से, डेवलपर के तौर पर आपको एपीआई नहीं मिलते.

  • इसलिए, हम ML Kit GenAI सुइट में सही एपीआई जोड़ने पर भी काम कर रहे हैं, ताकि एजेंट बनाना वाकई आसान हो जाए.

  • इसलिए, हमने डायरेक्ट ऐक्सेस एपीआई से शुरुआत की, जो हमारे पास पहले से मौजूद थे. साथ ही, हमने इसमें फ़ंक्शन टाइप और बातचीत के इतिहास के टाइप जोड़े.

  • ML Kit के Prompt API में जोड़ी गई इन दो नई सुविधाओं की मदद से, अब अपने ऐप्लिकेशन में एजेंटिक एआई की सुविधाएँ जोड़ी जा सकेंगी.

  • हालांकि, इस दौरान आपको कई काम खुद करने होंगे.

  • इसलिए, आपको फ़ंक्शन को मैन्युअल तरीके से चलाना होगा, कॉल इतिहास को सेव करना होगा, और कई कॉल के लिए खुद को लूप में रखना होगा.

  • इसलिए, अगर आपको कई कॉल करने हैं, तो आपको खुद ही कोई लूपिंग सिस्टम बनाना होगा. साथ ही, आपको सिस्टम के लिए खुद ही गार्ड रेल बनानी होंगी.

  • ऐसा हो सकता है, लेकिन हम इस प्रोसेस को तेज़ और आसान बनाना चाहते हैं.

  • इसलिए, हमने Prompt API लाइब्रेरी के साथ-साथ, एजेंटिक फ़्लो की एक नई लाइब्रेरी भी जोड़ी है.

  • इसे com.mlkit.genai:agent-api की मदद से ढूंढा जा सकता है. फ़िलहाल, यह ऐल्फ़ा वर्शन में उपलब्ध है.

  • अब इस नए एपीआई की मदद से, हम आपके लिए ज़्यादातर मुश्किल काम कर देते हैं.

  • इसलिए, आपको मैन्युअल तरीके से कई चरण पूरे करने के बजाय, कोड की कुछ लाइनों की मदद से एजेंट बनाने की सुविधा मिलेगी.

  • आज हम यही करने वाले हैं.

Jetpacker एजेंट का डेमो और फ़ंक्शन कॉलिंग

  • इसलिए, हम देखेंगे कि ये एपीआई, सैंपल के तौर पर मिले हमारे ऐप्लिकेशन Jetpacker के साथ कैसे काम करते हैं.

  • आपने Google I/O और इस कॉन्फ़्रेंस के दौरान, Jetpacker को पहले ही देख लिया है.

  • हालांकि, इस क्यूआर कोड को स्कैन करके, कोड को देखा जा सकता है. अगर आपकी दिलचस्पी है, तो अपने एजेंट को कोड पर ले जाएं, कोड के साथ इंटरैक्ट करें, और इस बारे में ज़्यादा जानें कि हमने इन सभी सुविधाओं को असल में कैसे लागू किया.

  • Jetpacker, यात्रा से जुड़ी एक आधुनिक असिस्टेंट है. इसे हमने कई तरह की इंटेलिजेंट सुविधाओं को दिखाने के लिए बनाया है.

  • इसलिए, यह पहले से ही सभी तरह के प्रॉम्प्टिंग एपीआई के लिए, उपयोगकर्ता के डिवाइस पर मॉडल और क्लाउड मॉडल का इस्तेमाल कर रहा है. हालांकि, अब हम इसमें एक एजेंट जोड़ने जा रहे हैं.

  • Jetpacker के लिए, हम ML Kit GenAI Agent API का इस्तेमाल करेंगे. इसके बारे में हमने अभी बात की थी. यह Gemini Nano मॉडल से इंटरैक्ट करने के लिए, Android डिवाइसों पर मौजूद AI Core सिस्टम का इस्तेमाल करेगा.

  • अब, मैं जितना चाहूं उतना बोल सकता हूं और हम काफ़ी बात करेंगे, लेकिन ज़ाहिर है कि हम इसे दिखाना चाहते हैं.

  • चलिए, अब फ़ोन पर स्विच करते हैं और इसे डेमो के तौर पर दिखाते हैं.

  • मेरे पास यहां Pixel 11 Pro है.

  • मुझे लगता है कि हम Pro पर स्विच कर सकते हैं और आपको यह दिखना चाहिए.

  • यह रहा, यह रहा.

  • जैसा कि आप देख सकते हैं, यहां Jetpacker ऐप्लिकेशन चल रहा है.

  • इसमें हमारी आने वाली कई यात्राओं की जानकारी है. साथ ही, मैं हमारी मौजूदा यात्रा की जानकारी देख सकता हूं. हमारी मौजूदा यात्रा में, आपको दिख रहा होगा कि आज 29 अक्टूबर है. इसलिए, आज हमारी उपयोगकर्ता के डिवाइस पर एआई वर्कशॉप और डेमो शोकेस है. इसके बाद, कल मुझे गोल्डन गेट बे क्रूज़ पर जाना है और म्यूज़ियम भी जाना है.

  • यह सब बहुत अच्छी बात है.

  • अब हम खर्च वाली स्क्रीन पर जा सकते हैं. यहां हम इस यात्रा के बजट को ट्रैक कर रहे हैं.

  • सबसे नीचे दाईं ओर, आपको एजेंटिक स्पार्कल दिख रहा होगा. यह उपयोगकर्ता के डिवाइस पर मौजूद एजेंट है, जिसे हमने बनाया है.

  • चलिए, एक आसान निर्देश से शुरुआत करते हैं.

  • मुझे लगता है कि हम इसे कोई खास खर्च जोड़ने के लिए कह सकते हैं.

  • मान लें कि आपने कहा: माउंटेन व्यू जाने के लिए टैक्सी का खर्च जोड़ो, जो 45 डॉलर था.

  • आपने कर दिखाया।

  • यह खर्च की जानकारी तैयार कर रहा है और इसने खर्च की जानकारी जोड़ दी है.

  • शानदार.

  • ठीक है, पहला डेमो काम कर गया.

  • चलिए, स्लाइड पर वापस चलते हैं और देखते हैं कि यह असल में कैसे काम करता है.

  • ठीक है, तो सबसे पहले, जैसा कि आपने देखा, मैं अपनी आवाज़ का इस्तेमाल कर रहा था. वह आवाज़, स्पीच रेकग्निशन एपीआई का इस्तेमाल करके Gemini Nano मॉडल का भी इस्तेमाल कर रही है. इससे, मैं जो कुछ भी कह रहा था उसे टेक्स्ट में बदला जा सकता है.

  • इसके बाद, उस टेक्स्ट को Gemini Nano मॉडल को भेजा जा सकता है.

  • लेकिन, इससे क्या होगा?

  • जैसे, मैंने इसे खर्चों में कुछ जोड़ने के लिए कहा और 45 डॉलर के बारे में कुछ बताया. हालाँकि, इसे वाकई में नहीं पता कि क्या करना है, है ना?

  • इस समय, यह मुझे सिर्फ़ यह बताएगा, "मुझे नहीं पता कि आप किस बारे में बात कर रहे हैं."

  • इसलिए, हम उस प्रॉम्प्ट में थोड़ा और टेक्स्ट जोड़ना चाहते हैं.

  • हम प्रॉम्प्ट में टूल जोड़ सकते हैं. हम हर तरह के टूल जोड़ सकते हैं. इस मामले में, मैं यात्रा का बजट, यात्रा की योजना वगैरह जोड़ रहा हूँ. अगर आप इसे हमारे एपीआई के साथ Nano मॉडल को पास करते हैं, तो यह अपने-आप समझ जाएगा कि टेक्स्ट दिखाने के बजाय, अब यह फ़ंक्शन कॉल दिखा सकता है.

  • इसलिए, हमारे मामले में यह कहेगा, "टेक्स्ट में जवाब देने के बजाय, मैं माउंटेन व्यू जाने के लिए टैक्सी के किराये के तौर पर 45 डॉलर का खर्च जोड़ रहा हूँ."

  • यह तो बहुत अच्छी बात है, लेकिन विक्टोरिया, यह असल में कैसे काम करता है?

  • हम इसे कैसे बनाएं?

  • हाँ।

  • तो हम अपने कोड में टूल को कैसे तय करते हैं?

  • इसलिए, मैं आपको इसके बारे में बताऊंगी.

  • इसलिए, Android एमसीपी के साथ, हम इन टूल को तय करने और पब्लिश करने के लिए, Jetpack AppFunctions लाइब्रेरी का इस्तेमाल करते हैं.

  • इसलिए, AppFunctions लाइब्रेरी आपके ऐप्लिकेशन की सेवाओं, डेटा, और कार्रवाइयों को Android OS रजिस्ट्री में दिखा सकती है. इससे हम टूल के बारे में बताने और उनका ब्यौरा देने के लिए, बिलकुल एक जैसे फ़ंक्शन का फिर से इस्तेमाल कर सकते हैं. साथ ही, उन्हें आपके ऐप्लिकेशन में इस्तेमाल कर सकते हैं.

  • साथ ही, इससे उपयोगकर्ता को एजेंट और सिस्टम-लेवल इंटरैक्शन के ज़रिए इस टास्क को पूरा करने की अनुमति मिलती है.

  • इसलिए, मैं आपको कोड में एक ठोस उदाहरण देने जा रहा हूं.

    /**
     * Adds an expense to a trip.
     *
     * @param tripId Identifier of the trip (e.g., "paris-2026").
     * @param amount Expense amount in dollars.
     * @param description Short description of what the expense was for.
     */
    @AppFunctionDeclaration(isDescribedByKDoc = true)
    @AppFunctionAccessLevel(
      level = ACCESS_LEVEL_SELF,
      isCompatEnforcementEnabled = true,
    )
    suspend fun addExpense(tripId: String, amount: Double, description: String) {
      // Save expense to local DB / repository...
    }
  • इसलिए, यह AppFunctionDeclaration का एक उदाहरण है.

  • सबसे ऊपर मौजूद KDoc टिप्पणी में, फ़ंक्शन और उसके पैरामीटर के बारे में नैचुरल लैंग्वेज में बताया गया है.

  • इसलिए, सबसे सही तरीका यह है कि आप ज़्यादा से ज़्यादा साफ़ तौर पर जानकारी दें, क्योंकि हम इसे मॉडल को भेजने वाले हैं.

  • इसके बाद, आपको इसके नीचे एक एनोटेशन, @AppFunctionAccessLevel दिखेगा.

  • इसलिए, यह फ़ंक्शन की विज़िबिलिटी को सीमित करता है.

  • इस उदाहरण में, हमारे पास ACCESS_LEVEL_SELF है. इसका मतलब है कि हम जो फ़ंक्शन लिख रहे हैं वे सिर्फ़ आपके ऐप्लिकेशन और उसके एजेंट को दिखेंगे.

  • इसके बाद, हम suspend फ़ंक्शन को तय और लागू कर सकते हैं. साथ ही, हम जितने चाहें उतने ऐप्लिकेशन फ़ंक्शन लिख सकते हैं और उन सभी को एक ही सर्विस क्लास में ग्रुप कर सकते हैं.

एआई एजेंट रनर बनाना और उसे लागू करना

  • ठीक है।

  • इसलिए, हमारे पास टूल हैं और हम उन टूल को लिख सकते हैं, यह बहुत अच्छी बात है.

  • हालांकि, एजेंट बनाने के लिए हमें सिर्फ़ उन AppFunctions से ज़्यादा की ज़रूरत होती है.

  • इसलिए, हमारे पास तीन और तरह के हिस्से हैं जिनके बारे में जानना ज़रूरी है, जब आप कोई एजेंट लिख रहे हों.

  • सबसे पहले, हम एजेंट को तय कर रहे हैं.

  • इसलिए, हम सिस्टम के लिए निर्देश तय कर रहे हैं. साथ ही, हम सुरक्षा के लिए दिशा-निर्देश, कॉन्फ़िगरेशन, और इसके साथ काम करने का तरीका तय कर रहे हैं.

  • इसके अलावा, हमारे पास AgentRunner भी है.

  • AgentRunner, एजेंट को हमारे लिए चलाता है.

  • इसलिए, यह उस लूपिंग मैकेनिज़्म का ध्यान रखता है जिसके बारे में हम बात कर रहे थे.

  • आखिर में, हमारे पास AgentEvents है. AgentEvents, सिस्टम और एपीआई के लिए एक तरीका है, जिससे हमें पता चलता है कि वह असल में क्या कर रहा है.

  • इसलिए, यह हमें बताएगा कि यह कब टेक्स्ट दिखा रहा है, कब टूल कॉल कर रहा है वगैरह. इससे हम उसे अपने यूज़र इंटरफ़ेस (यूआई) में दिखा पाएंगे.

  • ठीक है।

  • चलिए, उस कोड को देखते हैं.

  • ठीक है।

  • कोड लिखने से पहले, हमें यह देखना होगा कि आपके डिवाइस पर फ़ंक्शन कॉलिंग की सुविधा उपलब्ध है या नहीं. ऐसा इसलिए, क्योंकि फ़ंक्शन कॉलिंग की सुविधा सिर्फ़ Gemini Nano 4 पर काम करती है.

    val model = Generation.getClient()
    val features = model.getAvailableFeatures()
    if(FUNCTION_CALLING in features) {
      // Device is supported!
    } else {
      // Graceful fallback
    }
  • सबसे पहले, हमें जनरेटिव मॉडल getAvailableFeatures को कॉल करके यह देखना होगा कि क्या यह सुविधा उपलब्ध है.

  • इसके बाद, हम यह देख सकते हैं कि सुविधाओं की सूची में फ़ंक्शन कॉलिंग शामिल है या नहीं.

  • अगर ऐसा नहीं है, तो हम एक ग्रेसफ़ुल फ़ॉलबैक लागू कर सकते हैं.

  • ठीक है।

  • चलिए, अब कोड पर चलते हैं.

    if(FUNCTION_CALLING in features) {
      // 1. Build the agent configuration
      val agent = Agent.builder()
        .setName("Assistant")
        .setInstructions("You are a helpful on-device assistant.")
        .enableAppFunctions()
        .build()
    
      // 2. Initialize the runner
      val runner = AgentRunner(agent = agent)
    
      // 3. Create your prompt
      val prompt = content { text(userPrompt)}
    
      // 4. Start the agent
      runner.runSingleTurnAsync(prompt).textTokens().collect { responseMessage += it }
    
    }
  • हमें पता है कि हमारे डिवाइस पर फ़ंक्शन कॉलिंग की सुविधा काम करती है. इसके बाद, हम Agent.builder का इस्तेमाल करके, एजेंट को बनाना शुरू कर सकते हैं.

  • इसके बाद, हम इसका नाम सेट कर सकते हैं.

  • हम setInstructions का इस्तेमाल करके, कॉन्टेक्स्ट और पर्सोना तय कर सकते हैं.

  • आखिर में, हम enableAppFunctions को कॉल करते हैं.

  • इसलिए, यह फ़ंक्शन कॉल, लूप के ज़रिए उन सभी AppFunctions को अपने-आप खोज लेगा जिन्हें हमने पहले लिस्ट किया था और जिनके लिए हमने एजेंट बनाया था.

  • इसके बाद, हमें AgentRunner को शुरू करना होगा.

  • इसलिए, यह एजेंट रनर हमारे लिए, एक्ज़ीक्यूशन लूप को मैनेज करेगा.

  • हम इसे कॉल करने के लिए, कंस्ट्रक्टर को कॉल करते हैं और एजेंट को पास करते हैं.

  • आखिर में, हम बोले गए निर्देश को टेक्स्ट में बदलकर, उसे कॉन्टेंट ब्लॉक में रैप कर सकते हैं, ताकि प्रॉम्प्ट बनाया जा सके.

  • इसके बाद, हम रनर को कॉल करते हैं.

  • हम प्रॉम्प्ट पर इस फ़ंक्शन runSingleTurnAsync को कॉल करते हैं. इससे एजेंट शुरू हो जाएगा, अनुमान चलेगा, और पूरा एआई अनुमान चलेगा.

  • अगर हमें मॉडल के सिर्फ़ फ़ाइनल टेक्स्ट जवाब को अपने यूज़र इंटरफ़ेस (यूआई) में स्ट्रीम करना है, तो हम textTokens को कॉल करेंगे. इससे जवाब मिलते ही उसे इकट्ठा कर लिया जाएगा.

  • बस इतना ही.

  • यह वाकई कोड की कुछ लाइनें हैं. इसलिए, जब हमने यह कहा था, तो हम मज़ाक़ नहीं कर रहे थे.

  • कोड की कुछ लाइनों की मदद से, आपके पास एक एजेंट होगा.

  • वह एजेंट आपकी पसंद के मुताबिक काम करेगा.

  • यह हमें टेक्स्ट के तौर पर जवाब देगा.

  • हालांकि, हमने जो पहला डेमो दिखाया था उसमें सिर्फ़ एक आसान सा निर्देश दिया था, है न?

  • जैसे, मैंने एक निर्देश दिया और उसने एक कार्रवाई की. बस इतना ही. इसलिए, यह अभी तक पूरी तरह से एजेंट नहीं है, है ना?

  • इसलिए, चलिए इसे थोड़ा और मज़ेदार बनाते हैं.

  • अगले हिस्से में, मुझे एक निर्देश देना है. हालांकि, मैं एजेंट के लिए इसे थोड़ा मुश्किल बनाना चाहता हूं.

कई चरणों वाला एजेंट आर्किटेक्चर और एक्ज़ीक्यूशन

  • चलिए, डेमो डिवाइस पर वापस चलते हैं और देखते हैं कि क्या हम इसे थोड़ा और मुश्किल बना सकते हैं.

  • हम पहले से ही वहां मौजूद हैं.

  • शानदार.

  • जैसा कि मैंने बताया, हमने कल म्यूज़ियम जाने का प्लान बनाया है.

  • म्यूज़ियम की यात्रा के लिए, अगर मैं इसे खोलूं, तो आपको दिखेगा कि एंट्री की कीमत 25 डॉलर है.

  • अब देखते हैं कि हमारा एजेंट खुद से यह पता लगा पाता है या नहीं.

  • इसलिए, मैं खर्च वाली स्क्रीन पर वापस जा रहा हूँ और इसे एक निर्देश दूँगा. मैं कहूँगा, "म्यूज़ियम के टिकट को मेरे खर्चों में जोड़ो."

  • आपने कर दिखाया।

  • अब जैसा कि आप देख सकते हैं, यह मेरी यात्रा की योजना की जांच कर रहा है, म्यूज़ियम की यात्रा की जानकारी ढूंढ रहा है, और इसे मेरे खर्चों में जोड़ रहा है.

  • इसलिए, अपने लक्ष्य तक पहुंचने के लिए, इसने तीन चरणों का इस्तेमाल किया और मुझे टेक्स्ट के तौर पर जवाब भी दिया.

  • यह सब अपने-आप काम करता है.

  • आपने डिवाइस पर उस मॉडल की असल स्पीड देखी.

  • चलिए, अब स्लाइड पर वापस चलते हैं और देखते हैं कि यह कैसे काम करता है.

  • जैसा कि आपने देखा, हमने अपने पहले डेमो के मुकाबले कुछ बदलाव किए हैं.

  • इस मामले में, जैसा कि आप देख सकते हैं, मैंने इसे म्यूज़ियम के बारे में नहीं बताया था. मैंने इसे खर्च के बारे में भी नहीं बताया था. इसलिए, जब मॉडल को प्रॉम्प्ट और टूल मिले, तो उसने यह तय करने की कोशिश की कि पहले क्या करना है.

  • इसलिए, यहां यह तय करता है कि, ओह, इसे मेरी मौजूदा यात्रा की योजना के बारे में ज़्यादा जानने की ज़रूरत है, इसलिए यह getItinerary को कॉल करेगा.

  • इसके बाद, उसे जवाब मिलता है और उसे पता चलता है कि इस यात्रा की योजना में म्यूज़ियम की यात्रा शामिल है. शायद वह इसी के बारे में बात कर रही थी.

  • इसलिए, चलिए उस इवेंट की जानकारी ढूंढते हैं.

  • साथ ही, उस इवेंट के अन्य सभी मेटाडेटा के बीच, यह दिखेगा कि इसकी कीमत 25 डॉलर है.

  • यह समझ जाता है कि उसे वापस जाना है और खर्च जोड़ने के लिए कॉल करना है.

  • इसलिए, यहां हमें एक के बाद एक कई चरण दिख रहे हैं.

  • विक्टोरिया, क्या इस बारे में थोड़ी और जानकारी दी जा सकती है?

  • हाँ।

  • जोलैंडा ने अभी जो बताया है वह उनके दिखाए गए डेमो का एक ठोस उदाहरण है. हालांकि, यहां मैं इसे थोड़ा और कॉन्सेप्चुअल, ऐब्स्ट्रैक्ट लेयर में ले जाने वाला हूं.

  • इसलिए, जब भी हम कई चरणों वाली फ़ंक्शन कॉलिंग करेंगे, तब ऐसा होगा.

  • सबसे पहले, यह हमारा ऐप्लिकेशन है और यह Gemini Nano मॉडल है.

  • इसके बाद, उपयोगकर्ता मॉडल को क्वेरी और उपलब्ध टूल की सूची भेजेगा.

  • इसलिए, मॉडल इस जानकारी का इस्तेमाल करके यह तय करेगा कि उसे क्या जवाब देना है.

  • मान लें कि पहले मामले में, यह टूल कॉल वापस भेजता है. इसे टूल कॉल 1 कहें.

  • इसके बाद, ऐप्लिकेशन इस टूल कॉल को एक्ज़ीक्यूट करेगा और टूल से जवाब हासिल करेगा.

  • इसके बाद, मॉडल को पूरी बातचीत का इतिहास भेजा जाएगा. इसमें ओरिजनल क्वेरी, टूल की सूची, पहला टूल कॉल, और पहला टूल रिस्पॉन्स शामिल होता है.

  • इसके बाद, मॉडल फिर से इस जानकारी का इस्तेमाल करके तय करता है कि आगे क्या करना है.

  • इसलिए, जब तक हमें फ़ाइनल नतीजा नहीं मिल जाता, तब तक यह प्रोसेस जारी रह सकती है.

  • मान लें कि मॉडल, nवें टूल कॉल को वापस करेगा. इसके बाद, ऐप्लिकेशन फिर से बातचीत का पूरा इतिहास वापस करेगा.

  • जब मॉडल को लगता है कि क्वेरी पूरी हो गई है, तो वह ऐप्लिकेशन को फ़ाइनल जवाब भेजता है. इसके बाद, ऐप्लिकेशन यूज़र इंटरफ़ेस (यूआई) में दिखा सकता है कि काम हो गया है.

  • ठीक है।

  • अब मैं आपको बताऊंगा कि हम इसे कोड में कैसे लागू करते हैं.

    /**
    * Retrieves the itinerary events (ID, title, location) for a trip.
    * Note: Call getEventDetails(eventId) to retrieve ticket prices or notes.
    */
    @AppFunctionDeclaration(isDescribedByKDoc = true)
    @AppFunctionAccessLevel(level = ACCESS_LEVEL_SELF, isCompatEnforcementEnabled = true)
    suspend fun getItinerary(tripId: String): List<EventSummary> { ... }
    
    /**
    * Retrieves details for a specific event, including admission ticket prices.
    */
    @AppFunctionDeclaration(isDescribedByKDoc = true)
    @AppFunctionAccessLevel(level = ACCESS_LEVEL_SELF, isCompatEnforcementEnabled = true)
    suspend fun getEventDetails(eventId: String): EventDetails { ... }
  • आपको सिंगल-स्टेप कोड का उदाहरण याद होगा. यह मल्टी-स्टेप कोड है, इसलिए यह काफ़ी मिलता-जुलता है. सबसे ज़रूरी बात यह है कि KDoc को बहुत साफ़ तौर पर लिखा जाए.

  • इसलिए, इस उदाहरण में getItinerary फ़ंक्शन साफ़ तौर पर बताता है कि यह सिर्फ़ इवेंट की खास जानकारी दिखाता है.

  • इसलिए, हम यह भी बताते हैं कि अगर हमें यात्रा की ज़्यादा जानकारी चाहिए, तो हमें eventId के साथ getEventDetails को कॉल करना होगा.

  • इसके बाद, getEventDetails में KDoc टिप्पणी भी है. इसमें बताया गया है कि यह टिकट की कीमतों और अन्य नोट जैसी जानकारी हासिल कर सकता है.

  • इसलिए, टिप्पणी का इस्तेमाल करके और उसे साफ़ तौर पर समझाकर, हम मॉडल को यह समझने में मदद कर सकते हैं कि टूल एक-दूसरे के साथ कैसे इंटरैक्ट करते हैं.

  • ठीक है।

  • इस तरह, हम एजेंट को इस लूप को पूरा करने के लिए बनाते हैं. इसे एजेंटिक लूप कहते हैं.

    val agent = Agent.builder()
     .setName("Assistant")
     .setInstructions("You are a helpful travel assistant. Active tripId: $tripId")
     .enableAppFunctions()
     .setMaxTurns(5) // Guardrail against infinite tool loops
     .build()
    val runner = AgentRunner(agent = agent)
    // Automatically loops through all 3 tool calls in a single user turn!
    runner.runSingleTurnAsync(prompt).collect { event ->
     when (event) {
       is AgentEvent.FunctionCall -> showToolRunning(event.name)
       is AgentEvent.FunctionResponse -> showToolCompleted(event.name)
       is AgentEvent.TextMessage -> responseMessage += event.text
     }
    }
  • यह सिंगल-स्टेप वाले उदाहरण से काफ़ी मिलता-जुलता है. इसमें सिर्फ़ दो चीज़ें जोड़ी गई हैं.

  • सबसे पहले, हमें टर्न की ज़्यादा से ज़्यादा संख्या सेट करनी होगी. इस उदाहरण में, हमने पांच टर्न सेट किए हैं.

  • तो यह कैसे काम करता है?

  • इससे मॉडल को लगातार लूप में चलने से रोका जा सकता है.

  • मान लें कि प्रॉम्प्ट साफ़ तौर पर नहीं दिया गया है या हो सकता है कि वह एक टूल से दूसरे टूल पर और फिर वापस उसी टूल पर स्विच करता रहे. ऐसे में, अगर हम इस पैरामीटर को सेट करते हैं, तो वह रुक जाएगा और लूप में नहीं रहेगा.

  • इसके बाद, हम इसे चलाने के लिए अब भी उसी फ़ंक्शन को कॉल करते हैं, runSingleTurnAsync.

  • इसलिए, भले ही इसे सिंगल-टर्न कहा जाता है, लेकिन असल में एक टर्न का मतलब एक उपयोगकर्ता क्वेरी होता है.

  • इसलिए, असली उपयोगकर्ता की उम्मीद यह होती है कि मैं एक क्वेरी भेजूं और मुझे एक जवाब मिले. इसमें इस बात की ज़्यादा परवाह नहीं की जाती कि बैकग्राउंड में क्या हुआ, जैसे कि कितनी बार लूप किया गया वगैरह.

  • इसलिए, हम उसी फ़ंक्शन का इस्तेमाल जारी रख सकते हैं.

  • इसके अलावा, मल्टी-स्टेप टूल कॉलिंग की सुविधा थोड़ा ज़्यादा समय लेती है. इसलिए, आपने डेमो में यह भी देखा कि यह सुविधा असल में यह दिखाती है कि फ़िलहाल कौनसा फ़ंक्शन कॉल किया जा रहा है, कौनसा फ़ंक्शन एक्ज़ीक्यूट किया जा रहा है, और कौनसा फ़ंक्शन पूरा हो गया है.

  • इसलिए, हम यूज़र इंटरफ़ेस (यूआई) में लाइव प्रोग्रेस दिखाना चाहते हैं.

  • इसलिए, सिर्फ़ टेक्स्ट के जवाब इकट्ठा करने के बजाय, हम टूल का नाम, event.name दिखा सकते हैं. ऐसा तब किया जा सकता है, जब AgentEvent कोई FunctionCall या FunctionResponse दिखाता है. इसके बाद, हम पहले की तरह ही TextMessage दिखा सकते हैं.

एक से ज़्यादा बार बातचीत करने वाले सेशन मैनेज करना

  • शानदार!

  • इसलिए, हम इस रन एसिंक को सिंगल-टर्न एसिंक रन कह रहे हैं. इससे यह भी पता चलता है कि एक और तरह का एपीआई भी है, है न?

  • हाँ।

  • इसलिए, सिर्फ़ एक चरण पूरा करना काफ़ी नहीं है.

  • हम कई चरणों वाले टास्क पूरे करना चाहते हैं.

  • चलिए, अब मल्टी-टर्न सेशन करते हैं. मुझे लगता है कि हम अपने डेमो पर वापस जाकर, इसे थोड़ा और मुश्किल बना सकते हैं.

  • हम बात कर रहे थे कि म्यूज़ियम घूमने के साथ-साथ, गोल्डन गेट बे क्रूज़ का भी आनंद लिया जा सकता है.

  • इसलिए, मुझे यह पता करना है कि बुकिंग करने से पहले, क्या मेरे पास इसके लिए ज़रूरत के मुताबिक बजट है.

  • चलिए, अब कोई सवाल पूछते हैं.

  • आइए देखें.

  • मैं कल अपनी टीम को गोल्डन गेट बे क्रूज़ पर ले जाने की सोच रहा हूं. मुझे लगा कि इसकी कीमत करीब 180 डॉलर है.

  • अगर मैं ऐसा करूं, तो मेरा बाकी बचा बजट असल में कितना होगा?

  • तो यह क्या कर रहा है?

  • इससे पता चलता है कि मेरा बचा हुआ बजट कितना होगा.

  • इससे उसे यात्रा की मौजूदा योजना समझ आ जाएगी.

  • इसके पास यह जानकारी है और यह आपको बता सकता है.

  • इसके बाद, मैं यहां फ़ॉलो-अप सवाल भी पूछ सकता हूं.

  • ठीक है, यह अच्छी बात है.

  • क्या तुम इसे मेरे खर्चों में जोड़ सकती हो?

  • इसके बाद, यह आगे बढ़ जाएगा.

  • ओह, इसे मुद्रा की ज़रूरत है, तो ठीक है, डेमो इफ़ेक्ट.

  • ठीक है, तो यह डॉलर में है.

  • 180 डॉलर.

  • आपने कर दिखाया।

  • ऐसा पहली बार हुआ है, यह बहुत अच्छी बात है.

  • ठीक है, तो यह क्या कर रहा है?

  • यह मुझे बता रहा है कि इसमें तीन टर्न लगे और इससे खर्च बढ़ गया. साथ ही, यह मुझे इस सेशन को रीफ़्रेश करने की अनुमति भी देता है.

  • इसलिए, मेरे पास सबसे ऊपर एक रीफ़्रेश बटन है. इस पर क्लिक करने से, पूरा इतिहास मिट जाता है और मैं फिर से शुरुआत कर सकती हूँ.

  • इसके साथ ही, मुझे लगता है कि हम अपनी स्लाइड पर वापस जा सकते हैं.

  • हमारे पास काम करने वाले डेमो हैं. वे सभी वही करते हैं जो हम चाहते हैं. इसलिए, मुझे लगता है कि हम कोड पर वापस जा सकते हैं.

  • हाँ।

  • यह वाकई बहुत शानदार है.

  • आपने देखा होगा कि जोलांडा ने यह नहीं बताया कि यह रकम किस चीज़ के लिए है. उन्होंने सिर्फ़ यह बताया कि यह रकम डॉलर में है. उन्होंने यह नहीं बताया कि यह रकम गोल्डन गेट बे क्रूज़ के टिकट के लिए है.

  • तो मॉडल को सारा कॉन्टेक्स्ट कैसे पता चलता है?

  • इसलिए, यह कोड स्निपेट पिछले दो कोड स्निपेट से थोड़ा अलग है.

    // 1. Get or create an isolated session for the current trip
    val session = runner.getOrCreateSession(tripId)
    
    // 2. Run a turn (history is preserved automatically across turns)
    session.runAsync(prompt).collect { event ->
      when (event) {
        is AgentEvent.FunctionCall -> showToolRunning(event)
        is AgentEvent.FunctionResponse -> showToolCompleted(event)
        is AgentEvent.TextMessage -> responseMessage += event.text
      }
    }
    
    // 3. Clear history when the user taps "New conversation"
    session.delete()
  • इसलिए, AgentRunner और runSingleTurnAsync का इस्तेमाल करने के बजाय, हमें एक सेशन बनाना होगा.

  • इसलिए, हम tripId के साथ runner.getOrCreateSession को कॉल करते हैं.

  • इसलिए, हमें सेशन बनाने की ज़रूरत क्यों है?

  • ऐसा इसलिए, क्योंकि runSingleTurnAsync को रीसेट करने पर, सेव की गई जानकारी मिट जाएगी. इसलिए, इसके पास कोई संदर्भ नहीं होगा.

  • हम एक से ज़्यादा बार बातचीत नहीं कर पाएंगे.

  • इसलिए, जब आपको कई बार बातचीत करनी होती है, तो हम सेशन का इस्तेमाल करते हैं. यह एजेंट सेशन होता है.

  • इसके बाद, हम tripId को पास करते हैं.

  • हमें ऐसा करने की ज़रूरत क्यों है?

  • आपने Jetpacker ऐप्लिकेशन को पहले भी देखा है. यह कई यात्राओं को मैनेज करता है.

  • जैसे, एडीएस ट्रिप, पेरिस ट्रिप, टोक्यो ट्रिप वगैरह.

  • इसलिए, हम यात्रा के दौरान ही कॉन्टेक्स्ट को बनाए रखना चाहते हैं.

  • हम एक-दूसरे के साथ कोई गड़बड़ी नहीं करना चाहते, समझे?

  • इसलिए, runSingleTurnAsync को कॉल करने के बजाय, हमारे पास runAsync है.

  • इसलिए, यह अलग है.

  • इसलिए, इसे सेशन पर चलाया जाता है और फिर भी हमारे पास वही प्रॉम्प्ट होता है.

  • इसके बाद, हम पहले की तरह ही AgentEvent, FunctionCall, FunctionResponse, और TextMessage को एमिट कर सकते हैं.

  • इसके बाद, जब योलैंडा ने नई बातचीत वाले बटन पर क्लिक किया, तो हमें रीफ़्रेश बटन दिखा. हम session.delete कर सकते हैं.

  • हाँ।

  • ठीक है।

  • हमने यह सब नए एजेंटिक एपीआई की मदद से किया. यह वाकई कमाल का है और आपके कई कामों में बहुत मददगार साबित होगा.

  • ज़ाहिर है कि हम हमेशा चीज़ों को तेज़ी से और आसानी से करना चाहते हैं. हालांकि, हम आपके लिए ज़्यादा मुश्किल मामलों को भी आसान बनाना चाहते हैं.

  • इसलिए, हम यह पक्का करना चाहते हैं कि ज़रूरत पड़ने पर, डायरेक्ट ऐक्सेस एपीआई का इस्तेमाल करके, इन चीज़ों का ज़्यादा लो-लेवल वर्शन भी बनाया जा सके.

  • विक्टोरिया, क्या आप बता सकती हैं कि इसका क्या मतलब है और हम इस डायरेक्ट ऐक्सेस लेवल पर फिर से कब आ सकते हैं?

ऐडवांस एजेंटिक वर्कफ़्लो और टूल इंटिग्रेशन

  • हां, बिलकुल जोलांडा.

  • इस डायरेक्ट ऐक्सेस के बारे में, आपको शायद Prompt API से पहले से ही पता हो.

  • इसलिए, हमने यहाँ भी फ़ंक्शन कॉलिंग की सुविधा दी है. हमारे पास दो ऐसे इस्तेमाल के उदाहरण हैं जिनमें हम आसान एजेंटिक फ़्लो के बजाय, इस एपीआई का इस्तेमाल करना पसंद करेंगे.

  • पहला उदाहरण बहुत आसान है.

  • आपको याद होगा कि एजेंटिक फ़्लो में, हम पूरी बातचीत, क्वेरी, टूल, टूल कॉल, टूल का जवाब, सब कुछ मॉडल को वापस भेजते हैं.

  • ऐसा भी हो सकता है कि कुछ मामलों में हमें ऐसा न करना हो. जैसे, हमें सिर्फ़ प्रॉम्प्ट भेजना हो.

  • मान लें कि हमें मॉडल को एक प्रॉम्प्ट भेजना है, जिसके जवाब में वह टूल कॉल करे. इसके बाद, हमें टूल कॉल नहीं करना है, बल्कि मॉडल को एक और प्रॉम्प्ट भेजना है. इसके लिए, हम इतिहास में बदलाव कर सकते हैं. इसका मतलब है कि हमारे पास इतिहास पर पूरा कंट्रोल है.

  • यहां हम आपको एक और उदाहरण देते हैं.

    // Turn 1: Execute function directly without a second model call
    val turn1 = content(Content.Role.USER) {
      text("Change the background to a sunset")
    }
    val response1 = generativeModel.generateContent(
      generateContentRequest(turn1) { setTools(tools) }
    )
    executeFunctionCalls(response1)
    
    // Turn 2: Send only user prompts to save context tokens
    val customHistory = listOf(
      turn1,
      content(Content.Role.USER) { text("Oh no, I meant a beach") }
    )
    val response2 = generativeModel.generateContent(
      GenerateContentRequest.Builder(customHistory).setTools(tools).build()
    )
  • मान लें कि हमारे पास एक ऐसा ऐप्लिकेशन है जो आपके डिवाइस की बैकग्राउंड थीम बदल सकता है.

  • मान लें कि उपयोगकर्ता यह क्वेरी भेजता है, "बैकग्राउंड को सूर्यास्त की इमेज में बदलें."

  • इसके बाद, हमारे ऐप्लिकेशन ने इस फ़ंक्शन को लागू किया और बैकग्राउंड बदलकर सूर्यास्त का हो गया.

  • इसके बाद, उपयोगकर्ता ने अपना इरादा बदल दिया और कहा, "ओह, नहीं, मेरा मतलब बीच से था."

  • यहां यह होता है कि हमें पूरी जानकारी भेजने की ज़रूरत नहीं पड़ती कि डिवाइस ने बैकग्राउंड को पहले ही सूर्यास्त में बदल दिया है और अब वह उसे बीच में बदलना चाहता है.

  • नहीं, हमें ऐसा करने की ज़रूरत नहीं है.

  • हमें सिर्फ़ पहला और दूसरा प्रॉम्प्ट भेजना होगा, क्योंकि पहले प्रॉम्प्ट में बैकग्राउंड की जानकारी होती है.

  • इससे इसे पता चलता है कि, ओह, इसका मतलब है कि इसे बैकग्राउंड को बीच में बदलना है.

  • इसलिए, हम Prompt API का इस्तेमाल करके ऐसा कर सकते हैं.

  • हमारे पास इतिहास का पूरा कंट्रोल होता है. हम कॉन्टेक्स्ट टोकन को उपयोगकर्ता के डिवाइस पर सेव करते हैं. ऐसा इसलिए, क्योंकि उपयोगकर्ता के डिवाइस पर टोकन विंडो ज़्यादा सीमित होती है. इससे हम ज़्यादा टोकन सेव कर सकते हैं.

  • दूसरा इस्तेमाल का उदाहरण, असल में बिलकुल अलग है.

  • अगर हमारे पास इस्तेमाल के ऐसे जटिल मामले हैं जो एजेंटिक एपीआई के साथ काम नहीं करते, तो मान लें कि हमारे पास मल्टी-एजेंट सिस्टम हैं. इनमें कई सब-एजेंट, जटिल टास्क को हल करने के लिए एक-दूसरे से इंटरैक्ट करते हैं. इसके अलावा, हमारे पास एक हाइब्रिड सिस्टम है, जिसमें उपयोगकर्ता के डिवाइस पर मॉडल और क्लाउड मॉडल, दोनों मौजूद हैं. इसके अलावा, अगर हमें कस्टम मेमोरी और कॉन्टेक्स्ट कंपैक्शन चाहिए, तो क्या होगा.

  • इसलिए, यह इतिहास से जुड़ा है. जैसे, इतिहास पर पूरा कंट्रोल, जिसके बारे में मैंने पहले बताया था.

  • मान लीजिए कि हमें कॉन्टेक्स्ट विंडो की सीमा की वजह से, मॉडल को सारी जानकारी वापस नहीं भेजनी है. हमें सिर्फ़ सबसे अहम हिस्से या शायद सबसे नए हिस्से की खास जानकारी देनी है, ताकि इस पर हमारा पूरा कंट्रोल हो. इसके लिए, हम डायरेक्ट ऐक्सेस एपीआई का इस्तेमाल करते हैं.

  • इस तरह के इस्तेमाल के उदाहरणों के लिए, एजेंट डेवलपमेंट किट (एडीके) या Crew जैसे फ़्रेमवर्क का इस्तेमाल किया जा सकता है. इसके अलावा, खुद का कस्टम ऑर्केस्ट्रेशन फ़्रेमवर्क भी बनाया जा सकता है.

  • ठीक है।

  • एजेंटिक एपीआई के बारे में हमारे पास इतनी ही जानकारी थी.

  • हालांकि, एक और चीज़ है जिसके बारे में हम बात करना चाहते हैं.

  • हम इन-ऐप्लिकेशन एजेंट के बारे में बात कर रहे हैं. इसलिए, अपने ऐप्लिकेशन में एजेंट वाला अनुभव बनाया जा रहा है. हालांकि, हम इस बारे में भी बात कर रहे थे कि हम AppFunctions का इस्तेमाल कैसे कर रहे हैं. अगर आपको सिर्फ़ अपने ऐप्लिकेशन में काम करना है, तो AppFunctions का इस्तेमाल क्यों करना चाहिए?

  • हमें पता है कि आप जैसे डेवलपर को एक ही काम दो बार करना पसंद नहीं है, है न?

  • हमें कोड को कॉपी-पेस्ट करना पसंद नहीं है. साथ ही, हमें किसी कारोबारी नियम को डुप्लीकेट करना पसंद नहीं है.

  • AppFunctions की मदद से, हम अपने टूल को सिस्टम एजेंट के लिए भी उपलब्ध करा सकते हैं. इसके लिए, हमें सिर्फ़ एक छोटा सा बदलाव करना होगा. इससे, हमारे इन-ऐप्लिकेशन एजेंट के अलावा, सिस्टम एजेंट भी इन टूल का इस्तेमाल कर पाएंगे.

  • कोड के साथ यह कैसा दिखता है?

  • हाँ।

  • AppFunctions की मदद से, हमें सिर्फ़ एक बार कोड लिखना होता है. इसके बाद, हम उन्हें अपनी ज़रूरत के हिसाब से अलग-अलग लेयर पर एक्सपोज़ कर सकते हैं.

  • आपको याद होगा कि पहले हमारे पास ACCESS_LEVEL_SELF था. यह सिर्फ़ उन फ़ंक्शन को दिखाता था जिन्हें हमने अपने इन-ऐप्लिकेशन एजेंट के लिए लिखा था. हालांकि, हम उस ऐक्सेस लेवल को ACCESS_LEVEL_ANDROID_TRUSTED में भी बदल सकते हैं.

  • इससे Android OS में भरोसेमंद एजेंट को फ़ंक्शन दिखेंगे.

  • इसलिए, फ़ंक्शन, कमांड या डेटाबेस लॉजिक को फिर से लिखने की ज़रूरत नहीं है.

  • AppFunctions, आपके ऐप्लिकेशन के लिए पहले से ही इंटरनल और एक्सटर्नल, दोनों तरह से काम करता है.

  • हमें उसका भी डेमो चाहिए, है न?

  • ठीक है, चलिए फ़ोन पर वापस चलते हैं. हमारे आखिरी डेमो के लिए, Jetpacker ऐप्लिकेशन से बाहर निकलते हैं.

  • इसलिए, हम Gemini पर जाकर,

  • इसलिए, Gemini में @Jetpacker को कॉल किया जा सकता है.

  • ध्यान देने वाली बात यह है कि फ़िलहाल यह सुविधा सीमित बीटा वर्शन में उपलब्ध है. इसलिए, यह आज ही सभी के लिए उपलब्ध नहीं होगी. हालांकि, इसे टेस्ट किया जा सकता है और आज़माया जा सकता है.

  • चलिए, Jetpacker के साथ देखते हैं.

  • हमें क्या करना चाहिए?

  • ओह, मैंने आज सुबह कॉफ़ी पी थी, है न?

  • क्या ADS ट्रिप के खर्चों में सात डॉलर की कॉफ़ी जोड़ी जा सकती है?

  • आपने कर दिखाया।

  • यहां देखा जा सकता है कि यह Jetpacker ऐप्लिकेशन से कनेक्ट हो जाता है.

  • बस, हो गया.

  • इसने मेरे लिए खर्च जोड़ दिया.

  • हमने Jetpacker में मौजूद सभी सुविधाओं को इस्तेमाल करने का तरीका देख लिया है.

  • Jetpacker की सबसे अच्छी बात यह है कि इसमें फ़्लाइट मोड भी चालू किया जा सकता है.

  • हमने आज इसे नहीं दिखाया है, लेकिन हम फ़्लाइट मोड चालू कर सकते हैं. साथ ही, डेमो में आपने जो कुछ भी देखा है, मैं उसे दिखाना चाहता हूं, क्योंकि मैं चाहता हूं कि आप सभी को मुझ पर भरोसा हो. इसलिए, चलिए वाई-फ़ाई बंद कर देते हैं.

  • क्या किसी के पास डेमो के लिए कोई अच्छा उदाहरण है? जैसे, कोई खर्च जिसे मैं जोड़ सकूं?

  • आइए देखें.

  • शायद हम कर सकते हैं. क्या है?

  • अरे, किराये पर कार लेना अच्छा रहेगा, है न?

  • ठीक है।

  • चलिए, "कार किराये पर लेने के लिए 300 डॉलर का खर्च जोड़ो" बोलकर देखते हैं.

  • यह देखिए, इसने इसे पहचान लिया.

  • ठीक है।

  • शानदार.

  • ठीक है, चलिए स्लाइड पर वापस चलते हैं.

  • हम AppFunctions के बारे में बात कर रहे थे.

  • मुझे पता है कि हमने इस बारे में बहुत कम बात की है.

  • अगर आपको इस बारे में ज़्यादा जानना है, तो डैन और सारा की एक और बातचीत है. इसमें उन्होंने इस बारे में ज़्यादा जानकारी दी है कि इसे कैसे चालू किया जा सकता है, इसकी जांच कैसे की जा सकती है, हमारे पास कौनसे टूल हैं वगैरह.

  • आज हमने कई अलग-अलग चीज़ों के बारे में बात की.

  • हमने सिंगल-स्टेप, मल्टी-स्टेप, और मल्टी-टर्न के बारे में जाना. आखिर में, हमने यह भी देखा कि सिस्टम AppFunction का इस्तेमाल कैसे किया जा सकता है.

  • अब, मुझे लगता है कि जाने से पहले हमारे पास कुछ सुझाव हैं.

सबसे सही तरीके और निष्कर्ष

  • हाँ।

  • इसलिए, जब हम एजेंटिक अनुभव तैयार करना शुरू करें, तो इन तीन बातों को ध्यान में रखें.

  • पहला तरीका है, टूल सेट पर फ़ोकस रखना.

  • इसलिए, याद रखें कि उपयोगकर्ता के डिवाइस पर मौजूद मॉडल की क्षमताएं सीमित होती हैं, क्योंकि उनका स्केल छोटा होता है.

  • इसलिए, दर्जनों टूल रजिस्टर करने के बजाय, कम संख्या में टूल रजिस्टर करना बेहतर होता है.

  • इसके बाद, जैसा कि मैंने पहले कहा था, KDoc के ब्यौरे साफ़ तौर पर लिखें. ऐसा इसलिए, क्योंकि मॉडल इनका इस्तेमाल करके यह तय करता है कि उसे क्या नतीजे देने हैं.

  • इसके बाद, हमें ज़्यादा से ज़्यादा टर्न गार्डरेल भी सेट करनी चाहिए.

  • इससे मॉडल को भ्रमित होने पर, बार-बार एक ही जवाब देने से भी रोका जा सकता है.

  • इसका मतलब है कि हम उपयोगकर्ता की बैटरी खत्म कर सकते हैं.

  • इसलिए, अगर हमारे पास यह सुविधा है, तो हम उपयोगकर्ता की बैटरी बचा सकते हैं.

  • आखिर में, हमें यह देखना होगा कि डिवाइस पर फ़ंक्शन कॉलिंग की सुविधा पहले से उपलब्ध है या नहीं. अगर उपलब्ध है, तो हमें ग्रेसफ़ुल फ़ॉलबैक लागू करना होगा.

  • उदाहरण के लिए, अगर यह सुविधा काम नहीं करती है, तो क्लाउड मॉडल या स्टैंडर्ड यूज़र इंटरफ़ेस (यूआई) का इस्तेमाल किया जा सकता है.

  • ठीक है, मुझे लगता है कि हम अपने संसाधनों की मदद से इस समस्या को हल कर सकते हैं.

  • इसलिए, मैं आपको एक बार फिर से क्यूआर कोड दिखाऊंगा.

  • कृपया इसे देखें.

  • मुझे लगता है कि हमें यह ध्यान रखना चाहिए कि हमारे पास इसके लिए Android Skills भी है.

  • इसलिए, आपको हर छोटी-छोटी जानकारी को गहराई से समझने की ज़रूरत नहीं है.

  • इस नए एजेंटिक एपीआई के लिए, हमारे पास पूरी जानकारी वाला दस्तावेज़ और Android स्किल है.

  • इसलिए, इस पर एक नज़र डालें.

  • AICore डेवलपर के लिए झलक को डाउनलोड करें, ताकि आप इन सभी चीज़ों को आज़मा सकें. कोडिंग का आनंद लें.

कोड

कोड स्निपेट

"Jetpacker agent demo and फ़ंक्शन कॉलिंग" में 09:53 पर Kotlin स्निपेट
/**
 * Adds an expense to a trip.
 *
 * @param tripId Identifier of the trip (e.g., "paris-2026").
 * @param amount Expense amount in dollars.
 * @param description Short description of what the expense was for.
 */
@AppFunctionDeclaration(isDescribedByKDoc = true)
@AppFunctionAccessLevel(
  level = ACCESS_LEVEL_SELF,
  isCompatEnforcementEnabled = true,
)
suspend fun addExpense(tripId: String, amount: Double, description: String) {
  // Save expense to local DB / repository...
}
"एआई एजेंट रनर को बनाना और लागू करना" में 11:41 पर Kotlin स्निपेट
val model = Generation.getClient()
val features = model.getAvailableFeatures()
if(FUNCTION_CALLING in features) {
  // Device is supported!
} else {
  // Graceful fallback
}
"एआई एजेंट रनर को बनाना और लागू करना" में 12:07 पर Kotlin स्निपेट
if(FUNCTION_CALLING in features) {
  // 1. Build the agent configuration
  val agent = Agent.builder()
    .setName("Assistant")
    .setInstructions("You are a helpful on-device assistant.")
    .enableAppFunctions()
    .build()

  // 2. Initialize the runner
  val runner = AgentRunner(agent = agent)

  // 3. Create your prompt
  val prompt = content { text(userPrompt)}

  // 4. Start the agent
  runner.runSingleTurnAsync(prompt).textTokens().collect { responseMessage += it }

}
"मल्टी-स्टेप एजेंट आर्किटेक्चर और एक्ज़ीक्यूशन" में 17:23 पर Kotlin स्निपेट
/**
* Retrieves the itinerary events (ID, title, location) for a trip.
* Note: Call getEventDetails(eventId) to retrieve ticket prices or notes.
*/
@AppFunctionDeclaration(isDescribedByKDoc = true)
@AppFunctionAccessLevel(level = ACCESS_LEVEL_SELF, isCompatEnforcementEnabled = true)
suspend fun getItinerary(tripId: String): List<EventSummary> { ... }

/**
* Retrieves details for a specific event, including admission ticket prices.
*/
@AppFunctionDeclaration(isDescribedByKDoc = true)
@AppFunctionAccessLevel(level = ACCESS_LEVEL_SELF, isCompatEnforcementEnabled = true)
suspend fun getEventDetails(eventId: String): EventDetails { ... }
"मल्टी-स्टेप एजेंट आर्किटेक्चर और एक्ज़ीक्यूशन" में 18:23 पर Kotlin स्निपेट
val agent = Agent.builder()
 .setName("Assistant")
 .setInstructions("You are a helpful travel assistant. Active tripId: $tripId")
 .enableAppFunctions()
 .setMaxTurns(5) // Guardrail against infinite tool loops
 .build()
val runner = AgentRunner(agent = agent)
// Automatically loops through all 3 tool calls in a single user turn!
runner.runSingleTurnAsync(prompt).collect { event ->
 when (event) {
   is AgentEvent.FunctionCall -> showToolRunning(event.name)
   is AgentEvent.FunctionResponse -> showToolCompleted(event.name)
   is AgentEvent.TextMessage -> responseMessage += event.text
 }
}
"मल्टी-टर्न बातचीत वाले सेशन मैनेज करना" में 22:13 पर Kotlin स्निपेट
// 1. Get or create an isolated session for the current trip
val session = runner.getOrCreateSession(tripId)

// 2. Run a turn (history is preserved automatically across turns)
session.runAsync(prompt).collect { event ->
  when (event) {
    is AgentEvent.FunctionCall -> showToolRunning(event)
    is AgentEvent.FunctionResponse -> showToolCompleted(event)
    is AgentEvent.TextMessage -> responseMessage += event.text
  }
}

// 3. Clear history when the user taps "New conversation"
session.delete()
"Advanced agentic workflows and tool integration" में 25:02 पर Kotlin स्निपेट
// Turn 1: Execute function directly without a second model call
val turn1 = content(Content.Role.USER) {
  text("Change the background to a sunset")
}
val response1 = generativeModel.generateContent(
  generateContentRequest(turn1) { setTools(tools) }
)
executeFunctionCalls(response1)

// Turn 2: Send only user prompts to save context tokens
val customHistory = listOf(
  turn1,
  content(Content.Role.USER) { text("Oh no, I meant a beach") }
)
val response2 = generativeModel.generateContent(
  GenerateContentRequest.Builder(customHistory).setTools(tools).build()
)