Chapter 64
Building and Deploying a Google Maps API Agent with Agent Engine
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.Building and Deploying a Google Maps API Agent with Agent Engine
Share to:
| Author(s) | Kristopher Overholt |
Overview
Gemini
Gemini is a family of Generative AI models developed by Google DeepMind that is designed for multimodal use cases.
Function Calling in Gemini
Function calling lets developers create a description of a function in their code, then pass that description to a language model in a request. The response from the model includes the name of a function that matches the description and the arguments to call it with.
Agent Engine in Vertex AI
Agent Engine is a managed service that helps you to build and deploy agent frameworks. It gives you the flexibility to choose how much reasoning you want to delegate to the LLM and how much you want to handle with customized code. You can define Python functions that get used as tools via Gemini Function Calling. Agent Engine integrates closely with the Python SDK for the Gemini model in Vertex AI, and it can manage prompts, agents, and examples in a modular way. Agent Engine is compatible with LangChain, LlamaIndex, or other Python frameworks.
Objectives
In this tutorial, you will build and deploy an agent (model, tools, and reasoning) using the Vertex AI SDK for Python.
You'll build and deploy an agent that uses different components of the Google Maps API to help with various tasks related to planning and building a community solar panel project:
- Install the Vertex AI SDK for Python
- Define a model for your agent
- Define Python functions as tools so that our agent can:
- Geocode addresses to lat/lon coordinates using the Maps Geocoding API
- Get information about places using the Maps Places API
- Generate satellite map images using the Maps Static API
- Generate solar potential map images using the Maps Solar API
- Use the LangChain agent template provided in the Vertex AI SDK for Agent Engine
- Test your agent locally before deploying
- Deploy and test your agent on Agent Engine in Vertex AI
Enable APIs and Services
This tutorial uses the following billable components of Google Cloud, which you'll need to enable for this tutorial:
- Enable Vertex AI API
- Enable Maps Geocoding API
- Enable Maps Places API
- Enable Maps Static API
- Enable Maps Solar API
- Enable Resource Manager API
Learn about Vertex AI pricing and use the Pricing Calculator to generate a cost estimate based on your projected usage.
Getting Started
Install Vertex AI SDK for Python
Install the latest version of the Vertex AI SDK for Python as well as extra dependencies related to Agent Engine and LangChain:
%pip install --upgrade --quiet \
"google-cloud-aiplatform[langchain,agent_engines]" \
googlemaps \
google-cloud-storage \
google-cloud-resource-manager \
matplotlib \
rasterio \
requestsAuthenticate your notebook environment (Colab only)
If you are running this notebook on Google Colab, run the following cell to authenticate your environment. This step is not required if you are using Vertex AI Workbench.
import sys
if "google.colab" in sys.modules:
from google.colab import auth
auth.authenticate_user()Set Google Cloud project information and initialize Vertex AI SDK
To get started using Vertex AI, you must have an existing Google Cloud project and enable the Vertex AI API.
Learn more about setting up a project and a development environment.
PROJECT_ID = "[your-project-id]" # @param {type:"string"}
LOCATION = "us-central1" # @param {type:"string"}
STAGING_BUCKET = f"gs://{PROJECT_ID}-agent-engine-staging" # @param {type:"string"}
import vertexai
vertexai.init(project=PROJECT_ID, location=LOCATION)Example: Build and Deploy an Agent for Community Solar Project Planning
In this tutorial, you'll build Python functions as tools that the Gemini model will use to help users plan for community solar panel projects.
When designing a community solar project, you'll need to identify potential locations to build your solar project on, look up relevant government offices and suppliers to help you with the planning and implementation process, and review satellite images and solar potential of regions and buildings to find the optimal location to install your solar panels.
Rather than doing all of this research work manually, it would be nice to build and deploy an agent powered by the Gemini model so to help us with these geocoding and mapping tasks along the way?
Let's build an agent that does exactly that!
Import libraries
import matplotlib.pyplot as plt
from IPython.display import Image, Markdown, display
from google.cloud import resourcemanager_v3, storage
from rasterio.io import MemoryFile
from vertexai.agent_engines import LangchainAgentDefine generative model
The first step of your agent involves the generative model you want to use. Here you'll define the Gemini model for your agent:
model = "gemini-2.5-flash"Input your Google Maps API key
Once you've enable the relevant Google Maps APIs, you can generate a Maps API key and paste it in the cell below.
You'll use this Maps API key to work with the Maps Geocoding API, Maps Places API, and other Maps APIs using the functions in the next section:
MAPS_API_KEY = "YOUR_MAPS_API_KEY"Define Python functions as tools
The second component of your agent involves Python functions as tools, which will enable the Gemini model to interact with external systems, databases, document stores, and other APIs so that the model can get the most up-to-date information or take action with those systems.
In this example, you'll define four functions that work with different components of the Maps API to perform geocoding of addresses, search for places, and generate maps:
def geocode_address(query: str):
"""Convert an address or location into latitude and longitude coordinates using the Google Maps Geocoding API"""
import googlemaps
gmaps = googlemaps.Client(key=MAPS_API_KEY)
response = gmaps.geocode(query)
return response[0]["geometry"]["location"]
def search_places(query: str):
"""Search for places using the Google Maps Places API"""
import googlemaps
gmaps = googlemaps.Client(key=MAPS_API_KEY)
response = gmaps.places(query)
return response
def create_satellite_map(location: str):
"""Create a satellite map of a specific location using the Google Maps Static API"""
import googlemaps
from google.cloud import storage
gmaps = googlemaps.Client(key=MAPS_API_KEY)
response = gmaps.static_map(
size=800,
maptype="hybrid",
center=location,
zoom=18,
)
f = open("satellite_map.png", "wb")
for chunk in response:
if chunk:
f.write(chunk)
f.close()
storage_client = storage.Client()
bucket = storage_client.bucket(STAGING_BUCKET.replace("gs://", ""))
blob = bucket.blob("agent_engine/satellite_map.png")
blob.upload_from_filename("satellite_map.png")
return response
def create_solar_potential_map(
latitude: str,
longitude: str,
):
"""Get raw solar information as a TIFF image for an area surrounding a location using the Google Maps Solar API"""
import requests
from google.cloud import storage
response = requests.get(
"https://solar.googleapis.com/v1/dataLayers:get",
params={
"location.latitude": latitude,
"location.longitude": longitude,
"radiusMeters": 100,
"view": "FULL_LAYERS",
"requiredQuality": "HIGH",
"pixelSizeMeters": 0.5,
"key": MAPS_API_KEY,
},
)
solar_flux_url = response.json()["annualFluxUrl"] + "&key=" + MAPS_API_KEY
response_solar_flux = requests.get(solar_flux_url)
with open("solar_flux_map.tiff", "wb") as f:
f.write(response_solar_flux.content)
storage_client = storage.Client()
bucket = storage_client.bucket(STAGING_BUCKET.replace("gs://", ""))
blob = bucket.blob("agent_engine/solar_flux_map.tiff")
blob.upload_from_filename("solar_flux_map.tiff")
return responseNow you can test the above functions with sample inputs to ensure that they are working as expected:
# Test geocoding
geocode_address("Tempelhof Airport Field in Berlin, Germany")Output
{'lat': 52.48249740000001, 'lng': 13.38914}# Test places search
response = search_places(query="Parking lots near the Tempelhof Airport Field")
for result in response["results"]:
print(result["name"], result["formatted_address"])Output
P+R Tempelhof (S+U) Tempelhofer Damm 118, 12099 Berlin, Germany THF Parkplatz Tempelhofer Damm 45, 12101 Berlin, Germany McParking Parkplatz Bohnsdorf Flughafen BER Berlin Brandenburg Gebrüder-Hirth-Straße 27, 12526 Berlin, Germany Dein Stellplatz - Parken Flughafen Berlin - Günstig Parken am BER Hufenweg 16, 12526 Berlin, Germany 123 Park & Fly Schönefeld DE, Zeppelinring 21, 15749 Mittenwalde, Germany Easy Airport Parking Berlin Brandenburg Am Flughafen 1-5, 12529 Schönefeld, Germany P+R Priesterweg Priesterweg, 12157 Berlin, Germany
# Test satellite map generation
create_satellite_map("Tempelhof Airport Field")
# Retrieve and display the satellite image from your GCS bucket
storage_client = storage.Client()
bucket = storage_client.bucket(STAGING_BUCKET.replace("gs://", ""))
blob = bucket.blob("agent_engine/satellite_map.png")
image_content = blob.download_as_bytes()
Image(image_content)Output
<IPython.core.display.Image object>
[省略较大 image/png 输出]
# Test solar potential map
create_solar_potential_map(latitude="52.482115", longitude="13.389191")
# Retrieve and display the solar flux image from your GCS bucket
storage_client = storage.Client()
bucket = storage_client.bucket(STAGING_BUCKET.replace("gs://", ""))
blob = bucket.blob("agent_engine/solar_flux_map.tiff")
image_content = blob.download_as_bytes()
with MemoryFile(image_content) as memfile, memfile.open() as dataset:
img = dataset.read()
plt.imshow(img[0])
plt.show()Output
<Figure size 640x480 with 1 Axes>
[省略较大 image/png 输出]
Define agent
The third component of your agent involves adding a reasoning layer, which helps your agent use the tools that you provided to help the end user achieve a higher-level goal.
If you were to use Gemini and Function Calling on their own without a reasoning layer, you would need to handle the process of calling functions and APIs in your application code, and you would need to implement retries and additional logic to ensure that your function calling code is resilient to failures and malformed requests.
Here, you'll use the LangChain agent template provided in the Vertex AI SDK for Agent Engine, which brings together the model, tools, and reasoning that you've built up so far:
agent = LangchainAgent(
model=model,
model_kwargs={"temperature": 0},
tools=[
geocode_address,
search_places,
create_satellite_map,
create_solar_potential_map,
],
)Test your agent locally
Now you can test the model and agent behavior to ensure that it's working as expected before we deploy it:
response = agent.query(
input="""I'd like to start a community effort to build a solar panel project
near the Tokyo Big Sight Exhibition Center. What are some nearby government
offices that might help me?"""
)
display(Markdown(response["output"]))Output
<IPython.core.display.Markdown object>
Deploy your agent on Vertex AI
Now that you've tested your agent locally, you're ready to deploy it to Agent Engine in Vertex AI. This will make your agent accessible remotely and allow you to integrate it into larger systems or provide it as a service.
client = vertexai.Client(project=PROJECT_ID, location=LOCATION)
remote_agent = client.agent_engines.create(
agent=agent,
config={
"staging_bucket": STAGING_BUCKET,
"requirements": [
"google-cloud-aiplatform[agent_engines,langchain]",
"googlemaps",
"google-cloud-storage",
"rasterio",
"requests",
],
},
)Grant Storage Object User access to GCS bucket
Before you send queries to your remote agent, you'll need to grant write permissions to your GCS bucket for the "Storage Object User" role so that the Agent Engine service can read and write image files in this tutorial to your bucket:
# Retrieve the project number associated with your project ID
rm_client = resourcemanager_v3.ProjectsClient()
project = rm_client.get_project(name=f"projects/{PROJECT_ID}")
project_number = project.name.split("/")[-1] # Extract number from resource name
# Grant the "Storage Object User" role on your staging bucket in GCS
storage_client = storage.Client()
bucket = storage_client.bucket(STAGING_BUCKET.replace("gs://", ""))
policy = bucket.get_iam_policy(requested_policy_version=3)
policy.bindings.append(
{
"role": "roles/storage.objectUser",
"members": [
f"serviceAccount:service-{project_number}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
],
}
)
bucket.set_iam_policy(policy)Output
<google.api_core.iam.Policy at 0x78ad0c19dc70>
Test your remotely deployed agent
With all of the core components of your community solar planning agent in place, you can send prompts to your remotely deployed agent to perform different tasks and test that it's working as expected:
response = remote_agent.query(
input="""I'd like to start a community effort to build a solar panel project
near the Tokyo Big Sight Exhibition Center. What are some nearby government
offices that might help me?"""
)
display(Markdown(response["output"]))Output
<IPython.core.display.Markdown object>
response = remote_agent.query(
input="""I'd like to start a community effort to build a solar panel project
near the Tokyo Big Sight Exhibition Center. Can you show me a satellite map
of the area?"""
)
display(Markdown(response["output"]))Output
<IPython.core.display.Markdown object>
# Retrieve and display the satellite image from your GCS bucket
bucket = storage_client.bucket(STAGING_BUCKET.replace("gs://", ""))
blob = bucket.blob("agent_engine/satellite_map.png")
image_content = blob.download_as_bytes()
Image(image_content)Output
<IPython.core.display.Image object>
[省略较大 image/png 输出]
response = remote_agent.query(
input="""I'd like to start a community effort to build a solar panel project
near the Tokyo Big Sight Exhibition Center. Can you show me a map the solar
potential for this area?"""
)
display(Markdown(response["output"]))Output
<IPython.core.display.Markdown object>
# Retrieve and display the solar flux image from your GCS bucket
bucket = storage_client.bucket(STAGING_BUCKET.replace("gs://", ""))
blob = bucket.blob("agent_engine/solar_flux_map.tiff")
image_content = blob.download_as_bytes()
with MemoryFile(image_content) as memfile, memfile.open() as dataset:
img = dataset.read()
plt.imshow(img[0])
plt.show()Output
<Figure size 640x480 with 1 Axes>
[省略较大 image/png 输出]
Querying your deployed agent
You've now deployed your Agent Engine agent and can interact with it in multiple ways, both within this notebook and from other applications or environments. The primary methods for accessing your deployed agent are via the Python client library or through REST API calls. Here's an overview of both methods:
Method 1: Reusing within this notebook or another Python environment
You can directly reuse and query the remote_agent instance you created in this notebook.
Or, you can instantiate a new instance in another notebook or Python script. To do this, you'll need to retrieve your deployed agent's resource name that uniquely identifies your agent, which is a string that includes the project, location, and Agent Engine ID. You can retrieve it by running the following code in the notebook or environment where you created your agent:
remote_agent.api_resource.nameUse the resource name to load the agent in your other notebook or Python script, then query the remote agent as usual:
# from vertexai import agent_engines
# client = vertexai.Client(project=PROJECT_ID, location=LOCATION)
# AGENT_ENGINE_RESOURCE_NAME = "YOUR_AGENT_ENGINE_RESOURCE_NAME" # Replace with the resource name of your deployed Agent Engine
# remote_agent = client.agent_engines.get(name=AGENT_ENGINE_RESOURCE_NAME)
# response = remote_agent.query(input="What is the lat/long of Tempelhof Airport Field in Berlin, Germany?")Method 2: Accessing from other environments via REST API
Beyond the Python client library, your deployed Vertex AI agent can be queried using REST API calls, including:
- Python: You can use Python's
requestslibrary or similar tools to make HTTP calls to the Vertex AI REST API. - cURL: A command-line tool, cURL allows you to send HTTP requests directly. This is useful for testing and debugging.
- Other Programming Languages: If you prefer a different language for your application, you can use its native HTTP client library to make REST API calls.
In summary, you have access to your deployed Agent Engine agent through the Python client library within Python environments, and more universally through its REST API via tools and programming languages of your choosing.
Cleaning up
After you've finished experimenting, it's a good practice to clean up your cloud resources. You can delete the deployed Agent Engine instance and optionally remove the staging bucket to avoid any unexpected charges on your Google Cloud account.
# Delete the deployed agent
client.agent_engines.delete(name=remote_agent.api_resource.name)
# Optionally, delete the staging bucket
# from google.cloud import storage
# storage.Client().bucket(STAGING_BUCKET.replace("gs://", "")).delete(force=True)