1. 소개
개요
BigQuery 원격 함수를 사용하면 SQL 및 JavaScript 이외의 언어나 BigQuery 사용자 정의 함수에서 허용되지 않는 라이브러리 및 서비스로 함수를 구현할 수 있습니다. BigQuery 원격 함수는 Cloud Run 함수 및 Cloud Run과의 직접 통합을 제공합니다. 하나 이상의 열을 입력으로 취한 후 단일 값을 출력으로 반환하여 SQL 쿼리 내에서 BigQuery 원격 함수를 호출할 수 있습니다.
Cloud Run 함수는 개발자가 서버 또는 런타임 환경을 관리할 필요 없이 HTTPS를 사용하여 트리거하거나 CloudEvents에 응답할 수 있는 단일 목적의 독립형 함수를 만들 수 있는 경량형 컴퓨팅 솔루션입니다. Cloud Run 함수는 Node.js, Python, Go, Java, .NET, Ruby, PHP를 지원합니다.
이 Codelab에서는 Vertex AI 시각적 질의 응답 (VQA)을 사용하여 Cloud Storage에 저장된 이미지에 관한 질문에 대한 답변을 가져오는 BigQuery 원격 함수를 만드는 방법을 알아봅니다. SQL 쿼리는 BigQuery의 테이블에서 이미지의 URI를 가져옵니다. 그런 다음 BigQuery 원격 함수를 사용하여 이미지 URI를 Cloud Run 함수로 전송합니다. 이 함수는 이미지에 관한 VQA의 답변으로 응답합니다.
이미지
개발 관점에서 이 Codelab에서 완료할 단계는 다음과 같습니다.
- Cloud Run 함수에서 HTTP 엔드포인트 만들기
- CLOUD_RESOURCE 유형의 연결 만들기
- Cloud Storage 버킷의 BigQuery 객체 테이블 만들기
- 원격 함수 만들기
- 다른 사용자 정의 함수와 마찬가지로 쿼리에서 원격 함수 사용
학습할 내용
- Python으로 HTTP Cloud Run 함수를 만드는 방법
- SQL 쿼리 내에서 BigQuery 원격 함수를 만들고 사용하는 방법
- BigQuery 객체 테이블을 만드는 방법
- Python용 Vertex AI SDK를 사용하여 시각적 질의 응답 (VQA)을 사용하는 방법
2. 설정 및 요구사항
기본 요건
- Cloud Console에 로그인되어 있습니다.
- 이전에 HTTP Cloud Run 함수를 배포했습니다. Python 빠른 시작을 참조하세요.
- 이전에 Cloud Storage에서 버킷을 만들었습니다. Cloud Storage 빠른 시작을 참조하세요.
- BigQuery 내에서 데이터 세트, 테이블, 원격 함수를 만들 수 있는 적절한 역할이 있어야 합니다. BigQuery에서 데이터 로드 및 쿼리하기 빠른 시작 참고
Cloud Shell 활성화
- Cloud Console에서 Cloud Shell 활성화를 클릭합니다.
Cloud Shell을 처음 시작하는 경우 Cloud Shell에 대한 설명이 포함된 중간 화면이 표시됩니다. 중간 화면이 표시되면 계속을 클릭합니다.
Cloud Shell을 프로비저닝하고 연결하는 데 몇 분 정도만 걸립니다.
가상 머신에는 필요한 개발 도구가 모두 들어 있습니다. 영구적인 5GB 홈 디렉터리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 Codelab에서 대부분의 작업은 브라우저만으로도 수행할 수 있습니다.
Cloud Shell에 연결되면 인증이 완료되었고 프로젝트가 해당 프로젝트 ID로 설정된 것을 확인할 수 있습니다.
- Cloud Shell에서 다음 명령어를 실행하여 인증되었는지 확인합니다.
gcloud auth list
명령어 결과
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- Cloud Shell에서 다음 명령어를 실행하여 gcloud 명령어가 프로젝트를 알고 있는지 확인합니다.
gcloud config list project
명령어 결과
[core] project = <PROJECT_ID>
또는 다음 명령어로 설정할 수 있습니다.
gcloud config set project <PROJECT_ID>
명령어 결과
Updated property [core/project].
3. 로컬 환경 변수 설정
이 코드에서는 이 Codelab에서 사용되는 gcloud
명령어의 가독성을 개선하기 위해 몇 가지 환경 변수를 만듭니다.
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 함수 만들기
BigQuery 원격 함수를 만들려면 먼저 Cloud Run 함수를 사용하여 HTTP 엔드포인트를 만들어야 합니다. 엔드포인트는 단일 HTTP POST 요청에서 행 배치를 처리하고 배치 결과를 HTTP 응답으로 반환할 수 있어야 합니다.
이 Cloud Run 함수는 이미지 스토리지 URI와 질문 프롬프트를 SQL 쿼리의 입력으로 수신하고 VQA (시각적 질의 응답)에서 답변을 반환합니다.
이 Codelab에서는 Python용 Vertex AI SDK를 사용하는 python311 런타임의 예시를 사용합니다.
함수의 소스 코드 만들기
먼저 디렉터리를 만들고 해당 디렉터리로 이동합니다.
mkdir imagen-vqa && cd $_
그런 다음 requirements.txt
파일을 만듭니다.
google-cloud-aiplatform[preview] google-cloud-storage functions-framework==3.*
다음으로 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
Cloud Run 함수 배포
이제 python311 런타임용 Cloud Run 함수를 배포할 수 있습니다.
Cloud Run 함수를 Cloud Run에 직접 배포하려면 다음 명령어를 실행합니다.
gcloud beta run deploy $FUNCTION_NAME \ --source . \ --function imagen_vqa \ --region $FUNCTION_REGION \ --no-allow-unauthenticated
Cloud Functions 2세대로 배포하려면 다음 명령어를 사용하세요.
gcloud functions deploy $FUNCTION_NAME \ --gen2 \ --region=$FUNCTION_REGION \ --runtime=python311 \ --trigger-http \ --source=. \ --no-allow-unauthenticated
그런 다음 함수 URL을 환경 변수로 저장하여 나중에 사용할 수 있습니다.
ENDPOINT_URL="$(gcloud beta run services describe $FUNCTION_NAME --region $FUNCTION_REGION --format='value(status.url)')"
5. Cloud Storage 버킷 만들기
먼저 이미지를 저장할 Cloud Storage 버킷을 만듭니다.
gcloud storage buckets create gs://$BUCKET_NAME
다음으로 VQA에서 사용할 이미지를 업로드합니다. 이 Codelab에서는 VQA 문서의 예시 이미지를 사용합니다.
Cloud Storage용 Cloud 콘솔을 사용하여 이미지를 버킷에 직접 업로드할 수 있습니다. 또는 다음 명령어를 실행하여 예시 이미지를 현재 Cloud Shell 디렉터리에 다운로드할 수 있습니다.
wget -O image.jpg -o /dev/null https://unsplash.com/photos/QqN25A3iF9w/download?ixid=M3wxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNjk1NzYxMjY2fA&force=true
그런 다음 Cloud Storage 버킷에 업로드합니다.
gcloud storage cp image.jpg gs://$BUCKET_NAME
6. BigQuery 클라우드 리소스 연결 만들기
BigQuery는 CLOUD_RESOURCE 연결을 사용하여 Cloud 함수와 상호작용합니다. 다음 명령어를 실행하여 이 연결을 만듭니다.
bq mk --connection --location=$BQ_REGION --project_id=$PROJECT_ID \ --connection_type=CLOUD_RESOURCE $CONNECTION_ID
다음으로 새 BigQuery 연결의 세부정보를 표시합니다.
bq show --connection $PROJECT_ID.$BQ_REGION.$CONNECTION_ID
표시된 대로 BigQuery 연결 서비스 계정의 이름을 변수에 저장합니다.
CONNECTION_SA="<YOUR-SERVICE-ACCOUNT-ID>@gcp-sa-bigquery-condel.iam.gserviceaccount.com"
Cloud Storage 버킷에 액세스할 수 있도록 서비스 계정에 액세스 권한을 부여합니다.
gsutil iam ch serviceAccount:$CONNECTION_SA:objectAdmin gs://$BUCKET_NAME
7. BigQuery 객체 테이블 만들기
BigQuery 객체 테이블은 Cloud Storage에 있는 비정형 데이터 객체에 대한 읽기 전용 테이블입니다.
객체 테이블을 사용하면 Cloud Storage에서 구조화되지 않은 데이터를 분석할 수 있습니다. 원격 함수로 분석을 수행한 다음 이러한 작업 결과를 BigQuery의 나머지 구조화된 데이터와 조인할 수 있습니다.
먼저 데이터 세트를 만듭니다.
bq --location=$BQ_REGION mk \ --dataset \ $DATASET_ID
다음 명령어는 Cloud Storage 이미지 버킷을 기반으로 객체 테이블을 만듭니다. 결과 테이블에는 해당 버킷의 모든 이미지에 대한 URI가 포함됩니다.
bq mk --table \ --external_table_definition=gs://$BUCKET_NAME/*@$BQ_REGION.$CONNECTION_ID \ --object_metadata=SIMPLE \ $PROJECT_ID:$DATASET_ID.$TABLE_NAME
8. BigQuery 원격 함수 만들기
이제 마지막 단계로 BigQuery 원격 함수를 구성합니다.
먼저 BigQuery 연결 서비스 계정에 Cloud Run 함수를 호출할 수 있는 권한을 부여합니다. Cloud Run 함수 서비스에 인증되지 않은 호출을 허용하지 않는 것이 좋습니다.
gcloud run services add-iam-policy-binding $FUNCTION_NAME \ --member=serviceAccount:$CONNECTION_SA \ --role="roles/run.invoker" \ --region $FUNCTION_REGION
그런 다음 SQL 쿼리를 변수에 저장합니다.
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' )"
이제 쿼리를 실행합니다.
bq query --nouse_legacy_sql $SQL_CREATE_FUNCTION
쿼리를 실행하여 원격 함수를 만든 후 Created <your-project-id>.remote_function_codelab.vqa
가 표시됩니다.
9. SQL 쿼리에서 BigQuery 원격 함수 호출
이제 원격 함수를 생성하기 위한 개발 단계를 완료했습니다. 이제 SQL 쿼리 내에서 Cloud Run 함수를 호출할 수 있습니다.
먼저 질문과 SQL 쿼리를 변수에 저장합니다. 이 Codelab에서는 시각적 질문 답변 문서의 예를 사용합니다. 이 쿼리는 저장소 버킷에 추가된 최신 이미지를 사용합니다.
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; "
그런 다음 SQL 쿼리를 실행하여 Vertex AI VQA (시각적 질의 응답) 서비스의 응답을 표시합니다.
bq query --nouse_legacy_sql $SQL_QUERY
결과는 아래 출력 예와 유사합니다.
+---------------------------------+--------------------------------+----------+ | uri | image_prompt | result | +---------------------------------+--------------------------------+----------+ | gs://<YOUR_BUCKET>/image.jpg | What objects are in the image? | marbles | +---------------------------------+--------------------------------+----------+
10. 문제 해결
BigQuery 테이블을 만들 때 BigQuery error in mk operation: Source URI must be a Google Cloud Storage location: gs://$BUCKET_NAME
오류가 발생하면 명령어에서 $BUCKET_NAME
뒤에 /*
경로를 포함했는지 확인합니다.
SQL 쿼리를 실행할 때 Access Denied: BigQuery BigQuery: Received response code 403 from endpoint <your-function-endpoint>
오류가 발생하면 Cloud 함수 호출자 역할 권한 부여가 BigQuery 연결 서비스 계정에 적용될 때까지 약 1~2분 정도 기다린 후 다시 시도해 보세요.
11. 축하합니다.
Codelab을 완료했습니다. 축하합니다.
BigQuery 원격 함수 및 시각적 질의 응답 (VQA)에 대한 문서를 검토하는 것이 좋습니다.
학습한 내용
- Cloud Run 함수에서 인증을 구성하고 인증이 올바르게 구성되었는지 확인하는 방법
- gcloud ID의 토큰을 제공하여 로컬 개발 환경에서 인증된 함수 호출
- 서비스 계정을 만들고 함수를 호출하는 적절한 역할을 부여하는 방법
- 함수 호출에 적절한 역할이 있는 로컬 개발 환경에서 서비스를 가장하는 방법
12. 삭제
의도치 않은 청구를 방지하려면(예: 이 Cloud Run 함수가 무료 등급의 월별 Cloud Run 함수 호출 할당량보다 더 많은 횟수로 실수로 호출된 경우) Cloud 함수를 삭제하거나 2단계에서 만든 프로젝트를 삭제하면 됩니다.
Cloud Run 함수를 삭제하려면 Cloud Run Cloud 콘솔(https://console.cloud.google.com/functions/)으로 이동하여 imagen-vqa 함수(또는 다른 이름을 사용한 경우 $FUNCTION_NAME)를 삭제합니다.
전체 프로젝트를 삭제하려면 https://console.cloud.google.com/cloud-resource-manager로 이동하여 2단계에서 만든 프로젝트를 선택하고 삭제를 선택합니다. 프로젝트를 삭제하면 Cloud SDK에서 프로젝트를 변경해야 합니다. gcloud projects list
를 실행하면 사용 가능한 모든 프로젝트의 목록을 볼 수 있습니다.