1. 簡介
在本程式碼研究室中,您將瞭解如何結合向量搜尋與 Vertex AI 嵌入功能,使用 AlloyDB AI。
必要條件
- 具備 Google Cloud 控制台的基本知識
- 指令列介面和 Google Shell 的基本技能
課程內容
- 如何部署 AlloyDB 叢集和主要執行個體
- 如何從 Google Compute Engine VM 連線至 AlloyDB
- 如何建立資料庫並啟用 AlloyDB AI
- 如何將資料載入資料庫
- 如何在 AlloyDB 中使用 Vertex AI 嵌入模型
- 如何使用 Vertex AI 生成式模型豐富結果
- 如何使用向量索引提升效能
軟硬體需求
- Google Cloud 帳戶和 Google Cloud 專案
- 網路瀏覽器,例如 Chrome
2. 設定和需求
自助式環境設定
- 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請務必建立帳戶。
- 「Project name」是這個專案參與者的顯示名稱。這是 Google API 不會使用的字元字串。您隨時可以更新。
- 專案 ID 在所有 Google Cloud 專案中都是不重複的值,且無法變更 (設定後即無法變更)。Cloud 控制台會自動產生專屬字串,您通常不需要特別留意。在大多數程式碼研究室中,您都需要參照專案 ID (通常會以
PROJECT_ID
表示)。如果您不喜歡系統產生的 ID,可以隨機產生另一個 ID。或者,您也可以自行嘗試,看看是否可用。在這個步驟後就無法變更,且會在專案期間維持不變。 - 提醒您,有些 API 會使用第三個值「專案編號」。如要進一步瞭解這三個值,請參閱說明文件。
- 接下來,您需要在 Cloud 控制台中啟用帳單功能,才能使用 Cloud 資源/API。執行這個程式碼研究室不會產生太多費用,甚至可能完全不會產生費用。如要關閉資源,避免在本教學課程結束後繼續產生費用,您可以刪除建立的資源或專案。Google Cloud 新使用者可享有價值 $300 美元的免費試用期。
啟動 Cloud Shell
雖然 Google Cloud 可透過筆記型電腦遠端操作,但在本程式碼研究室中,您將使用 Google Cloud Shell,這是在雲端運作的指令列環境。
在 Google Cloud 控制台中,按一下右上方工具列的 Cloud Shell 圖示:
佈建並連線至環境的作業需要一些時間才能完成。完成後,畫面應如下所示:
這個虛擬機器會載入您需要的所有開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,可大幅提升網路效能和驗證功能。您可以在瀏覽器中完成本程式碼研究室的所有工作。您不需要安裝任何東西。
3. 事前準備
啟用 API
輸出:
在 Cloud Shell 中,確認專案 ID 已設定完畢:
gcloud config set project [YOUR-PROJECT-ID]
設定環境變數 PROJECT_ID:
PROJECT_ID=$(gcloud config get-value project)
啟用所有必要服務:
gcloud services enable alloydb.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
aiplatform.googleapis.com
預期的輸出內容:
student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417 Updated property [core/project]. student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project) Your active configuration is: [cloudshell-14650] student@cloudshell:~ (test-project-001-402417)$ student@cloudshell:~ (test-project-001-402417)$ gcloud services enable alloydb.googleapis.com \ compute.googleapis.com \ cloudresourcemanager.googleapis.com \ servicenetworking.googleapis.com \ aiplatform.googleapis.com Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.
設定預設區域,以便使用 Vertex AI 嵌入模型。進一步瞭解 Vertex AI 的服務地區。本範例使用 us-central1 區域。
gcloud config set compute/region us-central1
4. 部署 AlloyDB
在建立 AlloyDB 叢集之前,我們需要在虛擬私人雲端中提供可供日後 AlloyDB 執行個體使用的私人 IP 範圍。如果沒有,我們需要建立,並指派給內部 Google 服務使用,之後才能建立叢集和執行個體。
建立私人 IP 範圍
我們需要在 AlloyDB 的 VPC 中設定私人服務存取權設定。這裡假設我們在專案中使用「預設」虛擬私有雲端網路,並且會用於所有動作。
建立私人 IP 範圍:
gcloud compute addresses create psa-range \
--global \
--purpose=VPC_PEERING \
--prefix-length=24 \
--description="VPC private service access" \
--network=default
使用分配的 IP 範圍建立私人連線:
gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=psa-range \
--network=default
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ gcloud compute addresses create psa-range \ --global \ --purpose=VPC_PEERING \ --prefix-length=24 \ --description="VPC private service access" \ --network=default Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/global/addresses/psa-range]. student@cloudshell:~ (test-project-402417)$ gcloud services vpc-peerings connect \ --service=servicenetworking.googleapis.com \ --ranges=psa-range \ --network=default Operation "operations/pssn.p24-4470404856-595e209f-19b7-4669-8a71-cbd45de8ba66" finished successfully. student@cloudshell:~ (test-project-402417)$
建立 AlloyDB 叢集
在 us-central1 區域中建立 AlloyDB 叢集。
定義 postgres 使用者的密碼。您可以自行定義密碼,也可以使用隨機函式產生密碼
export PGPASSWORD=`openssl rand -hex 12`
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ export PGPASSWORD=`openssl rand -hex 12`
請記下 PostgreSQL 密碼,以供日後使用:
echo $PGPASSWORD
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ echo $PGPASSWORD bbefbfde7601985b0dee5723
定義區域和 AlloyDB 叢集名稱。我們將使用 us-central1 區域,並以 alloydb-aip-01 做為叢集名稱:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
執行指令建立叢集:
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
預期的控制台輸出內容:
export REGION=us-central1 export ADBCLUSTER=alloydb-aip-01 gcloud alloydb clusters create $ADBCLUSTER \ --password=$PGPASSWORD \ --network=default \ --region=$REGION Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4 Creating cluster...done.
建立 AlloyDB 主要執行個體
在同一個 Cloud Shell 工作階段中,為叢集建立 AlloyDB 主要執行個體。如果連線中斷,您必須重新定義地區和叢集名稱環境變數。
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=2 \
--region=$REGION \
--cluster=$ADBCLUSTER
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \ --instance-type=PRIMARY \ --cpu-count=2 \ --region=$REGION \ --availability-type ZONAL \ --cluster=$ADBCLUSTER Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721 Creating instance...done.
5. 連線至 AlloyDB
AlloyDB 是使用僅限私人連線部署,因此我們需要安裝 PostgreSQL 用戶端的 VM,才能與資料庫搭配使用。
部署 GCE VM
在與 AlloyDB 叢集相同的區域和 VPC 中建立 GCE VM。
在 Cloud Shell 中執行:
export ZONE=us-central1-a
gcloud compute instances create instance-1 \
--zone=$ZONE \
--create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \
--scopes=https://www.googleapis.com/auth/cloud-platform
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ export ZONE=us-central1-a student@cloudshell:~ (test-project-402417)$ export ZONE=us-central1-a gcloud compute instances create instance-1 \ --zone=$ZONE \ --create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \ --scopes=https://www.googleapis.com/auth/cloud-platform Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/zones/us-central1-a/instances/instance-1]. NAME: instance-1 ZONE: us-central1-a MACHINE_TYPE: n1-standard-1 PREEMPTIBLE: INTERNAL_IP: 10.128.0.2 EXTERNAL_IP: 34.71.192.233 STATUS: RUNNING
安裝 Postgres 用戶端
在已部署的 VM 上安裝 PostgreSQL 用戶端軟體
連線至 VM:
gcloud compute ssh instance-1 --zone=us-central1-a
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ gcloud compute ssh instance-1 --zone=us-central1-a Updating project ssh metadata...working..Updated [https://www.googleapis.com/compute/v1/projects/test-project-402417]. Updating project ssh metadata...done. Waiting for SSH key to propagate. Warning: Permanently added 'compute.5110295539541121102' (ECDSA) to the list of known hosts. Linux instance-1.us-central1-a.c.gleb-test-short-001-418811.internal 6.1.0-18-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. student@instance-1:~$
在 VM 中安裝執行軟體的指令:
sudo apt-get update
sudo apt-get install --yes postgresql-client
預期的控制台輸出內容:
student@instance-1:~$ sudo apt-get update sudo apt-get install --yes postgresql-client Get:1 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable InRelease [5146 B] Get:2 https://packages.cloud.google.com/apt cloud-sdk-bullseye InRelease [6406 B] Hit:3 https://deb.debian.org/debian bullseye InRelease Get:4 https://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB] Get:5 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable/main amd64 Packages [1930 B] Get:6 https://deb.debian.org/debian bullseye-updates InRelease [44.1 kB] Get:7 https://deb.debian.org/debian bullseye-backports InRelease [49.0 kB] ...redacted... update-alternatives: using /usr/share/postgresql/13/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode Setting up postgresql-client (13+225) ... Processing triggers for man-db (2.9.4-2) ... Processing triggers for libc-bin (2.31-13+deb11u7) ...
連線至執行個體
使用 psql 從 VM 連線至主要執行個體。
在同一個 Cloud Shell 分頁中,開啟 instance-1 VM 的 SSH 工作階段。
使用上述 AlloyDB 密碼 (PGPASSWORD) 值和 AlloyDB 叢集 ID,透過 GCE VM 連線至 AlloyDB:
export PGPASSWORD=<Noted password>
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)")
psql "host=$INSTANCE_IP user=postgres sslmode=require"
預期的控制台輸出內容:
student@instance-1:~$ export PGPASSWORD=CQhOi5OygD4ps6ty student@instance-1:~$ ADBCLUSTER=alloydb-aip-01 student@instance-1:~$ REGION=us-central1 student@instance-1:~$ INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)") gleb@instance-1:~$ psql "host=$INSTANCE_IP user=postgres sslmode=require" psql (15.6 (Debian 15.6-0+deb12u1), server 15.5) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off) Type "help" for help. postgres=>
關閉 psql 工作階段:
exit
6. 準備資料庫
我們需要建立資料庫、啟用 Vertex AI 整合功能、建立資料庫物件,然後匯入資料。
授予 AlloyDB 必要權限
將 Vertex AI 權限新增至 AlloyDB 服務代理。
使用頂端的「+」符號開啟另一個 Cloud Shell 分頁。
在新的 Cloud Shell 分頁中執行:
PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"
預期的控制台輸出內容:
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project) Your active configuration is: [cloudshell-11039] student@cloudshell:~ (test-project-001-402417)$ gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \ --role="roles/aiplatform.user" Updated IAM policy for project [test-project-001-402417]. bindings: - members: - serviceAccount:service-4470404856@gcp-sa-alloydb.iam.gserviceaccount.com role: roles/aiplatform.user - members: ... etag: BwYIEbe_Z3U= version: 1
在分頁中執行「exit」指令,關閉分頁:
exit
建立資料庫
建立資料庫快速入門。
在 GCE VM 工作階段中執行:
建立資料庫:
psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"
預期的控制台輸出內容:
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db" CREATE DATABASE student@instance-1:~$
啟用 Vertex AI 整合功能
啟用資料庫中的 Vertex AI 整合功能和 pgvector 擴充功能。
在 GCE VM 中執行:
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE"
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector"
預期的控制台輸出內容:
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE" psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector" CREATE EXTENSION CREATE EXTENSION student@instance-1:~$
匯入資料
下載準備好的資料,然後匯入新資料庫。
在 GCE VM 中執行:
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header"
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header"
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header"
預期的控制台輸出內容:
student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" SET SET SET SET SET set_config ------------ (1 row) SET SET SET SET SET SET CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE SEQUENCE ALTER TABLE ALTER SEQUENCE ALTER TABLE ALTER TABLE ALTER TABLE student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header" COPY 941 student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header" COPY 263861 student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header" COPY 4654 student@instance-1:~$
7. 計算嵌入
匯入資料後,我們在 cymbal_products 資料表中取得產品資料、在 cymbal_inventory 資料表中取得顯示各商店可供應產品數量的商品目錄,以及在 cymbal_stores 資料表中取得商店清單。我們需要根據產品說明計算向量資料,因此會使用嵌入函式。我們將使用這個函式,透過 Vertex AI 整合功能,根據產品說明計算向量資料,並將其加入資料表。如要進一步瞭解所用技術,請參閱說明文件。
建立嵌入欄
使用 psql 連線至資料庫,並在 cymbal_products 資料表中使用嵌入函式,建立含有向量資料的虛擬欄。嵌入函式會根據 product_description 欄提供的資料,傳回 Vertex AI 的向量資料。
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
連線至資料庫後,在 psql 工作階段中執行:
ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED;
這項指令會建立虛擬欄,並以向量資料填入該欄。
預期的控制台輸出內容:
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" psql (13.11 (Debian 13.11-0+deb11u1), server 14.7) WARNING: psql major version 13, server major version 14. Some psql features might not work. SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help. quickstart_db=> ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED; ALTER TABLE quickstart_db=>
8. 執行相似搜尋
我們現在可以使用相似度搜尋,根據為說明計算的向量值和我們要求的向量值執行搜尋。
您可以透過相同的 psql 指令列介面執行 SQL 查詢,也可以改用 AlloyDB Studio 執行。任何多列和複雜的輸出內容在 AlloyDB Studio 中可能會看起來更清楚。
連線至 AlloyDB Studio
在後續章節中,所有需要連線至資料庫的 SQL 指令都可以改為在 AlloyDB Studio 中執行。如要執行指令,您必須按一下主要執行個體,開啟 AlloyDB 叢集的網路主控台介面。
然後按一下左側的 AlloyDB Studio:
請選擇 quickstart_db 資料庫、使用者 postgres,並提供我們在建立叢集時記下的密碼。然後按一下「驗證」按鈕。
系統會開啟 AlloyDB Studio 介面。如要在資料庫中執行指令,請按一下右側的「編輯器 1」分頁。
系統會開啟介面,讓您執行 SQL 指令
如果您偏好使用指令列 psql,請按照替代路徑操作,並透過 VM SSH 工作階段連線至資料庫,如前幾章所述。
透過 psql 執行相似度搜尋
如果資料庫工作階段已中斷連線,請使用 psql 或 AlloyDB Studio 再次連線至資料庫。
連線至資料庫:
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
執行查詢,取得與客戶要求最相關的可用產品清單。我們要傳送給 Vertex AI 的向量值要求,聽起來就像「這裡適合種植哪種果樹?」
以下是可以執行的查詢,可選擇最符合要求的前 10 項項目:
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) as distance
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
distance ASC
LIMIT 10;
以下是預期的輸出內容:
quickstart_db=> SELECT cp.product_name, left(cp.product_description,80) as description, cp.sale_price, cs.zip_code, (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) as distance FROM cymbal_products cp JOIN cymbal_inventory ci on ci.uniq_id=cp.uniq_id JOIN cymbal_stores cs on cs.store_id=ci.store_id AND ci.inventory>0 AND cs.store_id = 1583 ORDER BY distance ASC LIMIT 10; product_name | description | sale_price | zip_code | distance -------------------------+----------------------------------------------------------------------------------+------------+----------+--------------------- Cherry Tree | This is a beautiful cherry tree that will produce delicious cherries. It is an d | 75.00 | 93230 | 0.43922018972266397 Meyer Lemon Tree | Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by | 34 | 93230 | 0.4685112926118228 Toyon | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e | 10.00 | 93230 | 0.4835677149651668 California Lilac | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d | 5.00 | 93230 | 0.4947204525907498 California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e | 25.00 | 93230 | 0.5054166905547247 California Black Walnut | This is a beautiful walnut tree that can grow to be over 80 feet tall. It is a d | 100.00 | 93230 | 0.5084219510932597 California Sycamore | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is | 300.00 | 93230 | 0.5140519790508755 Coast Live Oak | This is a beautiful oak tree that can grow to be over 100 feet tall. It is an ev | 500.00 | 93230 | 0.5143126438081371 Fremont Cottonwood | This is a beautiful cottonwood tree that can grow to be over 100 feet tall. It i | 200.00 | 93230 | 0.5174774727252058 Madrone | This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an | 50.00 | 93230 | 0.5227400803389093
9. 改善回覆
您可以使用查詢結果改善對用戶端應用程式的回應,並使用提供的查詢結果,做為 Vertex AI 生成式基礎語言模型提示的一部分,準備有意義的輸出內容。
為達成這個目標,我們打算產生含有向量搜尋結果的 JSON,然後使用產生的 JSON 做為 Vertex AI 文字 LLM 模型的提示,以便產生有意義的輸出內容。在第一步中,我們會產生 JSON,然後在 Vertex AI Studio 中進行測試,最後將 JSON 納入可在應用程式中使用的 SQL 陳述式。
以 JSON 格式產生輸出內容
修改查詢,以 JSON 格式產生輸出內容,並只傳回一列資料,以便傳遞至 Vertex AI
以下是查詢範例:
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
以下是輸出內容中預期的 JSON:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
在 Vertex AI Studio 中執行提示
我們可以使用產生的 JSON,在 Vertex AI Studio 中將其做為生成式 AI 文字模型提示的一部分
在雲端控制台中開啟 Vertex AI Studio。
系統可能會要求您啟用其他 API,但您可以忽略這項要求。我們不需要任何其他 API 就能完成實驗室。
以下是我們要使用的提示:
你是親切的顧問,可根據客戶需求協助他們找到合適的產品。
根據用戶要求,我們載入了與搜尋內容密切相關的產品清單。
JSON 格式的清單,其中包含值清單,例如:{"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
產品清單如下:
[JSON 位置]
客戶詢問:「這裡哪種樹木生長得最好?」
您應提供產品資訊、價格和一些補充資訊
以下是使用 JSON 值和 gemini-1.5-flash 模型執行提示的結果:
以下是我們在本例中從模型取得的答案。請注意,由於模型和參數會隨時間變更,因此您的答案可能會有所不同:
「我知道你正在尋找適合你所在地區的樹木,根據你的郵遞區號 93230,櫻桃樹似乎是個不錯的選擇!
它被描述為一種美麗的樹木,能結出美味的櫻桃。目前特價 $75.00 美元。
雖然我無法提供該地區的具體生長率,但我可以告訴你,櫻花樹通常喜歡排水良好的土壤和充足的陽光。
為確保獲得最佳結果,建議你諮詢當地的苗圃或園藝專家,他們可以根據你的所在位置和土壤狀況提供更適合的建議。他們還可以協助你選擇最適合你需求的品種,並提供種植和照顧訣竅。」
在 PSQL 中執行提示
我們可以使用 AlloyDB AI 與 Vertex AI 的整合功能,直接在資料庫中使用 SQL 取得生成式模型的相同回應。不過,如要使用 gemini-1.5-flash 模型,我們必須先註冊該模型。
將擴充功能升級至 1.4.1 版 (如果目前的版本較低)。如先前所示,透過 psql 連線至 quickstart_db 資料庫 (或使用 AlloyDB Studio),然後執行以下指令:
SELECT extversion from pg_extension where extname='google_ml_integration';
如果傳回的值小於 1.4.1,請執行以下操作:
ALTER EXTENSION google_ml_integration UPDATE TO '1.4.1';
接著,我們需要將 google_ml_integration.enable_model_support 資料庫旗標設為「開啟」。如要執行這項操作,您可以使用 AlloyDB 網路主控台介面,或執行下列 gcloud 指令。
PROJECT_ID=$(gcloud config get-value project)
REGION=us-central1
ADBCLUSTER=alloydb-aip-01
gcloud beta alloydb instances update $ADBCLUSTER-pr \
--database-flags google_ml_integration.enable_model_support=on \
--region=$REGION \
--cluster=$ADBCLUSTER \
--project=$PROJECT_ID \
--update-mode=FORCE_APPLY
這項指令在背景執行時,大約需要 3 到 5 分鐘。接著,您可以在 psql 工作階段中驗證新標記,或使用 AlloyDB Studio 連線至 quickstart_db 資料庫。
show google_ml_integration.enable_model_support;
psql 工作階段的預期輸出內容為「on」:
postgres=> show google_ml_integration.enable_model_support; google_ml_integration.enable_model_support -------------------------------------------- on (1 row)
接著,我們需要註冊兩個模型。第一個是已使用的 text-embedding-004 模型。我們已啟用模型註冊功能,因此需要註冊。
如要在 psql 或 AlloyDB Studio 中註冊模型執行作業,請使用下列程式碼:
CALL
google_ml.create_model(
model_id => 'text-embedding-004',
model_provider => 'google',
model_qualified_name => 'text-embedding-004',
model_type => 'text_embedding',
model_auth_type => 'alloydb_service_agent_iam',
model_in_transform_fn => 'google_ml.vertexai_text_embedding_input_transform',
model_out_transform_fn => 'google_ml.vertexai_text_embedding_output_transform');
接下來,我們需要註冊的模型是 gemini-1.5-flash-002,用於產生使用者友善的輸出內容。
CALL
google_ml.create_model(
model_id => 'gemini-1.5-flash-002',
model_request_url => 'https://$REGION-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/publishers/google/models/gemini-1.5-flash-002:streamGenerateContent',
model_provider => 'google',
model_auth_type => 'alloydb_service_agent_iam');
您隨時可以從 google_ml.model_info_view 選取資訊,驗證已註冊的模型清單。
select model_id,model_type from google_ml.model_info_view;
以下是輸出內容範例
quickstart_db=> select model_id,model_type from google_ml.model_info_view; model_id | model_type -------------------------+---------------- textembedding-gecko | text_embedding textembedding-gecko@001 | text_embedding text-embedding-004 | text_embedding gemini-1.5-flash-001 | generic (4 rows)
我們現在可以使用子查詢 JSON 中產生的內容,透過 SQL 將其當做提示的一部分提供給生成式 AI 文字模型。
在資料庫的 psql 或 AlloyDB Studio 工作階段中執行查詢
WITH trees AS (
SELECT
cp.product_name,
cp.product_description AS description,
cp.sale_price,
cs.zip_code,
cp.uniq_id AS product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci ON
ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON
cs.store_id = ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-004',
'What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1),
prompt AS (
SELECT
'You are a friendly advisor helping to find a product based on the customer''s needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","product_description":"some description","sale_price":10}
Here is the list of products:' || json_agg(trees) || 'The customer asked "What kind of fruit trees grow well here?"
You should give information about the product, price and some supplemental information' AS prompt_text
FROM
trees),
response AS (
SELECT
json_array_elements(google_ml.predict_row( model_id =>'gemini-1.5-flash-002',
request_body => json_build_object('contents',
json_build_object('role',
'user',
'parts',
json_build_object('text',
prompt_text)))))->'candidates'->0->'content'->'parts'->0->'text' AS resp
FROM
prompt)
SELECT
string_agg(resp::text,
' ')
FROM
response;
以下是預期的輸出內容。輸出結果可能因模型版本和參數而異:
"That" "'s a great question! Based on your location (assuming you're" " in zip code 93230), I have a suggestion for a" " fruit tree that should thrive.\n\nWe have the **Cherry Tree** available.\n\n**Product Name:** Cherry Tree\n\n**Description:** This is a beautiful cherry" " tree that will produce delicious cherries. It's a deciduous tree (meaning it loses its leaves in the fall) growing to about 15 feet tall." " The leaves are dark green in summer, turning a beautiful red in the fall. Cherry trees are known for their beauty, shade, and privacy.\n\n**Sale Price:** $75.00\n\n**Important Considerations for Growing" " Cherry Trees:**\n\n* **Climate:** Cherry trees prefer a cool, moist climate, and 93230 falls within a suitable range (USDA zones 4-9). However, it's always a good idea to" " check the specific microclimate of your property (sun exposure, drainage etc.).\n* **Soil:** They do best in sandy soil. If your soil is different, you may need to amend it to improve drainage.\n* **Pollination:** Many cherry varieties require a second, compatible cherry tree for proper pollination" ". Check the specific pollination needs of this variety before purchase if you want a significant cherry yield.\n\nThis cherry tree is a beautiful addition to any yard and will provide you with delicious cherries if you can meet its needs. Would you like to know more about its pollination requirements, or perhaps see if we have any other" " fruit trees suitable for your area?\n" ""
10. 建立向量索引
我們的資料集相當小,回應時間主要取決於與 AI 模型的互動情形。但如果您有數百萬個向量,向量搜尋部分可能會占用大量回應時間,並對系統造成高負載。為了改善這個問題,我們可以建立向量索引。
建立 ScaNN 索引
如要建構 SCANN 索引,我們需要啟用另一個擴充功能。擴充功能 alloydb_scann 提供介面,可使用 Google ScaNN 演算法處理 ANN 類型的向量索引。
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
預期輸出內容:
quickstart_db=> CREATE EXTENSION IF NOT EXISTS alloydb_scann; CREATE EXTENSION Time: 27.468 ms quickstart_db=>
我們現在可以建立索引。在以下範例中,我將大多數參數設為預設值,只為索引提供分割數量 (num_leaves):
CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
USING scann (embedding cosine)
WITH (num_leaves=31, max_num_levels = 2);
如要瞭解如何調整索引參數,請參閱說明文件。
預期輸出內容:
quickstart_db=> CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products USING scann (embedding cosine) WITH (num_leaves=31, max_num_levels = 2); CREATE INDEX quickstart_db=>
比較回應
我們現在可以以 EXPLAIN 模式執行向量搜尋查詢,並驗證是否已使用索引。
EXPLAIN (analyze)
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
預期輸出內容:
Aggregate (cost=16.59..16.60 rows=1 width=32) (actual time=2.875..2.877 rows=1 loops=1) -> Subquery Scan on trees (cost=8.42..16.59 rows=1 width=142) (actual time=2.860..2.862 rows=1 loops=1) -> Limit (cost=8.42..16.58 rows=1 width=158) (actual time=2.855..2.856 rows=1 loops=1) -> Nested Loop (cost=8.42..6489.19 rows=794 width=158) (actual time=2.854..2.855 rows=1 loops=1) -> Nested Loop (cost=8.13..6466.99 rows=794 width=938) (actual time=2.742..2.743 rows=1 loops=1) -> Index Scan using cymbal_products_embeddings_scann on cymbal_products cp (cost=7.71..111.99 rows=876 width=934) (actual time=2.724..2.724 rows=1 loops=1) Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,-0.00355923,0.0055611245,0.015985578,...<redacted>...5685,-0.03914233,-0.018452475,0.00826032,-0.07372604]'::vector) -> Index Scan using walmart_inventory_pkey on cymbal_inventory ci (cost=0.42..7.26 rows=1 width=37) (actual time=0.015..0.015 rows=1 loops=1) Index Cond: ((store_id = 1583) AND (uniq_id = (cp.uniq_id)::text))
從輸出內容中,我們可以清楚看到查詢使用了「Index Scan using cymbal_products_embeddings_scann on cymbal_products」。
如果我們不執行 explain 查詢:
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
預期輸出內容:
[{"product_name":"Meyer Lemon Tree","description":"Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by ","sale_price":34,"zip_code":93230,"product_id":"02056727942aeb714dc9a2313654e1b0"}]
我們可以看到結果略有不同,傳回的不是在未建立索引的情況下搜尋時位居頂端的櫻桃樹,而是第二個選項梅耶檸檬樹。因此,索引雖然能提供效能,但仍能提供準確的結果。
您可以嘗試不同向量索引,並在說明文件頁面中查看更多實驗室和範例,這些內容都已整合 Langchain。
11. 清理環境
完成實驗室後,請銷毀 AlloyDB 執行個體和叢集
刪除 AlloyDB 叢集和所有執行個體
叢集會使用強制選項進行銷毀,同時刪除屬於叢集的所有執行個體。
如果您已與網路中斷連線,且先前的所有設定都已遺失,請在 Cloud Shell 中定義專案和環境變數:
gcloud config set project <your project id>
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export PROJECT_ID=$(gcloud config get-value project)
刪除叢集:
gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force
預期的控制台輸出內容:
student@cloudshell:~ (test-project-001-402417)$ gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force All of the cluster data will be lost when the cluster is deleted. Do you want to continue (Y/n)? Y Operation ID: operation-1697820178429-6082890a0b570-4a72f7e4-4c5df36f Deleting cluster...done.
刪除 AlloyDB 備份
刪除叢集的所有 AlloyDB 備份:
for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done
預期的控制台輸出內容:
student@cloudshell:~ (test-project-001-402417)$ for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done Operation ID: operation-1697826266108-60829fb7b5258-7f99dc0b-99f3c35f Deleting backup...done.
我們現在可以刪除 VM
刪除 GCE VM
在 Cloud Shell 中執行:
export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
--zone=$ZONE \
--quiet
預期的控制台輸出內容:
student@cloudshell:~ (test-project-001-402417)$ export GCEVM=instance-1 export ZONE=us-central1-a gcloud compute instances delete $GCEVM \ --zone=$ZONE \ --quiet Deleted
12. 恭喜
恭喜您完成程式碼研究室!
涵蓋內容
- 如何部署 AlloyDB 叢集和主要執行個體
- 如何從 Google Compute Engine VM 連線至 AlloyDB
- 如何建立資料庫並啟用 AlloyDB AI
- 如何將資料載入資料庫
- 如何在 AlloyDB 中使用 Vertex AI 嵌入模型
- 如何使用 Vertex AI 生成式模型豐富結果
- 如何使用向量索引提升效能
13. 問卷調查
輸出: