使用 ADK 建構具備狀態和個人化功能的代理

1. 簡介

title

「金魚」問題

假設你聘請旅行社規劃東京夢幻假期。使用工作階段代理,查看「金魚問題」的實際運作情形。

你走進他們的辦公室,說:

「你好,我想規劃東京 2 日遊。我對歷史遺跡和壽司感興趣。」

代理熱情地回覆:

「Great! 我安排了皇居參觀行程,晚餐則在數寄屋橋次郎享用壽司。」

你微笑著說:

「聽起來很棒!可以傳送行程給我嗎?」

服務專員一臉茫然地看著你,然後問道:

「你好,今天需要我幫忙規劃行程嗎?」

這就是「金魚問題」。如果沒有記憶,每次互動都得從頭開始。雖然代理具備智慧,知道如何規劃行程,但缺乏連貫性。AI 代理必須具備記憶能力,才能真正發揮作用。

今日任務

在本工作坊中,您將建構能記住、學習和適應的旅遊代理,解決金魚問題。您將逐步完成代理記憶用量的 6 個等級,打造出更像專屬個人助理,而非聊天機器人的系統。

等級

概念

「超能力」

第 1 關

工作階段和狀態

對話不中斷

第 2 關

多代理狀態

與團隊成員共用筆記

第 3 關

資料保留設定

即使系統重新啟動,也能記住您的身分

第 4 關

回呼

完全自主更新記憶

第 5 關

自訂工具

讀取及寫入結構化使用者個人資料

第 6 關

多模態記憶

「查看」及記住相片和影片

ADK 記憶體堆疊

在編寫程式碼之前,我們先來瞭解要使用的工具。Google Agent Development Kit (ADK) 提供結構化的記憶體處理方式:

  1. 工作階段:對話的容器。其中包含對話記錄。
  2. 狀態:附加至工作階段的鍵/值「記事本」。代理會使用這個空間儲存特定事實 (例如 destination="Tokyo")。
  3. MemoryService:長期儲存空間。我們會在這裡永久保存資料,例如使用者偏好設定或分析過的文件。

2. 設定

如要打造 AI 代理,需要兩項要素:Google Cloud 專案做為基礎,

第一部分:啟用帳單帳戶

如要執行這個程式碼實驗室,您需要有具備抵免額的帳單帳戶。請使用本程式碼實驗室頂端橫幅中的抵免額,開始進行實驗室。如果您已連結帳單帳戶,可以略過這個步驟。

第二部分:開放式環境

  1. 👉 點選這個連結,直接前往 Cloud Shell 編輯器
  2. 👉 如果今天在任何時候看到授權提示,請點選「授權」繼續操作。按一下即可授權 Cloud Shell
  3. 👉 如果終端機未顯示在畫面底部,請開啟終端機:
    • 點選「查看」。
    • 按一下「終端機」在 Cloud Shell 編輯器中開啟新的終端機
  4. 👉💻 在終端機中,使用下列指令確認您已通過驗證,且專案已設為您的專案 ID:
    gcloud auth list
    
  5. 👉💻 從 GitHub 複製 bootstrap 專案:
    git clone https://github.com/cuppibla/memory_agent_starter
    
    
  6. 👉💻 從專案目錄執行設定指令碼。
    cd ~/memory_agent_starter
    ./init.sh
    
    指令碼會自動處理其餘設定程序。
  7. 👉💻 設定所需的專案 ID:
    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 檔案。這會顯示專案資訊。

3. 基礎:工作階段和狀態

有狀態

概念:脈絡是關鍵

最基本的記憶體形式是工作階段記憶體。這樣一來,代理就能知道「我想買它」這句話中的「它」,是指你 10 秒前談到的鞋子。

在 ADK 中,我們使用 Session 物件管理這項作業。

  • 無狀態方法:為每則訊息建立新的工作階段。
  • 有狀態方法:建立一個工作階段,並在整個對話中重複使用。

步驟 1:檢查代理

👉💻 在 Cloud Shell 終端機中執行下列指令,在 Cloud Shell 編輯器中開啟檔案:

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]
)

指令會告訴 LLM 要記住,但程式碼必須提供記住的能力。

步驟 2:兩種情境

開啟 ~/memory_agent_starter/01_session_agent/main.py。

👉 在 Cloud Shell 終端機中執行下列指令,在 Cloud Shell 編輯器開啟檔案:

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
    )

測試

我們有兩個函式,可示範「金魚」和「大象」記憶之間的差異。

情境 1:有狀態 (共用工作階段)

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, ...)

情境 2:無狀態 (每次都是新工作階段)

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, ...)

步驟 3:執行代理

一起來看看實際的差異。執行指令碼:

👉💻 在指令列中執行下列指令:

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

觀察情境 1:代理記住您在第一則訊息中的偏好設定,並在第二則訊息中調整計畫。

觀察情境 2:在第二輪對話 (「你還記得我喜歡這道菜的什麼嗎?」) 中,代理完全失敗,因為這是新的工作階段。這基本上表示「我不知道你在說什麼」。

重點摘要

記憶體規則 1:一律重複使用 session.id,以保留對話內容。Session 物件是代理的短期記憶體緩衝區。

4. 團隊 - 多代理狀態

食物

概念:「傳話遊戲」

多個代理協同運作時,就像同事之間來回傳遞資料夾。如果某個代理在資料夾中寫下附註,下一個代理應能讀取。

在 ADK 中,這個「資料夾」就是狀態。

  • 狀態是工作階段中的字典 ({"key": "value"})。
  • 工作階段中的任何代理都能讀取或寫入資料。

Step 1:檢查工作流程

👉💻 在 Cloud Shell 終端機中執行下列指令,在 Cloud Shell 編輯器中開啟檔案:

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 代理的答案已有效率地儲存。
  2. {destination}:運輸服務代理會自動讀取該答案。

(不需採取任何行動) 步驟 2:Orchestrator

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

代理會協同合作,回答問題。

步驟 3:管理團隊

👉💻 在 Cloud Shell 終端機執行多代理工作流程:

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

會發生什麼情況?

  1. 美食家代理:找到「Jin Sho」(或類似餐廳)。
  2. ADK:將「Jin Sho」儲存至 state['destination']。
  3. 運輸代理:在指令中收到「Jin Sho」。
  4. 結果:「如要從加州列車站前往 Jin Sho,請沿著 University Ave 步行...」

重點摘要

記憶體規則 #2:使用狀態在代理之間傳遞結構化資訊。使用 output_key 寫入,並使用 {placeholders} 讀取。

5. 重新啟動 - 持續性

有狀態

概念:「重新啟動問題」

到目前為止,我們的記憶體為 InMemory。如果停止指令碼並重新啟動,代理就會忘記所有內容。就像電腦每次關機時都會清除硬碟資料一樣。

為解決這個問題,我們需要持續性。將 InMemorySessionService 換成 DatabaseSessionService。

步驟 1:切換資料庫

👉💻 在 Cloud Shell 終端機中執行下列指令,在 Cloud Shell 編輯器中開啟檔案:

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 檔案。

步驟 2:跨工作階段檢索

持久性不僅能讓代理繼續對話,還能從過去的對話中學習。

在同一個檔案 ~/memory_agent_starter/03_persistent_agent/main.py中,查看「Test Case 3: Cross-Session Retrieval」。

👉 找出留言 # 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?
    """

這會模擬使用者在幾個月後返回的情況。只有資料庫才能擷取舊記錄。

步驟 3:重新啟動後仍能運作

👉💻 在終端機執行指令碼:

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

這會建立 ~/memory_agent_starter/trip_planner.db 檔案。試試看:執行指令碼兩次。

  • 第二次執行時,請尋找「Resumed existing session」。
  • 代理會從資料庫檔案載入,因此會記住第一次執行的內容!

重點摘要

記憶體規則 3:在正式環境中使用 DatabaseSessionService。確保使用者對話不會因伺服器重新啟動而中斷,並可進行長期記錄分析。

6. The Spy - Callbacks

有狀態

有時,您需要根據代理的動作 (而不只是說的話) 自動更新記憶。您需要一個「間諜」來觀察代理並記錄。

在 ADK 中,這個間諜就是回呼。adk_callback

  • after_tool_callback:每次代理運作時都會執行的函式。
  • ToolContext:從該函式內部寫入狀態的方法。

步驟 1:邏輯生成法

👉💻 在 Cloud Shell 終端機中執行下列指令,在 Cloud Shell 編輯器中開啟檔案:

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

步驟 3:測試 Spy

👉💻 在終端機中複製並貼上以下指令,執行指令碼:

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

執行這個代理時,您會看到迴圈。

  1. 第 1 輪:你詢問博物館。Spy 設定 last_activity="CULTURAL"。
  2. 第 2 輪:你詢問另一間博物館。
  3. 代理指令更新:「禁止文化相關內容」。
  4. 服務專員說:「我不想再逛博物館了。公園怎麼樣?」

查看 [CALLBACK] 和 [STATE UPDATE] 的控制台記錄。代理執行工作時,您可以即時查看記憶體變化。

重點摘要

記憶體規則 4:使用回呼自動管理狀態。代理只要執行工作,就會自行建立脈絡。

7. 檔案櫃頁面 - 自訂工具

概念:「結構化記憶」

有狀態

到目前為止,「記憶」功能只是對話記錄或簡單的鍵/值組合。但如果需要記住複雜的使用者個人資料,例如 diet: vegan, budget: high, pets: [cat, dog],該怎麼辦?

因此,我們會將記憶視為工具。代理會明確決定何時開啟檔案櫃頁面 (讀取),以及何時提交報告 (寫入)。自訂工具圖表

步驟 1:工具

👉💻 在 Cloud Shell 終端機中執行下列指令,在 Cloud Shell 編輯器中開啟檔案:

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

步驟 2:執行

👉💻 在 Cloud Shell 終端機中執行下列指令,在 Cloud Shell 編輯器中開啟檔案:

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。

步驟 3:建構設定檔

👉💻 執行指令碼:

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

建議的對話流程如下:

  1. 「嗨,幫我規劃晚餐。」-> 服務專員查看資料庫,但找不到任何資訊。詢問偏好設定。
  2. 「我是全素食者。」-> 代理將「vegan」儲存至資料庫。
  3. 重新啟動指令碼。
  4. 「嗨,幫我規劃晚餐。」-> 代理檢查資料庫,看到「純素」,立即推薦純素餐廳。

重點摘要

記憶體規則 5:針對複雜的結構化資料,請為代理提供讀寫工具。讓 LLM 自行管理長期儲存空間。

8. 大腦:多模態記憶

有狀態

概念:「人類體驗」

人類不只會記住文字,我們會記得相片的氛圍、聲音的音色、影片的感覺。

Vertex AI Memory Bank 可讓代理處理多模態記憶。可擷取圖片、影片和音訊,並「理解」這些內容,以便日後擷取。

步驟 1:設定

👉💻 在 Cloud Shell 終端機中執行下列指令,在 Cloud Shell 編輯器中開啟檔案:

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"
    },
}

Step 2: Ingesting the World

在test_trip_planner,我們會傳送:

  1. 文字訊息 (「Hello」)
  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 進行處理和建立索引。

步驟 3:檢索

👉💻 在 Cloud Shell 終端機中執行下列指令,在 Cloud Shell 編輯器中開啟檔案:

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

這個代理有 PreloadMemoryTool。

tools=[PreloadMemoryTool(), budget_tool]

新工作階段開始時,這項工具會自動在記憶庫中搜尋相關的過往經驗,並將這些經驗插入情境。

步驟 4:執行 Brain

👉💻 在 Cloud Shell 終端機執行指令碼 (注意:必須使用已啟用 Vertex AI 的 Google Cloud 專案):

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

觀看最終驗證步驟:

「根據我之前與你分享的圖片、影片和音訊...」

代理會回覆:

「你應該去加埃塔!你給我看了一部地中海的影片,還有一段你說喜歡蓋塔的音訊片段。」

這項功能可將過去不同媒體類型的資料串連起來。

重點摘要

記憶體規則 6:使用 Vertex AI Memory Bank,享有極致的記憶體體驗。將文字、圖片和影片整合為單一可搜尋的大腦。

9. 結語

您已從健忘的金魚,蛻變為多模態大象。

您建立的

功能

工作階段代理

短期對話記憶

多代理

團隊共用記憶體

永久代理

長期記錄

有狀態代理

動態自我更新記憶

設定檔代理程式

結構化資料記憶體

多模態代理

類似人類的感官記憶

信任建立在記憶之上。只要採用這些模式,就能打造出尊重使用者時間和記錄的代理,進而提供更深入、更有效的互動。

立即開始建構個人化代理!