Создайте и разверните агент для выдачи паспортов домашних животных в Cloud Run.

1. Обзор

В этом практическом занятии вы узнаете, как развернуть приложение Pet Passport — агента искусственного интеллекта, использующего протокол контекста модели (MCP) для объединения анализа данных и служб определения местоположения.

Приложение помогает пользователям спланировать идеальный день с собакой, основываясь на популярности породы в Нью-Йорке. Агент использует цепочку рассуждений «от макро- к микро-фактору»:

  1. Strategic Discovery (BigQuery): Определяет почтовый индекс Нью-Йорка с наибольшей численностью представителей определенной породы.
  2. Локальное исполнение (карты): Использует почтовый индекс в качестве параметра местоположения для поиска «кафе, где разрешено находиться с домашними животными» и «площадок для выгула собак».
  3. Создание маршрута: Объединяет данные для создания маршрута «Паспорт питомца» с кликабельными ссылками и изображениями.

Агент создан с использованием фреймворка google-adk и работает на платформе Gemini.

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

2. Настройка и требования

Для начала давайте убедимся, что ваша среда разработки настроена правильно.

1. Аутентификация в Google Cloud

Укажите активный проект Google Cloud и пройдите аутентификацию. Это необходимо для доступа агента к BigQuery и другим сервисам.

gcloud config set project [YOUR-PROJECT-ID]
gcloud auth application-default login --project [YOUR-PROJECT-ID]

Примечание: Если во время аутентификации возникают ошибки, связанные с другим проектом, вы можете обойти их, отключив проект с квотой и установив его вручную:

gcloud auth application-default login --disable-quota-project
gcloud auth application-default set-quota-project [YOUR-PROJECT-ID]

2. Требования к программному обеспечению

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

  • Требуется Python (версия 3.13 или выше).
  • Git (для загрузки репозитория)

Скачать репозиторий

Код этого проекта доступен в репозитории Google MCP. Клонируйте репозиторий и перейдите в папку проекта:

git clone https://github.com/google/mcp.git
cd examples/petpassport

3. Установка

Теперь, когда у вас есть файлы, давайте настроим среду Python.

  1. Создайте виртуальное окружение: это обеспечит изоляцию ваших зависимостей.
    python3 -m venv .venv
    
  2. Активируйте виртуальную среду:
    • В Linux/macOS:
      source .venv/bin/activate
      
    • В Windows:
      .venv\Scripts\activate
      
  3. Установите зависимости:
    pip install google-adk==1.28.0 python-dotenv google-genai pillow uvicorn
    

Включите облачные API.

Включите следующие API в вашем проекте:

gcloud services enable \
  bigquery.googleapis.com \
  aiplatform.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  run.googleapis.com \
  storage.googleapis.com

Выберите регион

Установите регион в качестве переменной окружения в вашей оболочке:

export REGION=us-central1

4. Получите ключи API.

Для использования сервисов Maps и Gemini необходимо получить ключи API и сохранить их в файле .env в корне проекта.

1. Ключ API Google Maps

  1. Перейдите в консоль Google Cloud .
  2. Перейдите в раздел API и сервисы > Учетные данные .
  3. Нажмите «Создать учетные данные» > «Ключ API» .
  4. Скопируйте сгенерированный ключ и добавьте его в файл .env следующим образом: MAPS_API_KEY=[YOUR_KEY] .
  5. (Рекомендуется) Ограничьте доступ к ключу, разрешив только те API карт, которые используются сервером MCP.

2. Ключ API Gemini (AI Studio)

  1. Перейдите в Google AI Studio .
  2. Нажмите «Получить ключ API» или перейдите в раздел «Ключи API».
  3. Нажмите «Создать ключ API» .
  4. Скопируйте ключ и добавьте его в файл .env следующим образом: GEMINI_API_KEY=[YOUR_KEY] .

5. Установите зависимости

Создайте файл requirements.txt в папке petpassport/ :

google-adk==1.28.0
python-dotenv
google-genai
pillow

6. Аутентификация серверов MCP

Это приложение использует серверы протокола Model Context Protocol (MCP) для взаимодействия с Google Maps и BigQuery. Для аутентификации на этих серверах необходимо настроить соответствующие переменные среды и заголовки.

  1. Google Maps MCP: Требуется действительный ключ API карт, переданный в заголовке X-Goog-Api-Key .
  2. BigQuery MCP: Требуются учетные данные OAuth с доступом к сервису BigQuery. Агент использует учетную запись вычислительной службы по умолчанию при работе в Cloud Run или ваши локальные учетные данные при локальной работе.

В репозитории находится скрипт настройки setup/setup_env.sh , который поможет настроить эти переменные в вашем файле .env .

7. Создание таблицы BigQuery

Прежде чем агент сможет запрашивать данные о лицензиях на собак, нам необходимо создать набор данных и таблицу в BigQuery и загрузить данные.

Мы предоставляем скрипт setup/setup_bigquery.sh , который выполняет следующие шаги:

  1. Создает сегмент облачного хранилища с именем pet-passport-data-[PROJECT_ID] для хранения необработанных данных.
  2. Загружает общедоступный набор данных о лицензировании собак в Нью-Йорке (CSV).
  3. Загружает CSV-файл в хранилище.
  4. Создает набор данных BigQuery с именем nyc_dogs .
  5. Загружает данные из хранилища в таблицу с именем licenses в наборе данных.

Для запуска скрипта установки выполните следующую команду в терминале:

bash setup/setup_bigquery.sh

8. Подключитесь к серверам MCP.

Ключевой частью этого приложения является использование MCP для подключения к данным и сервисам. В этом разделе вы настроите наборы инструментов MCP для BigQuery и Google Maps в файле petpassport/tools.py .

Полный код tools.py

Вот полная реализация tools.py , включая наборы инструментов MCP и пользовательские инструменты для сохранения изображений и данных. Мы оптимизировали этот код, чтобы уменьшить избыточность, перенеся разрешение сегментов на уровень модуля:

import os
import dotenv
import google.auth
import time
import datetime
from google.cloud import storage
from PIL import Image
from google import genai
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams 

MAPS_MCP_URL = "https://mapstools.googleapis.com/mcp" 
BIGQUERY_MCP_URL = "https://bigquery.googleapis.com/mcp" 

PROJECT_ID = os.getenv('GOOGLE_CLOUD_PROJECT', 'project_not_set')
BUCKET_NAME = f"pet-passport-data-{PROJECT_ID}" 

def get_maps_mcp_toolset():
    dotenv.load_dotenv()
    maps_api_key = os.getenv('MAPS_API_KEY', 'no_api_found')
    
    tools = MCPToolset(
        connection_params=StreamableHTTPConnectionParams(
            url=MAPS_MCP_URL,
            headers={    
                "X-Goog-Api-Key": maps_api_key
            },
            timeout=30.0,          
            sse_read_timeout=300.0
        )
    )
    print("Maps MCP Toolset configured.")
    return tools


def get_bigquery_mcp_toolset():   
    credentials, project_id = google.auth.default(
            scopes=["https://www.googleapis.com/auth/bigquery"]
    )

    credentials.refresh(google.auth.transport.requests.Request())
    oauth_token = credentials.token
        
    HEADERS_WITH_OAUTH = {
        "Authorization": f"Bearer {oauth_token}",
        "x-goog-user-project": project_id
    }

    tools = MCPToolset(
        connection_params=StreamableHTTPConnectionParams(
            url=BIGQUERY_MCP_URL,
            headers=HEADERS_WITH_OAUTH,
            timeout=30.0,          
            sse_read_timeout=300.0
        )
    )
    print("BigQuery MCP Toolset configured.")
    return tools

def generate_pet_passport_photo(prompt: str, image_path: str = None) -> str:
    """Generates an image using gemini-3.1-flash-image-preview based on a prompt and a reference image."""
    client = genai.Client()
    output_path = f"/tmp/pet_passport_{int(time.time())}.png"
    
    try:
        image = Image.open(image_path)
        response = client.models.generate_content(
            model="gemini-3.1-flash-image-preview",
            contents=[prompt, image],
        )
        
        for part in response.parts:
            if part.inline_data is not None:
                generated_image = part.as_image()
                generated_image.save(output_path)
                
                # Upload to GCS and generate signed URL
                try:
                    storage_client = storage.Client()
                    bucket = storage_client.bucket(BUCKET_NAME)
                    blob_name = os.path.basename(output_path)
                    blob = bucket.blob(blob_name)
                    
                    blob.upload_from_filename(output_path)
                    
                    url = blob.generate_signed_url(
                        version="v4",
                        expiration=datetime.timedelta(hours=24),
                        method="GET",
                    )
                    return url
                except Exception as e:
                    print(f"Error uploading image to GCS: {e}")
                    return output_path
                
        raise ValueError("No image was returned by the model.")
    except Exception as e:
        print(f"Error generating image: {e}")
        raise

def save_pet_passport(user_id: str, breed: str, postal_code: str, route_details: str, image_paths: list[str] = None) -> str:
    """Appends the generated itinerary to the user's history in GCS."""
    try:
        storage_client = storage.Client()
        bucket = storage_client.bucket(BUCKET_NAME)
        blob = bucket.blob(f"user-{user_id}.json")
        
        # Download existing or start fresh
        # ... (Implementation details hidden for brevity) ...
        return "Success"
    except Exception as e:
        print(f"Error saving path: {e}")
        raise

Пояснение к коду: tools.py

  • get_maps_mcp_toolset и get_bigquery_mcp_toolset настраивают клиенты MCP с правильными конечными точками и заголовками аутентификации.
  • generate_pet_passport_photo использует Gemini для создания сцены и загружает результат в Google Cloud Storage, возвращая подписанный URL-адрес на фронтенд для сохранения работоспособности после перезапуска сервера.

9. Создание агента

После настройки инструментов пришло время создать «мозг» агента. Для создания агента в файле petpassport/agent.py вы будете использовать комплект разработки агентов (ADK).

Полный код agent.py

Вот полная реализация файла agent.py , где мы определяем агента и его инструкции:

import os
import dotenv
import tools
from google.adk.agents import LlmAgent

dotenv.load_dotenv()

PROJECT_ID = os.getenv('GOOGLE_CLOUD_PROJECT', 'project_not_set')

maps_toolset = tools.get_maps_mcp_toolset()
bigquery_toolset = tools.get_bigquery_mcp_toolset()

root_agent = LlmAgent(
    model='gemini-2.5-pro',
    name='root_agent',
    instruction=f"""
        You are the Pet Passport Agent. Your goal is to help users find a fun walking route for their dog in NYC.
        
        When given a breed and a postal code, follow this flow:
        1. **Strategic Discovery:** Use BigQuery to find the most popular neighborhood for that breed in NYC.
        2. **Local Execution:** Use Maps to build a walking route with specific places (parks, cafes) in that area.
        
        **NO DIRECTIONS LINKS:** You must NOT include a Google Maps directions link (e.g., `https://www.google.com/maps/dir/...`) in your final response. Only provide links to individual places.
        
        After generating the itinerary, you MUST call the `save_pet_passport` tool to save this path to the user's profile. Pass a clean summary of the itinerary as `route_details`. The summary should include details (like rating, description from maps).
    """,
    tools=[maps_toolset, bigquery_toolset, tools.generate_pet_passport_photo, tools.save_pet_passport]
)

Пояснение к коду: agent.py

  • Мы импортируем tools напрямую (в плоской структуре) для поддержки контейнерной среды.
  • Агент инициализируется с помощью gemini-2.5-pro .
  • Инструкции определяют строгую многоступенчатую последовательность действий (сначала BigQuery, затем Maps) и категорически запрещают создание или отображение пешеходных маршрутов, которые приводят к загромождению пространства.

10. Запуск приложения локально

Перед развертыванием в Cloud Run рекомендуется протестировать приложение локально.

  1. Убедитесь, что вы находитесь в каталоге проекта:
    cd examples/petpassport
    
  2. Запуск сервера FastAPI: для запуска приложения мы используем uvicorn . Точкой входа является main.py расположенный в папке petpassport .
    uvicorn petpassport.main:app --reload
    
  3. Откройте пользовательский интерфейс: перейдите по адресу http://127.0.0.1:8000/ui/ в вашем браузере, чтобы взаимодействовать с интерфейсом «Паспорт питомца».

11. Развертывание в Cloud Run

После того, как ваш агент готов, пришло время развернуть его в Cloud Run. Мы используем стандартную команду gcloud напрямую, чтобы обеспечить строгий контроль над средой контейнера.

Из каталога проекта выполните следующую команду:

gcloud run deploy petpassport \
  --source petpassport \
  --region $REGION \
  --allow-unauthenticated \
  --labels dev-tutorial=google-mcp

Настройка переменных среды

После развертывания перейдите к службе Cloud Run в консоли Google Cloud и установите следующие переменные среды на вкладке «Переменные и секреты» :

  • MAPS_API_KEY : Ваш ключ API Google Maps.
  • GOOGLE_CLOUD_PROJECT : Идентификатор вашего проекта.
  • PROJECT_ID : Идентификатор вашего проекта (поддерживается избыточность для устаревших модулей).

12. Примеры подсказок

Попробуйте взаимодействовать с развернутым агентом, используя следующие подсказки:

  1. Стандартный маршрут: «Я хочу пойти на прогулку со своим золотистым ретривером в Нью-Йорке, недалеко от 10021. Найдите маршрут, где есть кафе».
  2. Другая порода: «У меня французский бульдог, и мы живем в Верхнем Вест-Сайде (недалеко от 10024). Посоветуйте короткую прогулку с остановкой в ​​популярном собачьем парке».
  3. С изображением: (Загрузите фотографию вашей собаки) «Вот фотография моей корги! Мы живем недалеко от 10013. Спланируйте для нас идеальный день».

13. Уборка

Чтобы избежать расходов на ресурсы, использованные в этом руководстве:

  • Удалите службу Cloud Run: gcloud run services delete petpassport --region=$REGION
  • Удалите корзину GCS: gcloud storage rm -r gs://pet-passport-data-$PROJECT_ID