Używaj funkcji zdalnych BigQuery do zadawania pytań usłudze Vertex AI Visual Question Answering (VQA) w zapytaniu SQL

1. Wprowadzenie

Omówienie

Funkcje zdalne BigQuery umożliwiają implementowanie funkcji w językach innych niż SQL i JavaScript lub z użyciem bibliotek i usług niedozwolonych w funkcjach zdefiniowanych przez użytkownika w BigQuery. Zdalne funkcje BigQuery umożliwiają bezpośrednią integrację z funkcjami Cloud Run i Cloud Run. Funkcję zdalną BigQuery możesz wywołać w zapytaniu SQL, podając co najmniej 1 kolumnę jako dane wejściowe, a potem zwracając jedną wartość jako dane wyjściowe.

Funkcje Cloud Run to wymagające niewielu zasobów rozwiązanie oparte na obliczeniach, które umożliwia programistom tworzenie samodzielnych funkcji o ściśle zdefiniowanym przeznaczeniu, które można aktywować za pomocą HTTPS lub które reagują na CloudEvents bez konieczności zarządzania serwerem lub środowiskiem wykonawczym. Funkcje Cloud Run obsługują języki Node.js, Python, Go, Java, .NET, Ruby i PHP.

W tym ćwiczeniu w Codelabs dowiesz się, jak utworzyć funkcję zdalną BigQuery, która za pomocą Visual Question Answering (VQA) w Vertex AI uzyska odpowiedzi na pytania dotyczące obrazów przechowywanych w Cloud Storage. Zapytanie SQL pobierze adres URI obrazu z tabeli w BigQuery. Następnie za pomocą funkcji zdalnej BigQuery wyślij identyfikator URI obrazu do funkcji w Cloud Run, która odpowie z odpowiedziami VQA na temat obrazu.

Ilustracja

5832020184ccf2b2.png

W ramach tego ćwiczenia z programowania wykonaj te czynności z perspektywy programowania:

  1. Tworzenie punktu końcowego HTTP w funkcjach Cloud Run
  2. Tworzenie połączenia typu CLOUD_RESOURCE
  3. Tworzenie tabeli obiektów BigQuery dla zasobnika Cloud Storage
  4. Tworzenie funkcji zdalnej
  5. Używaj funkcji zdalnej w zapytaniu tak samo jak innych funkcji zdefiniowanych przez użytkownika.

Czego się nauczysz

2. Konfiguracja i wymagania

Wymagania wstępne

Aktywowanie Cloud Shell

  1. W konsoli Cloud kliknij Aktywuj Cloud Shell d1264ca30785e435.png.

cb81e7c8e34bc8d.png

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni, na którym opisano, czym jest to środowisko. Jeśli taki ekran się wyświetlił, kliknij Dalej.

d95252b003979716.png

Uproszczenie i połączenie z Cloud Shell powinno zająć tylko kilka chwil.

7833d5e1c5d18f54.png

Ta maszyna wirtualna zawiera wszystkie niezbędne narzędzia programistyczne. Zawiera stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie poprawia wydajność sieci i uwierzytelnianie. Większość, jeśli nie wszystkie, zadań w tym ćwiczeniu można wykonać w przeglądarce.

Po nawiązaniu połączenia z Cloud Shell powinno pojawić się potwierdzenie, że użytkownik jest uwierzytelniony, a projekt jest ustawiony na identyfikator Twojego projektu.

  1. Aby potwierdzić uwierzytelnianie, uruchom w Cloud Shell to polecenie:
gcloud auth list

Dane wyjściowe polecenia

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Aby sprawdzić, czy polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project

Wynik polecenia

[core]
project = <PROJECT_ID>

Jeśli nie, możesz ustawić je za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Dane wyjściowe polecenia

Updated property [core/project].

3. Konfigurowanie zmiennych środowiskowych lokalnych

W tym kodzie utworzysz kilka zmiennych środowiskowych, aby poprawić czytelność poleceń gcloud używanych w tym ćwiczeniu z programowania.

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. Tworzenie funkcji Cloud Run

Aby utworzyć funkcję zdalną BigQuery, musisz najpierw utworzyć punkt końcowy HTTP za pomocą funkcji Cloud Run. Punkt końcowy musi być w stanie przetworzyć zbiór wierszy w pojedynczym żądaniu HTTP POST i zwrócić wyniki zbioru jako odpowiedź HTTP.

Ta funkcja w Cloud Run otrzyma identyfikator URI pamięci masowej obrazu oraz pytanie jako dane wejściowe z zapytania SQL i zwróci odpowiedź z Visual Question Answering (VQA).

Ten moduł Codelab wykorzystuje przykład środowiska wykonawczego python311 z użyciem pakietu Vertex AI SDK for Python.

Tworzenie kodu źródłowego funkcji

Najpierw utwórz katalog i przejdź do niego.

mkdir imagen-vqa && cd $_

Następnie utwórz plik requirements.txt.

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

Następnie utwórz plik źródłowy main.py.

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

Wdrażanie funkcji Cloud Run

Teraz możesz wdrożyć funkcję Cloud Run dla środowiska wykonawczego python311.

Aby wdrożyć funkcję Cloud Run bezpośrednio w Cloud Run, uruchom to polecenie:

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

Jeśli wolisz wdrożyć funkcję jako funkcję Cloud Functions 2 generacji, użyj tego polecenia:

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

Następnie możesz zapisać adres URL funkcji jako zmienną środowiskową, aby użyć jej później.

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

5. Tworzenie zasobnika Cloud Storage

Najpierw utwórz zasobnik Cloud Storage, w którym będą przechowywane obrazy.

gcloud storage buckets create gs://$BUCKET_NAME

Następnie prześlij obraz, którego chcesz używać do VQA. Ten warsztat używa przykładowego obrazu z dokumentacji VQA.

Możesz przesłać obraz bezpośrednio do zasobnika, korzystając z konsoli Cloud Storage. Możesz też uruchomić podane niżej polecenia, aby pobrać przykładowy obraz do bieżącego katalogu Cloud Shell.

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

a następnie prześlij do zasobnika Cloud Storage.

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

6. Tworzenie połączenia z zasobem Cloud w BigQuery

BigQuery używa połączenia CLOUD_RESOURCE do interakcji z funkcją Cloud Functions. Aby utworzyć to połączenie, uruchom podane niżej polecenie.

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

Następnie wyświetl szczegóły nowego połączenia z BigQuery.

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

Zapisz nazwę konta usługi połączenia z BigQuery w zmiennej, jak pokazano na ilustracji.

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

Przyznaj kontu usługi dostęp do zasobnika Cloud Storage.

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

7. Tworzenie tabeli obiektów BigQuery

Tabele obiektów BigQuery to tabele tylko do odczytu dotyczące nieuporządkowanych obiektów danych znajdujących się w Cloud Storage.

Tabele obiektów umożliwiają analizowanie nieuporządkowanych danych w Cloud Storage. Możesz przeprowadzać analizy za pomocą funkcji zdalnych, a potem złączać wyniki tych operacji z resztą ustrukturyzowanych danych w BigQuery.

Najpierw utwórz zbiór danych.

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

Podane niżej polecenie tworzy tabelę obiektów na podstawie zasobnika Cloud Storage z obrazami. Powstała tabela będzie zawierać identyfikatory URI wszystkich obrazów w tym zasobniku.

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

8. Tworzenie funkcji zdalnej BigQuery

Ostatnim krokiem jest skonfigurowanie funkcji zdalnej BigQuery.

Najpierw przyznaj uprawnienia do wywołania funkcji Cloud Run kontu usługi połączenia z BigQuery. Nie zalecamy zezwalania na nieuwierzytelnione wywołania usługi funkcji w Cloud Run.

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

Następnie zapisz zapytanie SQL w zmiennej.

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'
)"

Teraz uruchom zapytanie.

bq query --nouse_legacy_sql $SQL_CREATE_FUNCTION

Po uruchomieniu zapytania w celu utworzenia funkcji zdalnej zobaczysz Created <your-project-id>.remote_function_codelab.vqa

9. Wywoływanie funkcji zdalnej BigQuery w zapytaniu SQL

Skończyłeś już etap tworzenia funkcji zdalnej. Teraz możesz wywoływać funkcję Cloud Run z poziomu zapytania SQL.

Najpierw zapisz pytanie i zapytanie SQL w zmiennej. Ten warsztat programistyczny korzysta z przykładu z dokumentacji dotyczącej wizualnych odpowiedzi na pytania. To zapytanie używa najnowszego obrazu dodanego do zasobnika pamięci.

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;
"

Następnie uruchom zapytanie SQL, aby wyświetlić odpowiedź z usługi Vertex AI Visual Question Answering (VQA).

bq query --nouse_legacy_sql $SQL_QUERY

Wyniki powinny wyglądać podobnie do przykładowych danych wyjściowych poniżej:

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

10. Rozwiązywanie problemów

Jeśli podczas tworzenia tabeli BigQuery pojawi się błąd BigQuery error in mk operation: Source URI must be a Google Cloud Storage location: gs://$BUCKET_NAME, upewnij się, że w komendzie po $BUCKET_NAME podana jest ścieżka /*.

Jeśli podczas uruchamiania zapytania SQL wyświetli się błąd Access Denied: BigQuery BigQuery: Received response code 403 from endpoint <your-function-endpoint>, poczekaj około 1–2 minuty na rozpowszechnienie uprawnień roli wywołującego funkcje Cloud Functions, zanim spróbujesz ponownie.

11. Gratulacje!

Gratulujemy ukończenia ćwiczenia.

Zapoznaj się z dokumentacją dotyczącą funkcji zdalnych BigQueryvisual question answering (VQA).

Omówione zagadnienia

  • Jak skonfigurować uwierzytelnianie w funkcji Cloud Run i sprawdzić, czy zostało ono prawidłowo skonfigurowane
  • Wywołaj uwierzytelnione funkcję z lokalnego środowiska programistycznego, podając token tożsamości gcloud.
  • Jak utworzyć konto usługi i przypisać mu odpowiednią rolę, aby wywołać funkcję
  • Jak podszyć się pod usługę z lokalnego środowiska programistycznego, która ma odpowiednie role do wywołania funkcji

12. Czyszczenie danych

Aby uniknąć niezamierzonych opłat (na przykład jeśli ta funkcja w Cloud Run została przypadkowo wywołana więcej razy niż miesięczna przydział wywołań funkcji Cloud Run na poziomie bezpłatnym), możesz usunąć funkcję w Cloud Functions lub projekt utworzony w kroku 2.

Aby usunąć funkcję Cloud Run, otwórz konsolę Cloud Run na stronie https://console.cloud.google.com/functions/ i usuń funkcję imagen-vqa (lub funkcję $FUNCTION_NAME w przypadku użycia innej nazwy).

Jeśli chcesz usunąć cały projekt, otwórz stronę https://console.cloud.google.com/cloud-resource-manager, wybierz projekt utworzony w kroku 2 i kliknij Usuń. Jeśli usuniesz projekt, musisz zmienić projekty w Cloud SDK. Aby wyświetlić listę wszystkich dostępnych projektów, uruchom gcloud projects list.