Создание агентов с сохранением состояния и персонализацией с помощью ADK

1. Введение

заголовок

Проблема "золотой рыбки"

Представьте, что вы нанимаете турагента для планирования вашего отпуска мечты в Токио. Используйте Session Agent , чтобы увидеть «Проблему золотой рыбки» в действии.

Вы заходите к ним в офис и говорите:

Привет! Хочу спланировать двухдневную поездку в Токио. Интересуют исторические места и суши.

Агент с энтузиазмом отвечает:

«Отлично! Я запланировал посещение Императорского дворца и ужин с суши в ресторане Сукиябаси Дзиро».

Вы улыбаетесь и говорите:

"Звучит идеально! Можете прислать мне маршрут?"

Агент смотрит на вас пустым взглядом и спрашивает:

«Здравствуйте! Чем я могу вам помочь спланировать поездку сегодня?»

Это «проблема золотой рыбки». Без памяти каждое взаимодействие — это чистый лист. Интеллект есть — агент знает, как планировать поездки, — но отсутствует непрерывность. Чтобы ИИ-агент был действительно полезен, ему необходимо запоминать.

Ваша миссия сегодня

На этом мастер-классе вы решите «проблему золотой рыбки», создав турагента, который запоминает, учится и адаптируется. Вы пройдете 6 уровней памяти агента , создав систему, которая ведет себя не столько как чат-бот, сколько как персональный помощник.

Уровень

Концепция

«Сверхдержава»

Уровень 1

Сессия и штат

Умение вести разговор, не забывая ничего.

Уровень 2

Многоагентное состояние

Обмен заметками между членами команды.

Уровень 3

Упорство

Мы будем помнить о вас даже после перезагрузки системы.

Уровень 4

Обратные звонки

Обновление памяти полностью автономно.

Уровень 5

Пользовательские инструменты

Чтение и написание структурированных профилей пользователей.

Уровень 6

Мультимодальная память

«Визуализация» и запоминание фотографий и видео

Стек памяти ADK

Прежде чем писать код, давайте разберемся с используемыми инструментами. Google Agent Development Kit (ADK) предоставляет структурированный способ управления памятью:

  1. Сессия : Контейнер для разговора. В нем хранится история сказанного.
  2. Состояние : Ключ-значение, представляющее собой "временный файл", прикрепленный к сессии. Агенты используют его для хранения конкретных фактов (например, destination="Tokyo" ).
  3. MemoryService : Долгосрочное хранилище. Здесь мы храним информацию вечно, например, пользовательские настройки или проанализированные документы.

2. Настройка

Для работы наших агентов искусственного интеллекта нам необходимы две вещи: проект Google Cloud, который обеспечит необходимую основу.

Часть первая: Включение платёжного аккаунта

  • Для развертывания вам потребуется пополнить свой платежный аккаунт на 5 долларов. Убедитесь, что вы активировали свою учетную запись Gmail .

Часть вторая: Открытая среда

  1. 👉 Нажмите на эту ссылку, чтобы перейти непосредственно в редактор Cloud Shell.
  2. 👉 Если сегодня вам будет предложено авторизоваться, нажмите «Авторизовать» , чтобы продолжить. Нажмите, чтобы авторизовать Cloud Shell.
  3. 👉 Если терминал не отображается внизу экрана, откройте его:
    • Нажмите «Просмотреть».
    • Нажмите «Терминал» Откройте новый терминал в редакторе Cloud Shell.
  4. 👉💻 В терминале убедитесь, что вы уже авторизованы и что проект настроен на ваш идентификатор проекта, используя следующую команду:
    gcloud auth list
    
  5. 👉💻 Клонируйте проект Bootstrap с 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. 👉💻 Включите необходимые 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 .

👉 Найдите комментарий # TODO: Create a root agent внутри функции agent.py .

Замените всю эту строку следующим кодом:

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 и найдите комментарий # TODO: Create a runner with in memorysession service inside main.py function.

Замените всю эту строку следующим кодом:

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

👉 Найдите комментарий # TODO: create a different session to test внутри функции main.py

Замените всю эту строку следующим кодом:

    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 эта "папка" называется State .

  • State — это словарь ( {"key": "value"} ), который хранится внутри сессии.
  • Любой агент в сессии может читать данные из неё или записывать в неё.

Шаг 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']
)

👉 Найдите комментарий # TODO: transportation agent внутри функции agent.py .

Замените всю эту строку следующим кодом:

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

👉 Найдите комментарий # TODO: root_agent внутри функции agent.py .

Замените всю эту строку следующим кодом:

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} : Транспортный агент автоматически считывает этот ответ.

(Никаких действий не требуется) Шаг 2: Организатор

Откройте 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. Агент-гурмана : Находит "Джин Шо" (или что-то подобное).
  2. ADK : Сохраняет "Jin Sho" в state['destination'] .
  3. Транспортный агент : получает в своих инструкциях «Джин Шо».
  4. Результат : «Чтобы добраться до Джин Шо от станции Caltrain, пройдите по Университетской авеню...»

Главный вывод

Правило №2 работы с памятью: используйте состояние для передачи структурированной информации между агентами. Используйте output_key для записи и {placeholders} для чтения.

5. Перезагрузка - Сохранение

состояние

Концепция: «Проблема перезагрузки»

До сих пор наша память работала в InMemory . Если остановить скрипт и запустить его снова, агент всё забудет. Это как компьютер, который стирает данные с жёсткого диска каждый раз, когда его выключают.

Для решения этой проблемы нам необходима функция Persistence . Мы заменяем 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 найдите тестовый пример 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
    )

👉 Найдите комментарий # TODO: Extract content from the OLD session внутри функции main.py

Замените всю эту строку следующим кодом:

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

👉 Найдите комментарий # TODO: Manually inject the context to the query внутри функции main.py

Замените всю эту строку следующим кодом:

    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 . Попробуйте следующее: запустите скрипт дважды .

  • При втором запуске найдите сообщение "Возобновлена ​​существующая сессия".
  • Агент запомнит контекст с первого запуска, поскольку он загружается из файла базы данных!

Главный вывод

Правило №3 использования памяти: используйте DatabaseSessionService в производственной среде. Это гарантирует сохранение диалогов пользователей после перезапуска сервера и позволяет проводить анализ истории в долгосрочной перспективе.

6. Шпион - Отсылки

состояние

Иногда необходимо автоматически обновлять память на основе действий агента, а не только его слов. Вам нужен «шпион», который следит за агентом и делает заметки.

В ADK этот шпион называется Callback . adk_callback

  • after_tool_callback : Функция, которая выполняется каждый раз, когда агент работает.
  • ToolContext : Способ записи в State изнутри этой функции.

Шаг 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

👉 В том же файле найдите комментарий # TODO: add callback to root agent inside the 04_stateful_agent/agent.py function.

Замените всю эту строку следующим кодом:

    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: Проверьте шпиона.

👉💻 В терминале запустите скрипт, скопировав и вставив команду ниже:

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

При запуске этого агента вы увидите зацикливание.

  1. Ход 1: Вы запрашиваете музей. Шпион устанавливает last_activity="CULTURAL" .
  2. Ход 2: Вы запрашиваете еще один музей.
  3. Обновление инструкций для агентов: «CULTURAL ЗАПРЕЩЕН».
  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 : Считывает данные из базы данных.

Найдите комментарий # TODO: implement save_user_preferences tools внутри функции ~/memory_agent_starter/05_profile_agent/tools.py .

Замените всю эту строку следующим кодом:

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())}"

👉 Найдите комментарий # TODO: implement recall_user_preferences tools внутри функции 05/tools.py .

Замените всю эту строку следующим кодом:

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. "Я веган." -> Агент сохраняет "веган" в базу данных.
  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"
    },
}

Шаг 2: Поглощение мира

В test_trip_planner мы отправляем:

  1. Текстовое сообщение («Привет»)
  2. Изображение (достопримечательность)
  3. Видео (Средиземное море)
  4. Аудиозапись (голосовое сообщение о Гаэте)

Найдите комментарий # TODO create session service and memory service внутри функции 6_multimodal_agent/main.py .

Замените всю эту строку следующим кодом:

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: Запустите мозг

👉💻 В терминале Cloud Shell запустите скрипт (Примечание: для этого требуется проект Google Cloud с включенной функцией Vertex AI):

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

Посмотрите заключительный этап проверки:

"Основываясь на фотографиях, видео и аудио, которыми я поделился с вами ранее..."

Агент ответит:

«Вам стоит посетить Гаэту ! Вы показали мне видео Средиземного моря и аудиозапись, где сказали, что вам очень нравится Гаэта».

Это позволило связать воедино различные виды медиа из прошлого.

Главный вывод

Правило №6 для улучшения памяти: используйте Vertex AI Memory Bank для достижения наилучших результатов в запоминании. Он объединяет текст, изображения и видео в единый, доступный для поиска «мозг».

9. Заключение

Вы прошли путь от забывчивой золотой рыбки до мультимодального слона.

Вы построили

Возможности

Агент сессии

Кратковременная разговорная память

Многоагентный

Общая командная память

Стойкий агент

Долгосрочная история

Государственный агент

Динамическая, самообновляющаяся память

Профиль агента

Структурированная память данных

Мультимодальный агент

Человекоподобная сенсорная память

Доверие строится на памяти. Внедряя эти модели, вы создаете агентов, которые уважают время и историю пользователя, что приводит к более глубокому и эффективному взаимодействию.

Начните создавать своих персональных агентов уже сегодня!