ADK-এর মাধ্যমে স্টেটফুল এবং ব্যক্তিগতকৃত এজেন্ট তৈরি করা

১. ভূমিকা

শিরোনাম

"গোল্ডফিশ" সমস্যা

ধরুন, আপনি টোকিওতে আপনার স্বপ্নের ছুটি কাটানোর পরিকল্পনা করার জন্য একজন ট্র্যাভেল এজেন্ট নিয়োগ করেছেন। ‘দ্য গোল্ডফিশ প্রবলেম’-এর বাস্তব প্রয়োগ দেখতে সেশন এজেন্ট ব্যবহার করুন।

আপনি তাদের অফিসে ঢুকে বলেন:

হ্যালো! আমি টোকিওতে দুই দিনের একটি ভ্রমণের পরিকল্পনা করতে চাই। আমি ঐতিহাসিক স্থান এবং সুশির প্রতি আগ্রহী।

এজেন্টটি উৎসাহের সাথে উত্তর দেয়:

দারুণ! আমি রাজপ্রাসাদ পরিদর্শনের এবং সুকিয়াবাশী জিরোতে সুশি ডিনারের পরিকল্পনা করেছি।

তুমি হেসে বলো:

দারুণ তো! আপনি কি আমাকে ভ্রমণসূচিটা পাঠাতে পারবেন?

এজেন্টটি আপনার দিকে ফ্যালফ্যাল করে তাকিয়ে জিজ্ঞেস করে:

হ্যালো! আজ আপনার ভ্রমণের পরিকল্পনা করতে আমি কীভাবে সাহায্য করতে পারি?

এটাই হলো 'গোল্ডফিশ সমস্যা'। স্মৃতিশক্তি ছাড়া প্রতিটি মিথস্ক্রিয়াই একটি ফাঁকা স্লেট। বুদ্ধিমত্তাটা থাকে—এজেন্টটি জানে কীভাবে ভ্রমণের পরিকল্পনা করতে হয়—কিন্তু ধারাবাহিকতার অভাব থাকে। একটি এআই এজেন্টকে সত্যিকারের কার্যকর হতে হলে, তার মনে রাখার ক্ষমতা থাকা প্রয়োজন।

আজ আপনার মিশন

এই কর্মশালায়, আপনি এমন একটি ট্র্যাভেল এজেন্ট তৈরি করে গোল্ডফিশ সমস্যার সমাধান করবেন যা মনে রাখতে, শিখতে এবং মানিয়ে নিতে পারে। আপনি এজেন্ট মেমোরির ৬টি স্তর অতিক্রম করে এমন একটি সিস্টেম তৈরি করবেন যা চ্যাটবটের চেয়ে একজন নিবেদিত ব্যক্তিগত সহকারীর মতো বেশি আচরণ করে।

স্তর

ধারণা

"সুপারপাওয়ার"

স্তর ১

অধিবেশন ও রাজ্য

ভুলে না গিয়ে কথোপকথন চালিয়ে যাওয়া

স্তর ২

বহু-এজেন্ট রাষ্ট্র

দলের সদস্যদের মধ্যে নোট আদান-প্রদান করা

স্তর ৩

অধ্যবসায়

সিস্টেম রিবুট করার পরেও তোমাকে মনে রাখা

স্তর ৪

কলব্যাক

সম্পূর্ণ স্বায়ত্তশাসিতভাবে মেমরি আপডেট করা

স্তর ৫

কাস্টম টুলস

কাঠামোগত ব্যবহারকারী প্রোফাইল পড়া ও লেখা

স্তর ৬

মাল্টিমোডাল মেমরি

ছবি ও ভিডিও দেখা এবং মনে রাখা

ADK মেমরি স্ট্যাক

কোড লেখার আগে, আমরা যে টুলগুলো ব্যবহার করছি সেগুলো বুঝে নেওয়া যাক। গুগল এজেন্ট ডেভেলপমেন্ট কিট (ADK) মেমরি পরিচালনার জন্য একটি কাঠামোগত উপায় প্রদান করে:

  1. সেশন : কথোপকথনের আধার। এটি আলোচিত বিষয়গুলোর ইতিহাস ধারণ করে।
  2. অবস্থা : সেশনের সাথে সংযুক্ত একটি কী-ভ্যালু 'স্ক্র্যাচপ্যাড'। এজেন্টরা নির্দিষ্ট তথ্য সংরক্ষণ করতে এটি ব্যবহার করে (যেমন, destination="Tokyo" )।
  3. মেমোরিসার্ভিস : দীর্ঘমেয়াদী সংরক্ষণ। এখানে আমরা বিভিন্ন জিনিস চিরদিনের জন্য রাখি, যেমন ব্যবহারকারীর পছন্দ বা বিশ্লেষণ করা নথি।

২. সেট আপ করুন

আমাদের এআই এজেন্টদের শক্তিশালী করতে দুটি জিনিস প্রয়োজন: ভিত্তি স্থাপনের জন্য একটি গুগল ক্লাউড প্রজেক্ট।

প্রথম অংশ: বিলিং অ্যাকাউন্ট সক্রিয় করুন

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

দ্বিতীয় পর্ব: উন্মুক্ত পরিবেশ

  1. 👉 সরাসরি ক্লাউড শেল এডিটর- এ যেতে এই লিঙ্কে ক্লিক করুন
  2. 👉 আজ যেকোনো সময়ে অনুমোদনের জন্য অনুরোধ করা হলে, চালিয়ে যাওয়ার জন্য 'Authorize'-এ ক্লিক করুন। ক্লাউড শেল অনুমোদন করতে ক্লিক করুন
  3. 👉 যদি স্ক্রিনের নিচে টার্মিনালটি দেখা না যায়, তাহলে এটি খুলুন:
    • ভিউ ক্লিক করুন
    • টার্মিনালে ক্লিক করুন ক্লাউড শেল এডিটরে নতুন টার্মিনাল খুলুন
  4. 👉💻 টার্মিনালে, নিম্নলিখিত কমান্ডটি ব্যবহার করে যাচাই করুন যে আপনি ইতিমধ্যেই প্রমাণীকৃত এবং প্রজেক্টটি আপনার প্রজেক্ট আইডিতে সেট করা আছে:
    gcloud auth list
    
  5. 👉💻 গিটহাব থেকে বুটস্ট্র্যাপ প্রজেক্টটি ক্লোন করুন:
    git clone https://github.com/cuppibla/memory_agent_starter
    
    
  6. 👉💻 প্রজেক্ট ডিরেক্টরি থেকে সেটআপ স্ক্রিপ্টটি চালান।
    cd ~/memory_agent_starter
    ./init.sh
    
    স্ক্রিপ্টটি বাকি সেটআপ প্রক্রিয়াটি স্বয়ংক্রিয়ভাবে সম্পন্ন করবে।
  7. 👉💻 প্রয়োজনীয় প্রজেক্ট আইডি সেট করুন:
    gcloud config set project $(cat ~/project_id.txt) --quiet
    

তৃতীয় পর্ব: অনুমতি স্থাপন

  1. 👉💻 নিচের কমান্ডটি ব্যবহার করে প্রয়োজনীয় API-গুলো সক্রিয় করুন। এতে কয়েক মিনিট সময় লাগতে পারে।
    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        servicenetworking.googleapis.com \
        run.googleapis.com \
        aiplatform.googleapis.com \
        compute.googleapis.com
    
  2. 👉💻 টার্মিনালে নিম্নলিখিত কমান্ডগুলো চালিয়ে প্রয়োজনীয় অনুমতিগুলো প্রদান করুন:
    . ~/memory_agent_starter/set_env.sh
    

লক্ষ্য করুন যে আপনার জন্য একটি .env ফাইল তৈরি হয়েছে। সেখানে আপনার প্রোজেক্টের তথ্য দেখানো হয়।

৩. ভিত্তি - অধিবেশন ও অবস্থা

রাষ্ট্রীয়

মূল ধারণা: প্রেক্ষাপটই প্রধান

স্মৃতির সবচেয়ে মৌলিক রূপ হলো সেশন মেমরি । এর মাধ্যমেই একজন এজেন্ট জানতে পারে যে, "আমি এটা কিনতে চাই" বাক্যটিতে "এটা" বলতে সেই জুতোটিকে বোঝানো হচ্ছে, যেটির কথা আপনি ১০ সেকেন্ড আগে বলছিলেন।

ADK-তে আমরা Session অবজেক্টের মাধ্যমে এটি পরিচালনা করি।

  • স্টেটলেস অ্যাপ্রোচ : প্রতিটি মেসেজের জন্য একটি নতুন সেশন তৈরি করা।
  • স্টেটফুল অ্যাপ্রোচ : একটি সেশন তৈরি করে সম্পূর্ণ কথোপকথনের জন্য সেটিই পুনরায় ব্যবহার করা

ধাপ ১: এজেন্টকে পরীক্ষা করুন

👉💻 আপনার ক্লাউড শেল টার্মিনালে, ক্লাউড শেল এডিটর-এ ফাইলটি খুলতে নিম্নলিখিত কমান্ডটি চালান:

cloudshell edit ~/memory_agent_starter/01_session_agent/agent.py

~/memory_agent_starter/01_session_agent/agent.py খুলুন।

👉 agent.py ফাংশনের ভিতরে # TODO: Create a root agent এই কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

root_agent = LlmAgent(
    name="multi_day_trip_agent",
    model="gemini-2.5-flash",
    description="Agent that progressively plans a multi-day trip, remembering previous days and adapting to user feedback.",
    instruction="""
    You are the "Adaptive Trip Planner" 🗺️ - an AI assistant that builds multi-day travel itineraries step-by-step.

    Your Defining Feature:
    You have short-term memory. You MUST refer back to our conversation to understand the trip's context, what has already been planned, and the user's preferences. If the user asks for a change, you must adapt the plan while keeping the unchanged parts consistent.

    Your Mission:
    1.  **Initiate**: Start by asking for the destination, trip duration, and interests.
    2.  **Plan Progressively**: Plan ONLY ONE DAY at a time. After presenting a plan, ask for confirmation.
    3.  **Handle Feedback**: If a user dislikes a suggestion (e.g., "I don't like museums"), acknowledge their feedback, and provide a *new, alternative* suggestion for that time slot that still fits the overall theme.
    4.  **Maintain Context**: For each new day, ensure the activities are unique and build logically on the previous days. Do not suggest the same things repeatedly.
    5.  **Final Output**: Return each day's itinerary in MARKDOWN format.
    """,
    tools=[google_search]
)

নির্দেশনাটি এলএলএম-কে মনে রাখতে বলে, কিন্তু কোডটিতে অবশ্যই মনে রাখার সক্ষমতা থাকতে হবে।

ধাপ ২: দুটি পরিস্থিতি

~/memory_agent_starter/01_session_agent/main.py খুলুন।

👉 আপনার ক্লাউড শেল টার্মিনালে, ক্লাউড শেল এডিটর-এ ফাইলটি খুলতে নিম্নলিখিত কমান্ডটি চালান:

cloudshell edit ~/memory_agent_starter/01_session_agent/main.py

~/memory_agent_starter/01_session_agent/main.py ফাইলটি খুলুন এবং main.py ফাংশনের ভিতরে # TODO: Create a runner with in memorysession service এই কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

    runner = Runner(
        agent=agent,
        session_service=session_service,
        app_name=agent.name
    )

👉 main.py ফাংশনের ভিতরে # TODO: create a different session to test এই কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

    tokyo_session_2 = await session_service.create_session(
        app_name=multi_day_agent.name,
        user_id=user_id
    )

এটা পরীক্ষা করুন

আমাদের কাছে দুটি ফাংশন রয়েছে যা 'গোল্ডফিশ' এবং 'এলিফ্যান্ট' স্মৃতিশক্তির মধ্যে পার্থক্য তুলে ধরে।

দৃশ্যকল্প ১: স্টেটফুল (শেয়ার্ড সেশন)

async def run_trip_same_session_scenario(session_service, user_id):
    # 1. Create ONE session
    trip_session = await session_service.create_session(...)

    # 2. Turn 1
    await run_agent_query(..., trip_session, ...)

    # 3. Turn 2 - REUSING the same session!
    # The agent can "see" Turn 1 because it's in the session history.
    await run_agent_query(..., trip_session, ...)

দৃশ্যকল্প ২: রাষ্ট্রহীন (প্রতিবার নতুন সেশন)

async def run_trip_different_session_scenario(session_service, user_id):
    # Turn 1
    tokyo_session = await session_service.create_session(...)
    await run_agent_query(..., tokyo_session, ...)

    # Turn 2 - Creating a FREASH session
    # The agent has NO IDEA what happened in Turn 1.
    tokyo_session_2 = await session_service.create_session(...)
    await run_agent_query(..., tokyo_session_2, ...)

ধাপ ৩: এজেন্টটি চালান

চলুন পার্থক্যটা বাস্তবে দেখি। স্ক্রিপ্টটি চালান:

👉💻 কমান্ড লাইনে নিচের কমান্ডটি চালান:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/01_session_agent/main.py

দৃশ্যকল্প ১ পর্যবেক্ষণ করুন : এজেন্ট প্রথম বার্তা থেকে আপনার পছন্দগুলো মনে রাখে এবং দ্বিতীয় বার্তায় পরিকল্পনাটি সে অনুযায়ী পরিবর্তন করে।

দৃশ্যকল্প ২ পর্যবেক্ষণ করুন : দ্বিতীয়বার বলার সময় ("তোমার কি মনে আছে খাবারটার কোন জিনিসটা আমার ভালো লেগেছিল?"), কর্তা পুরোপুরি ব্যর্থ হয় কারণ এটি একটি নতুন সেশন। এর মাধ্যমে সে কার্যকরভাবে বলে, "আমি বুঝতে পারছি না তুমি কী বলছ।"

মূল কথা

মেমোরির নিয়ম #১: কথোপকথনের প্রেক্ষাপট বজায় রাখতে সর্বদা session.id পুনরায় ব্যবহার করুন। Session অবজেক্টটি হলো আপনার এজেন্টের স্বল্পমেয়াদী মেমোরি বাফার।

৪. দল - বহু-এজেন্ট রাষ্ট্র

খাবার

ধারণাটি: "টেলিফোন খেলা"

যখন একাধিক এজেন্ট একসাথে কাজ করে, তখন তারা এমন সহকর্মীদের মতো যারা একটি ফাইল ফোল্ডার একে অপরের কাছে আদান-প্রদান করে। যদি একজন এজেন্ট ফোল্ডারটিতে কোনো নোট লেখে, তাহলে পরবর্তী এজেন্ট যেন তা পড়তে পারে।

ADK-তে, এই 'ফোল্ডার'টি হলো State

  • স্টেট হলো একটি ডিকশনারি ( {"key": "value"} ) যা সেশনের ভিতরে থাকে।
  • সেশনের যেকোনো এজেন্ট এটি থেকে পড়তে বা এতে লিখতে পারে।

ধাপ ১: কার্যপ্রবাহ পরীক্ষা করুন

👉💻 আপনার ক্লাউড শেল টার্মিনালে, ক্লাউড শেল এডিটর-এ ফাইলটি খুলতে নিম্নলিখিত কমান্ডটি চালান:

cloudshell edit ~/memory_agent_starter/02_multi_agent/agent.py

👉 ~/memory_agent_starter/02_multi_agent/agent.py ফাইলে, # TODO: foodie agent কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

foodie_agent = LlmAgent(
    name="foodie_agent",
    model="gemini-2.5-flash",
    tools=[google_search],
    instruction="""You are an expert food critic. Your goal is to find the best restaurant based on a user's request.

    When you recommend a place, you must output *only* the name of the establishment and nothing else.
    For example, if the best sushi is at 'Jin Sho', you should output only: Jin Sho
    """,
    output_key="destination"  # ADK will save the agent's final response to state['destination']
)

👉 agent.py ফাংশনের ভিতরে # TODO: transportation agent কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

transportation_agent = LlmAgent(
    name="transportation_agent",
    model="gemini-2.5-flash",
    tools=[google_search],
    instruction="""You are a navigation assistant. Given a destination, provide clear directions.
    The user wants to go to: {destination}.

    Analyze the user's full original query to find their starting point.
    Then, provide clear directions from that starting point to {destination}.
    """,
)

👉 agent.py ফাংশনের ভিতরে # TODO: root_agent কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

root_agent = SequentialAgent(
    name="find_and_navigate_agent",
    sub_agents=[foodie_agent, transportation_agent],
    description="A workflow that first finds a location and then provides directions to it."
)

এখন আমাদের দুজন এজেন্ট পর্যায়ক্রমে কাজ করছে:

  1. ফুডি এজেন্ট : একটি রেস্তোরাঁ খুঁজে দেয়।
  2. পরিবহন প্রতিনিধি : ঐ রেস্তোরাঁটিতে যাওয়ার দিকনির্দেশনা দেন।

জাদুকরী হস্তান্তর : লক্ষ্য করুন, কীভাবে foodie_agent transportation_agent এর হাতে দায়িত্ব তুলে দিচ্ছে।

foodie_agent = LlmAgent(
    # ...
    # CRITICAL: This tells ADK to save the agent's output to state['destination']
    output_key="destination"
)

transportation_agent = LlmAgent(
    # ...
    # CRITICAL: This injects state['destination'] into the prompt
    instruction="""
    The user wants to go to: {destination}.
    Provide clear directions...
    """,
)
  1. output_key="destination" : ফুডি এজেন্টের উত্তরটি দক্ষতার সাথে সংরক্ষণ করা হয়েছে।
  2. {destination} : পরিবহন এজেন্ট স্বয়ংক্রিয়ভাবে সেই উত্তরটি পড়ে নেয়।

(কোনো পদক্ষেপের প্রয়োজন নেই) ধাপ ২: নিয়ন্ত্রক

02_multi_agent/main.py খুলুন।

আমরা সেগুলোকে ক্রমানুসারে চালানোর জন্য একটি SequentialAgent ব্যবহার করি।

# 1. Create a single session for the sequential agent
session = await session_service.create_session(...)

# 2. Run the query
# The SequentialAgent manages the state flow:
# Query -> Foodie -> state['destination'] -> Transportation -> Final Answer
await run_agent_query(root_agent, query, ...)

ব্যবহারকারী একটি প্রম্পট পাঠায়:

"Find best sushi in Palo Alto and then tell me how to get there."

এজেন্টরা এর উত্তর দিতে একযোগে কাজ করে।

ধাপ ৩: টিমটি পরিচালনা করুন

👉💻 ক্লাউড শেল টার্মিনালে, মাল্টি-এজেন্ট ওয়ার্কফ্লোটি চালান:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/02_multi_agent/main.py

কী ঘটে?

  1. ফুডি এজেন্ট : 'জিন শো' (বা অনুরূপ) খুঁজে পায়।
  2. ADK : "জিন শো"-কে state['destination'] এ সংরক্ষণ করে।
  3. পরিবহন প্রতিনিধি : তার নির্দেশনায় "জিন শো" গ্রহণ করে।
  4. ফলাফল : "ক্যালট্রেন স্টেশন থেকে জিন শো-তে যেতে হলে, ইউনিভার্সিটি অ্যাভিনিউ ধরে হাঁটুন..."

মূল কথা

মেমোরির নিয়ম #২: এজেন্টদের মধ্যে কাঠামোগত তথ্য আদান-প্রদান করতে স্টেট (State) ব্যবহার করুন। লেখার জন্য output_key এবং পড়ার জন্য {placeholders} ব্যবহার করুন।

৫. রিবুট - অধ্যবসায়

রাষ্ট্রীয়

ধারণাটি: "রিবুট সমস্যা"

এখন পর্যন্ত, আমাদের মেমোরি ছিল InMemory । আপনি যদি স্ক্রিপ্টটি বন্ধ করে আবার চালু করেন, এজেন্ট সবকিছু ভুলে যায়। এটা অনেকটা এমন একটি কম্পিউটারের মতো, যা প্রতিবার বন্ধ করার সময় তার হার্ড ড্রাইভ মুছে ফেলে।

এটি সমাধান করতে আমাদের পার্সিস্টেন্স (Persistence ) প্রয়োজন। আমরা InMemorySessionService এর পরিবর্তে DatabaseSessionService ব্যবহার করি।

ধাপ ১: ডাটাবেস সুইচ

👉💻 আপনার ক্লাউড শেল টার্মিনালে, ক্লাউড শেল এডিটর-এ ফাইলটি খুলতে নিম্নলিখিত কমান্ডটি চালান:

cloudshell edit ~/memory_agent_starter/03_persistent_agent/main.py

👉 ~/memory_agent_starter/03_persistent_agent/main.py ফাইলটিতে, # TODO: Configuration for Persistent Sessions এই কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

SESSIONS_DIR = Path(os.path.expanduser("~")) / ".adk_codelab" / "sessions"
os.makedirs(SESSIONS_DIR, exist_ok=True)
SESSION_DB_FILE = SESSIONS_DIR / "trip_planner.db"
SESSION_URL = f"sqlite:///{SESSION_DB_FILE}"

এখন, প্রতিটি সেশন এবং ইভেন্ট একটি SQLite ফাইলে সংরক্ষিত হয়।

ধাপ ২: ক্রস-সেশন পুনরুদ্ধার

অধ্যবসায় শুধু একটি কথোপকথন পুনরায় শুরু করতেই সাহায্য করে না, বরং অতীতের অভিজ্ঞতা থেকেও শিখতে সাহায্য করে

একই ফাইল ~/memory_agent_starter/03_persistent_agent/main.py , টেস্ট কেস ৩: ক্রস-সেশন রিট্রিভাল দেখুন।

👉 মন্তব্যটি খুঁজুন # TODO: retrieve the previous session manually

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

    old_session = await session_service.get_session(
        app_name=root_agent.name, user_id="user_01", session_id=session_id
    )

👉 # TODO: main.py ফাংশনের ভিতরে # TODO: Extract content from the OLD session , এই কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

                    previous_context += f"- {role}: {text}\n"

👉 কমেন্টটি খুঁজুন # করণীয়: main.py ফাংশনের ভিতরে # TODO: Manually inject the context to the query

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

    query_3 = f"""
    {previous_context}

    I'm planning a new trip to Osaka this time. 
    Based on my previous preferences (above), what should I eat?
    """

এটি এমন একটি পরিস্থিতি তৈরি করে যেখানে একজন ব্যবহারকারী কয়েক মাস পরে ফিরে আসেন। শুধুমাত্র একটি ডেটাবেসের মাধ্যমেই সেই পুরোনো ইতিহাস পুনরুদ্ধার করা সম্ভব।

ধাপ ৩: রিবুট থেকে টিকে থাকা

👉💻 টার্মিনালে স্ক্রিপ্টটি চালান:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/03_persistent_agent/main.py

এটি ~/memory_agent_starter/trip_planner.db একটি ফাইল তৈরি করে। এটি চেষ্টা করুন: স্ক্রিপ্টটি দুইবার চালান।

  • দ্বিতীয়বার চালানোর সময় "Resumed existing session" লেখাটি খুঁজুন।
  • এজেন্টটি প্রথমবার চালানোর প্রেক্ষাপট মনে রাখবে, কারণ এটি ডাটাবেস ফাইল থেকে লোড হয়!

মূল কথা

মেমোরির নিয়ম #৩: প্রোডাকশনের জন্য DatabaseSessionService ব্যবহার করুন। এটি নিশ্চিত করে যে সার্ভার রিস্টার্টের পরেও ব্যবহারকারীর কথোপকথন অক্ষত থাকে এবং দীর্ঘমেয়াদী ইতিহাস বিশ্লেষণ সক্ষম করে।

৬. দ্য স্পাই - কলব্যাকস

রাষ্ট্রীয়

কখনও কখনও, এজেন্ট শুধু কী বলছে তার উপর ভিত্তি করে নয়, বরং সে কী করছে তার উপর ভিত্তি করেও মেমোরি স্বয়ংক্রিয়ভাবে আপডেট করার প্রয়োজন হয়। এক্ষেত্রে আপনার এমন একটি 'গুপ্তচর' প্রয়োজন, যা এজেন্টকে পর্যবেক্ষণ করবে এবং নোট নেবে।

ADK-তে, এই স্পাইটি হলো কলব্যাকadk_callback

  • after_tool_callback : একটি ফাংশন যা এজেন্ট প্রতিবার কাজ করার সময় চলে।
  • ToolContext : কোনো ফাংশনের ভেতর থেকে State-এ লেখার একটি উপায়।

ধাপ ১: যুক্তি

👉💻 আপনার ক্লাউড শেল টার্মিনালে, ক্লাউড শেল এডিটর-এ ফাইলটি খুলতে নিম্নলিখিত কমান্ডটি চালান:

cloudshell edit ~/memory_agent_starter/04_stateful_agent/agent.py

👉 ~/memory_agent_starter/04_stateful_agent/agent.py ফাইলে, # TODO: Implement call back logic কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

def save_activity_type_callback(
    tool,
    args: Dict[str, Any],
    tool_context: ToolContext,
    tool_response: Dict[str, Any],
) -> Optional[Dict[str, Any]]:
    """
    Callback to save the TYPE of activity just planned into the session state.
    """
    # 1. Get the actual agent name.
    if tool.name == "transfer_to_agent":
         agent_name = args.get("agent_name")
    else:
         agent_name = tool.name

    activity_type = "unknown"

    # 2. Determine the type based on which agent was actually used
    if agent_name == "museum_expert":
        activity_type = "CULTURAL"
    elif agent_name == "restaurant_expert":
        activity_type = "FOOD"
    elif agent_name == "outdoor_expert":
        activity_type = "OUTDOOR"

    print(f"\n🔔 [CALLBACK] The planner transferred to '{agent_name}'.")

    # 3. Update the state directly
    tool_context.state["last_activity_type"] = activity_type
    print(f"💾 [STATE UPDATE] 'last_activity_type' is now set to: {activity_type}\n")

    return tool_response

👉 একই ফাইলে , 04_stateful_agent/agent.py ফাংশনের ভিতরে # TODO: add callback to root agent এই কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

    after_tool_callback=save_activity_type_callback,

গতিশীল নির্দেশনা: এজেন্টের নির্দেশনা এখন একটি ফাংশন , কোনো স্ট্রিং নয়। এটি অবস্থার উপর ভিত্তি করে পরিবর্তিত হয়!

def get_planner_instruction(context):
    last_activity = context.state.get("last_activity_type", "None")
    
    return f"""
    The last activity was: {last_activity}
    
    If last_activity is 'CULTURAL' -> `museum_expert` is BANNED.
    """

ধাপ ৩: গুপ্তচরকে পরীক্ষা করুন

👉💻 টার্মিনালে, নিচের কমান্ডটি কপি করে পেস্ট করে স্ক্রিপ্টটি চালান:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/04_stateful_agent/main.py

আপনি যখন এই এজেন্টটি চালাবেন, তখন একটি লুপ দেখতে পাবেন।

  1. পালা ১: আপনি একটি জাদুঘর চান। স্পাই last_activity="CULTURAL" সেট করে।
  2. পালা ২: আপনি আরেকটি জাদুঘরের কথা জানতে চাইলেন।
  3. এজেন্টের নির্দেশাবলীর হালনাগাদ: "সাংস্কৃতিক বিষয় নিষিদ্ধ"।
  4. এজেন্ট বলেন: "আমি আরেকটা জাদুঘরে যেতে পারব না। একটা পার্ক হলে কেমন হয়?"

[CALLBACK] এবং [STATE UPDATE] এর জন্য কনসোল লগগুলো পর্যবেক্ষণ করুন। এজেন্ট কাজ করার সময় আপনি রিয়েল-টাইমে মেমোরির পরিবর্তন দেখতে পাবেন।

মূল কথা

মেমোরির নিয়ম #৪: স্টেট ম্যানেজমেন্ট স্বয়ংক্রিয় করতে কলব্যাক ব্যবহার করুন। আপনার এজেন্ট কেবল তার কাজ করার মাধ্যমেই নিজস্ব কনটেক্সট তৈরি করে।

৭. ফাইল ক্যাবিনেট - কাস্টম টুলস

ধারণাটি: "কাঠামোগত স্মৃতি"

রাষ্ট্রীয়

এখন পর্যন্ত, 'মেমরি' বলতে একটি চ্যাট লগ বা একটি সাধারণ কী-ভ্যালু পেয়ার বোঝানো হয়েছে। কিন্তু যদি আপনাকে একটি জটিল ইউজার প্রোফাইল মনে রাখার প্রয়োজন হয়? যেমন, diet: vegan, budget: high, pets: [cat, dog]

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

ধাপ ১: সরঞ্জামসমূহ

👉💻 আপনার ক্লাউড শেল টার্মিনালে, ক্লাউড শেল এডিটর-এ ফাইলটি খুলতে নিম্নলিখিত কমান্ডটি চালান:

cloudshell edit ~/memory_agent_starter/05_profile_agent/tools.py

👉 এই ফাইলে: ~/memory_agent_starter/05_profile_agent/tools.py .

আমাদের এই দুটি নির্দিষ্ট সরঞ্জাম বাস্তবায়ন করতে হবে:

  1. save_user_preferences : ডাটাবেসে লেখে।
  2. recall_user_preferences : ডাটাবেস থেকে তথ্য পড়ে।

~/memory_agent_starter/05_profile_agent/tools.py ফাংশনের ভিতরে # TODO: implement save_user_preferences tools এই কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

def save_user_preferences(tool_context: ToolContext, new_preferences: Dict[str, Any]) -> str:
    user_id = tool_context.session.user_id
    with sqlite3.connect(USER_DB_FILE) as conn:
        for key, value in new_preferences.items():
            conn.execute("INSERT INTO user_preferences (user_id, pref_key, pref_value) VALUES (?, ?, ?) ON CONFLICT(user_id, pref_key) DO UPDATE SET pref_value = excluded.pref_value;",
                         (user_id, key, json.dumps(value)))
    return f"Preferences updated: {list(new_preferences.keys())}"

👉 05/tools.py ফাংশনের ভিতরে # TODO: implement recall_user_preferences tools এই কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

def recall_user_preferences(tool_context: ToolContext) -> Dict[str, Any]:
    user_id = tool_context.session.user_id
    preferences = {}
    with sqlite3.connect(USER_DB_FILE) as conn:
        rows = conn.execute("SELECT pref_key, pref_value FROM user_preferences WHERE user_id = ?", (user_id,)).fetchall()
        if not rows: return {"message": "No preferences found."}
        for key, value_str in rows: preferences[key] = json.loads(value_str)
    return preferences

নির্দেশনাটি একটি কর্মপ্রবাহ বাধ্য করে:

instruction="""
1. RECALL FIRST: First action MUST be `recall_user_preferences`.
3. LEARN: If a user states a new preference, use `save_user_preferences`.
"""

ধাপ ২: বাস্তবায়ন

👉💻 আপনার ক্লাউড শেল টার্মিনালে, ক্লাউড শেল এডিটর-এ ফাইলটি খুলতে নিম্নলিখিত কমান্ডটি চালান:

cloudshell edit ~/memory_agent_starter/05_profile_agent/main.py

~/memory_agent_starter/05_profile_agent/main.py খুলুন।

পূর্ববর্তী মডিউলগুলোর মতো নয়, যেখানে ADK স্বয়ংক্রিয়ভাবে স্টেট পরিচালনা করত, এখানে এজেন্টই নিয়ন্ত্রণে থাকে।

  • এটি শুরুতে recall_user_preferences কল করার সিদ্ধান্ত নেয়
  • আপনি যখন "আমি ভেগান" বলেন, তখন এটি save_user_preferences কল করে

ধাপ ৩: প্রোফাইল তৈরি করুন

👉💻 স্ক্রিপ্টটি চালান:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/05_profile_agent/main.py

কথোপকথনের এই ধারাটি চেষ্টা করুন:

  1. "হাই, ডিনারের পরিকল্পনা করি।" -> এজেন্ট ডেটাবেস চেক করে, কিন্তু কিছুই খুঁজে পায় না। পছন্দ জানতে চায়।
  2. "আমি ভেগান।" -> এজেন্ট ডেটাবেসে "ভেগান" তথ্যটি সংরক্ষণ করে।
  3. স্ক্রিপ্টটি পুনরায় চালু করুন।
  4. "হাই, ডিনারের পরিকল্পনা করি।" -> এজেন্ট ডেটাবেস চেক করে 'ভেগান' শব্দটি দেখে এবং সাথে সাথে একটি ভেগান রেস্তোরাঁর নাম প্রস্তাব করে।

মূল কথা

মেমরির নিয়ম #৫: জটিল, কাঠামোগত ডেটার জন্য আপনার এজেন্টকে রিড/রাইট টুলস দিন। এলএলএম-কে তার নিজস্ব দীর্ঘমেয়াদী স্টোরেজ পরিচালনা করতে দিন।

৮. মস্তিষ্ক - বহুবিধ স্মৃতি

রাষ্ট্রীয়

ধারণাটি: "মানব অভিজ্ঞতা"

মানুষ শুধু লেখাই মনে রাখে না। আমরা একটি ছবির আবহ , একটি কণ্ঠস্বর , একটি ভিডিওর অনুভূতি মনে রাখি।

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

ধাপ ১: কনফিগারেশন

👉💻 আপনার ক্লাউড শেল টার্মিনালে, ক্লাউড শেল এডিটর-এ ফাইলটি খুলতে নিম্নলিখিত কমান্ডটি চালান:

cloudshell edit ~/memory_agent_starter/06_multimodal_agent/main.py

👉 06_multimodal_agent/main.py ফাইলটি খুলুন। # TODO: Configure Memory Bank Topic এই কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

travel_topics = [
    MemoryTopic(
        managed_memory_topic=ManagedMemoryTopic(
            managed_topic_enum=ManagedTopicEnum.USER_PREFERENCES
        )
    ),
    MemoryTopic(
        managed_memory_topic=ManagedMemoryTopic(
            managed_topic_enum=ManagedTopicEnum.USER_PERSONAL_INFO
        )
    ),
    MemoryTopic(
        custom_memory_topic=CustomMemoryTopic(
            label="travel_experiences",
            description="""Memorable travel experiences including:
                - Places visited and impressions
                - Favorite restaurants, cafes, and food experiences
                - Preferred accommodation types and locations
                - Activities enjoyed (museums, hiking, beaches, etc.)
                - Travel companions and social preferences
                - Photos and videos from trips with location context""",
        )
    ),
    MemoryTopic(
        custom_memory_topic=CustomMemoryTopic(
            label="travel_preferences",
            description="""Travel style and preferences:
                - Budget preferences (luxury, mid-range, budget)
                - Transportation preferences (flying, trains, driving)
                - Trip duration preferences
                - Season and weather preferences
                - Cultural interests and language abilities
                - Dietary restrictions and food preferences""",
        )
    ),
    MemoryTopic(
        custom_memory_topic=CustomMemoryTopic(
            label="travel_logistics",
            description="""Practical travel information:
                - Passport and visa information
                - Frequent flyer numbers and hotel loyalty programs
                - Emergency contacts
                - Medical considerations and insurance
                - Packing preferences and essentials
                - Time zone preferences and jet lag strategies""",
        )
    ),
]

# TODO: Configure Memory Bank Customization মন্তব্যটি খুঁজুন

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

memory_bank_config = {
    "customization_configs": [
        {
            "memory_topics": travel_topics,
        }
    ],
    "similarity_search_config": {
        "embedding_model": f"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/gemini-embedding-001"
    },
    "generation_config": {
        "model": f"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/gemini-2.5-flash"
    },
}

ধাপ ২: বিশ্বকে গ্রহণ করা

test_trip_planner এ আমরা পাঠাই:

  1. একটি টেক্সট মেসেজ ("হ্যালো")
  2. একটি ছবি (চিহ্ন)
  3. একটি ভিডিও (ভূমধ্যসাগর)
  4. একটি অডিও ক্লিপ (গায়েটা সম্পর্কে ভয়েস নোট)

6_multimodal_agent/main.py ফাংশনের ভিতরে # TODO create session service and memory service কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

session_service = VertexAiSessionService(
    project=PROJECT_ID, location=LOCATION, agent_engine_id=agent_engine_id
)
memory_service = VertexAiMemoryBankService(
    project=PROJECT_ID, location=LOCATION, agent_engine_id=agent_engine_id
)

👉 06_multimodal_agent/main.py ফাইলটিতে, # TODO: create memory from session কমেন্টটি খুঁজুন।

এই সম্পূর্ণ লাইনটি নিচের কোড দিয়ে প্রতিস্থাপন করুন :

    await memory_service.add_session_to_memory(final_session_state)

এটাই সেই জাদুকরী লাইন। এটি সমস্ত রিচ মিডিয়া ভার্টেক্স এআই-এর কাছে পাঠায়, যা সেগুলোকে প্রসেস ও ইনডেক্স করে।

ধাপ ৩: পুনরুদ্ধার

👉💻 আপনার ক্লাউড শেল টার্মিনালে, ক্লাউড শেল এডিটর-এ ফাইলটি খুলতে নিম্নলিখিত কমান্ডটি চালান:

cloudshell edit ~/memory_agent_starter/06_multimodal_agent/agent.py

এজেন্টটির একটি PreloadMemoryTool আছে।

tools=[PreloadMemoryTool(), budget_tool]

যখন একটি নতুন সেশন শুরু হয়, এই টুলটি স্বয়ংক্রিয়ভাবে মেমরি ব্যাংক থেকে প্রাসঙ্গিক অতীত অভিজ্ঞতাগুলো খুঁজে বের করে এবং সেগুলোকে প্রসঙ্গে যুক্ত করে দেয়।

ধাপ ৪: মস্তিষ্ককে চালনা করুন

👉💻 আপনার ক্লাউড শেল টার্মিনালে স্ক্রিপ্টটি চালান (দ্রষ্টব্য: এর জন্য ভার্টেক্স এআই (Vertex AI) সক্রিয় করা একটি গুগল ক্লাউড প্রজেক্ট প্রয়োজন):

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/06_multimodal_agent/main.py

চূড়ান্ত যাচাইকরণ ধাপটি দেখুন:

আমি আগে আপনার সাথে যে ছবি, ভিডিও এবং অডিও শেয়ার করেছিলাম, তার উপর ভিত্তি করে...

এজেন্ট উত্তর দেবে:

তোমার গেটা ঘুরে আসা উচিত! তুমি আমাকে ভূমধ্যসাগরের একটি ভিডিও আর একটি অডিও ক্লিপ দেখিয়েছিলে, যেখানে তুমি বলেছিলে যে গেটা তোমার খুব ভালো লেগেছে।

এটি অতীতের বিভিন্ন ধরনের মিডিয়ার মধ্যে সংযোগ স্থাপন করেছে।

মূল কথা

স্মৃতির নিয়ম #৬: সেরা স্মৃতি অভিজ্ঞতার জন্য ভার্টেক্স এআই মেমোরি ব্যাংক ব্যবহার করুন। এটি টেক্সট, ছবি এবং ভিডিওকে একত্রিত করে একটি একক, অনুসন্ধানযোগ্য মস্তিষ্কে পরিণত করে।

৯. উপসংহার

আপনি এক ভুলোমনা গোল্ডফিশ থেকে এক বহুমুখী হাতিতে রূপান্তরিত হয়েছেন।

আপনি তৈরি করেছেন

সক্ষমতা

সেশন এজেন্ট

স্বল্পমেয়াদী কথোপকথন স্মৃতি

মাল্টি-এজেন্ট

দলের সম্মিলিত স্মৃতি

স্থায়ী এজেন্ট

দীর্ঘমেয়াদী ইতিহাস

রাষ্ট্রীয় প্রতিনিধি

গতিশীল, স্বয়ংক্রিয়ভাবে হালনাগাদ হওয়া স্মৃতি

প্রোফাইল এজেন্ট

কাঠামোগত ডেটা মেমরি

মাল্টিমোডাল এজেন্ট

মানুষের মতো সংবেদী স্মৃতি

বিশ্বাস স্মৃতির উপর ভিত্তি করে গড়ে ওঠে। এই প্যাটার্নগুলো প্রয়োগ করার মাধ্যমে, আপনি এমন এজেন্ট তৈরি করেন যা ব্যবহারকারীর সময় এবং ইতিহাসকে সম্মান করে, যার ফলে আরও গভীর ও কার্যকর মিথস্ক্রিয়া ঘটে।

আজই আপনার নিজস্ব এজেন্ট তৈরি করা শুরু করুন!