PetVerse에 오신 것을 환영합니다.

1. 소개

Petverse에 오신 것을 환영합니다. 모든 반려동물 환영 🐈🐶🐍🐟🦄

기본 요건

  • Google Cloud 콘솔에 대한 기본 이해
  • SQL 문에 대한 기본 이해

학습할 내용

  • BigQuery에서 데이터 세트 및 테이블 만들기
  • BigQuery의 스토리지 버킷에 있는 멀티미디어를 참조하는 ObjectRef 열 만들기
  • BigQuery의 AI 함수를 사용하여 비정형 데이터의 콘텐츠에서 데이터 세트 강화
  • 유사한 미디어를 검색하기 위해 멀티미디어 임베딩 만들기
  • 텍스트 임베딩을 만들어 VECTOR_SEARCH로 시맨틱 검색 실행
  • Gemini CLI를 사용하여 웹 애플리케이션 만들기

필요한 항목

  • 결제 계정이 있는 Google Cloud 계정 및 Google Cloud 프로젝트
  • 웹브라우저(예: Chrome)

2. 설정 및 요구사항

자습형 환경 설정

  1. Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
  • 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud 콘솔은 고유한 문자열을 자동으로 생성합니다. 일반적으로는 신경 쓰지 않아도 됩니다. 대부분의 Codelab에서는 프로젝트 ID (일반적으로 PROJECT_ID로 식별됨)를 참조해야 합니다. 생성된 ID가 마음에 들지 않으면 다른 임의 ID를 생성할 수 있습니다. 또는 직접 시도해 보고 사용 가능한지 확인할 수도 있습니다. 이 단계 이후에는 변경할 수 없으며 프로젝트 기간 동안 유지됩니다.
  • 참고로 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참고하세요.
  1. 다음으로 Cloud 리소스/API를 사용하려면 Cloud 콘솔에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼이 끝난 후에 요금이 청구되지 않도록 리소스를 종료하려면 만든 리소스 또는 프로젝트를 삭제하면 됩니다. Google Cloud 신규 사용자는 300달러(USD) 상당의 무료 체험판 프로그램에 참여할 수 있습니다.

3. Cloud Shell 열기

https://shell.cloud.google.com/?show=ide%2Cterminal로 이동합니다 . 메시지가 표시되면 승인을 클릭합니다.

1bfca4be2c270a9f.png

편집기와 콘솔이 모두 표시되는지 확인합니다.

785d186a8b11b32b.png

4. 도우미 스크립트 만들기

이 환경을 더 원활하게 만들기 위해 관련 환경 변수를 설정하는 도우미 스크립트를 만듭니다.

아래에서 <<Project ID>>를 프로젝트 ID로 바꿉니다.

다음 명령어를 Cloud Shell 터미널에 복사하고 Enter 키를 눌러 실행합니다.

gcloud config set project <<PROJECT_ID>>

ffd97bad1f398b4b.png

다음 명령어를 Cloud Shell 터미널에 복사하고 Enter 키를 눌러 실행합니다. 이렇게 하면 필요한 서비스가 사용 설정되고 파일이 생성되어 Cloud Shell에서 수정됩니다.

gcloud services enable compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       aiplatform.googleapis.com \
                       storage-component.googleapis.com  \
                       bigqueryconnection.googleapis.com \
run.googleapis.com \
secretmanager.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com  \
iap.googleapis.com
edit  ~/petverse-setup.sh

파일 이름이 표시된 새 탭이 표시됩니다. 다음 스크립트를 새 파일에 붙여넣습니다.

#!/bin/bash

# -----------------------------------------------------------------------------
# 1. Global Variables: Set your desired project ID and region here.
# -----------------------------------------------------------------------------

# 🦄 🦄 Set your project ID here ⬇️.

# Example: PROJECT_ID="your-project-id"
PROJECT_ID=""

# Set your desired region here. Default is 'us-central1'.
# Example: REGION="us-east1"
REGION="us-central1"

# -----------------------------------------------------------------------------
# 2. Check and Authenticate
# -----------------------------------------------------------------------------

echo "  ➡️   Checking for active Google Cloud authentication..."

# Check if the user is authenticated; if not, prompt for authentication.
if ! gcloud auth list --format="value(account)" | grep -q @; then
  echo "⚠️   Not authenticated. Please authenticate now."
  gcloud auth login
fi

echo "  ✅   Authentication check passed."

# -----------------------------------------------------------------------------
# 3. Get Project ID from User if not set
# -----------------------------------------------------------------------------

# If PROJECT_ID is not set in the script or as an environment variable,
# prompt the user to choose one.
if [[ -z "$PROJECT_ID" ]] && [[ -n "$DEVSHELL_PROJECT_ID" ]]; then
  PROJECT_ID=$DEVSHELL_PROJECT_ID
fi

if [[ -z "$PROJECT_ID" ]]; then
  echo "  ⚠️   Project ID is not set. Listing available projects:"
 
  # List projects and store them in an array.
  projects_array=($(gcloud projects list --format="value(projectId)"))
 
  # Check if projects were found.
  if [[ ${#projects_array[@]} -eq 0 ]]; then
    echo "  ❌   No projects found. Please ensure your account has access to projects."
    exit 1
  fi
 
  # Display the projects and prompt for input.
  echo " "
  echo "Available Projects:"
  for project in "${projects_array[@]}"; do
    echo "$project"
  done
 
  echo " "
  read -p "Please enter your desired project ID from the list above: " PROJECT_ID
 
  # Validate the user's input by checking if it's in the array.
  if [[ ! " ${projects_array[@]} " =~ " ${PROJECT_ID} " ]]; then
    echo "  ❌   Invalid project ID. Please run the script again and select a valid ID."
    exit 1
  fi
fi

echo "  ✅   Project ID set to: $PROJECT_ID"

# -----------------------------------------------------------------------------
# 4. Set Environment Variables
# -----------------------------------------------------------------------------

# Set the project and region for the current session.
echo "  🔄   Setting Google Cloud configuration for this session..."
gcloud config set project "$PROJECT_ID"
gcloud config set compute/region "$REGION"

echo "  ✅   Google Cloud configuration updated."
echo "Project ID: $PROJECT_ID"
echo "Region: $REGION"
echo " "
echo "  🎉 🦄 🦄   Script execution complete. You can now use Google Cloud commands in this shell session."

PROJECT_ID 자리표시자를 프로젝트 이름으로 바꿉니다.

aec2195d576244dd.png

다음 명령어를 복사하여 터미널에서 실행합니다.

chmod +x petverse-setup.sh
~/petverse-setup.sh

예상 출력:

83d1f7405624443b.png

5. 스토리지 버킷 만들기

Cloud Storage 버킷을 만들고 사용 가능한 미디어를 자체 버킷에 복사합니다. 이 버킷은 멋진 반려동물을 위한 사용 가능한 미디어를 저장하는 데 사용됩니다. 또한 BigQuery를 통해 버킷에 액세스할 수 있는 연결을 만듭니다.

터미널에 다음을 붙여넣고 실행합니다.

~/petverse-setup.sh
cd ~/
gcloud storage buckets create gs://$DEVSHELL_PROJECT_ID-petverse --uniform-bucket-level-access --location=us-central1
gcloud storage cp -r gs://sample-data-and-media/petverse/* gs://$DEVSHELL_PROJECT_ID-petverse/
bq mk --dataset --location=us-central1 --project_id=$DEVSHELL_PROJECT_ID petverse
bq mk --connection --location=us-central1 --project_id=$DEVSHELL_PROJECT_ID \
--connection_type=CLOUD_RESOURCE pet-connection
echo "your bucket is gs://$DEVSHELL_PROJECT_ID-petverse "

379f72ee2908da36.png

6. pets 테이블 만들기

이제 BigQuery에서 반려동물에 관한 정보를 저장할 테이블을 만듭니다.

브라우저에서 새 탭을 엽니다. https://console.cloud.google.com/bigquery로 이동합니다 .

사용 중인 프로젝트가 콘솔에서 선택되어 있는지 확인합니다.

f82010a317866e6.png

이제 pets.csv 파일의 데이터를 사용하여 테이블을 만들 수 있습니다. 이 파일에는 반려동물의 이름, 좋아하는 음식, 장난감, 기타 흥미로운 정보가 포함되어 있습니다.

다음 코드를 새 SQL 쿼리에 복사하여 실제 테이블을 만들고 데이터를 로드합니다.

LOAD DATA INTO petverse.pets
OPTIONS(
    description="Table for furry friend data"
  )
FROM FILES (
  skip_leading_rows=1,
  uris = ['gs://<<your_bucket_name>>/pets.csv'],
  format = 'CSV'
);

코드에서 버킷 자리표시자를 이전 단계에서 만든 버킷으로 바꿉니다.

https://console.cloud.google.com/storage/browser URL을 가리키는 별도의 브라우저 탭에서 모든 스토리지 버킷을 확인할 수 있습니다 .

757813944bb3d8ba.png

실행 버튼을 사용하여 쿼리를 실행합니다.

데이터가 로드되면 표로 이동을 클릭합니다.

d6aab61d533bedde.png

미리보기를 클릭하여 테이블의 콘텐츠를 확인합니다. 20fb1cbf8826efca.png

7. BigQuery를 스토리지 버킷에 연결

이전에 만든 버킷을 살펴보면 각 반려동물과 관련된 미디어 파일 세트가 있습니다.

243751f1b0aab329.gif

BigQuery는 이러한 버킷을 읽고 테이블의 데이터와 함께 파일을 사용할 수 있습니다. 이 값 유형을 ObjectRef라고 합니다.

외부 연결에서 이전에 만든 연결을 클릭하여 연결의 서비스 계정 ID를 가져옵니다.

1d9d3275483f5650.png

서비스 계정 ID복사합니다.

새 브라우저 탭에서 IAM 관리 콘솔 ( https://console.cloud.google.com/iam-admin/)로 이동합니다.

스토리지 객체 뷰어Vertex AI 사용자 권한을 서비스 계정에 부여합니다 (이 권한은 나중에 사용됩니다).

f1ff6b305d914532.png

저장하고 🕰️ 몇 분 정도 기다립니다.

BigQuery 탭으로 돌아가서 BigQuery 스튜디오에서 다음 쿼리를 사용하여 BigQuery와 스토리지 버킷 간의 연결을 테스트합니다.

<<PROJECT_ID>>를 프로젝트 ID로 바꿉니다.

SET @@location='us-central1';
SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/yoda_profile_picture.png', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))

결과 보기를 클릭합니다. 결과에 메타데이터가 표시됩니다.

9e3d986b797e413a.png

8. 구조화된 데이터에 저장 매체 추가

pets 테이블을 개선하여 각 반려동물의 프로필 사진이 있는 열을 추가할 수 있습니다(있는 경우). 각 반려동물과 관련된 다른 모든 파일을 저장하기 위해 미디어 참조 배열이 있는 다른 열도 추가합니다.

멀티미디어에 액세스하려면 버킷을 만든 후 이 Codelab의 시작 부분에서 만든 연결이 필요합니다.

다음 명령어를 BigQuery SQL 콘솔에 붙여넣고 실행하여 pets 테이블에 두 개의 열을 추가합니다.

SET @@location='us-central1';
ALTER TABLE petverse.pets
ADD COLUMN IF NOT EXISTS profile_picture STRUCT<uri STRING, version STRING, authorizer STRING, details JSON>,
ADD COLUMN IF NOT EXISTS additional_media ARRAY<STRUCT<uri STRING, version STRING, authorizer STRING, details JSON>>;

다음 문을 복사하고 PROJECT_ID 자리표시자를 프로젝트 ID로 바꿉니다.

SET @@location='us-central1';

UPDATE petverse.pets
SET profile_picture = (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/yoda_profile_picture.png', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
    additional_media = [(SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/Yoda_asks_for_cuddles.mp4', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection')))]
WHERE Id = 1;

UPDATE petverse.pets
SET profile_picture = (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/madonna_profile_picture.jpg', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
    additional_media = [(SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/Madonna_description.wav', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection')))]
WHERE Id = 2;

UPDATE petverse.pets
SET profile_picture = (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/pixel_profile_picture.png', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
    additional_media = [(SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/pixel_thug_life.mp4', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
                       (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/pixel_description.wav', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection')))]
WHERE Id = 3;

UPDATE petverse.pets
SET profile_picture = (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/sql_profile_picture.png', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
    additional_media = [(SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/SQL_description.wav', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
                       (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/SQL_favorite_toy.mp4', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection')))]
WHERE Id = 4;

UPDATE petverse.pets
SET profile_picture = (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/buddy_golden_retriever.png', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
    additional_media = NULL
WHERE Id = 5;

UPDATE petverse.pets
SET profile_picture = (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/daisy_french_bulldog.png', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
    additional_media = NULL
WHERE Id = 6;

UPDATE petverse.pets
SET profile_picture = (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/max_german_shepherd.png', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
    additional_media = [(SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/max_description_tells_jokes.mp4', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection')))]
WHERE Id = 7;

UPDATE petverse.pets SET profile_picture = NULL, additional_media = NULL WHERE Id = 8;

UPDATE petverse.pets SET profile_picture = NULL, additional_media = [(SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/rocky_description.mp4', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection')))] WHERE Id = 9;

UPDATE petverse.pets
SET profile_picture = (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/pip_hamster.png', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
    additional_media = [(SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/pip_Hamster_Wheel_Video_Generated.mp4', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection')))]
WHERE Id = 10;

UPDATE petverse.pets SET profile_picture = NULL, additional_media = NULL WHERE Id = 11;

UPDATE petverse.pets
SET profile_picture = (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/scales_snake.png', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
    additional_media = NULL
WHERE Id = 12;

UPDATE petverse.pets SET profile_picture = NULL, additional_media = NULL WHERE Id = 13;

UPDATE petverse.pets
SET profile_picture = (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/Joel_Profile_Picture.jpg', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
    additional_media = [(SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/Joel_Catwalk.jpg', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
                       (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/Joel_Flowers.jpg', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection'))),
                       (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://<<PROJECT_ID>>-petverse/additional_media/Joel_Plays.jpg', 'projects/<<PROJECT_ID>>/locations/us-central1/connections/pet-connection')))]
WHERE Id = 14;

명령문을 실행합니다. 몇 분 후 성공적인 실행이 표시됩니다.

4fa3bba70440fa65.png

표 미리보기를 사용하여 결과를 확인합니다. Pixel이라는 고양이의 기존 프로필 사진과 추가 미디어의 메타데이터가 표시됩니다.

SELECT *
FROM `petverse.pets`
WHERE name = 'Pixel'

a1511d749e88d5f5.png

9. 반려동물 설명 생성

pets 테이블을 미리 보면 Yoda, Pixel, Rocky와 같은 일부 반려동물에 좋아하는 음식이나 좋아하는 장난감이 누락되어 있습니다.

이러한 질문에 대한 답변은 이러한 반려동물과 관련된 동영상 및 오디오에 있을 수 있습니다. 내장된 AI 함수를 사용하여 확인합니다.

다음 문으로 테스트합니다.

SELECT name,
AI.GENERATE(
   prompt=> ('What are this pet\'s favorite toy and favorite foods', additional_media ),
    connection_id => 'us-central1.pet-connection',
    endpoint => 'gemini-2.5-flash',
output_schema => 'food STRING, toy STRING')
FROM petverse.pets
WHERE name = 'Rocky'

스토리지 버킷에서 Rocky의 동영상을 확인할 수 있습니다.

다음 문을 사용하여 누락된 설명을 업데이트합니다.

UPDATE petverse.pets AS p
SET FavoriteFood = aigen.food
FROM
  (
    SELECT Id, name,
          AI.GENERATE(
                prompt=> ('What are this pet\'s favorite toy and favorite foods', additional_media ),
                connection_id => 'us-central1.pet-connection',
                endpoint => 'gemini-2.5-flash',
                output_schema => 'food STRING').food
    FROM petverse.pets ) AS  aigen
WHERE p.Id = aigen.Id
AND p.FavoriteFood IS NULL
AND p.additional_media IS NOT NULL

다음 문을 사용하여 멀티미디어를 기반으로 반려동물에 대한 설명을 새 열에 만듭니다.

ALTER TABLE petverse.pets ADD COLUMN MediaDescription STRING;
UPDATE petverse.pets AS p
SET MediaDescription = aigen.description
FROM
  (
    SELECT Id, name,
          AI.GENERATE(
                prompt=> ('Create a description in an epic tone for this pet based on these media: ', additional_media ),
                connection_id => 'us-central1.pet-connection',
                endpoint => 'gemini-2.5-flash',
                output_schema => 'description STRING').description
    FROM petverse.pets ) AS  aigen
WHERE p.Id = aigen.Id
AND p.MediaDescription IS NULL
AND p.additional_media IS NOT NULL

몇 분 후 다음과 같은 광고 소재 설명이 표시됩니다.

fab3b59caa69aec7.png

10. 임베딩 만들기

시맨틱 검색에 사용할 프로필 사진, 설명, 취미의 임베딩을 저장하는 테이블을 만듭니다. 벡터 검색을 사용하여 반려동물 간의 유사성을 찾습니다.

SET @@location='us-central1';

CREATE OR REPLACE MODEL petverse.multimodalembedding
  REMOTE WITH CONNECTION `us-central1.pet-connection`
  OPTIONS(ENDPOINT = 'multimodalembedding@001');

CREATE TABLE IF NOT EXISTS petverse.profile_embeddings
AS
SELECT *
FROM ML.GENERATE_EMBEDDING(
  MODEL petverse.multimodalembedding,
    (
      SELECT profile_picture as content,
      Id
      FROM petverse.pets)
 );

CREATE OR REPLACE MODEL petverse.textembedding
  REMOTE WITH CONNECTION `us-central1.pet-connection`
  OPTIONS (ENDPOINT = 'text-embedding-005');

CREATE OR REPLACE TABLE petverse.text_embeddings AS
SELECT * FROM ML.GENERATE_EMBEDDING(
  MODEL petverse.textembedding,
  (
    SELECT CONCAT(AdoptionStory, ' . This pet\'s hobby is: ', Hobby, ' and their nickname(s) is: ', COALESCE(Nicknames, Name)) AS content,
    Id, Name
    FROM petverse.pets
    WHERE LENGTH(AdoptionStory) > 0 AND LENGTH(Hobby) > 0
  )
)
WHERE LENGTH(ml_generate_embedding_status) = 0;

결과 탭에서 새 테이블을 확인합니다.

c9e876d75147c343.png

다음 문을 사용하여 모든 삽입의 상태를 확인합니다.

SELECT DISTINCT(ml_generate_embedding_status),
  COUNT(content.uri) AS num_rows
FROM petverse.profile_embeddings
GROUP BY 1;

오류가 있으면 상태가 비어 있지 않은 상태로 표시됩니다. 올바른 출력 - 오류가 있는 레코드가 없습니다**:**

e6754936c31ca5cf.png

다음은 오류가 있는 레코드의 예입니다. 다음은 예상되지 않지만 다음 단계를 진행하기 전에 수정해야 하는 사항입니다.

736545fbc7ce4ac8.png

유사한 반려동물 찾기

기본 데이터 세트에는 비슷한 반려동물이 있습니다. 다음은 Pixel (ID: 3)과 SQL (ID: 4)의 두 가지 예입니다.

cfebe01afc5f4858.png

임베딩 간 거리를 사용하여 유사한 반려동물을 계산할 수 있습니다.

SELECT
t2.id AS similar_pet_id,
COSINE_DISTANCE(t1.ml_generate_embedding_result, t2.ml_generate_embedding_result) AS distance
FROM
petverse.profile_embeddings AS t1,
petverse.profile_embeddings AS t2
WHERE
t1.Id = 3 -- The pet you want to find similar ones to
AND t1.Id != t2.Id -- Exclude the pet itself from the results
AND t1.content.uri IS NOT NULL
AND t2.content.uri IS NOT NULL
ORDER BY
distance
LIMIT 5;

서로 유사한 사진의 ID가 결과로 표시됩니다. 이렇게 하면 사진의 모든 항목이 포함됩니다. 이 예에서 Pixel과 SQL은 유사하며, 다음으로 유사한 반려동물은 Joel (ID: 14)입니다.

99ce203add04a6b1.png

참고용 Joel 사진은 다음과 같습니다.

f78e0ca0fe235ba2.png

VECTOR_SEARCH 함수를 사용하여 텍스트 임베딩에서 시맨틱 검색을 할 수 있습니다. 이 표가 더 컸다면 임베딩을 만들고 색인을 생성해야 합니다.

SELECT query.query, base.content, base.Name
FROM VECTOR_SEARCH(
  TABLE `petverse.text_embeddings`, 'ml_generate_embedding_result',
  (
  SELECT ml_generate_embedding_result, content AS query
  FROM ML.GENERATE_EMBEDDING(
  MODEL `petverse.textembedding`,
  (SELECT 'Pets who like to relax' AS content))
  ),
  top_k => 5, options => '{"fraction_lists_to_search": 0.50}')
ORDER BY distance DESC

시맨틱 검색어 (Pets who like to relax)와 매개변수 fraction_lists_to_search도 변경해 보고 어떤 일이 일어나는지 확인해 보세요. 이러한 함수에 대한 자세한 내용은 여기를 참고하세요.

11. 프로필 페이지 바이브 코딩

Cloud Shell에서 Gemini CLI를 사용하여 간단한 데모 웹 애플리케이션을 빠르게 시작합니다. 이 웹 애플리케이션은 Petverse가 어떻게 구현될 수 있는지 보여주기 위해 프롬프트가 간소화되었습니다.

Cloud Shell로 돌아갑니다. 전체 화면에서 콘솔만 사용하면 다음과 같은 이점이 있습니다.

b5061fb060f2a958.png

초기화 스크립트를 실행하여 환경 변수가 설정되었는지 확인하고, 이 프로젝트를 포함할 디렉터리를 만들고, Gemini CLI를 실행합니다.

~/petverse-setup.sh
mkdir petverse-profiles
cd petverse-profiles
gemini

Gemini의 CLI가 표시됩니다.

910fda2312082974.png

아래 프롬프트에서 버킷 이름을 바꿉니다.

프롬프트를 Gemini 명령줄에 붙여넣습니다.

You are a fullstack engineer creating an application to display the profiles of cats, dogs and other pets stored in BigQuery. The table where these are stored is called pets, in the dataset petverse.
1.Application Requirements: Display the pets with their profile picture, all the other information in the Pets table, and other media that may be available. The pictures are in a GCS bucket, the field in the table pets profile_picture.uri contains the URI for the storage bucket of that profile picture.  The field additional_media is an array of objectref that contains multiple URI to different media stored in a GCS bucket.
Important: In the code, in the values for the URIs retrieved from BigQuery, replace gs://<<YOUR_PROJECT_ID>>-petverse/ with https://storage.mtls.cloud.google.com/<<YOUR_PROJECT_ID>>-petverse/ as follows: replace('gs://', 'https://storage.mtls.cloud.google.com/'). Use the python library. Media can be pictures, videos and audio. Consider these formats in the code. Some pets may not have profile pictures or additional media.
2.Hosting: Create a web application hosted in a single container and service in Cloud Run, use the following syntax to deploy it using IAP. IMPORTANT: DO NOT ADD IAM AUTHENTICATION AND DO NOT ALLOW UNAUTHENTICATED: gcloud beta run deploy SERVICE_NAME  --region=REGION --image=IMAGE_URL  --no-allow-unauthenticated --iap
3.Database access: Display similar pets based on a similarity between embeddings in table petverse.profile_embeddings. 
Here's the schema for the pets table in CSV format (Field name, type, mode):
Id,INTEGER,NULLABLE
Name,STRING,NULLABLE
Species,STRING,NULLABLE
Breed,STRING,NULLABLE
Nationality,STRING,NULLABLE
Nicknames,STRING,NULLABLE
Hobby,STRING,NULLABLE
AdoptionStory,STRING,NULLABLE
FavoriteFood,STRING,NULLABLE
FavoriteToy,STRING,NULLABLE
profile_picture,RECORD,NULLABLE
additional_media,RECORD,REPEATED
profile_embeddings,FLOAT,REPEATED
Here's a sample query to check for similarity:
SELECT
t2.id AS similar_pet_id,
COSINE_DISTANCE(t1.ml_generate_embedding_result, t2.ml_generate_embedding_result) AS distance
FROM
petverse.profile_embeddings AS t1,
petverse.profile_embeddings AS t2
WHERE
t1.Id = 3 -- The pet you want to find similar ones to
AND t1.Id != t2.Id -- Exclude the pet itself from the results
AND t1.content.uri IS NOT NULL
AND t2.content.uri IS NOT NULL
ORDER BY
distance
LIMIT 5;
Complement the profile of each pet with a description. Here's an example of the access to such table:
SELECT Name, MediaDescription from petverse.pets;
4.For each access to BigQuery, show the SQL statement that is used in the console logs.
5.Search functionality: Add a search bar for a semantic search for pets. There's a text embedding for the Adoption story, the pet's past-time or hobby and their nicknames in the table: petverse.text_embeddings . This is a sample of semantic search:
SELECT query.query, base.content, base.Name FROM VECTOR_SEARCH(TABLE `petverse.text_embeddings`, 'ml_generate_embedding_result', ( SELECT ml_generate_embedding_result, content AS query FROM ML.GENERATE_EMBEDDING(MODEL `petverse.textembedding`,(SELECT 'Pets who like to relax' AS content))), top_k => 5, options => '{"fraction_lists_to_search": 0.50}') ORDER BY distance DESC
6.Use Python for the backend. Generate the deployment scripts for an authenticated service using IAP with the flags --no-allow-unauthenticated --iap
7. Make the UI look like a modern art museum.
8. Use the gunicorn library. Validate version dependencies.

이제부터는 여러분의 모험입니다. 진행 중에 계획이 표시되고 확인을 요청받게 됩니다.

코드와 배포가 처음부터 작동할 가능성은 매우 낮습니다. Gemini CLI가 올바르게 이해할 때까지 반복해야 합니다.

프로세스가 루프에 갇힌 경우 Ctrl/Command + C를 사용하여 중지하고 문제를 조사한 후 다시 프롬프트를 표시합니다.

47d6e394fc4f5b60.png

CLI에서 수행할 작업을 이해하려면 각 확인을 하나씩 신중하게 읽어보는 것이 좋습니다.

6a62b9c077d4cd11.png

몇 분 후 애플리케이션을 실행할 수 있습니다. 콘솔이 멈춘 것처럼 보일 수 있습니다.

ca51ecf7b1ce08bf.png

새 Cloud Shell 탭에서 gunicorn을 사용하여 애플리케이션을 수동으로 시도해 볼 수 있습니다. 프로젝트가 설정되어 있는지 확인합니다.

f0ee1095386f7ec.png

새 사이트가 표시됩니다 (모습은 다를 수 있음). 작동하지 않는 항목이 있으면 로컬에서 실행되는 Cloud Shell 명령줄에 오류 및 디버깅 로그가 표시됩니다.

27bf3e2a8d429169.gif

문제가 없으면 원하는 경우 애플리케이션을 Cloud Run에 배포할 수 있습니다.

프로젝트가 조직에 속하는 경우 이 안내에 따라 IAP를 구성해야 합니다. 프로젝트가 조직에 속하지 않는 경우 이 안내에 따라 애플리케이션에 대한 액세스를 보호할 수 있습니다. 특히 프로덕션 설정의 경우 인증되지 않은 액세스를 허용하지 않는 것이 좋습니다.

2365a90ac6a7d4e5.png

배포가 작동하면 Cloud Run 콘솔에서 Cloud Run 애플리케이션이 실행되는 것을 확인할 수 있습니다.

액세스가 IAP 전용인지 확인합니다. 정책 수정을 사용하여 바인딩에 사용자를 추가하고 저장합니다.

IAP 바인딩이 전파될 때까지 몇 분 정도 기다린 후 상단의 URL을 클릭합니다. 사이트가 표시됩니다.

3943c556ba912466.png

12. 삭제

이 단계에서는 이 Codelab에서 만든 리소스를 삭제하는 방법을 안내합니다.

Cloud Run 서비스를 삭제합니다 (필요에 따라 서비스 이름과 리전을 조정).

gcloud run services delete petverse-profiles --region us-central1

모든 BigQuery 애셋을 삭제합니다.

bq rm -f petverse
gcloud bigquery connections delete pet-connection --location=us-central1