BigQuery Remote Functions verwenden, um in einer SQL-Abfrage Fragen an Vertex AI Visual Question Answering (VQA) zu stellen

1. Einführung

Übersicht

Mit BigQuery-Remote-Funktionen können Sie eine Funktion in anderen Sprachen als SQL und JavaScript oder mit den Bibliotheken und Diensten implementieren, die in benutzerdefinierten BigQuery-Funktionen nicht zulässig sind. BigQuery-Remote-Funktionen bieten eine direkte Integration mit Cloud Run-Funktionen und Cloud Run. Sie können eine BigQuery-Remotefunktion in einer SQL-Abfrage aufrufen, indem Sie eine oder mehrere Spalten als Eingabe angeben und dann einen einzelnen Wert als Ausgabe zurückgeben.

Cloud Run Functions ist eine einfache Computing-Lösung für Entwickler zum Erstellen eigenständiger und zweckgebundener Funktionen, die über HTTPS ausgelöst werden können oder auf CloudEvents reagieren, ohne dass ein Server oder eine Laufzeitumgebung verwaltet werden muss. Cloud Run-Funktionen unterstützen Node.js, Python, Go, Java, .NET, Ruby und PHP.

In diesem Codelab erfahren Sie, wie Sie eine BigQuery-Remotefunktion erstellen, um mithilfe von Vertex AI Visual Question Answering (VQA) Antworten auf Fragen zu in Cloud Storage gespeicherten Bildern zu erhalten. Ihre SQL-Abfrage ruft einen URI für ein Bild aus einer Tabelle in BigQuery ab. Anschließend senden Sie mit einer BigQuery-Remote-Funktion den URI des Bildes an eine Cloud Run-Funktion, die mit Antworten von VQA zum Bild antwortet.

Illustration

5832020184ccf2b2.png

Aus Entwicklersicht führen Sie in diesem Codelab die folgenden Schritte aus:

  1. HTTP-Endpunkt in Cloud Run-Funktionen erstellen
  2. Verbindung vom Typ CLOUD_RESOURCE erstellen
  3. BigQuery-Objekttabelle für den Cloud Storage-Bucket erstellen
  4. Remote-Funktion erstellen
  5. Sie können die Remote-Funktion in einer Abfrage wie alle anderen benutzerdefinierten Funktionen verwenden.

Aufgaben in diesem Lab

2. Einrichtung und Anforderungen

Voraussetzungen

Cloud Shell aktivieren

  1. Klicken Sie in der Cloud Console auf Cloud Shell aktivieren d1264ca30785e435.png.

cb81e7c8e34bc8d.png

Wenn Sie Cloud Shell zum ersten Mal starten, wird ein Zwischenbildschirm mit einer Beschreibung angezeigt. Klicken Sie in diesem Fall auf Weiter.

d95252b003979716.png

Die Bereitstellung und Verbindung mit Cloud Shell sollte nur wenige Minuten dauern.

7833d5e1c5d18f54.png

Auf dieser virtuellen Maschine sind alle erforderlichen Entwicklungstools installiert. Sie bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und läuft in Google Cloud, was die Netzwerkleistung und Authentifizierung erheblich verbessert. Die meisten, wenn nicht alle Aufgaben in diesem Codelab können mit einem Browser erledigt werden.

Sobald Sie mit Cloud Shell verbunden sind, sollten Sie sehen, dass Sie authentifiziert sind und das Projekt auf Ihre Projekt-ID festgelegt ist.

  1. Führen Sie in Cloud Shell den folgenden Befehl aus, um zu prüfen, ob Sie authentifiziert sind:
gcloud auth list

Befehlsausgabe

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Führen Sie in Cloud Shell den folgenden Befehl aus, um zu prüfen, ob der gcloud-Befehl Ihr Projekt kennt:
gcloud config list project

Befehlsausgabe

[core]
project = <PROJECT_ID>

Ist dies nicht der Fall, können Sie die Einstellung mit diesem Befehl vornehmen:

gcloud config set project <PROJECT_ID>

Befehlsausgabe

Updated property [core/project].

3. Lokale Umgebungsvariablen einrichten

In diesem Code erstellen Sie einige Umgebungsvariablen, um die Lesbarkeit der gcloud-Befehle in diesem Codelab zu verbessern.

PROJECT_ID=$(gcloud config get-value project)

# Cloud Function variables
FUNCTION_NAME="imagen-vqa"
FUNCTION_REGION="us-central1"

# Cloud Function variables
BUCKET_NAME=$PROJECT_ID-imagen-vqa

# BigQuery variables
DATASET_ID="remote_function_codelab"
TABLE_NAME="images"
BQ_REGION="US"
CONNECTION_ID="imagen_vqa_connection"

4. Cloud Run-Funktion erstellen

Wenn Sie eine BigQuery-Remotefunktion erstellen möchten, müssen Sie zuerst einen HTTP-Endpunkt mithilfe der Cloud Run-Funktion erstellen. Der Endpunkt muss einen Zeilen-Batch in einer einzelnen HTTP-POST-Anfrage verarbeiten und die Ergebnisse für den Batch als HTTP-Antwort zurückgeben können.

Diese Cloud Run-Funktion empfängt die URI des Bildspeichers und den Fragevorschlag als Eingabe von Ihrer SQL-Abfrage und gibt die Antwort von Visual Question Answering (VQA) zurück.

In diesem Codelab wird ein Beispiel für die python311-Laufzeit mit dem Vertex AI SDK für Python verwendet.

Quellcode für die Funktion erstellen

Erstellen Sie zuerst ein Verzeichnis und wechseln Sie dann in dieses Verzeichnis.

mkdir imagen-vqa && cd $_

Erstellen Sie dann eine requirements.txt-Datei.

google-cloud-aiplatform[preview]
google-cloud-storage
functions-framework==3.*

Erstellen Sie als Nächstes eine main.py-Quelldatei.

from vertexai.preview.vision_models import ImageQnAModel
from vertexai.preview.vision_models import Image
from flask import jsonify
from google.cloud import storage
from urllib.parse import urlparse
import functions_framework

# This is the entry point for the cloud function
@functions_framework.http
def imagen_vqa(request):
    try:
        # See if you can parse the incoming JSON
        return_value = []
        request_json = request.get_json()
        # This grabs the input into the function as called from the SQL function 
        calls = request_json['calls']
        for call in calls:
            # We call the VQA function here in another function defined below
            ai_result = vqa(call)
            # The result to BigQuery is in the order it was prepared in 
            return_value.append(ai_result[0])
        # Prepare the response back to BigQuery
        return_json = jsonify( { "replies": return_value } )
        return return_json
    except Exception as e:
        return jsonify( { "errorMessage": str(e) } ), 400

# Helper function to split apart the GCS URI 
def decode_gcs_url(url):
    # Read the URI and parse it
    p = urlparse(url)
    bucket = p.netloc
    file_path = p.path[0:].split('/', 1)
    # Return the relevant objects (bucket, path to object)
    return bucket, file_path[1]
    
# We can't use the image load from local file since it expects a local path
# We use a GCS URL and get the bytes of the image 
def read_file(object_path):
    # Parse the path
    bucket, file_path = decode_gcs_url(object_path)
    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket)
    blob = bucket.blob(file_path)
    # Return the object as bytes
    return blob.download_as_bytes()

# This is the function that calls the VQA function
def vqa (parameters):
    # This is the model we want to use
    image_qna_model = ImageQnAModel.from_pretrained("imagetext@001")
    # The location is the first parameter 
    image_loc = parameters[0]
    # Get the bytes 
    image_bytes = read_file(image_loc)
    # Load the bytes into the Image handler
    input_image = Image(image_bytes)
    # Ask the VQA the question
    results = image_qna_model.ask_question(
        image=input_image,
        # The prompt was the second parameter
        question=parameters[1],
        number_of_results=1
    )
    return results

Cloud Run-Funktion bereitstellen

Sie können Ihre Cloud Run-Funktion jetzt für die Laufzeit python311 bereitstellen.

Führen Sie den folgenden Befehl aus, um eine Cloud Run-Funktion direkt in Cloud Run bereitzustellen:

gcloud beta run deploy $FUNCTION_NAME \
      --source . \
      --function imagen_vqa \
      --region $FUNCTION_REGION \
      --no-allow-unauthenticated

Wenn Sie die Bereitstellung als Cloud Functions (2. Generation) bevorzugen, verwenden Sie den folgenden Befehl:

gcloud functions deploy $FUNCTION_NAME \
--gen2 \
--region=$FUNCTION_REGION \
--runtime=python311 \
--trigger-http \
--source=. \
--no-allow-unauthenticated

Sie können die Funktions-URL dann als Umgebungsvariable speichern, um sie später zu verwenden.

ENDPOINT_URL="$(gcloud beta run services describe $FUNCTION_NAME --region $FUNCTION_REGION --format='value(status.url)')"

5. Cloud Storage-Bucket erstellen

Erstellen Sie zuerst einen Cloud Storage-Bucket, um Ihre Bilder zu speichern.

gcloud storage buckets create gs://$BUCKET_NAME

Laden Sie als Nächstes ein Bild für die VQA hoch. In diesem Codelab wird das Beispiel-Image aus der VQA-Dokumentation verwendet.

Sie können das Bild entweder über die Cloud Console für Cloud Storage direkt in Ihren Bucket hochladen. Sie können auch die folgenden Befehle ausführen, um das Beispielbild in Ihr aktuelles Cloud Shell-Verzeichnis herunterzuladen

wget -O image.jpg -o /dev/null https://unsplash.com/photos/QqN25A3iF9w/download?ixid=M3wxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNjk1NzYxMjY2fA&force=true

und dann in Ihren Cloud Storage-Bucket hochladen.

gcloud storage cp image.jpg gs://$BUCKET_NAME

6. Verbindung zu BigQuery-Cloud-Ressourcen erstellen

BigQuery verwendet eine CLOUD_RESOURCE-Verbindung für die Interaktion mit Ihrer Cloud Functions-Funktion. Führen Sie den folgenden Befehl aus, um diese Verbindung zu erstellen.

bq mk --connection --location=$BQ_REGION --project_id=$PROJECT_ID \
--connection_type=CLOUD_RESOURCE $CONNECTION_ID

Rufen Sie als Nächstes die Details der neuen BigQuery-Verbindung auf.

bq show --connection $PROJECT_ID.$BQ_REGION.$CONNECTION_ID

Speichern Sie den Namen des BigQuery-Verbindungsdienstkontos in einer Variablen, wie hier gezeigt.

CONNECTION_SA="<YOUR-SERVICE-ACCOUNT-ID>@gcp-sa-bigquery-condel.iam.gserviceaccount.com"

Gewähren Sie dem Dienstkonto Zugriff auf Ihren Cloud Storage-Bucket.

gsutil iam ch serviceAccount:$CONNECTION_SA:objectAdmin gs://$BUCKET_NAME

7. BigQuery-Objekttabelle erstellen

BigQuery-Objekttabellen sind schreibgeschützte Tabellen für unstrukturierte Datenobjekte, die sich in Cloud Storage befinden.

Mit Objekttabellen können Sie unstrukturierte Daten in Cloud Storage analysieren. Sie können Analysen mit Remotefunktionen ausführen und dann die Ergebnisse dieser Vorgänge mit den restlichen strukturierten Daten in BigQuery zusammenführen.

Zuerst erstellen Sie ein Dataset.

bq --location=$BQ_REGION mk \
    --dataset \
    $DATASET_ID

Mit dem folgenden Befehl wird eine Objekttabelle basierend auf Ihrem Cloud Storage-Bucket für Bilder erstellt. Die resultierende Tabelle enthält die URIs für alle Bilder in diesem Bucket.

bq mk --table \
--external_table_definition=gs://$BUCKET_NAME/*@$BQ_REGION.$CONNECTION_ID \
--object_metadata=SIMPLE \
$PROJECT_ID:$DATASET_ID.$TABLE_NAME

8. BigQuery-Remote-Funktion erstellen

Im letzten Schritt konfigurieren Sie jetzt die BigQuery-Remote-Funktion.

Gewähren Sie zuerst dem Dienstkonto für die BigQuery-Verbindung Berechtigungen zum Aufrufen der Cloud Run-Funktion. Es wird nicht empfohlen, einen nicht authentifizierten Aufruf für Ihren Cloud Run-Funktionsdienst zuzulassen.

gcloud run services add-iam-policy-binding $FUNCTION_NAME \
 --member=serviceAccount:$CONNECTION_SA \
 --role="roles/run.invoker" \
 --region $FUNCTION_REGION

Speichern Sie die SQL-Abfrage als Nächstes in einer Variablen.

SQL_CREATE_FUNCTION="CREATE FUNCTION \`$PROJECT_ID.$DATASET_ID\`.vqa(uri STRING, image_prompt STRING) RETURNS STRING
REMOTE WITH CONNECTION \`$PROJECT_ID.$BQ_REGION.$CONNECTION_ID\`
OPTIONS (
  endpoint = '$ENDPOINT_URL'
)"

Führen Sie jetzt die Abfrage aus.

bq query --nouse_legacy_sql $SQL_CREATE_FUNCTION

Nachdem Sie die Abfrage zum Erstellen der Remotefunktion ausgeführt haben, wird Created <your-project-id>.remote_function_codelab.vqa

9. BigQuery-Remote-Funktion in einer SQL-Abfrage aufrufen

Sie haben jetzt die Entwicklungsschritte zum Erstellen der Remote-Funktion abgeschlossen. Sie können Ihre Cloud Run-Funktion jetzt über eine SQL-Abfrage aufrufen.

Speichern Sie zuerst Ihre Frage und Ihre SQL-Abfrage in einer Variablen. In diesem Codelab wird das Beispiel aus der Dokumentation zur visuellen Fragenbeantwortung verwendet. Bei dieser Abfrage wird das zuletzt Ihrem Speicher-Bucket hinzugefügte Bild verwendet.

export SQL_QUERY="DECLARE question STRING DEFAULT 'What objects are in the image?';
SELECT uri, image_prompt ,\`$DATASET_ID\`.vqa(uri, image_prompt) as result
FROM ( 
  SELECT 
  *, 
  dense_rank() over (order by updated) as rnk ,
  question as image_prompt
  FROM \`$PROJECT_ID.$DATASET_ID.images\`) as innertable
  WHERE rnk  = 1;
"

Führen Sie dann die SQL-Abfrage aus, um die Antwort des Vertex AI-Visual Question Answering-Dienstes (VQA) zu sehen.

bq query --nouse_legacy_sql $SQL_QUERY

Die Ergebnisse sollten in etwa so aussehen:

+---------------------------------+--------------------------------+----------+
|               uri               |    image_prompt                |  result  |
+---------------------------------+--------------------------------+----------+
| gs://<YOUR_BUCKET>/image.jpg    | What objects are in the image? |  marbles |
+---------------------------------+--------------------------------+----------+

10. Fehlerbehebung

Wenn beim Erstellen der BigQuery-Tabelle der Fehler BigQuery error in mk operation: Source URI must be a Google Cloud Storage location: gs://$BUCKET_NAME auftritt, prüfen Sie, ob Sie den Pfad /* nach $BUCKET_NAME im Befehl angegeben haben.

Wenn Sie beim Ausführen Ihrer SQL-Abfrage die Fehlermeldung Access Denied: BigQuery BigQuery: Received response code 403 from endpoint <your-function-endpoint> erhalten, warten Sie etwa 1 bis 2 Minuten, bis die Berechtigung für die Rolle „Cloud Function Invoker“ an das BigQuery-Verbindungsdienstkonto übertragen wurde, bevor Sie es noch einmal versuchen.

11. Glückwunsch!

Herzlichen Glückwunsch zum Abschluss des Codelabs!

Wir empfehlen Ihnen, sich die Dokumentation zu BigQuery-Remote-Funktionen und Visual Question Answering (VQA) anzusehen.

Behandelte Themen

  • Authentifizierung für eine Cloud Run-Funktion konfigurieren und prüfen, ob die Authentifizierung richtig konfiguriert wurde
  • Authentifizierte Funktion aus einer lokalen Entwicklungsumgebung aufrufen, indem das Token für Ihre gcloud-Identität angegeben wird
  • So erstellen Sie ein Dienstkonto und weisen ihm die entsprechende Rolle zum Aufrufen einer Funktion zu
  • So übernehmen Sie die Identität eines Dienstes aus einer lokalen Entwicklungsumgebung, die die entsprechenden Rollen zum Aufrufen einer Funktion hat

12. Bereinigen

Wenn Sie versehentliche Kosten vermeiden möchten, z. B. wenn diese Cloud Run-Funktion versehentlich mehrmals aufgerufen wird als Ihre monatliche Zuweisung für Cloud Run-Funktionen in der kostenlosen Stufe, können Sie entweder die Cloud Function oder das in Schritt 2 erstellte Projekt löschen.

Wenn Sie die Cloud Run-Funktion löschen möchten, rufen Sie die Cloud Run-Cloud Console unter https://console.cloud.google.com/functions/ auf und löschen Sie die Funktion imagen-vqa (oder den $FUNCTION_NAME, falls Sie einen anderen Namen verwendet haben).

Wenn Sie das gesamte Projekt löschen möchten, rufen Sie https://console.cloud.google.com/cloud-resource-manager auf, wählen Sie das in Schritt 2 erstellte Projekt aus und klicken Sie auf „Löschen“. Wenn Sie das Projekt löschen, müssen Sie die Projekte in Ihrem Cloud SDK ändern. Sie können die Liste aller verfügbaren Projekte mit dem Befehl gcloud projects list aufrufen.