import os

# The Google Cloud Notebook product has specific requirements
IS_GOOGLE_CLOUD_NOTEBOOK = os.path.exists("/opt/deeplearning/metadata/env_version")

# Google Cloud Notebook requires dependencies to be installed with '--user'
USER_FLAG = ""
if IS_GOOGLE_CLOUD_NOTEBOOK:
    USER_FLAG = "--user"

!pip3 install {USER_FLAG} --upgrade pip
!pip3 install {USER_FLAG} --upgrade scikit-learn
!pip3 install {USER_FLAG} --upgrade google-cloud-aiplatform tensorboard-plugin-profile
!pip3 install {USER_FLAG} --upgrade tensorflow

"""
Explanation: <table align="left">

  <td>
    <a href="https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/master/notebooks/official/matching_engine/intro-swivel.ipynb"">
      <img src="https://cloud.google.com/ml-engine/images/colab-logo-32px.png" alt="Colab logo"> Run in Colab
    </a>
  </td>
  <td>
    <a href="https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/master/notebooks/official/matching_engine/intro-swivel.ipynb">
      <img src="https://cloud.google.com/ml-engine/images/github-logo-32px.png" alt="GitHub logo">
      View on GitHub
    </a>
  </td>
</table>

Overview
This notebook demonstrate how to train an embedding with Submatrix-wise Vector Embedding Learner (Swivel) using Vertex Pipelines. The purpose of the embedding learner is to compute cooccurrences between tokens in a given dataset and to use the cooccurrences to generate embeddings.
Vertex AI provides a pipeline template
for training with Swivel, so you don't need to design your own pipeline or write
your own training code.
It will require you provide a bucket where the dataset will be stored.
Note: you may incur charges for training, storage or usage of other GCP products (Dataflow) in connection with testing this SDK.
Dataset
You will use the following sample datasets in the public bucket gs://cloud-samples-data/vertex-ai/matching-engine/swivel:

movielens_25m: A movie rating dataset for the items input type that you can use to create embeddings for movies. This dataset is processed so that each line contains the movies that have same rating by the same user. The directory also includes movies.csv, which maps the movie ids to their names.
wikipedia: A text corpus dataset created from a Wikipedia dump that you can use to create word embeddings.

Objective
In this notebook, you will learn how to train custom embeddings using Vertex Pipelines and deploy the model for serving. The steps performed include:

Setup: Importing the required libraries and setting your global variables.
Configure parameters: Setting the appropriate parameter values for the pipeline job.
Train on Vertex Pipelines: Create a Swivel job to Vertex Pipelines using pipeline template.
Deploy on Vertex Prediction: Importing and deploying the trained model to a callable endpoint.
Predict: Calling the deployed endpoint using online prediction.
Cleaning up: Deleting resources created by this tutorial.

Costs
This tutorial uses billable components of Google Cloud:

Vertex AI
Dataflow
Cloud Storage

Learn about Vertex AI
pricing, Cloud Storage
pricing, and Dataflow pricing, and use the Pricing
Calculator
to generate a cost estimate based on your projected usage.
Set up your local development environment
If you are using Colab or Google Cloud Notebooks, your environment already meets
all the requirements to run this notebook. You can skip this step.
Otherwise, make sure your environment meets this notebook's requirements.
You need the following:

The Google Cloud SDK
Git
Python 3
virtualenv
Jupyter notebook running in a virtual environment with Python 3

The Google Cloud guide to Setting up a Python development
environment and the Jupyter
installation guide provide detailed instructions
for meeting these requirements. The following steps provide a condensed set of
instructions:


Install and initialize the Cloud SDK.


Install Python 3.


Install
   virtualenv
   and create a virtual environment that uses Python 3. Activate the virtual environment.


To install Jupyter, run pip3 install jupyter on the
command-line in a terminal shell.


To launch Jupyter, run jupyter notebook on the command-line in a terminal shell.


Open this notebook in the Jupyter Notebook Dashboard.


Install additional packages
Install additional package dependencies not installed in your notebook environment, such as google-cloud-aiplatform, tensorboard-plugin-profile. Use the latest major GA version of each package.
End of explanation
"""


# Automatically restart kernel after installs
import os

if not os.getenv("IS_TESTING"):
    # Automatically restart kernel after installs
    import IPython
    
    app = IPython.Application.instance()
    app.kernel.do_shutdown(True)

"""
Explanation: Restart the kernel
After you install the additional packages, you need to restart the notebook kernel so it can find the packages.
End of explanation
"""


import os

PROJECT_ID = ""

# Get your Google Cloud project ID and project number from gcloud
if not os.getenv("IS_TESTING"):
    shell_output = !gcloud config list --format 'value(core.project)' 2>/dev/null
    PROJECT_ID = shell_output[0]
    print("Project ID: ", PROJECT_ID)
    shell_output = !gcloud projects list --filter="$(gcloud config get-value project)" --format="value(PROJECT_NUMBER)" 2>/dev/null
    PROJECT_NUMBER = shell_output[0]
    print("Project number: ", PROJECT_NUMBER)

"""
Explanation: Before you begin
Set up your Google Cloud project
The following steps are required, regardless of your notebook environment.


Select or create a Google Cloud project. When you first create an account, you get a $300 free credit towards your compute/storage costs.


Make sure that billing is enabled for your project.


Enable the Vertex AI API and Dataflow API.


If you are running this notebook locally, you will need to install the Cloud SDK.


Enter your project ID in the cell below. Then run the cell to make sure the
Cloud SDK uses the right project for all the commands in this notebook.


Note: Jupyter runs lines prefixed with ! as shell commands, and it interpolates Python variables prefixed with $ into these commands.
Set your project ID
If you don't know your project ID, you may be able to get your project ID using gcloud.
End of explanation
"""


if PROJECT_ID == "" or PROJECT_ID is None:
    PROJECT_ID = "[your-project-id]"  # @param {type:"string"}

"""
Explanation: Otherwise, set your project ID here.
End of explanation
"""


from datetime import datetime

TIMESTAMP = datetime.now().strftime("%Y%m%d%H%M%S")

"""
Explanation: Timestamp
If you are in a live tutorial session, you might be using a shared test account or project. To avoid name collisions between users on resources created, you create a timestamp for each instance session, and append it onto the name of resources you create in this tutorial.
End of explanation
"""


import os
import sys

# If you are running this notebook in Colab, run this cell and follow the
# instructions to authenticate your GCP account. This provides access to your
# Cloud Storage bucket and lets you submit training jobs and prediction
# requests.

# The Google Cloud Notebook product has specific requirements
IS_GOOGLE_CLOUD_NOTEBOOK = os.path.exists("/opt/deeplearning/metadata/env_version")

# If on Google Cloud Notebooks, then don't execute this code
if not IS_GOOGLE_CLOUD_NOTEBOOK:
    if "google.colab" in sys.modules:
        from google.colab import auth as google_auth

        google_auth.authenticate_user()

    # If you are running this notebook locally, replace the string below with the
    # path to your service account key and run this cell to authenticate your GCP
    # account.
    elif not os.getenv("IS_TESTING"):
        %env GOOGLE_APPLICATION_CREDENTIALS ''

"""
Explanation: Authenticate your Google Cloud account
If you are using Google Cloud Notebooks, your environment is already
authenticated. Skip this step.
If you are using Colab, run the cell below and follow the instructions
when prompted to authenticate your account via oAuth.
Otherwise, follow these steps:


In the Cloud Console, go to the Create service account key
   page.


Click Create service account.


In the Service account name field, enter a name, and
   click Create.


In the Grant this service account access to project section, click the Role drop-down list. Type "Vertex AI"
into the filter box, and select
   Vertex AI Administrator. Type "Storage Object Admin" into the filter box, and select Storage Object Admin.


Click Create. A JSON file that contains your key downloads to your
local environment.


Enter the path to your service account key as the
GOOGLE_APPLICATION_CREDENTIALS variable in the cell below and run the cell.
End of explanation
"""


BUCKET_NAME = "gs://[your-bucket-name]"  # @param {type:"string"}
REGION = "us-central1"  # @param {type:"string"}

if BUCKET_NAME == "" or BUCKET_NAME is None or BUCKET_NAME == "gs://[your-bucket-name]":
    BUCKET_NAME = "gs://" + PROJECT_ID + "aip-" + TIMESTAMP

"""
Explanation: Create a Cloud Storage bucket
The following steps are required, regardless of your notebook environment.
When you submit a built-in Swivel job using the Cloud SDK, you need a Cloud Storage bucket for storing the input dataset and pipeline artifacts (the trained model).
Set the name of your Cloud Storage bucket below. It must be unique across all Cloud Storage buckets.
You may also change the REGION variable, which is used for operations
throughout the rest of this notebook. Make sure to choose a region where Vertex AI services are
available. You may
not use a Multi-Regional Storage bucket for training with Vertex AI.
End of explanation
"""


! gsutil mb -l $REGION $BUCKET_NAME

"""
Explanation: Only if your bucket doesn't already exist: Run the following cell to create your Cloud Storage bucket.
End of explanation
"""


! gsutil ls -al $BUCKET_NAME

"""
Explanation: Finally, validate access to your Cloud Storage bucket by examining its contents:
End of explanation
"""


SERVICE_ACCOUNT = "[your-service-account]"  # @param {type:"string"}

if (
    SERVICE_ACCOUNT == ""
    or SERVICE_ACCOUNT is None
    or SERVICE_ACCOUNT == "[your-service-account]"
):
    # Get your GCP project id from gcloud
    shell_output = !gcloud auth list 2>/dev/null
    SERVICE_ACCOUNT = shell_output[2].split()[1]
    print("Service Account:", SERVICE_ACCOUNT)

"""
Explanation: Service Account
If you don't know your service account, try to get your service account using gcloud command by executing the second cell below.
End of explanation
"""


!gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectCreator $BUCKET_NAME

!gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectViewer $BUCKET_NAME

"""
Explanation: Set service account access for Vertex AI Pipelines
Run the following commands to grant your service account access to read and write pipeline artifacts in the bucket that you created in the previous step -- you only need to run these once per service account.
End of explanation
"""


SOURCE_DATA_PATH = "{}/swivel".format(BUCKET_NAME)
PIPELINE_ROOT = "{}/pipeline_root".format(BUCKET_NAME)

"""
Explanation: Import libraries and define constants
Define constants used in this tutorial.
End of explanation
"""


import pandas as pd
import tensorflow as tf
from google.cloud import aiplatform
from sklearn.metrics.pairwise import cosine_similarity

"""
Explanation: Import packages used in this tutorial.
End of explanation
"""


!gsutil cp gs://cloud-samples-data/vertex-ai/matching-engine/swivel/pipeline/* .

"""
Explanation: Copy and configure the Swivel template
Download the Swivel template and configuration script.
End of explanation
"""


YOUR_PIPELINE_SUFFIX = "swivel-pipeline-movie"  # @param {type:"string"}
MACHINE_TYPE = "n1-standard-16"  # @param {type:"string"}
ACCELERATOR_COUNT = 2  # @param {type:"integer"}
ACCELERATOR_TYPE = "NVIDIA_TESLA_V100"  # @param {type:"string"}
BUCKET = BUCKET_NAME[5:]  # remove "gs://" for the following command.

!chmod +x swivel_template_configuration*

!./swivel_template_configuration_basic.sh -pipeline_suffix {YOUR_PIPELINE_SUFFIX} -project_number {PROJECT_NUMBER} -project_id {PROJECT_ID} -machine_type {MACHINE_TYPE} -accelerator_count {ACCELERATOR_COUNT} -accelerator_type {ACCELERATOR_TYPE} -pipeline_root {BUCKET}
!./swivel_template_configuration.sh -pipeline_suffix {YOUR_PIPELINE_SUFFIX} -project_number {PROJECT_NUMBER} -project_id {PROJECT_ID} -machine_type {MACHINE_TYPE} -accelerator_count {ACCELERATOR_COUNT} -accelerator_type {ACCELERATOR_TYPE} -pipeline_root {BUCKET}

"""
Explanation: Change your pipeline configurations: 

pipeline_suffix: Suffix of your pipeline name (lowercase and hyphen are allowed).
machine_type: e.g. n1-standard-16.
accelerator_count: Number of GPUs in each machine.
accelerator_type: e.g. NVIDIA_TESLA_P100, NVIDIA_TESLA_V100.
region: e.g. us-east1 (optional, default is us-central1)
network_name: e.g., my_network_name (optional, otherwise it uses "default" network).

VPC Network peering, subnetwork and private IP address configuration
Executing the following cell will generate two files:
1. swivel_pipeline_basic.json: The basic template allows public IPs and default network for the Dataflow job, and doesn't require setting up VPC Network peering for Vertex AI and you will use it in this notebook sample.
1. swivel_pipeline.json: This template enables private IPs and subnet configuration for the Dataflow job, also requires setting up VPC Network peering for the Vertex custom training. This template includes the following args:
* "--subnetwork=regions/%REGION%/subnetworks/%NETWORK_NAME%",
* "--no_use_public_ips",
* \"network\": \"projects/%PROJECT_NUMBER%/global/networks/%NETWORK_NAME%\"
WARNING In order to specify private IPs and configure VPC network, you need to set up VPC Network peering for Vertex AI for your subnetwork (e.g. "default" network on "us-central1") before submitting the following job. This is required for using private IP addresses for DataFlow and Vertex AI.
End of explanation
"""


# Copy the MovieLens sample dataset
! gsutil cp -r gs://cloud-samples-data/vertex-ai/matching-engine/swivel/movielens_25m/train/* {SOURCE_DATA_PATH}/movielens_25m

# MovieLens items embedding sample

PARAMETER_VALUES = {
    "embedding_dim": 100,  # <---CHANGE THIS (OPTIONAL)
    "input_base": "{}/movielens_25m/train".format(SOURCE_DATA_PATH),
    "input_type": "items",  # For movielens sample
    "max_vocab_size": 409600,  # <---CHANGE THIS (OPTIONAL)
    "num_epochs": 5,  # <---CHANGE THIS (OPTIONAL)
}

"""
Explanation: Both swivel_pipeline_basic.json and swivel_pipeline.json are generated.
Create the Swivel job for MovieLens items embeddings
You will submit the pipeline job by passing the compiled spec to the create_run_from_job_spec() method. Note that you are passing a parameter_values dict that specifies the pipeline input parameters to use.
The following table shows the runtime parameters required by the Swivel job:
| Parameter                  |Data type | Description                                                        | Required               |
|----------------------------|----------|--------------------------------------------------------------------|------------------------|
| embedding_dim            | int      | Dimensions of the embeddings to train.                         | No - Default is 100    |
| input_base         | string   | Cloud Storage path where the input data is stored.                       | Yes                    |
| input_type               | string   | Type of the input data.  Can be either 'text' (for wikipedia sample) or 'items'(for movielens sample).      | Yes                    |
| max_vocab_size               | int      | Maximum vocabulary size to generate embeddings for.                | No - Default is 409600 |
|num_epochs | int | Number of epochs for training. | No - Default is 20 |
In short, the items input type means that each line of your input data should be space-separated item ids. Each line is tokenized by splitting on whitespace. The text input type means that each line of your input data should be equivalent to a sentence. Each line is tokenized by lowercasing, and splitting on whitespace.
End of explanation
"""


# Instantiate PipelineJob object
pl = aiplatform.PipelineJob(
    display_name=YOUR_PIPELINE_SUFFIX,

    # Whether or not to enable caching
    # True = always cache pipeline step result
    # False = never cache pipeline step result
    # None = defer to cache option for each pipeline component in the pipeline definition
    enable_caching=False,

    # Local or GCS path to a compiled pipeline definition
    template_path="swivel_pipeline_basic.json",

    # Dictionary containing input parameters for your pipeline
    parameter_values=PARAMETER_VALUES,

    # GCS path to act as the pipeline root
    pipeline_root=PIPELINE_ROOT,
)

# Submit the Pipeline to Vertex AI
# Optionally you may specify the service account below: submit(service_account=SERVICE_ACCOUNT)
# You must have iam.serviceAccounts.actAs permission on the service account to use it
pl.submit()

"""
Explanation: Submit the pipeline to Vertex AI:
End of explanation
"""


! gsutil -m cp -r gs://cloud-samples-data/vertex-ai/matching-engine/swivel/models/movielens/model {SOURCE_DATA_PATH}/movielens_model

SAVEDMODEL_DIR = os.path.join(SOURCE_DATA_PATH, "movielens_model/model")
LOGS_DIR = os.path.join(SOURCE_DATA_PATH, "movielens_model/tensorboard")

"""
Explanation: After the job is submitted successfully, you can view its details (including run name that you'll need below) and logs.
Use TensorBoard to check the model
You may use the TensorBoard to check the model training process. In order to do that, you need to find the path to the trained model artifact. After the job finishes successfully (~ a few hours), you can view the trained model output path in the Vertex ML Metadata browser. It is going to have the following format:

{BUCKET_NAME}/pipeline_root/{PROJECT_NUMBER}/swivel-{TIMESTAMP}/EmbTrainerComponent_-{SOME_NUMBER}/model/

You may copy this path for the MODELOUTPUT_DIR below.
Alternatively, you can download a pretrained model to {SOURCE_DATA_PATH}/movielens_model and proceed. This pretrained model is for demo purpose and not optimized for production usage.
End of explanation
"""


# If on Google Cloud Notebooks, then don't execute this code.
if not IS_GOOGLE_CLOUD_NOTEBOOK:
    if "google.colab" in sys.modules:
        # Load the TensorBoard notebook extension.
        %load_ext tensorboard

# If on Google Cloud Notebooks, then don't execute this code.
if not IS_GOOGLE_CLOUD_NOTEBOOK:
    if "google.colab" in sys.modules:
        %tensorboard --logdir $LOGS_DIR

"""
Explanation: When the training starts, you can view the logs in TensorBoard:
End of explanation
"""


ENDPOINT_NAME = "swivel_embedding"  # <---CHANGE THIS (OPTIONAL)
MODEL_VERSION_NAME = "movie-tf2-cpu-2.4"  # <---CHANGE THIS (OPTIONAL)

aiplatform.init(project=PROJECT_ID, location=REGION)

# Create a model endpoint
endpoint = aiplatform.Endpoint.create(display_name=ENDPOINT_NAME)

# Upload the trained model to Model resource
model = aiplatform.Model.upload(
    display_name=MODEL_VERSION_NAME,
    artifact_uri=SAVEDMODEL_DIR,
    serving_container_image_uri="us-docker.pkg.dev/vertex-ai/prediction/tf2-cpu.2-4:latest",
)

# Deploy the Model to the Endpoint
model.deploy(
    endpoint=endpoint,
    machine_type="n1-standard-2",
)

"""
Explanation: For Google Cloud Notebooks, you can do the following:

Open Cloud Shell from the Google Cloud Console.
Install dependencies: pip3 install tensorflow tensorboard-plugin-profile
Run the following command: tensorboard --logdir {LOGS_DIR}. You will see a message "TensorBoard 2.x.0 at http://localhost:<PORT>/ (Press CTRL+C to quit)" as the output. Take note of the port number.
You can click on the Web Preview button and view the TensorBoard dashboard and profiling results. You need to configure Web Preview's port to be the same port as you receive from step 3.

Deploy the embedding model for online serving
To deploy the trained model, you will perform the following steps:
* Create a model endpoint (if needed).
* Upload the trained model to Model resource.
* Deploy the Model to the endpoint.
End of explanation
"""


!gsutil cp gs://cloud-samples-data/vertex-ai/matching-engine/swivel/movielens_25m/movies.csv ./movies.csv

movies = pd.read_csv("movies.csv")
print(f"Movie count: {len(movies.index)}")
movies.head()

# Change to your favourite movies.
query_movies = [
    "Lion King, The (1994)",
    "Aladdin (1992)",
    "Star Wars: Episode IV - A New Hope (1977)",
    "Star Wars: Episode VI - Return of the Jedi (1983)",
    "Terminator 2: Judgment Day (1991)",
    "Aliens (1986)",
    "Godfather, The (1972)",
    "Goodfellas (1990)",
]

def get_movie_id(title):
    return list(movies[movies.title == title].movieId)[0]


input_items = [str(get_movie_id(title)) for title in query_movies]

"""
Explanation: Load the movie ids and titles for querying embeddings
End of explanation
"""


predictions = endpoint.predict(instances=input_items)
embeddings = predictions.predictions
print(len(embeddings))

"""
Explanation: Look up embedding by making an online prediction request
End of explanation
"""


for idx1 in range(0, len(input_items) - 1, 2):
    item1 = input_items[idx1]
    title1 = query_movies[idx1]
    print(title1)
    print("==================")
    embedding1 = embeddings[idx1]
    for idx2 in range(0, len(input_items)):
        item2 = input_items[idx2]
        embedding2 = embeddings[idx2]
        similarity = round(cosine_similarity([embedding1], [embedding2])[0][0], 5)
        title1 = query_movies[idx1]
        title2 = query_movies[idx2]
        print(f" - Similarity to '{title2}' = {similarity}")
    print()

"""
Explanation: Explore movie embedding similarities:
End of explanation
"""


# Copy the wikipedia sample dataset
! gsutil -m cp -r gs://cloud-samples-data/vertex-ai/matching-engine/swivel/wikipedia/* {SOURCE_DATA_PATH}/wikipedia

YOUR_PIPELINE_SUFFIX = "my-first-pipeline-wiki"  # @param {type:"string"}

!./swivel_template_configuration.sh -pipeline_suffix {YOUR_PIPELINE_SUFFIX} -project_id {PROJECT_ID} -machine_type {MACHINE_TYPE} -accelerator_count {ACCELERATOR_COUNT} -accelerator_type {ACCELERATOR_TYPE} -pipeline_root {BUCKET}

# wikipedia text embedding sample

PARAMETER_VALUES = {
    "embedding_dim": 100,  # <---CHANGE THIS (OPTIONAL)
    "input_base": "{}/wikipedia".format(SOURCE_DATA_PATH),
    "input_type": "text",  # For wikipedia sample
    "max_vocab_size": 409600,  # <---CHANGE THIS (OPTIONAL)
    "num_epochs": 20,  # <---CHANGE THIS (OPTIONAL)
}

"""
Explanation: Create the Swivel job for Wikipedia text embedding (Optional)
This section shows you how to create embeddings for the movies in the wikipedia dataset using Swivel. You need to do the following steps:
1. Configure the swivel template (using the text input_type) and create a pipeline job.
2. Run the following item embedding exploration code.
The following cell overwrites swivel_pipeline_template.json; the new pipeline template file is almost identical, but it's labeled with your new pipeline suffix to distinguish it. This job will take a few hours.
End of explanation
"""


! gsutil -m cp -r gs://cloud-samples-data/vertex-ai/matching-engine/swivel/models/wikipedia/model {SOURCE_DATA_PATH}/wikipedia_model

SAVEDMODEL_DIR = os.path.join(SOURCE_DATA_PATH, "wikipedia_model/model")
embedding_model = tf.saved_model.load(SAVEDMODEL_DIR)

"""
Explanation: Submit the pipeline job through aiplatform.PipelineJob object.
After the job finishes successfully (~a few hours), you can view the trained model in your CLoud Storage browser. It is going to have the following format:

{BUCKET_NAME}/{PROJECT_NUMBER}/swivel-{TIMESTAMP}/EmbTrainerComponent_-{SOME_NUMBER}/model/

You may copy this path for the MODELOUTPUT_DIR below. For demo purpose, you can download a pretrained model to {SOURCE_DATA_PATH}/wikipedia_model and proceed. This pretrained model is for demo purpose and not optimized for production usage.
End of explanation
"""


input_items = ["horror", "film", '"HORROR! Film"', "horror-film"]
output_embeddings = embedding_model(input_items)
horror_film_embedding = tf.math.reduce_mean(output_embeddings[:2], axis=0)

# Average of embeddings for 'horror' and 'film' equals that for '"HORROR! Film"'
# since preprocessing cleans punctuation and lowercases.
assert tf.math.reduce_all(tf.equal(horror_film_embedding, output_embeddings[2])).numpy()
# Embedding for '"HORROR! Film"' equal that for 'horror-film' since the
# latter contains a hyphenation and thus is a separate token.
assert not tf.math.reduce_all(
    tf.equal(output_embeddings[2], output_embeddings[3])
).numpy()

# Change input_items with your own item tokens

input_items = ["apple", "orange", "hammer", "nails"]

output_embeddings = embedding_model(input_items)

for idx1 in range(len(input_items)):
    item1 = input_items[idx1]
    embedding1 = output_embeddings[idx1].numpy()
    for idx2 in range(idx1 + 1, len(input_items)):
        item2 = input_items[idx2]
        embedding2 = output_embeddings[idx2].numpy()
        similarity = round(cosine_similarity([embedding1], [embedding2])[0][0], 5)
        print(f"Similarity between '{item1}' and '{item2}' = {similarity}")

"""
Explanation: Explore the trained text embeddings
Load the SavedModel to lookup embeddings for items. Note the following:
* The SavedModel expects a list of string inputs.
* Each string input is treated as a list of space-separated tokens.
* If the input is text, the string input is lowercased with punctuation removed.
* An embedding is generated for each input by looking up the embedding of each token in the input and computing the average embedding per string input.
* The embedding of an out-of-vocabulary (OOV) token is a vector of zeros.
For example, if the input is ['horror', 'film', 'HORROR! Film'], the output will be three embedding vectors, where the third is the average of the first two.
End of explanation
"""


# Delete endpoint resource
# If force is set to True, all deployed models on this Endpoint will be undeployed first.
endpoint.delete(force=True)

# Delete model resource
MODEL_RESOURCE_NAME = model.resource_name
! gcloud ai models delete $MODEL_RESOURCE_NAME --region $REGION --quiet

# Delete Cloud Storage objects that were created
! gsutil -m rm -r $SOURCE_DATA_PATH

"""
Explanation: You can use the TensorBoard Embedding Projector to graphically represent high dimensional embeddings, which can be helpful in examining and understanding your embeddings.
Cleaning up
To clean up all Google Cloud resources used in this project, you can delete the Google Cloud
project you used for the tutorial.
Otherwise, you can delete the individual resources you created in this tutorial:
End of explanation
"""


