ADK की मदद से, स्टेटफ़ुल और अपने हिसाब से बनाए गए एजेंट बनाना

1. परिचय

title

"गोल्डफ़िश" समस्या

मान लें कि आपने टोक्यो में छुट्टियां बिताने के लिए, किसी ट्रैवल एजेंट को काम पर रखा है. सेशन एजेंट का इस्तेमाल करके, "गोल्डफ़िश की समस्या" को ऐक्शन में देखें.

आप उनके ऑफ़िस में जाकर कहते हैं:

"नमस्ते! मुझे टोक्यो की दो दिन की ट्रिप प्लान करनी है. मुझे ऐतिहासिक जगहों और सुशी में दिलचस्पी है."

एजेंट उत्साह के साथ जवाब देता है:

"बहुत बढ़िया! मैंने इंपीरियल पैलेस घूमने और सुकियाबाशी जिरो में सुशी खाने का प्लान बनाया है."

मुस्कुराते हुए कहो:

"यह बहुत बढ़िया है! क्या मुझे यात्रा का प्लान मिल सकता है?"

एजेंट आपकी ओर देखता है और पूछता है:

"नमस्ते! आज मैं आपकी यात्रा प्लान करने में कैसे मदद कर सकता/सकती हूं?"

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

आज का आपका मिशन

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

लेवल

सिद्धांत

"सुपरपावर"

पहला लेवल

सेशन और स्थिति

बातचीत को याद रखना

दूसरा लेवल

मल्टी-एजेंट स्टेट

टीम के सदस्यों के साथ नोट शेयर करना

तीसरा लेवल

परसिस्टेंस

सिस्टम रीबूट होने के बाद भी आपको याद रखना

चौथा लेवल

कॉल बैक

यादगार पल को पूरी तरह से अपने-आप अपडेट करना

पांचवां लेवल

कस्टम टूल

उपयोगकर्ता की स्ट्रक्चर्ड प्रोफ़ाइल को पढ़ना और लिखना

छठा लेवल

मल्टीमॉडल मेमोरी

फ़ोटो और वीडियो को "देखना" और उन्हें याद रखना

ADK मेमोरी स्टैक

कोड लिखने से पहले, आइए उन टूल के बारे में जानते हैं जिनका हम इस्तेमाल कर रहे हैं. Google एजेंट डेवलपमेंट किट (एडीके), मेमोरी को मैनेज करने का एक व्यवस्थित तरीका उपलब्ध कराती है:

  1. सेशन: यह बातचीत के लिए कंटेनर होता है. इसमें बातचीत का इतिहास सेव होता है.
  2. स्टेट: यह सेशन से जुड़ा एक की-वैल्यू "स्क्रैचपैड" होता है. एजेंट इसका इस्तेमाल कुछ खास तथ्यों को सेव करने के लिए करते हैं. जैसे, destination="Tokyo").
  3. MemoryService: लंबे समय तक डेटा सेव करने की सुविधा. हम यहां उपयोगकर्ता की प्राथमिकताओं या विश्लेषण किए गए दस्तावेज़ों जैसी चीज़ों को हमेशा के लिए सेव रखते हैं.

2. सेट करें

एआई एजेंट को बेहतर तरीके से काम करने के लिए, हमें दो चीज़ों की ज़रूरत होती है: पहला, Google Cloud प्रोजेक्ट.

पहला हिस्सा: बिलिंग खाता चालू करना

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

दूसरा हिस्सा: ओपन एनवायरमेंट

  1. 👉 सीधे Cloud Shell Editor पर जाने के लिए, इस लिंक पर क्लिक करें
  2. 👉 अगर आज किसी भी समय अनुमति देने के लिए कहा जाता है, तो जारी रखने के लिए अनुमति दें पर क्लिक करें. Cloud Shell को अनुमति देने के लिए क्लिक करें
  3. 👉 अगर टर्मिनल स्क्रीन पर सबसे नीचे नहीं दिखता है, तो इसे खोलें:
    • देखें पर क्लिक करें
    • टर्मिनलCloud Shell Editor में नया टर्मिनल खोलना पर क्लिक करें
  4. 👉💻 टर्मिनल में, पुष्टि करें कि आपने पहले ही पुष्टि कर ली है और प्रोजेक्ट को अपने प्रोजेक्ट आईडी पर सेट किया गया है. इसके लिए, यह कमांड इस्तेमाल करें:
    gcloud auth list
    
  5. 👉💻 GitHub से बूटस्ट्रैप प्रोजेक्ट का क्लोन बनाएं:
    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. 👉💻 यहां दी गई कमांड का इस्तेमाल करके, ज़रूरी एपीआई चालू करें. इसमें कुछ मिनट लग सकते हैं.
    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 फ़ाइल बनाई गई है. इससे आपके प्रोजेक्ट की जानकारी दिखती है.

3. The Foundation - Session & State

स्टेटफ़ुल

कॉन्सेप्ट: कॉन्टेक्स्ट सबसे ज़रूरी है

मेमोरी का सबसे बुनियादी रूप सेशन मेमोरी है. इसी से एजेंट को यह पता चलता है कि "मुझे इसे खरीदना है" वाक्य में "इसे" शब्द का मतलब, उस जूते से है जिसके बारे में आपने 10 सेकंड पहले बात की थी.

ADK में, हम इसे Session ऑब्जेक्ट की मदद से मैनेज करते हैं.

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

पहला चरण: एजेंट की जांच करना

👉💻 Cloud Shell टर्मिनल में, Cloud Shell Editor में फ़ाइल खोलने के लिए यह कमांड चलाएं:

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 खोलें.

👉 Cloud Shell टर्मिनल में, Cloud Shell Editor में फ़ाइल खोलने के लिए यह कमांड चलाएं:

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 ऑब्जेक्ट, आपके एजेंट का शॉर्ट-टर्म मेमोरी बफ़र होता है.

4. टीम - मल्टी-एजेंट की स्थिति

भोजन

कॉन्सेप्ट: "टेलीफ़ोन गेम"

जब कई एजेंट एक साथ काम करते हैं, तो वे ऐसे होते हैं जैसे सहकर्मी किसी फ़ाइल फ़ोल्डर को एक-दूसरे को पास कर रहे हों. अगर कोई एजेंट फ़ोल्डर में कोई नोट लिखता है, तो दूसरे एजेंट को उसे पढ़ने की अनुमति होनी चाहिए.

ADK में, इस "फ़ोल्डर" को स्टेट कहा जाता है.

  • State एक डिक्शनरी ({"key": "value"}) है, जो सेशन में मौजूद होती है.
  • सेशन में मौजूद कोई भी एजेंट, इसे पढ़ सकता है या इसमें लिख सकता है.

पहला चरण: वर्कफ़्लो की जांच करना

👉💻 Cloud Shell टर्मिनल में, Cloud Shell Editor में फ़ाइल खोलने के लिए यह कमांड चलाएं:

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": Foodie Agent के जवाब को सेव किया गया.
  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."

एजेंट, जवाब देने के लिए एक साथ काम करते हैं.

तीसरा चरण: टीम के लिए रन

👉💻 Cloud Shell टर्मिनल में, मल्टी-एजेंट वर्कफ़्लो लागू करें:

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

इससे क्या होगा?

  1. फ़ूडी एजेंट: "जिन शो" (या इसी तरह के अन्य रेस्टोरेंट) के बारे में जानकारी देता है.
  2. ADK: यह कुकी, "Jin Sho" को state['destination'] में सेव करती है.
  3. ट्रांसपोर्टेशन एजेंट: इसे निर्देश में "जिन शो" मिलता है.
  4. जवाब: "कैलट्रेन स्टेशन से जिन शो तक पहुंचने के लिए, यूनिवर्सिटी एवेन्यू पर पैदल चलें..."

मुख्य जानकारी

मेमोरी का दूसरा नियम: एजेंटों के बीच स्ट्रक्चर्ड जानकारी पास करने के लिए, स्टेट का इस्तेमाल करें. लिखने के लिए output_key और पढ़ने के लिए {placeholders} का इस्तेमाल करें.

5. रीबूट - परसिस्टेंस

स्टेटफ़ुल

कॉन्सेप्ट: "रीबूट की समस्या"

अब तक, हमारी मेमोरी InMemory रही है. स्क्रिप्ट को बंद करके फिर से शुरू करने पर, एजेंट को पिछली बातचीत की जानकारी नहीं रहती. यह एक ऐसे कंप्यूटर की तरह है जिसे बंद करने पर, उसकी हार्ड ड्राइव का डेटा मिट जाता है.

इस समस्या को ठीक करने के लिए, हमें Persistence की ज़रूरत है. हम InMemorySessionService को DatabaseSessionService से बदल देते हैं.

पहला चरण: डेटाबेस स्विच करना

👉💻 Cloud Shell टर्मिनल में, Cloud Shell Editor में फ़ाइल खोलने के लिए यह कमांड चलाएं:

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 में, टेस्ट केस 3: क्रॉस-सेशन रिट्रीवल देखें.

👉 टिप्पणी ढूंढें # 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
    )

👉 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" ढूंढें.
  • एजेंट को पहले रन का कॉन्टेक्स्ट याद रहेगा, क्योंकि यह डेटाबेस फ़ाइल से लोड होता है!

मुख्य जानकारी

Memory का तीसरा नियम: प्रोडक्शन के लिए DatabaseSessionService का इस्तेमाल करें. इससे यह पक्का किया जाता है कि सर्वर को रीस्टार्ट करने के बाद भी उपयोगकर्ता की बातचीत जारी रहे. साथ ही, इससे लंबे समय तक के इतिहास का विश्लेषण किया जा सकता है.

6. The Spy - Callbacks

स्टेटफ़ुल

कभी-कभी, आपको एजेंट की कार्रवाई के आधार पर मेमोरी को अपने-आप अपडेट करना होता है. सिर्फ़ एजेंट के जवाब के आधार पर नहीं. आपको एक "जासूस" चाहिए, जो एजेंट पर नज़र रखे और नोट ले.

ADK में, इस स्पाई को Callback कहा जाता है. adk_callback

  • after_tool_callback: यह एक ऐसा फ़ंक्शन है जो एजेंट के काम करने पर हर बार चलता है.
  • ToolContext: इस फ़ंक्शन के अंदर से स्टेट में लिखने का तरीका.

पहला चरण: लॉजिक

👉💻 Cloud Shell टर्मिनल में, Cloud Shell Editor में फ़ाइल खोलने के लिए यह कमांड चलाएं:

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.
    """

तीसरा चरण: Spy की जांच करना

👉💻 टर्मिनल में, यहां दिए गए निर्देश को कॉपी करके चिपकाएं और स्क्रिप्ट चलाएं:

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

इस एजेंट को चलाने पर, आपको एक लूप दिखेगा.

  1. पहली बारी: आपने म्यूज़ियम के बारे में पूछा. जासूस last_activity="CULTURAL" सेट करता है.
  2. दूसरा जवाब: आपने किसी दूसरे म्यूज़ियम के बारे में पूछा.
  3. एजेंट के लिए निर्देश अपडेट किए गए: "CULTURAL is BANNED".
  4. एजेंट कहता है: "मैं किसी और म्यूज़ियम के बारे में जानकारी नहीं दे सकता. पार्क के बारे में क्या ख़याल है?"

[CALLBACK] और [STATE UPDATE] के लिए कंसोल लॉग देखें. एजेंट के काम करने के दौरान, मेमोरी में होने वाले बदलावों को रीयल टाइम में देखा जा सकता है.

मुख्य जानकारी

मेमोरी का चौथा नियम: स्टेट मैनेजमेंट को ऑटोमेट करने के लिए, कॉल बैक का इस्तेमाल करें. आपका एजेंट, सिर्फ़ अपना काम करके अपना कॉन्टेक्स्ट बनाता है.

7. फ़ाइल कैबिनेट - कस्टम टूल

कॉन्सेप्ट: "स्ट्रक्चर्ड मेमोरी"

स्टेटफ़ुल

अब तक, "याददाश्त" सुविधा के तहत चैट लॉग या सामान्य की-वैल्यू पेयर सेव किए जाते थे. हालांकि, अगर आपको किसी जटिल उपयोगकर्ता प्रोफ़ाइल को याद रखना है, तो क्या होगा? उदाहरण के लिए, diet: vegan, budget: high, pets: [cat, dog].

इसके लिए, हम मेमोरी को टूल के तौर पर इस्तेमाल करते हैं. एजेंट यह तय करता है कि फ़ाइल कैबिनेट को कब खोलना है (पढ़ना) और रिपोर्ट कब फ़ाइल करनी है (लिखना). कस्टम टूल का डायग्राम

पहला चरण: टूल

👉💻 Cloud Shell टर्मिनल में, Cloud Shell Editor में फ़ाइल खोलने के लिए यह कमांड चलाएं:

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`.
"""

दूसरा चरण: लागू करना

👉💻 Cloud Shell टर्मिनल में, Cloud Shell Editor में फ़ाइल खोलने के लिए यह कमांड चलाएं:

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. "नमस्ते, डिनर का प्लान बनाओ." -> एजेंट, डेटाबेस में "वीगन" कीवर्ड खोजता है और तुरंत वीगन रेस्टोरेंट का सुझाव देता है.

मुख्य जानकारी

मेमोरी का पांचवां नियम: जटिल और स्ट्रक्चर्ड डेटा के लिए, अपने एजेंट को पढ़ने/लिखने के टूल दें. एलएलएम को अपने लॉन्ग-टर्म स्टोरेज को मैनेज करने की अनुमति दें.

8. The Brain - मल्टीमॉडल मेमोरी

स्टेटफ़ुल

कॉन्सेप्ट: "इंसानी अनुभव"

इंसानों को टेक्स्ट से ज़्यादा, इमेज याद रहती हैं. हमें किसी फ़ोटो की वाइब, किसी आवाज़ की साउंड, और किसी वीडियो की फ़ीलिंग याद रहती है.

Vertex AI Memory Bank की मदद से, आपका एजेंट मल्टीमॉडल मेमोरी को मैनेज कर सकता है. यह इमेज, वीडियो, और ऑडियो को "समझ" सकता है और उन्हें बाद में वापस पा सकता है.

पहला चरण: कॉन्फ़िगरेशन

👉💻 Cloud Shell टर्मिनल में, Cloud Shell Editor में फ़ाइल खोलने के लिए यह कमांड चलाएं:

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)

यह मैजिक लाइन है. यह सभी रिच मीडिया को Vertex AI पर भेजता है. Vertex AI, इसे प्रोसेस और इंडेक्स करता है.

तीसरा चरण: डेटा वापस पाना

👉💻 Cloud Shell टर्मिनल में, Cloud Shell Editor में फ़ाइल खोलने के लिए यह कमांड चलाएं:

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

एजेंट के पास PreloadMemoryTool है.

tools=[PreloadMemoryTool(), budget_tool]

नया सेशन शुरू होने पर, यह टूल मेमोरी बैंक में मौजूद पिछले अनुभवों से जुड़ी जानकारी को अपने-आप खोजता है और उसे कॉन्टेक्स्ट में शामिल कर देता है.

चौथा चरण: Brain को चालू करना

👉💻 अपने Cloud Shell टर्मिनल में, स्क्रिप्ट चलाएं (ध्यान दें: इसके लिए, Vertex AI की सुविधा वाला Google Cloud प्रोजेक्ट ज़रूरी है):

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

पुष्टि करने का आखिरी चरण देखें:

"मैंने आपके साथ पहले जो फ़ोटो, वीडियो, और ऑडियो शेयर किया था उसके आधार पर..."

एजेंट जवाब देगा:

"आपको गीता पढ़नी चाहिए! आपने मुझे भूमध्य सागर का एक वीडियो दिखाया था. साथ ही, आपने एक ऑडियो क्लिप में कहा था कि आपको गैटा बहुत पसंद है."

इसने अलग-अलग तरह के मीडिया को एक साथ जोड़कर, पिछले समय की झलक दिखाई.

मुख्य जानकारी

मेमोरी से जुड़ा छठा नियम: मेमोरी का बेहतर अनुभव पाने के लिए, Vertex AI Memory Bank का इस्तेमाल करें. यह टेक्स्ट, इमेज, और वीडियो को एक ही जगह पर इकट्ठा करता है, ताकि उन्हें आसानी से खोजा जा सके.

9. नतीजा

आपने एक भूलक्कड़ गोल्डफ़िश से लेकर मल्टीमॉडल हाथी तक का सफ़र तय किया है.

आपने बनाया

क्षमता

सेशन एजेंट

कुछ समय के लिए बातचीत की मेमोरी

मल्टी-एजेंट

शेयर की गई टीम मेमोरी

परसिस्टेंट एजेंट

लंबे समय का इतिहास

स्टेटफ़ुल एजेंट

डाइनैमिक, अपने-आप अपडेट होने वाली मेमोरी

प्रोफ़ाइल एजेंट

स्ट्रक्चर्ड डेटा मेमोरी

मल्टीमॉडल एजेंट

इंसानों की तरह इंद्रियों से मिली जानकारी को याद रखने की क्षमता

भरोसा, यादों के आधार पर बनता है. इन पैटर्न को लागू करके, ऐसे एजेंट बनाए जाते हैं जो उपयोगकर्ता के समय और इतिहास का ध्यान रखते हैं. इससे, ज़्यादा बेहतर और असरदार इंटरैक्शन होते हैं.

आज ही, अपनी ज़रूरत के हिसाब से एजेंट बनाना शुरू करें!