ইন্টেলিজেন্ট অ্যাপ

ML Kit GenAI-এর মাধ্যমে আপনার অ্যাপে এজেন্টসুলভ দক্ষতা আনলক করুন

স্পিকার

  • Jolanda Verhoef

    ডেভেলপার রিলেশনস ইঞ্জিনিয়ার

  • Victoria Lestari

    সফ্টওয়্যার ইঞ্জিনিয়ার

সম্পর্কে

টক সম্পর্কে

অটোনোমাস অন-ডিভাইস এজেন্ট তৈরি করে আপনার Android AI ফিচারকে পরবর্তী লেভেলে নিয়ে যান। এই সেশনে, আমরা ML Kit-এর নতুন এজেন্টিক API সম্পর্কে বিস্তারিত আলোচনা করব, যা আপনি আগে থেকেই জানেন এমন ডাইরেক্ট মডেল অ্যাক্সেস API-এর উপরে সরাসরি তৈরি করা হয়েছে।

ওপেন-সোর্স Jetpacker অ্যাপ ব্যবহার করে, আপনি শিখবেন কীভাবে লোকাল ডেটা জুড়ে মাল্টি-স্টেপ অ্যাকশন চেইন করতে হয়, আইসোলেটেড কন্টেক্সট সহ স্টেটফুল মাল্টি-টার্ন সেশন ম্যানেজ করতে হয় এবং একটি সিঙ্গেল কোডবেস সহ অ্যাপ-মধ্যস্থ অ্যাসিস্ট্যান্ট এবং Android সিস্টেম-লেভেল সারফেস উভয়কেই শক্তিশালী করতে Android MCP ওয়্যার আপ করতে হয়।

সারাংশ

  • Gemini Nano 4-এ নেটিভভাবে ফাংশন কলিং কাজ করে, যার ফলে অন-ডিভাইস মডেল ন্যাচারাল ল্যাঙ্গুয়েজকে অ্যাকশনে অনুবাদ করতে এবং লোকাল API চালাতে পারে।
  • Jetpack AppFunctions লাইব্রেরি ন্যাচারাল ল্যাঙ্গুয়েজ KDoc বিবরণের মাধ্যমে টুল সংজ্ঞায়িত করে। অ্যাক্সেস লেভেল পরিবর্তন করলে, Gemini-র মতো সিস্টেম এজেন্টের কাছে এইসব ফাংশন প্রকাশ হয়ে যেতে পারে।
  • ML Kit GenAI-তে নতুন এজেন্টিক ফ্লো লাইব্রেরি (আলফা) এক্সিকিউশন লুপ এবং টুল কল ম্যানেজ করার মাধ্যমে এজেন্ট তৈরি করা সহজ করে তোলে।
  • AgentRunner টুল এক্সিকিউশন কোঅর্ডিনেট করে এবং প্রসঙ্গ না হারিয়ে মাল্টি-টার্ন কথোপকথনের জন্য সেশন পদ্ধতি প্রদান করে।
  • সহজ ইতিহাস কন্ট্রোল বা মাল্টি-এজেন্ট ও হাইব্রিড সিস্টেমের মতো জটিল সেট-আপের জন্য Prompt API-এর মাধ্যমে সরাসরি অ্যাক্সেস উপলভ্য থাকে।

দক্ষতা

রিসোর্স

Gemini Notebook

বিষয়

  • ml-kit
  • on-device-ai
  • gemini-nano
  • ai-agents
  • ফাংশন-কলিং
  • অ্যাপ-ফাংশন
  • aicore

ট্রান্সস্ক্রিপ্ট করা

অন-ডিভাইস AI ও Gemini Nano-এর সাথে পরিচিতি

  • আমার নাম জোলান্ডা ভারহোয়েফ।

  • আমি Android-এ ডেভেলপার রিলেশনস ইঞ্জিনিয়ার এবং আজ আমার সাথে যোগ দিয়েছেন ভিক্টোরিয়া লেস্তারি, যিনি AICore ইঞ্জিনিয়ারিং টিমের অংশ।

  • হ্যালো।

  • আজ সকালে আমাদের সাথে যোগ দেওয়ার জন্য ধন্যবাদ।

  • তাই, আমাদের টিম বছরের পর বছর ধরে ঘনিষ্ঠভাবে সহযোগিতা করে চলেছে যাতে ক্লাউড থেকে সর্বাধুনিক AI মডেলগুলি বের করে সরাসরি Android ডিভাইসে চালানো যায়।

  • এইসব প্রচেষ্টা ML Kit GenAI স্যুটের অধীনে গ্রুপ করা হয়েছে।

  • একদিকে, এই ML Kit GenAI স্যুটে, আমাদের কাছে টার্নকি সমাধানের জন্য হাই-লেভেল API আছে, যেমন টেক্সট সামারাইজেশন, ইমেজ ডেসক্রিপশন এবং স্পিচ রেকগনিশন।

  • অন্যদিকে, আমরা অন-ডিভাইস মডেল, Gemini Nano-তে সরাসরি অ্যাক্সেসও খুলে দিয়েছি।

  • আর আজ, আমরা আসলে একটি অতিরিক্ত পদক্ষেপ নিচ্ছি।

  • তাই, এই সরাসরি অ্যাক্সেসের মাধ্যমে, আমরা আসলে আপনাকে ইন-অ্যাপ এজেন্ট তৈরি করার অনুমতি দিতে চলেছি, এমন এজেন্ট যা একাধিক টার্ন জুড়ে যুক্তি দিতে পারে, কথোপকথনের প্রসঙ্গ সেভ করতে পারে এবং আপনার অ্যাপে অ্যাকশন নিতে পারে।

  • তাহলে, আমরা আসলে কী বলতে চাইছি, ভিক্টোরিয়া?

  • হ্যাঁ।

  • এখনও পর্যন্ত, অন-ডিভাইস ব্যবহারের ক্ষেত্রে, আমরা ছোট, সহজ, বিচ্ছিন্ন টাস্কের কথা ভাবছি, যেমন সম্ভাব্য স্ক্যাম শনাক্ত করা বা ফোন কলের সারসংক্ষেপ করা।

  • এবং আমরা যখন আরও জটিল কিছু তৈরি করতে চাই, যেমন আপনার ফটো ক্যাটালগ সম্পর্কে প্রশ্ন জিজ্ঞাসা করা বা Google Maps-কে জিজ্ঞাসা করা, তখন আমরা স্বাভাবিকভাবেই বড় ক্লাউড মডেলের সাহায্য নিই।

  • তাই, ক্লাউড মডেলগুলি প্রচুর প্রসেসিং এবং রিয়েল-টাইম ডেটার সুবিধা প্রদান করে, তবে অন-ডিভাইস AI কম লেটেন্সি এবং রিয়েল-টাইম ও লোকাল ডেটা প্রসেসিংয়ের জন্য নতুন সম্ভাবনা উন্মুক্ত করে।

  • তাই, আপনার ডিভাইসে আপনি কী কী করতে পারবেন তা Gemini Nano ইতিমধ্যেই বাড়িয়ে দিয়েছে।

  • এরকমই একটি উদাহরণ হল Pixel Screenshots, যা আপনাকে লোকাল স্ক্রিনশট সার্চ করতে এবং সেগুলি সম্পর্কে প্রশ্ন করতে দেয়।

  • তাই, আমরা যখন অন-ডিভাইস এজেন্ট রান করি, তার অর্থ হল আমাদের মডেলের দক্ষতায় একটি বড়সড় পরিবর্তন প্রয়োজন এবং সেই কারণেই আমরা Gemini Nano 4 তৈরি করছি যা বিভিন্ন ধাপ জুড়ে যুক্তি দিতে এবং বাস্তব পদক্ষেপ নিতে সক্ষম।

  • তবে, এই নতুন ক্ষমতা তখনই কাজে লাগে যখন ডেভেলপারদের কাছে টার্গেট করার জন্য আসল ডিভাইস থাকে।

  • সুতরাং, সুখবর হল, Gemini Nano 4 ইতিমধ্যেই বাছাই করা ফ্ল্যাগশিপ ডিভাইসে উপলভ্য এবং আপনি AICore ডেভেলপার প্রিভিউ ব্যবহার করে আরও অনেক ডিভাইসে এটি পরীক্ষা করতে পারেন।

  • এছাড়াও, আগামী বছরের শুরুতে ১০০ মিলিয়ন ডিভাইসে পৌঁছানোর লক্ষ্য নিয়ে আমরা এগিয়ে চলেছি।

  • তাহলে, এর অর্থ কী?

  • সুতরাং, এর অর্থ হল আপনি আজই এই অভিজ্ঞতাগুলি তৈরি এবং পরীক্ষা করা শুরু করতে পারেন, এটি জেনে যে আপনার-- আপনি আজ যা তৈরি করছেন তা বিপুল সংখ্যক দর্শকের কাছে পৌঁছে যাবে।

  • আমরা Gemini Nano 4 এবং এর সম্ভাব্য নাগাল নিয়ে আলোচনা করেছি, তাই এখন এজেন্টসুলভ দক্ষতার আসল অর্থ কী তা নিয়ে আলোচনা করা যাক।

  • তাই, প্রতিনিধি AI জটিল টাস্কের জন্য প্ল্যান করতে, এইসব টাস্ককে একাধিক ধাপে ভাগ করতে এবং তারপর আপনার অ্যাপ জুড়ে এইসব ধাপ এক্সিকিউট করতে পারে।

  • সুতরাং, ধরা যাক ডিভাইসে আমাদের Gemini Nano মডেল, এটি আপনার লোকাল ডেটাবেসে কোয়েরি করতে পারে, ব্যাক এন্ড থেকে ডেটা ফিরিয়ে আনতে পারে, আপনার জটিল প্রশ্নের কারণ ও উত্তর দিতে পারে এবং আপনার ডিভাইসে নেটিভ অ্যাপের ওয়ার্কফ্লো ট্রিগার করতে পারে।

  • কিন্তু AI কীভাবে কোনও প্ল্যান তৈরি করা থেকে শুরু করে আসল অ্যাকশন নেওয়ার দিকে এগিয়ে যায়?

  • আর এটি হল আজকের বিষয়, এটি হল ফাংশন কলিং।

  • এটি এজেন্টসুলভ দক্ষতার মূল ইঞ্জিন।

  • এটি ন্যাচারাল ল্যাঙ্গুয়েজকে সিস্টেম এক্সিকিউশনে অনুবাদ করে এবং জটিল টাস্ক সমাধান করার জন্য প্রয়োজনীয় লোকাল API বেছে নিয়ে ও চালিয়ে, মডেলকে প্যাসিভ রিজনিং থেকে অ্যাক্টিভ এক্সিকিউশনে নিয়ে যায়।

  • এছাড়াও, আমরা আনন্দের সাথে জানাচ্ছি যে Gemini Nano 4-এ ফাংশন কলিং নেটিভভাবে কাজ করে।

  • এটি বর্তমানে AICore ডেভেলপার প্রিভিউতে উপলভ্য এবং শীঘ্রই সব Nano 4-সমর্থিত ডিভাইসে প্রকাশ করা হবে।

  • তাই, মডেলে এই ধরনের ক্ষমতা থাকাটা দারুণ ব্যাপার, কিন্তু মডেলে কোনও ক্ষমতা থাকলে, ডেভেলপার হিসেবে আপনি এখনও API পান না।

  • তাই, আমরা ML Kit GenAI স্যুটে সঠিক API যোগ করার জন্য কাজ করছি যাতে এজেন্ট তৈরি করা সত্যিই সহজ হয়।

  • তাই, আমরা যা দিয়ে শুরু করেছি-- তা হল ডাইরেক্ট অ্যাক্সেস API যা আমাদের কাছে আগে থেকেই ছিল এবং আমরা এতে ফাংশনের ধরন এবং কথোপকথনের ইতিহাসের ধরন যোগ করেছি।

  • ML Kit-এর Prompt API-তে এই দুটি নতুন সংযোজনের মাধ্যমে, আপনি এখন আপনার অ্যাপে এই লো-লেভেল এজেন্টসুলভ দক্ষতা তৈরি করতে পারবেন।

  • তবে, সেই সময় আপনাকে অনেক কিছু করতে হবে।

  • তাই, আপনাকে ম্যানুয়ালি ফাংশনগুলি এক্সিকিউট করতে হবে, কল ইতিহাস সেভ করতে হবে এবং একাধিক কলের জন্য লুপ তৈরি করতে হবে।

  • তাই, আপনাকে একাধিক কল করতে হলে, আপনাকে, যেমন, নিজের জন্য কোনও ধরনের লুপিং সিস্টেম তৈরি করতে হবে এবং সিস্টেমের জন্য আপনাকে নিজের গার্ড রেল তৈরি করতে হবে।

  • এখন, এটি সম্ভব, তবে অবশ্যই, আমরা এটিকে দ্রুত এবং সহজ করতে চাই।

  • তাই, এই প্রম্পট API লাইব্রেরির উপরে, আমরা একটি নতুন এজেন্টিক ফ্লো লাইব্রেরিও যোগ করেছি।

  • আপনি এটি com.mlkit.genai:agent-api-এর মাধ্যমে খুঁজে পেতে পারেন এবং এটি বর্তমানে আলফা ভার্সনে উপলভ্য।

  • এখন, এই নতুন API-এর মাধ্যমে, আমরা আপনার জন্য অনেক কঠিন কাজ করি।

  • তাই, আপনাকে অনেক ম্যানুয়াল ধাপ অনুসরণ করার পরিবর্তে, মাত্র কয়েক লাইন কোড লিখেই আপনি একটি এজেন্ট তৈরি করতে পারবেন।

  • আর আজ আমরা ঠিক সেটাই করতে চলেছি।

Jetpacker এজেন্ট ডেমো ও ফাংশন কলিং

  • তাই, আমাদের স্যাম্পেল অ্যাপ Jetpacker-এর সাথে এই APIগুলি আসলে কীভাবে কাজ করে তা আমরা দেখতে যাচ্ছি।

  • এখন, আপনি ইতিমধ্যেই Google I/O-তে এবং এই কনফারেন্স চলাকালীন Jetpacker দেখেছেন।

  • তবে আপনি যা করতে পারেন তা হল, এই QR কোড স্ক্যান করুন এবং আপনি আগ্রহী হলে, কোডটি দেখতে পারেন, আপনার এজেন্টকে কোডটি দেখাতে পারেন, কোডের সাথে ইন্টার‍্যাক্ট করতে পারেন এবং আমরা কীভাবে এই সমস্ত ফিচার আসলে প্রয়োগ করেছি সেই সম্পর্কে আরও জানতে পারেন।

  • এখন, Jetpacker হল একটি আধুনিক ভ্রমণ সহকারী যা আমরা মূলত অনেক বিভিন্ন বুদ্ধিমান ফিচার দেখানোর জন্য তৈরি করেছি।

  • তাই, এটি ইতিমধ্যেই সব ধরনের প্রম্পটিং API-এর জন্য অন-ডিভাইস মডেল এবং ক্লাউড মডেল ব্যবহার করছে, তবে আমরা এখন যা তৈরি করতে যাচ্ছি তা হল আমরা এতে একটি এজেন্ট যোগ করতে যাচ্ছি।

  • এবং এই এজেন্টের জন্য, Jetpacker-এর জন্য, আমরা যা করছি তা হল আমরা নতুন ML Kit GenAI এজেন্ট API ব্যবহার করতে যাচ্ছি যার কথা আমরা এইমাত্র বলছিলাম এবং এটি Gemini Nano মডেলের সাথে কথা বলার জন্য Android ডিভাইসে চলা অন্তর্নিহিত AI Core সিস্টেম ব্যবহার করতে চলেছে।

  • এখন, আমি যা চাই তা বলতে পারি এবং আমরা অনেক কথা বলব, তবে অবশ্যই, আমরা এটি দেখাতে চাই।

  • তাই, ফোনে সুইচ করে, ডেমো হিসেবে এটি দেখানো যাক।

  • আমার কাছে Pixel 11 Pro আছে।

  • এবং আমি মনে করি আমরা Pro-তে সুইচ করতে পারি এবং আপনি এটি দেখতে পারবেন।

  • এই তো, এই যে।

  • আর আপনি দেখতেই পাচ্ছেন, এখানে Jetpacker অ্যাপ চলছে।

  • এতে আমাদের আসন্ন ট্রিপের তথ্য রয়েছে এবং আমি আমাদের বর্তমান ট্রিপ দেখতে পাচ্ছি। আমাদের বর্তমান ট্রিপে আপনি দেখতে পাচ্ছেন যে আজ ২৯ অক্টোবর, তাই আমাদের অন-ডিভাইস AI ওয়ার্কশপ, ডেমো শোকেস রয়েছে এবং আগামীকাল আমার গোল্ডেন গেট বে ক্রুজ এবং মিউজিয়াম ভিজিট রয়েছে।

  • এগুলি সবই খুব ভালো।

  • এখন, আমরা আমাদের খরচের স্ক্রিনে যেতে পারি যেখানে আমরা এই ট্রিপের বাজেটের ট্র্যাক রাখছি।

  • আর আপনি নিচে ডানদিকে দেখতে পাচ্ছেন, একটি নতুন ছোট এজেন্টিক স্পার্কল আছে, আর এটি হল অন-ডিভাইস এজেন্ট যা আমরা তৈরি করেছি।

  • তাহলে, একটি সহজ কমান্ড দিয়ে শুরু করা যাক।

  • আমার মনে হয়, আমরা এটিকে নির্দিষ্ট খরচ যোগ করতে বলতে পারি।

  • সুতরাং, ধরা যাক: মাউন্টেন ভিউতে ট্যাক্সির জন্য একটি খরচ যোগ করুন এবং এটি ছিল $৪৫।

  • এই তো হয়ে গেছে।

  • এটি খরচ প্রস্তুত করছে এবং এটি খরচ যোগ করেছে।

  • অসাধারণ।

  • ঠিক আছে, ডেমো ১ কাজ করেছে।

  • চলো, স্লাইডে ফিরে গিয়ে দেখি যে সেটি আসলে কীভাবে কাজ করেছে।

  • ঠিক আছে, প্রথমে আপনি যেমন লক্ষ্য করেছেন, আমি নিজের ভয়েস ব্যবহার করছিলাম এবং সেই ভয়েস আসলে Gemini Nano মডেলও ব্যবহার করছে। এটি স্পিচ রিকগনিশন API ব্যবহার করে আমি যা বলছিলাম তা টেক্সটে ট্রান্সক্রাইব করছিল।

  • তাহলে সেই টেক্সটটি দুর্দান্ত এবং আমরা সেটি Gemini Nano মডেলে পাঠাতে পারি।

  • কিন্তু এটি কী করবে?

  • যেমন, আমি এটিকে খরচে কিছু যোগ করতে বলছি, আমি এটিকে $৪৫ সম্পর্কে কিছু বলছি, কিন্তু এটি সত্যিই জানে না কীভাবে কাজ করতে হবে, তাই না?

  • এই মুহূর্তে, এটি আমাকে শুধু বলবে, "আপনি কী বলছেন আমি জানি না।"

  • তাই, আমরা যা করতে চাই তা হল সেই প্রম্পটে একটু যোগ করতে চাই।

  • আমরা প্রম্পটে টুল যোগ করতে পারি, তাই আমরা সব ধরনের টুল যোগ করতে পারি, এই ক্ষেত্রে, আমি ট্রিপের বাজেট, ভ্রমণসূচী ইত্যাদি যোগ করছি। এবং আপনি যদি আমাদের API-এর মাধ্যমে Nano মডেলে এটি পাস করেন, তাহলে এটি অটোমেটিক বুঝতে পারবে যে টেক্সট ফিরিয়ে দেওয়ার পরিবর্তে, এটি এখন একটি ফাংশন কল ফিরিয়ে দিতে সক্ষম।

  • তাই, আমাদের ক্ষেত্রে, এটি আসলে বলবে, "ঠিক আছে, টেক্সটের মাধ্যমে উত্তর দেওয়ার পরিবর্তে, আমি মাউন্টেন ভিউতে ট্যাক্সির জন্য $৪৫ খরচ যোগ করতে যাচ্ছি।"

  • খুব ভালো, কিন্তু ভিক্টোরিয়া, এটি আসলে কীভাবে কাজ করে?

  • আমরা কীভাবে এটি তৈরি করব?

  • হ্যাঁ।

  • তাহলে, আমাদের কোডে টুল কীভাবে সংজ্ঞায়িত করব?

  • তাই, আমি এই বিষয়েই ব্যাখ্যা করতে চলেছি।

  • তাই, Android MCP-এর সাথে, আমরা এইসব টুল নির্দিষ্ট ও প্রকাশ করতে 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 আছে, যার অর্থ হল আমরা যে ফাংশনগুলি লিখছি তা শুধুমাত্র আপনার অ্যাপ, আপনার অ্যাপের এজেন্টদের কাছে দৃশ্যমান।

  • তারপরে, আমরা সাসপেন্ড ফাংশনটি সংজ্ঞায়িত এবং বাস্তবায়ন করতে পারি এবং আমরা যতগুলি সম্ভব অ্যাপ ফাংশন লিখতে পারি এবং সেগুলিকে একটি একক পরিষেবা ক্লাসে গ্রুপ করতে পারি।

AI এজেন্ট রানার তৈরি ও প্রয়োগ করা

  • ঠিক আছে।

  • তাই, এর মাধ্যমে আমাদের কাছে টুল আছে এবং আমরা সেই টুলগুলি লিখতে পারি, এটি দারুণ।

  • তবে অবশ্যই, একটি এজেন্ট তৈরি করতে, আমাদের শুধু সেই AppFunctions-এর চেয়ে একটু বেশি প্রয়োজন।

  • সুতরাং, আমাদের কাছে আরও তিন ধরনের অংশ রয়েছে যা আপনি যখন কোনও এজেন্ট লিখছেন তখন জানা গুরুত্বপূর্ণ।

  • প্রথমত, আমরা আসলে এজেন্টকে সংজ্ঞায়িত করছি।

  • তাই আমরা সিস্টেমের নির্দেশাবলী, গার্ড রেল, কনফিগারেশন এবং কীভাবে এটির সাথে কাজ করতে হবে তা নির্ধারণ করছি।

  • আর তারপর আমাদের কাছে একটি AgentRunner আছে।

  • AgentRunner হল এমন একটি জিনিস যা আমাদের জন্য এজেন্টকে এক্সিকিউট করে।

  • সুতরাং, এটি সেই লুপিং মেকানিজমের যত্ন নিচ্ছে যা আমরা কথা বলছিলাম।

  • আর শেষে, আমাদের কাছে AgentEvents আছে এবং AgentEvents হল সিস্টেমের জন্য, API-এর জন্য একটি উপায়, যা আমাদের জানতে দেয় যে এটি আসলে কী করছে।

  • তাই, এটি আমাদের জানাবে যে কখন এটি টেক্সট ফেরত দিচ্ছে, কখন এটি টুল কল করছে ইত্যাদি, যাতে আমরা আসলে আমাদের UI-তে তা দেখাতে পারি।

  • ঠিক আছে।

  • তাহলে, আসুন আসল কোডটি দেখি।

  • ঠিক আছে।

  • কোড লেখার আগে, আপনার ডিভাইসে ফাংশন কলিং উপলভ্য কিনা তা চেক করতে হবে, কারণ ফাংশন কলিং শুধুমাত্র 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 বলি এবং এটি এজেন্টকে শুরু করবে, ইনফারেন্স রান করবে এবং সম্পূর্ণ AI ইনফারেন্স করবে।

  • আর আমরা যদি শুধু মডেলের ফাইনাল টেক্সট উত্তর আমাদের UI-তে স্ট্রিম করতে চাই, তাহলে আমরা শুধু textTokens কল করি এবং এটি উত্তর আসার সাথে সাথে তা সংগ্রহ করবে।

  • তাহলে, এইটুকুই।

  • এটি সত্যিই মাত্র কয়েক লাইনের কোড, তাই আমরা যখন এটি বলেছিলাম তখন আমরা মজা করছিলাম না।

  • সুতরাং, কোডের এই কয়েকটি লাইনের মাধ্যমে, আপনার কাছে একটি এজেন্ট আছে।

  • সেই এজেন্ট আপনার পছন্দমতো কাজ করবে।

  • এটি আমাদের টেক্সট উত্তর দেবে।

  • তবে অবশ্যই, আমরা যে প্রথম ডেমোটি দেখাচ্ছিলাম, সেখানে আমরা খুব সহজ একটি কমান্ড দিচ্ছিলাম, তাই না?

  • যেমন আমি একটা কমান্ড দিলাম আর সেটা একটা অ্যাকশন নিল আর ব্যস, তাই এটা এখনও পুরোপুরি একটা এজেন্ট নয়, তাই তো?

  • তাই, আসুন একটু অন্যরকম কিছু করা যাক।

  • পরের অংশে, আমি আসলে একটি কমান্ড দিতে চাই, তবে আমি এজেন্টের জন্য এটি একটু কঠিন করতে চাই।

মাল্টি-স্টেপ এজেন্ট আর্কিটেকচার ও এক্সিকিউশন

  • তাই, আমার ডেমো ডিভাইসে ফিরে যাওয়া যাক এবং দেখা যাক যে আমরা এটিকে আরও একটু বেশি, একটু কঠিন করতে পারি কিনা।

  • আমরা আগেই সেখানে পৌঁছে গেছি।

  • অসাধারণ।

  • তাই, আমি যেমন বলেছি, আগামীকাল আমাদের মিউজিয়ামে যাওয়ার প্ল্যান আছে।

  • এবং সেই মিউজিয়ামে যাওয়ার জন্য, আমি যদি এটি খুলি, তাহলে আপনি দেখতে পাবেন যে প্রবেশমূল্য হল $২৫।

  • এখন, দেখা যাক আমাদের এজেন্ট আসলে নিজে থেকে এটি বুঝতে পারে কিনা।

  • তাই, আমি আমার খরচের স্ক্রিনে ফিরে যাচ্ছি এবং আমি এটিকে একটি কমান্ড দেব এবং আমি বলব, "আমার খরচে আমার মিউজিয়ামের টিকিট যোগ করুন।"

  • এই তো হয়ে গেছে।

  • আর এখন, আপনি দেখতে পাচ্ছেন যে এটি আমার ভ্রমণসূচী চেক করছে, মিউজিয়ামে যাওয়ার তথ্য খুঁজে বের করছে এবং আমার খরচের তালিকায় এটি যোগ করছে।

  • সুতরাং, এখানে এটি তার লক্ষ্যে পৌঁছানোর জন্য তিনটি ধাপ নিচ্ছে এবং এটি আমাকে একটি চূড়ান্ত টেক্সট উত্তরও দিয়েছে।

  • এখন, আবার, এই সব অটোমেটিক কাজ করে।

  • আপনি ডিভাইসে সেই মডেলের আসল স্পিড দেখেছেন।

  • তাহলে, স্লাইডে ফিরে যাওয়া যাক এবং দেখা যাক যে এটি কীভাবে কাজ করে।

  • সুতরাং, আপনি দেখতেই পাচ্ছেন যে আমাদের প্রথম ডেমোর তুলনায় আমরা কিছু জিনিস একটু পরিবর্তন করেছি।

  • এই ক্ষেত্রে, আপনি দেখতে পাচ্ছেন যে আমি মিউজিয়াম বা খরচের ব্যাপারে কিছু বলিনি, তাই মডেল যখন প্রম্পট ও টুল পেয়েছে, তখন এটি প্রথমে কী করবে তা ঠিক করার চেষ্টা করছে।

  • তাই, এখানে, এটি সিদ্ধান্ত নেয় যে, ওহ, এটিকে আমার বর্তমান ভ্রমণসূচী সম্পর্কে আরও জানতে হবে, তাই এটি getItinerary কল করবে।

  • এটি একটি উত্তর পায় এবং তারপরে এটি জানতে পারে, ওহ, এই ভ্রমণসূচীতে একটি মিউজিয়াম ভিজিট আছে, সম্ভবত এটিই সেই মিউজিয়াম যার কথা সে বলছিল।

  • তাহলে, সেই নির্দিষ্ট ইভেন্টের বিবরণ খুঁজে দেখা যাক।

  • এবং এটি সেই নির্দিষ্ট ইভেন্টের অন্যান্য সমস্ত মেটাডেটার মধ্যে থেকে $২৫ দেখতে পাবে।

  • এটি বুঝতে পারে এবং ফিরে যায় এবং এটি বুঝতে পারে যে এটিকে খরচ যোগ করার জন্য কল করতে হবে।

  • সুতরাং, এখানে আমরা দেখতে পাচ্ছি যে একাধিক ধাপ একের পর এক ঘটছে।

  • তাহলে, ভিক্টোরিয়া, তুমি কি এই বিষয়ে আরও একটু গভীরে যেতে পারবে?

  • হ্যাঁ।

  • সুতরাং, জোলান্ডা এইমাত্র যা বর্ণনা করেছেন তা হল তিনি যে ডেমোটি দেখিয়েছেন তার একটি বাস্তব উদাহরণ, তবে এখানে, আমি এটিকে আরও একটু ধারণাগত, বিমূর্ত স্তরে নিয়ে যেতে চলেছি।

  • তাই, প্রতিবার মাল্টি-স্টেপ ফাংশন কলিং করার সময় এটি ঘটবে।

  • সুতরাং, প্রথমত, এটি আমাদের অ্যাপ এবং সেটি হল Gemini Nano মডেল।

  • এবং ব্যবহারকারী মডেলকে কোয়েরি এবং উপলভ্য টুলের তালিকা পাঠানোর মাধ্যমে শুরু করবেন।

  • তাই, মডেলটি তখন এই তথ্য ব্যবহার করে সিদ্ধান্ত নেবে যে কী ফেরত পাঠাতে হবে।

  • তারপর, ধরা যাক, প্রথম ক্ষেত্রে, এটি একটি টুল কল ফেরত পাঠায়, আসুন একে টুল কল ১ বলি।

  • তারপর, অ্যাপ এই টুল কল এক্সিকিউট করবে এবং টুল রেসপন্স পাবে।

  • এবং তারপরে, এটি আসলে মডেলের কাছে সম্পূর্ণ কথোপকথনের ইতিহাস ফেরত পাঠাবে, যার মধ্যে আসল কোয়েরি, টুলের তালিকা, প্রথম টুল কল এবং প্রথম টুল রেসপন্স অন্তর্ভুক্ত থাকে।

  • তারপর, মডেল আবার এই তথ্য ব্যবহার করে পরবর্তী পদক্ষেপ ঠিক করে।

  • তাই, চূড়ান্ত ফলাফল না পাওয়া পর্যন্ত এটি বারবার চলতে পারে।

  • সুতরাং, ধরা যাক, মডেলটি n-তম টুল কল ফিরিয়ে দেবে এবং তারপর অ্যাপটি আবার পুরো কথোপকথনের ইতিহাস ফিরিয়ে দেবে।

  • এবং যখন মডেলটি সন্তুষ্ট হয়, ঠিক আছে, এটি জানে যে কোয়েরিটি পূরণ হয়েছে, এটি অ্যাপে একটি চূড়ান্ত উত্তর পাঠাবে এবং তারপরে অ্যাপটি UI-তে দেখাতে পারে যে, ঠিক আছে, এটি হয়ে গেছে।

  • ঠিক আছে।

  • তাহলে, এখন আমি ব্যাখ্যা করব যে কোডে আমরা কীভাবে এটি প্রয়োগ করি।

    /**
    * 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।

  • তাই, এটিকে সিঙ্গেল-টার্ন বলা হলেও, আসলে একটি টার্ন মানে হল ব্যবহারকারীর একটি কোয়েরি।

  • তাই, ব্যবহারকারীর প্রত্যাশা হল, আমি একটি কোয়েরি পাঠাব, আপনি একটি উত্তর দেবেন, ব্যাকগ্রাউন্ডে কী ঘটছে, কতবার লুপ হচ্ছে ইত্যাদি বিষয়ে খুব বেশি বিশদে না গিয়ে।

  • তাই, আমরা একই ফাংশন ব্যবহার করা চালিয়ে যেতে পারি।

  • এবং তারপরে, আমরাও, কারণ মাল্টি-স্টেপ টুল কলিং টুলটি একটু বেশি সময় নেয়, আপনি ডেমোতেও দেখেছেন যে এটি আসলে দেখায় যে এটি এখন কোন ফাংশন কল করছে, এখন কী কার্যকর হচ্ছে এবং এটি করা হয়েছে কিনা।

  • তাই, আমরা UI-তে লাইভ প্রোগ্রেস দেখাতে চাই।

  • তাই, শুধু টেক্সট উত্তর সংগ্রহ করার পরিবর্তে, আমরা আসলে টুলের নাম, event.name, দেখাতে পারি, যখনই AgentEvent একটি FunctionCall বা একটি FunctionResponse নির্গত করে এবং এটি হয়ে গেলে, আমরা আগের মতো TextMessage ফেরত দিতে পারি।

মাল্টি-টার্ন কথোপকথন সেশন ম্যানেজ করা

  • অসাধারণ!

  • তাই, আমরা এই রান অ্যাসিঙ্ককে রান সিঙ্গেল-টার্ন অ্যাসিঙ্ক বলছি, যা অবশ্যই ধরে নেয় যে অন্য ধরনের API-ও আছে, তাই তো?

  • হ্যাঁ।

  • তাই অবশ্যই শুধু একটি ধাপ সম্পূর্ণ করাই যথেষ্ট নয়।

  • আমরা মাল্টি-স্টেপ করতে চাই।

  • তাহলে, এর পরে মাল্টি-টার্ন সেশন করা যাক এবং আমার মনে হয় আমরা আমার ডেমোতে ফিরে যেতে পারি এবং এখানে এটিকে আরও একটু কঠিন করতে পারি।

  • আমরা মিউজিয়ামে যাওয়ার কথা বলছিলাম, কিন্তু আমাদের গোল্ডেন গেট বে ক্রুজেও যাওয়ার কথা ছিল।

  • তাই, সেটির জন্য, আমি বুক করার আগে শুধু জানতে চাই যে আমার কাছে পর্যাপ্ত বাজেট আছে কিনা।

  • তাহলে চলুন, প্রশ্ন জিজ্ঞাসা করা যাক।

  • দেখা যাক।

  • তাই আমি ভাবছি আগামীকাল আমার টিমকে গোল্ডেন গেট বে ক্রুজে নিয়ে যাব এবং আমার মনে হয় এর জন্য $১৮০-এর মতো খরচ হবে।

  • তাহলে আমি যদি তা করি, তাহলে আমার বাকি থাকা বাজেট আসলে কত হবে?

  • তাহলে এটি কী করছে?

  • আমার বাকি বাজেট কত হবে তা উত্তর দিচ্ছে।

  • তাই এটি বর্তমান ভ্রমণসূচী বুঝতে পারে।

  • এর কাছে সেই তথ্য আছে এবং এটি তা বলতে পারে।

  • তবে আমি এখানে ফলো-আপ প্রশ্নও করতে পারি।

  • ঠিক আছে, এটা ভালো।

  • তুমি কি এটা আমার খরচে যোগ করতে পারবে?

  • আমরা সেখানে যাব এবং এটি এগিয়ে যাবে।

  • Oh, it needs to currency, so cool, demo effect.

  • ঠিক আছে, তাহলে এটি ডলারে আছে।

  • $১৮০।

  • এই তো হয়ে গেছে।

  • এই প্রথমবার এমনটা হল, দারুণ ব্যাপার।

  • আচ্ছা, তাহলে এটি কী করছে?

  • এটি আমাকে বলছে যে এটি তিনটি টার্ন নিয়েছে এবং এটি খরচে যোগ করেছে এবং এটি আমাকে এই সেশনটি রিফ্রেশ করার অনুমতি দেয়।

  • তাই আমার কাছে উপরে একটি রিফ্রেশ বোতামের মতো আছে এবং আমি যদি তা করি, তাহলে আমি সম্পূর্ণ ইতিহাস মুছে ফেলি এবং আমি আবার শুরু করতে পারি।

  • তাহলে, আমার মনে হয় আমরা এবার স্লাইডে ফিরে যেতে পারি।

  • আমাদের কাছে ওয়ার্কিং ডেমো আছে, সেগুলি আমাদের প্রয়োজন অনুযায়ী কাজ করে, তাই আমার মনে হয় আমরা কোডে ফিরে যেতে পারি।

  • হ্যাঁ।

  • তাই, এটি সত্যিই খুব দারুণ।

  • আপনি লক্ষ্য করেছেন যে জোলান্ডা উল্লেখ করেননি, এটি শুধু বলে, ওহ, এটি ডলারে, তিনি বলেননি যে এটি গোল্ডেন গেট বে ক্রুজ টিকিটের জন্য।

  • তাহলে মডেলটি কীভাবে সমস্ত প্রসঙ্গ জানে?

  • তাই এটি আগের দুটি কোড স্নিপেটে আমি যা দেখিয়েছি তার থেকে কিছুটা আলাদা।

    // 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 অ্যাপ, এটি একাধিক ট্রিপ ম্যানেজ করে।

  • ADS ট্রিপ, প্যারিস ট্রিপ, টোকিও ট্রিপ হতে পারে।

  • তাই আমরা ট্রিপের মধ্যেই প্রসঙ্গটি রাখতে চাই।

  • আমরা একে অপরের সাথে ঝামেলা করতে চাই না, বুঝলে?

  • তাই, runSingleTurnAsync-কে কল করার পরিবর্তে, আমাদের কাছে runAsync আছে।

  • তাই এটি আলাদা।

  • তাই এটি সেশনে রান করা হয় এবং তারপরেও আমাদের কাছে একই প্রম্পট থাকে।

  • এবং তারপরেও আমরা আগের মতোই AgentEvent, FunctionCall, FunctionResponse এবং TextMessage নির্গত করতে পারি, এটি একই।

  • তারপর জোলান্ডা যখন নতুন কথোপকথন বোতাম, রিফ্রেশ বোতামে ক্লিক করে, তখন আমরা আসলে session.delete পেতে পারি।

  • হ্যাঁ।

  • ঠিক আছে।

  • তাই আমরা নতুন এজেন্টিক API-এর মাধ্যমে এই সব কিছু করেছি এবং এটি অসাধারণ এবং আপনার অনেক ব্যবহারের ক্ষেত্রে এটি অসাধারণভাবে কাজ করবে।

  • তবে অবশ্যই, আমরা সবসময় দ্রুত কাজ করতে বা সহজ জিনিস সম্ভব করতে চাই, কিন্তু আমরা আপনার জন্য আরও জটিল কেসও সম্ভব করতে চাই।

  • তাই আমরা নিশ্চিত করতে চাই যে, আপনার প্রয়োজন হলে, আপনি এখনও এইসব জিনিসের আরও লো-লেভেল ভার্সন তৈরি করতে ডাইরেক্ট অ্যাক্সেস API ব্যবহার করতে পারবেন।

  • তাই ভিক্টোরিয়া, আপনি কি ব্যাখ্যা করতে পারবেন যে এর অর্থ কী এবং কখন আমরা আবার এই সরাসরি অ্যাক্সেস লেভেলে নেমে আসব?

উন্নত এজেন্টিক ওয়ার্কফ্লো ও টুল ইন্টিগ্রেশন

  • হ্যাঁ, অবশ্যই, জোলান্ডা।

  • তাই এই ডাইরেক্ট অ্যাক্সেস, আপনি হয়ত আগে থেকেই Prompt API-এর সাথে পরিচিত।

  • তাই আমরা এখানেও ফাংশন কলিংয়ের সুবিধা দিয়েছি এবং আমাদের কাছে দুটি ব্যবহারের কেস আছে যেখানে আমরা সহজ এজেন্টিক ফ্লোর পরিবর্তে এই API ব্যবহার করতে পছন্দ করব।

  • প্রথমটি হল একটি সহজ ব্যবহারের উদাহরণ, খুব সহজ ব্যবহারের উদাহরণ।

  • তাই, আপনি মনে রাখবেন যে এজেন্টিক ফ্লোতে আমরা সম্পূর্ণ কথোপকথন, কোয়েরি, টুল, টুল কল, টুল রেসপন্স, সবকিছুই মডেলে ফেরত পাঠাই।

  • And maybe there are some use cases that we don't want to do that, we just want to send the prompt, let's say.

  • ধরা যাক, আমরা মডেলকে একটি প্রম্পট পাঠাতে চাই যা টুল কলের মাধ্যমে উত্তর দেয় এবং তারপর আমরা টুল কলের উত্তর দিতে চাই না, আমরা শুধু মডেলকে আরেকটি প্রম্পট পাঠাতে চাই, তাই আমরা সেখানে ইতিহাস এডিট করতে পারি, যেমন ইতিহাসের উপর আমাদের সম্পূর্ণ নিয়ন্ত্রণ আছে।

  • আমি এখানে আপনাকে আরও একটি বাস্তব উদাহরণ দেব।

    // 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 ব্যবহার করতে পারি।

  • ইতিহাসের উপর আমাদের সম্পূর্ণ নিয়ন্ত্রণ আছে, আমরা ডিভাইসে কনটেক্সট টোকেন সেভ করি, কারণ, আপনি জানেন, ডিভাইসে আরও সীমিত টোকেন উইন্ডো আছে এবং এর মাধ্যমে আমরা আরও টোকেন সেভ করতে পারি।

  • আর দ্বিতীয় ব্যবহারিক ক্ষেত্রটি হল, এটি আসলে সম্পূর্ণ বিপরীত।

  • তাই, আমাদের কাছে যদি এমন জটিল ব্যবহারের কেস থাকে যা এজেন্টিক API এখনও সাপোর্ট করতে পারে না, ধরা যাক আমাদের কাছে মাল্টি-এজেন্ট সিস্টেম আছে যেখানে জটিল টাস্ক সমাধান করার জন্য একাধিক সাব-এজেন্ট একে অপরের সাথে ইন্টার‍্যাক্ট করছে, অথবা একটি হাইব্রিড সিস্টেম যেখানে আমাদের কাছে অন-ডিভাইস মডেল আছে, কিন্তু আমরা ক্লাউড মডেলও চাই, অথবা আমরা যদি কাস্টম মেমরি এবং কনটেক্সট কম্প্যাকশন চাই।

  • সুতরাং এটি ইতিহাসের সাথে সম্পর্কিত, যেমন ইতিহাসের সম্পূর্ণ নিয়ন্ত্রণ যা আমি আগে উল্লেখ করছিলাম।

  • সুতরাং, ধরা যাক আমরা চাই, কারণ কনটেক্সট উইন্ডো সীমিত, তাই আমরা সবকিছু মডেলে ফেরত পাঠাতে চাই না, আমরা শুধু সবচেয়ে গুরুত্বপূর্ণ অংশ বা লেটেস্ট অংশের সারসংক্ষেপ করতে চাই, যাতে এর উপর আমাদের সম্পূর্ণ নিয়ন্ত্রণ থাকে, তারপর আমরা ডাইরেক্ট অ্যাক্সেস API ব্যবহার করি।

  • এই ধরনের ব্যবহারের ক্ষেত্রে, আমরা Agent Development Kit বা ADK বা Crew-এর মতো ফ্রেমওয়ার্ক ব্যবহার করতে পারি অথবা আপনি নিজের কাস্টম অর্কেস্ট্রেশন ফ্রেমওয়ার্কও তৈরি করতে পারেন।

  • ঠিক আছে।

  • এজেন্টিক API সম্পর্কে আমাদের কাছে এই তথ্যই ছিল।

  • তবে, আরও একটি বিষয় আছে যা আমরা উল্লেখ করতে চাই।

  • আমরা সবসময় ইন-অ্যাপ এজেন্ট সম্পর্কে কথা বলছি, তাই আপনি নিজের অ্যাপের মধ্যে নিজস্ব এজেন্টিক অভিজ্ঞতা তৈরি করছেন, কিন্তু আমরা AppFunctions কীভাবে ব্যবহার করছি এবং আপনি যদি শুধুমাত্র নিজের অ্যাপের মধ্যে কাজ করেন, তাহলে কেন AppFunctions ব্যবহার করবেন, সেই সম্পর্কেও কথা বলছি?

  • আমরা জানি যে আপনার মতো ডেভেলপাররা একই কাজ দুবার করতে পছন্দ করেন না, তাই না?

  • আমরা কোড কপি-পেস্ট করতে পছন্দ করি না, আমরা কোনও ব্যবসায়িক লজিক ডুপ্লিকেট করতে পছন্দ করি না।

  • তাই, AppFunctions-এর মাধ্যমে, শুধুমাত্র আমাদের ইন-অ্যাপ এজেন্টকে সেগুলি ব্যবহার করার অনুমতি দেওয়ার পরিবর্তে, খুব সহজ পরিবর্তনের মাধ্যমে, আমরা আসলে আমাদের টুলগুলি সিস্টেম এজেন্টের জন্যও উপলভ্য করতে পারি।

  • তাহলে কোড সহ এটি দেখতে কেমন হবে?

  • হ্যাঁ।

  • তাই AppFunctions, AppFunction-এর সাহায্যে, আমাদের শুধু একবার লিখতে হবে এবং তারপর আমরা সেগুলিকে আমাদের ইচ্ছামতো বিভিন্ন লেভেলে প্রকাশ করতে পারব।

  • আপনার মনে আছে যে আগে আমাদের কাছে ACCESS_LEVEL_SELF ছিল, যা শুধুমাত্র আমাদের ইন-অ্যাপ এজেন্টের জন্য লেখা ফাংশনগুলি প্রকাশ করে, কিন্তু আমরা সেই অ্যাক্সেস লেভেল পরিবর্তন করে ACCESS_LEVEL_ANDROID_TRUSTED করতে পারি।

  • এবং এটি Android OS-এ বিশ্বস্ত এজেন্টদের কাছে ফাংশনগুলি প্রকাশ করবে।

  • তাই ফাংশন, কমান্ড বা ডেটাবেস লজিক আবার লেখার প্রয়োজন নেই।

  • AppFunctions আগে থেকেই ইন্টার্নাল ও এক্সটার্নাল, দুই ক্ষেত্রেই আপনার অ্যাপের ভয়েস হিসেবে কাজ করে।

  • আমরা সেটিরও ডেমো চাই, তাই তো?

  • ঠিক আছে, ফোনে ফিরে যাওয়া যাক এবং আমাদের শেষ ডেমোর জন্য, Jetpacker অ্যাপ থেকে বেরিয়ে আসা যাক।

  • তাই আমরা বাইরে যেতে পারি এবং আমরা আসলে Gemini-তে যেতে পারি।

  • তাই Gemini-তে আমরা @Jetpacker-কে কল করতে পারি।

  • এখন, একটি জিনিস মনে রাখতে হবে যে এটি শুধুমাত্র একটি সীমিত বিটা হিসাবে উপলভ্য, তাই এটি আজই প্রত্যেকের জন্য উপলভ্য হবে না, তবে এটি পরীক্ষা করা এবং এটি ব্যবহার করে দেখা সম্ভব।

  • তাহলে Jetpacker-এর সাথে, দেখা যাক।

  • আমরা কী করব?

  • ওহ, আমি আজ সকালে কফি খেয়েছি, তাই না?

  • ADS ট্রিপের খরচে $৭ মূল্যের কফি যোগ করতে পারবে?

  • এই তো হয়ে গেছে।

  • এবং আপনি দেখতে পাবেন যে এটি Jetpacker অ্যাপের সাথে কানেক্ট করে।

  • আর এই যে আমরা এসে গেছি।

  • এটি আমার জন্য খরচ যোগ করেছে।

  • তাহলে আমরা মূলত দেখেছি যে Jetpacker-এ সবকিছু কীভাবে ব্যবহার করতে হয়।

  • Jetpacker-এর সবচেয়ে ভালো দিক হল, আমরা আসলে বিমান মোডও চালু করতে পারি।

  • তাই আমরা আজ এটি দেখাইনি, তবে আমরা শুধু বিমান মোড চালু করতে পারি এবং আপনি ডেমোতে যা দেখেছেন এবং আমি এটি দেখাতে চাই, কারণ আমি নিশ্চিত করতে চাই যে আপনারা সবাই আমাকে বিশ্বাস করেন, তাই আসুন ওয়াই-ফাই বন্ধ করি।

  • Is there anyone that has a great demo example, an ex- an expense that I can add?

  • দেখা যাক।

  • আমরা কি এটা কী? করতে পারি

  • ওহ, গাড়ি ভাড়া করলে ভালো হয়, তাই না?

  • ঠিক আছে।

  • "গাড়ি ভাড়ার জন্য $৩০০ খরচ যোগ করো" বলে দেখুন।

  • এই তো, আর এটি পেয়ে গেছে।

  • ঠিক আছে।

  • অসাধারণ।

  • ঠিক আছে, স্লাইডে ফিরে যাওয়া যাক।

  • আমরা AppFunctions সম্পর্কে কথা বলছিলাম।

  • আমি জানি যে আমরা এই বিষয়ে খুব, খুব হালকাভাবে আলোচনা করেছি।

  • তাই আপনি যদি আরও জানতে চান, তাহলে ড্যান এবং সারাহর আরেকটি আলোচনাও রয়েছে যারা আপনি কীভাবে এটি আসলে চালু করতে পারেন, কীভাবে এটি পরীক্ষা করতে পারেন, আমাদের কাছে কী টুলিং আছে ইত্যাদি বিষয়ে আরও অনেক বিশদে আলোচনা করেছেন।

  • তাই আজ আমরা অনেক ধরনের জিনিস নিয়ে আলোচনা করেছি।

  • আমরা Single-Step, Multi-Step, Multi-Turn এবং সবশেষে কীভাবে System AppFunction ব্যবহার করতে হয় তা দেখেছি।

  • এখন, এর সাথে আমার মনে হয় যে আমরা যাওয়ার আগে আমাদের কাছে কয়েকটি পরামর্শ আছে।

পেশাদার পদ্ধতি ও উপসংহার

  • হ্যাঁ।

  • তাই, আমরা যখন এই এজেন্টিক অভিজ্ঞতা তৈরি করা শুরু করব, তখন এই তিনটি পরামর্শ মনে রাখবেন।

  • তাই প্রথমটি হল টুল সেটের ফোকাস বজায় রাখা।

  • তাই মনে রাখবেন যে অন-ডিভাইস মডেলের ক্ষমতা সীমিত কারণ এটি ছোট স্কেলে কাজ করে।

  • তাই, ডজন ডজন টুল রেজিস্টার করার পরিবর্তে, কম সংখ্যক টুল ব্যবহার করা ভালো।

  • আর তারপর, আমি যেমন আগে বলেছি, স্পষ্ট KDoc বিবরণ লিখুন কারণ মডেলটি এটি ব্যবহার করে সিদ্ধান্ত নেয় যে এটি কী রিটার্ন করবে।

  • এবং তারপরে আমরা সর্বাধিক টার্ন গার্ডরেলও সেট করতে পারি।

  • এছাড়াও, এটি মডেলকে বিভ্রান্ত হলে অবিরাম লুপ করা থেকে বিরত রাখে।

  • এর অর্থ হল, আমরা ব্যবহারকারীর ব্যাটারি ড্রেন করতে পারি।

  • তাই, এটি থাকলে আমরা ব্যবহারকারীর ব্যাটারি বাঁচাতে পারব।

  • এবং সবশেষে, ডিভাইসে ফাংশন কলিং আগে থেকেই কাজ করে কিনা তা আমাদের চেক করতে হবে এবং একটি গ্রেসফুল ফলব্যাক প্রয়োগ করতে হবে।

  • যেমন, এটি কাজ না করলে, আপনি ক্লাউড মডেল বা আপনার স্ট্যান্ডার্ড UI দেখতে পারেন।

  • ঠিক আছে, আমার মনে হয় আমাদের রিসোর্স দিয়ে আমরা এটি বন্ধ করতে পারব।

  • তাই আরও একবার, আমি আপনাকে QR কোড দেখাব।

  • একবার দেখে নিন।

  • আমার মনে হয়, একটি বিষয় মনে রাখতে হবে যে এর জন্য আমাদের কাছে Android Skills আছে।

  • তাই আপনাকে প্রতিটি খুঁটিনাটি বিষয় নিয়ে মাথা ঘামাতে হবে না।

  • এই নতুন এজেন্টিক API-এর সাথে ব্যবহার করার জন্য আমাদের কাছে সম্পূর্ণ ডকুমেন্টেশন এবং Android স্কিল আছে।

  • তাই, সেটি একবার দেখে নিন।

  • AICore ডেভেলপার প্রিভিউ ডাউনলোড করুন যাতে আপনি এইসব জিনিস পরীক্ষা করে দেখতে পারেন এবং কোডিং উপভোগ করতে পারেন।

কোড

কোড স্নিপেট

"Jetpacker এজেন্ট ডেমো এবং ফাংশন কলিং" ভিডিওতে 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...
}
"Building and implementing an AI agent runner" ভিডিওর 11:41-এ Kotlin স্নিপেট
val model = Generation.getClient()
val features = model.getAvailableFeatures()
if(FUNCTION_CALLING in features) {
  // Device is supported!
} else {
  // Graceful fallback
}
"Building and implementing an AI agent runner" ভিডিওর 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 }

}
"মাল্টি-স্টেপ এজেন্ট আর্কিটেকচার ও এক্সিকিউশন" ভিডিওর ১৭:২৩-এ 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 { ... }
"Multi-step agent architecture and execution" ভিডিওর 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
 }
}
"মাল্টি-টার্ন কথোপকথন সেশন ম্যানেজ করা" ভিডিওর ২২:১৩-এ 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" ভিডিওর ২৫:০২-এ 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()
)