開始在 PostgreSQL 適用的 Cloud SQL 中使用向量嵌入

1. 簡介

在本程式碼實驗室中,您將瞭解如何結合向量搜尋與 Vertex AI 嵌入功能,使用 PostgreSQL 適用的 Cloud SQL AI 整合功能。

30b7c4dcdd8bb68f.png

必要條件

  • 具備 Google Cloud 控制台的基本知識
  • 指令列介面和 Cloud Shell 的基本技能

課程內容

  • 如何部署 PostgreSQL 適用的 Cloud SQL 執行個體
  • 如何建立資料庫並啟用 Cloud SQL AI 整合
  • 如何將資料載入資料庫
  • 如何在 Cloud SQL 中使用 Vertex AI 嵌入模型
  • 如何使用 Vertex AI 生成式模型豐富結果
  • 如何使用向量索引提升效能

軟硬體需求

  • Google Cloud 帳戶和 Google Cloud 專案
  • 支援 Google Cloud 控制台和 Cloud Shell 的網路瀏覽器,例如 Chrome

2. 設定和需求

自助式環境設定

  1. 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請務必建立帳戶

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • 「Project name」是這個專案參與者的顯示名稱。這是 Google API 不會使用的字元字串。您隨時可以更新。
  • 專案 ID 在所有 Google Cloud 專案中都是不重複的值,且無法變更 (設定後即無法變更)。Cloud 控制台會自動產生專屬字串,您通常不需要特別留意。在大多數程式碼研究室中,您都需要參照專案 ID (通常會以 PROJECT_ID 表示)。如果您不喜歡系統產生的 ID,可以隨機產生另一個 ID。或者,您也可以自行嘗試,看看是否可用。在這個步驟後就無法變更,且會在專案期間維持不變。
  • 提醒您,有些 API 會使用第三個值「專案編號」。如要進一步瞭解這三個值,請參閱說明文件
  1. 接下來,您需要在 Cloud 控制台中啟用帳單功能,才能使用 Cloud 資源/API。執行這個程式碼研究室不會產生太多費用,甚至可能完全不會產生費用。如要關閉資源,避免在本教學課程結束後繼續產生費用,您可以刪除建立的資源或專案。Google Cloud 新使用者可享有價值 $300 美元的免費試用期

啟動 Cloud Shell

雖然 Google Cloud 可透過筆記型電腦遠端操作,但在本程式碼研究室中,您將使用 Google Cloud Shell,這是在雲端運作的指令列環境。

Google Cloud 控制台中,按一下右上方工具列的 Cloud Shell 圖示:

55efc1aaa7a4d3ad.png

佈建並連線至環境的作業需要一些時間才能完成。完成後,畫面應如下所示:

7ffe5cbb04455448.png

這個虛擬機器會載入您需要的所有開發工具。提供永久的 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 sqladmin.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 sqladmin.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.

4. 建立 Cloud SQL 執行個體

建立 Cloud SQL 執行個體,並整合 Vertex AI 資料庫。

建立資料庫密碼

為預設資料庫使用者定義密碼。您可以自行定義密碼,也可以使用隨機函式產生密碼:

export CLOUDSQL_PASSWORD=`openssl rand -hex 12`

請記下系統產生的密碼值:

echo $CLOUDSQL_PASSWORD

建立 PostgreSQL 適用的 Cloud SQL 執行個體

在 Cloud Shell 工作階段中執行:

gcloud sql instances create my-cloudsql-instance \
--database-version=POSTGRES_16 \
--tier=db-custom-1-3840 \
--region=us-central1 \
--edition=ENTERPRISE \
--enable-google-ml-integration \
--database-flags cloudsql.enable_google_ml_integration=on

建立執行個體後,我們需要為執行個體中的預設使用者設定密碼,並驗證是否可以使用密碼連線。

gcloud sql users set-password postgres \
    --instance=my-cloudsql-instance \
    --password=$CLOUDSQL_PASSWORD

執行指令,並在系統準備好連線時,在提示訊息中輸入密碼。

gcloud sql connect my-cloudsql-instance --user=postgres

啟用 Vertex AI 整合功能

將必要權限授予內部 Cloud SQL 服務帳戶,以便使用 Vertex AI 整合功能。

找出 Cloud SQL 內部服務帳戶的電子郵件地址,並將其匯出為變數。

SERVICE_ACCOUNT_EMAIL=$(gcloud sql instances describe my-cloudsql-instance --format="value(serviceAccountEmailAddress)")
echo $SERVICE_ACCOUNT_EMAIL

將 Vertex AI 存取權授予 Cloud SQL 服務帳戶:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
  --role="roles/aiplatform.user"

如要進一步瞭解如何建立及設定執行個體,請參閱 這篇文章中的 Cloud SQL 說明文件。

5. 準備資料庫

接下來,我們需要建立資料庫並啟用向量支援功能。

建立資料庫

建立名稱為 quickstart_db 的資料庫。為此,我們提供多種選項,例如 PostgreSQL 適用的 psql、SDK 或 Cloud SQL Studio 等指令列資料庫用戶端。我們將使用 SDK (gcloud) 建立資料庫並連線至執行個體。

在 Cloud Shell 中執行指令建立資料庫

gcloud sql databases create quickstart_db --instance=my-cloudsql-instance

啟用擴充功能

為了使用 Vertex AI 和向量,我們需要在建立的資料庫中啟用兩個擴充功能。

在 Cloud Shell 中執行指令,連線至已建立的資料庫 (您必須提供密碼)

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

連線成功後,您需要在 SQL 工作階段中執行兩個指令:

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector CASCADE;

結束 SQL 工作階段:

exit;

6. 載入資料

接下來,我們需要在資料庫中建立物件並載入資料。我們將使用虛構的 Cymbal Store 資料。資料以 CSV 格式儲存在公開的 Google Storage 值區中。

首先,我們需要在資料庫中建立所有必要物件。為此,我們將使用已熟悉的 gcloud sql connect 和 gcloud storage 指令,將結構定義物件下載並匯入資料庫。

在 Cloud Shell 中執行並提供建立執行個體時記下的密碼:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

我們在先前的指令中做了什麼?我們連線至資料庫,並執行下載的 SQL 程式碼,建立資料表、索引和序列。

下一個步驟是載入資料,因此我們需要從 Google Cloud Storage 下載 CSV 檔案。

gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv .
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv .

接著,我們需要連結至資料庫。

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

並從 CSV 檔案匯入資料。

\copy cymbal_products from 'cymbal_products.csv' csv header
\copy cymbal_inventory from 'cymbal_inventory.csv' csv header
\copy cymbal_stores from 'cymbal_stores.csv' csv header

結束 SQL 工作階段:

exit;

如果您有自己的資料,且 CSV 檔案與 Cloud 控制台提供的 Cloud SQL 匯入工具相容,可以使用該工具,而非指令列方法。

7. 建立嵌入

接下來,我們將使用 Google Vertex AI 的 textembedding-004 模型,為產品說明建立嵌入資料,並儲存為向量資料。

連線至資料庫:

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

並使用嵌入函式在 cymbal_products 資料表中建立虛擬欄

ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED;

這可能需要一些時間,但對於 900 到 1000 列,不應超過 5 分鐘,而且通常會更快。

8. 執行相似度搜尋

我們現在可以使用相似度搜尋,根據為說明計算的向量值和我們要求的向量值執行搜尋。

您可以使用 gcloud sql connect 或 Cloud SQL Studio 等相同指令列介面執行 SQL 查詢。任何多列和複雜查詢都建議在 Cloud SQL Studio 中管理。

啟動 Cloud SQL Studio

在控制台中,按一下我們先前建立的 Cloud SQL 執行個體。

b8d4844da1114a0b.png

在右側面板中開啟後,我們可以看到 Cloud SQL Studio。按一下該按鈕。

ce3f27dc21367f2e.png

系統會開啟對話方塊,要求您提供資料庫名稱和憑證:

  • 資料庫:quickstart_db
  • 使用者:postgres
  • 密碼:您記下的資料庫主要使用者密碼

然後按一下「驗證」按鈕。

2591c8bbc93e4e97.png

系統會開啟下一個視窗,請在右側按一下「Editor」分頁,開啟 SQL 編輯器。

74307cb101a3ba9d.png

我們現在可以執行查詢了。

執行查詢

執行查詢,取得與客戶要求最相關的可用產品清單。我們要傳送給 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;

將查詢複製並貼到 Cloud SQL Studio 編輯器,然後按下「RUN」按鈕,或將查詢貼到連線至 quickstart_db 資料庫的指令列工作階段。

cd07549522fd04c9.png

以下是符合查詢的產品清單。

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
(10 rows)

9. 使用擷取的資料改善 LLM 回覆

我們可以使用執行查詢的結果,改善向用戶端應用程式傳送的 Gen AI LLM 回應,並使用提供的查詢結果,做為向 Vertex AI 生成式基礎語言模型提示的一部分,準備有意義的輸出內容。

為此,我們需要使用向量搜尋結果產生 JSON,然後將產生的 JSON 與 Vertex AI 中的 LLM 模型提示結合,以便產生有意義的輸出內容。在第一步中,我們會產生 JSON,然後在 Vertex AI Studio 中進行測試,最後將 JSON 納入可在應用程式中使用的 SQL 陳述式。

以 JSON 格式產生輸出內容

修改查詢,以 JSON 格式產生輸出內容,並只傳回一列資料,以便傳送至 Vertex AI

PostgreSQL 適用的 Cloud SQL

以下是查詢範例:

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 文字模型提示的一部分

在 Cloud 控制台中開啟 Vertex AI Studio Chat。

449b5959fa0e93bd.png

系統可能會要求您啟用其他 API,但您可以忽略這項要求。我們不需要任何其他 API 就能完成實驗室。

以下是我們要使用的提示:

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","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[place your JSON here]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

以下是將 JSON 預留位置替換為查詢回應的結果:

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","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[{"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"}]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

以下是使用 JSON 值和 gemini-2.0-flash 模型執行提示的結果:

2c5145ebc04daae1.png

以下是我們在本例中從模型取得的答案。請注意,由於模型和參數會隨時間變更,因此您的答案可能會有所不同:

「好的,根據可供選擇的產品清單,我們最推薦的櫻花樹很適合在你所在地區生長。

價格為 $75.00 美元。

雖然我無法提供你所在郵遞區 (93230) 的具體栽種條件,但一般來說,櫻花樹在氣候溫和且排水良好的土壤中生長得很好。這些植物通常需要經過一段冬季寒冷期才能結果,請留意這一點。不過,在適當條件下,它們可以為花園增添美感,並提供美味的櫻桃。」

在 PSQL 中執行提示

我們也可以使用 Cloud SQL AI 與 Vertex AI 的整合功能,直接在資料庫中使用 SQL 從生成模型取得類似的回應。不過,我們必須先註冊 gemini-2.0-flash-exp 模型,才能使用該模型。

在 PostgreSQL 適用的 Cloud SQL 中執行

將擴充功能升級至 1.4.2 以上版本 (如果目前的版本較低)。如先前所示,透過 gcloud sql connect 連線至 quickstart_db 資料庫 (或使用 Cloud SQL Studio),然後執行以下指令:

SELECT extversion from pg_extension where extname='google_ml_integration';

如果傳回的值小於 1.4.2,請執行以下操作:

ALTER EXTENSION google_ml_integration UPDATE TO '1.4.2';

接著,我們需要將 google_ml_integration.enable_model_support 資料庫旗標設為「開啟」。如要執行這項操作,您可以使用網路主控台介面或執行下列 gcloud 指令。

gcloud sql instances patch my-cloudsql-instance \
--database-flags google_ml_integration.enable_model_support=on,cloudsql.enable_google_ml_integration=on

這個指令在背景執行時,大約需要 1 到 3 分鐘的時間。接著,您可以在 psql 工作階段中驗證新旗標,或使用 Cloud SQL Studio 連線至 quickstart_db 資料庫。

show google_ml_integration.enable_model_support;

psql 工作階段的預期輸出內容為「on」:

quickstart_db => show google_ml_integration.enable_model_support;
 google_ml_integration.enable_model_support 
--------------------------------------------
 on
(1 row)

接著,我們需要註冊兩個模型。第一個是已使用的 text-embedding-004 模型。我們已啟用模型註冊功能,因此需要註冊。

如要註冊在 psql 或 Cloud SQL 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 => 'cloudsql_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-2.0-flash-001,用於產生易於使用者理解的輸出內容。

CALL
  google_ml.create_model(
    model_id => 'gemini-2.0-flash-001',
    model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.0-flash-001:streamGenerateContent',
    model_provider => 'google',
    model_auth_type => 'cloudsql_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
 gemini-1.5-pro:streamGenerateContent | generic
 gemini-1.5-pro:generateContent       | generic
 gemini-1.0-pro:generateContent       | generic
 text-embedding-004                   | text_embedding
 gemini-2.0-flash-001                 | generic

我們現在可以使用子查詢 JSON 中產生的內容,透過 SQL 將其當做提示的一部分提供給生成式 AI 文字模型。

在資料庫的 psql 或 Cloud SQL 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 <=> google_ml.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-2.0-flash-001',
        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 模型的互動情形。但如果您有數百萬個向量,向量搜尋可能會占用大量回應時間,並對系統造成高負載。為了改善這個問題,我們可以建立向量索引。

建立 HNSW 索引

我們將嘗試使用 HNSW 索引類型進行測試。HNSW 代表「Hierarchical Navigable Small World」,代表多層圖形索引。

如要為嵌入資料欄建立索引,我們需要定義嵌入資料欄、距離函式,以及 m 或 ef_constructions 等選用參數。如要進一步瞭解這些參數,請參閱說明文件

CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

預期輸出內容:

quickstart_db=> CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);
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=779.12..779.13 rows=1 width=32) (actual time=1.066..1.069 rows=1 loops=1)
   ->  Subquery Scan on trees  (cost=769.05..779.12 rows=1 width=142) (actual time=1.038..1.041 rows=1 loops=1)
         ->  Limit  (cost=769.05..779.11 rows=1 width=158) (actual time=1.022..1.024 rows=1 loops=1)
               ->  Nested Loop  (cost=769.05..9339.69 rows=852 width=158) (actual time=1.020..1.021 rows=1 loops=1)
                     ->  Nested Loop  (cost=768.77..9316.48 rows=852 width=945) (actual time=0.858..0.859 rows=1 loops=1)
                           ->  Index Scan using cymbal_products_embeddings_hnsw on cymbal_products cp  (cost=768.34..2572.47 rows=941 width=941) (actual time=0.532..0.539 rows=3 loops=1)
                                 Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,...
<redacted>
...,0.017593635,-0.040275685,-0.03914233,-0.018452475,0.00826032,-0.07372604
]'::vector)
                           ->  Index Scan using product_inventory_pkey on cymbal_inventory ci  (cost=0.42..7.17 rows=1 width=37) (actual time=0.104..0.104 rows=0 loops=3)
                                 Index Cond: ((store_id = 1583) AND (uniq_id = (cp.uniq_id)::text))
                                 Filter: (inventory > 0)
                                 Rows Removed by Filter: 1
                     ->  Materialize  (cost=0.28..8.31 rows=1 width=8) (actual time=0.133..0.134 rows=1 loops=1)
                           ->  Index Scan using product_stores_pkey on cymbal_stores cs  (cost=0.28..8.30 rows=1 width=8) (actual time=0.129..0.129 rows=1 loops=1)
                                 Index Cond: (store_id = 1583)
 Planning Time: 112.398 ms
 Execution Time: 1.221 ms

從輸出內容中,我們可以清楚看到查詢使用了「使用 cymbal_products_embeddings_hnsw 的索引掃描」。

如果我們不執行 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":"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"}]

我們可以看到結果相同,並傳回在未編入索引的情況下,在搜尋中位於頂端的櫻桃樹。視參數和索引類型而定,結果可能會有些微差異。在測試期間,使用已編入索引的查詢傳回結果的時間為 131.301 毫秒,而未編入索引的查詢傳回結果的時間為 167.631 毫秒,但我們處理的是極小資料集,如果是處理大量資料,差異會更明顯。

您可以嘗試使用向量可用的不同索引,並在說明文件中查看更多實驗室和範例,瞭解如何整合 LangChain。

11. 清理環境

刪除 Cloud SQL 執行個體

完成實驗室後,請銷毀 Cloud SQL 執行個體

如果您已與網路中斷連線,且先前的所有設定都已遺失,請在 Cloud Shell 中定義專案和環境變數:

export INSTANCE_NAME=my-cloudsql-instance
export PROJECT_ID=$(gcloud config get-value project)

刪除執行個體:

gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID

預期的控制台輸出內容:

student@cloudshell:~$ gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID
All of the instance data will be lost when the instance is deleted.

Do you want to continue (Y/n)?  y

Deleting Cloud SQL instance...done.                                                                                                                
Deleted [https://sandbox.googleapis.com/v1beta4/projects/test-project-001-402417/instances/my-cloudsql-instance].

12. 恭喜

恭喜您完成程式碼研究室!

涵蓋內容

  • 如何部署 PostgreSQL 適用的 Cloud SQL 執行個體
  • 如何建立資料庫並啟用 Cloud SQL AI 整合
  • 如何將資料載入資料庫
  • 如何在 Cloud SQL 中使用 Vertex AI 嵌入模型
  • 如何使用 Vertex AI 生成式模型豐富結果
  • 如何使用向量索引提升效能

試著使用 ScaNN 索引 (而非 HNSW) 執行類似的 AlloyDB 程式碼研究室

13. 問卷調查

輸出:

您要如何使用這個教學課程?

只閱讀內容 閱讀內容並完成練習