1. 總覽
在現今快速變化的零售環境中,提供卓越的客戶服務,同時提供個人化購物體驗,是至關重要的事。我們將帶您踏上技術旅程,建立知識導向的即時通訊應用程式,用於回答客戶問題、引導產品探索,以及提供客製化搜尋結果。這項創新解決方案結合了 AlloyDB 的資料儲存功能、內部分析引擎的內容理解功能、Gemini (大型語言模型) 的關聯性驗證功能,以及 Google 的 Agent Builder 快速啟動智慧對話式助理的功能。
挑戰:現代零售業的消費者希望能即時獲得解答,並獲得符合個人偏好的產品推薦。傳統搜尋方法通常無法提供這麼高的個人化服務。
解決方案:我們的知識導向即時通訊應用程式正面解決這個問題。這項服務會運用從零售資料衍生的豐富知識庫,瞭解客戶意圖、做出聰明回應,並提供極具相關性的結果。
建構項目
在本實驗室 (第 1 部分) 中,您將:
- 建立 AlloyDB 例項並載入電子商務資料集
- 在 AlloyDB 中啟用 pgvector 和生成式 AI 模型擴充功能
- 根據產品說明產生嵌入
- 針對使用者搜尋文字執行即時餘弦相似度搜尋
- 在無伺服器 Cloud Run 函式中部署解決方案
實驗室的第二部分將介紹 Agent Builder 的步驟。
需求條件
2. 架構
資料流:讓我們進一步瞭解資料在系統中的移動歷程:
內容擷取:
首先,我們會將零售資料 (商品目錄、產品說明、顧客互動) 匯入 AlloyDB。
數據分析引擎:
我們會使用 AlloyDB 做為分析引擎,執行下列操作:
- 擷取情境:引擎會分析 AlloyDB 中儲存的資料,以瞭解產品、類別、客戶行為等之間的關係。
- 嵌入建立:系統會為使用者的查詢和 AlloyDB 中儲存的資訊產生嵌入項目 (文字的數學表示法)。
- Vector Search:引擎會執行相似度搜尋,將查詢嵌入項目與產品說明、評論和其他相關資料的嵌入項目進行比較。這項功能會找出 25 個最相關的「最近鄰居」。
Gemini 驗證:
這些潛在回應會傳送至 Gemini 進行評估。Gemini 會判斷這些資訊是否確實相關且安全,可否與使用者分享。
回覆產生:
經過驗證的回應會以 JSON 陣列的形式建構,整個引擎會封裝為從代理程式建構工具叫用的無伺服器 Cloud Run 函式。
對話式互動:
代理程式建構工具會以自然語言格式向使用者呈現回應,方便雙方進行對話。這部分將在後續實驗室中說明。
3. 事前準備
建立專案
- 在 Google Cloud 控制台的專案選取器頁面中,選取或建立 Google Cloud 專案。
- 確認 Cloud 專案已啟用計費功能。瞭解如何檢查專案是否已啟用計費功能。
- 您將使用 Cloud Shell,這是在 Google Cloud 中運作的指令列環境,並預先載入 bq。按一下 Google Cloud 控制台頂端的「啟用 Cloud Shell」。
- 連線至 Cloud Shell 後,請使用下列指令確認您已通過驗證,且專案已設為您的專案 ID:
gcloud auth list
- 在 Cloud Shell 中執行下列指令,確認 gcloud 指令知道您的專案。
gcloud config list project
- 如果您尚未設定專案,請使用下列指令進行設定:
gcloud config set project <YOUR_PROJECT_ID>
- 啟用必要的 API。
gcloud services enable alloydb.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
cloudfunctions.googleapis.com \
aiplatform.googleapis.com
您可以透過主控台搜尋每項產品,或使用這個連結,來代替 gcloud 指令。
如果遺漏任何 API,您隨時可以在實作期間啟用。
如要瞭解 gcloud 指令和用法,請參閱說明文件。
4. 資料庫設定
在本實驗室中,我們會使用 AlloyDB 做為儲存零售資料的資料庫。它會使用叢集來保存所有資源,例如資料庫和記錄。每個叢集都有一個主要例項,可提供資料的存取點。資料表會儲存實際資料。
我們來建立 AlloyDB 叢集、例項和資料表,用於載入電子商務資料集。
建立叢集和執行個體
- 前往 Cloud 控制台的 AlloyDB 頁面。如要輕鬆在 Cloud Console 中找到大部分的頁面,請使用控制台的搜尋列進行搜尋。
- 在該頁面中選取「建立叢集」:
- 您會看到類似下方的畫面。使用下列值建立叢集和執行個體:
- 叢集 ID:「
shopping-cluster
」 - 密碼:「
alloydb
」 - 與 PostgreSQL 15 相容
- 區域:「
us-central1
」 - 網路:
default
- 選取預設網路後,畫面會顯示如下圖所示畫面。選取「設定連線」。
- 接著選取「使用系統自動分配的 IP 範圍」和「繼續」。查看相關資訊後,請選取「建立連線」。
- 網路設定完成後,您可以繼續建立叢集。按一下「建立叢集」即可完成叢集設定,如下所示:
請務必將執行個體 ID 變更為「shopping-instance"
」。
請注意,建立叢集大約需要 10 分鐘。成功後,您應該會看到類似下圖的畫面:
5. 資料擷取
接下來,我們要新增一個包含商店資料的表格。前往 AlloyDB,選取主要叢集,然後選取 AlloyDB Studio:
您可能需要等待執行個體建立完成。完成後,請使用建立叢集時建立的憑證登入 AlloyDB。使用下列資料驗證 PostgreSQL:
- 使用者名稱:"
postgres
" - 資料庫:
postgres
- 密碼:"
alloydb
"
成功驗證 AlloyDB Studio 後,您就可以在編輯器中輸入 SQL 指令。您可以使用最後一個視窗右側的加號新增多個編輯器視窗。
您會在編輯器視窗中輸入 AlloyDB 指令,並視需要使用「Run」、「Format」和「Clear」選項。
啟用擴充功能
我們將使用擴充功能 pgvector
和 google_ml_integration
來建構這個應用程式。pgvector 擴充功能可讓您儲存及搜尋向量嵌入項目。google_ml_integration 擴充功能提供的函式可用於存取 Vertex AI 預測端點,以便在 SQL 中取得預測結果。執行下列 DDL 啟用這些擴充功能:
CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;
如要檢查資料庫已啟用的擴充功能,請執行下列 SQL 指令:
select extname, extversion from pg_extension;
建立表格
使用下列 DDL 陳述式建立資料表:
CREATE TABLE
apparels ( id BIGINT,
category VARCHAR(100),
sub_category VARCHAR(50),
uri VARCHAR(200),
image VARCHAR(100),
content VARCHAR(2000),
pdt_desc VARCHAR(5000),
embedding vector(768) );
執行上述指令成功後,您應該就能在資料庫中查看該資料表。以下是螢幕截圖範例:
擷取資料
在本實驗室中,我們在這個 SQL 檔案中提供約 200 筆記錄的測試資料。其中包含 id, category, sub_category, uri, image
和 content
。我們會在稍後的實驗室課程中填入其他欄位。
複製這裡的 20 行/插入陳述式,然後將這些行貼到空白編輯器分頁中,然後選取「RUN」。
如要查看資料表內容,請展開「Explorer」部分,直到看到名為 apparels 的資料表。選取三橫線 (⋮) 即可查看「查詢表格」選項。系統會在新編輯器分頁中開啟 SELECT 陳述式。
授予權限
執行下列陳述式,將 embedding
函式的執行權限授予使用者 postgres
:
GRANT EXECUTE ON FUNCTION embedding TO postgres;
將 Vertex AI 使用者角色授予 AlloyDB 服務帳戶
前往 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"
6. 背景資訊
返回 AlloyDB 執行個體頁面。
如要建立嵌入項目,我們需要有 context
,也就是我們想在單一欄位中納入的所有資訊。我們會透過建立產品說明 (稱為 pdt_desc
) 來完成這項操作。在本例中,我們會使用每項產品的所有資訊,但如果您要使用自己的資料執行這項操作,可以自由運用任何對自家業務有意義的資料處理方式。
在您新建立的執行個體的 AlloyDB Studio 中執行下列陳述式。這會使用情境資料更新 pdt_desc 欄位:
UPDATE
apparels
SET
pdt_desc = CONCAT('This product category is: ', category, ' and sub_category is: ', sub_category, '. The description of the product is as follows: ', content, '. The product image is stored at: ', uri)
WHERE
id IS NOT NULL;
這段 DML 會使用資料表中所有欄位和其他依附元件 (如果有) 的資訊,建立簡單的背景摘要。如要更精確地分類資訊和建立情境,您可以運用任何對業務有意義的方式來設計資料。
7. 為情境建立嵌入
電腦處理數字比處理文字容易得多。嵌入系統會將文字轉換為一系列浮點數,這些數字應可代表文字,無論文字的措詞、使用的語言為何等。
建議您描述海邊景色。這些詞彙可能會稱為「on the water」、「beachfront」、「walk from your room to the ocean」、「sur la mer」、「на берегу океана」等,這些詞彙看起來都不同,但其語意或機器學習術語中的嵌入值應會非常接近。
資料和背景資訊都準備就緒後,我們會執行 SQL 指令碼,將產品說明的嵌入資料新增至 embedding
欄位中的資料表。您可以使用各種嵌入模型。我們使用 Vertex AI 的 text-embedding-004
。請務必在整個專案中使用相同的嵌入模型!
注意:如果您使用的是已建立一段時間的現有 Google Cloud 專案,可能需要繼續使用舊版文字嵌入模型,例如 textembedding-gecko。
UPDATE
apparels
SET
embedding = embedding( 'text-embedding-004',
pdt_desc)
WHERE
TRUE;
再次查看 apparels
表格,看看其中的嵌入資料。請務必重新執行 SELECT 陳述式,查看變更內容。
SELECT
id,
category,
sub_category,
content,
embedding
FROM
apparels;
這項操作應會針對查詢中的範例文字傳回嵌入向量,如下所示,這類似於浮點陣列:
注意:如果新建立的 Google Cloud 專案屬於免費方案,每秒允許嵌入模型的嵌入要求數量可能會出現配額問題。建議您使用 ID 篩選器查詢,然後在產生嵌入內容時,選擇 1 到 5 筆記錄等。
8. 執行向量搜尋
表格、資料和嵌入項目都已準備就緒,現在讓我們針對使用者的搜尋字串執行即時向量搜尋。
假設使用者詢問:
「我想買女性上衣,粉紅色休閒款,只限純棉。」
您可以執行下列查詢,找出相符項目:
SELECT
id,
category,
sub_category,
content,
pdt_desc AS description
FROM
apparels
ORDER BY
embedding <=> embedding('text-embedding-004',
'I want womens tops, pink casual only pure cotton.')::vector
LIMIT
5;
讓我們進一步瞭解這個查詢:
在這個查詢中,
- 使用者的搜尋文字為:「我想要女性上衣,粉紅色休閒服,只限純棉。」
- 我們會使用模型
text-embedding-004
,將其轉換為embedding()
方法中的嵌入資料。在上一節中,我們將嵌入函式套用至資料表中的所有項目,因此這個步驟應該會讓您感到熟悉。 - 「
<=>
」代表使用 COSINE SIMILARITY 距離方法。如要查看所有可用的相似度評估指標,請參閱 pgvector 的說明文件。 - 我們會將嵌入方法的結果轉換為向量類型,以便與資料庫中儲存的向量相容。
- LIMIT 5 代表我們要擷取搜尋字串的 5 個最相近項目。
結果如下所示:
如您在結果中看到的,相符項目與搜尋文字非常相近。嘗試變更顏色,看看結果會如何變化。
9. 使用 LLM 進行比對驗證
在繼續建立服務,為應用程式傳回最相符的內容之前,我們先使用生成式 AI 模型,驗證這些潛在回覆是否確實相關,且可安全地與使用者分享。
確認已為 Gemini 設定執行個體
請先確認叢集和執行個體是否已啟用 Google ML 整合功能。在 AlloyDB Studio 中輸入下列指令:
show google_ml_integration.enable_model_support;
如果顯示的值為「on」,您可以略過接下來的 2 個步驟,直接設定 AlloyDB 和 Vertex AI 模型整合。
- 前往 AlloyDB 叢集的主要執行個體,然後按一下「編輯主要執行個體」
- 前往「進階設定選項」中的「標記」部分。並確認
google_ml_integration.enable_model_support flag
已設為「on
」,如下所示:
如果未設為「開啟」,請將其設為「開啟」,然後按一下「更新執行個體」按鈕。這項步驟需要幾分鐘的時間。
AlloyDB 與 Vertex AI 模型整合
您現在可以連線至 AlloyDB Studio,並執行下列 DML 陳述式,透過 AlloyDB 設定 Gemini 模型存取權,並在指定位置使用專案 ID。執行指令前,系統可能會警告您語法錯誤,但指令應該會正常執行。
首先,我們會建立 Gemini 1.5 模型連線,如下所示。請記得將下方指令中的 $PROJECT_ID
替換為您的 Google Cloud 專案 ID。
CALL
google_ml.create_model( model_id => 'gemini-1.5',
model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-1.5-pro:streamGenerateContent',
model_provider => 'google',
model_auth_type => 'alloydb_service_agent_iam');
您可以透過 AlloyDB Studio 中的下列指令,檢查已設定存取權限的模型:
select model_id,model_type from google_ml.model_info_view;
最後,我們需要授予資料庫使用者權限,讓他們執行 ml_predict_row 函式,透過 Google Vertex AI 模型執行預測。執行下列指令:
GRANT EXECUTE ON FUNCTION ml_predict_row to postgres;
注意:如果您使用的是現有的 Google Cloud 專案,以及先前建立的 AlloyDB 叢集/例項,則可能需要刪除對 gemini-1.5 模型的舊參照,並使用上述 CALL 陳述式重新建立,並再次對 ml_predict_row 函式執行授權執行作業,以防在之後的 gemini-1.5 叫用作業中遇到問題。
評估回覆
雖然我們會在下一節中使用一個大型查詢,確保查詢的回應合理,但這項查詢可能難以理解。我們現在就來看看這些片段,看看它們在幾分鐘內如何組合在一起。
- 首先,我們會向資料庫傳送要求,取得與使用者查詢最相符的 5 個項目。我們會將查詢硬式編碼,以便簡化操作。不過別擔心,我們稍後會將其插入查詢中。我們會納入
apparels
資料表中的產品說明,並新增兩個欄位:一個將說明與索引結合,另一個則與原始要求結合。所有資料都會儲存在名為xyz
的資料表中 (只是暫時性資料表名稱)。
CREATE TABLE
xyz AS
SELECT
id || ' - ' || pdt_desc AS literature,
pdt_desc AS content,
'I want womens tops, pink casual only pure cotton.' AS user_text
FROM
apparels
ORDER BY
embedding <=> embedding('text-embedding-004',
'I want womens tops, pink casual only pure cotton.')::vector
LIMIT
5;
這項查詢的輸出結果會是與使用者查詢最相似的 5 列。新的 xyz 表格將包含 5 列,每列都包含下列資料欄:
literature
content
user_text
- 為了判斷回應是否有效,我們會使用複雜的查詢,說明如何評估回應。它會使用
xyz
資料表中的user_text
和content
做為查詢的一部分。
"Read this user search text: ', user_text,
' Compare it against the product inventory data set: ', content,
' Return a response with 3 values: 1) MATCH: if the 2 contexts are at least 85% matching or not: YES or NO 2) PERCENTAGE: percentage of match, make sure that this percentage is accurate 3) DIFFERENCE: A clear short easy description of the difference between the 2 products. Remember if the user search text says that some attribute should not be there, and the record has it, it should be a NO match."
- 接著,我們會使用該查詢,查看
xyz
資料表中回應的「好壞程度」。
CREATE TABLE
x AS
SELECT
json_array_elements( google_ml.predict_row( model_id => 'gemini-1.5',
request_body => CONCAT('{
"contents": [
{ "role": "user",
"parts":
[ { "text": "Read this user search text: ', user_text, ' Compare it against the product inventory data set: ', content, ' Return a response with 3 values: 1) MATCH: if the 2 contexts are at least 85% matching or not: YES or NO 2) PERCENTAGE: percentage of match, make sure that this percentage is accurate 3) DIFFERENCE: A clear short easy description of the difference between the 2 products. Remember if the user search text says that some attribute should not be there, and the record has it, it should be a NO match."
} ]
}
] }'
)::json))-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'
AS LLM_RESPONSE
FROM
xyz;
predict_row
會以 JSON 格式傳回結果。程式碼「-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'"
」用於從該 JSON 中擷取實際文字。如要查看實際傳回的 JSON,您可以移除這段程式碼。- 最後,如要取得 LLM 欄位,您只需從 x 表格中擷取即可:
SELECT
LLM_RESPONSE
FROM
x;
- 這可以結合為單一下一個查詢,如下所示。
如果您已執行上述查詢來檢查中間結果,請先從 AlloyDB 資料庫中刪除/移除 xyz 和 x 資料表,再執行這項操作。
SELECT
LLM_RESPONSE
FROM (
SELECT
json_array_elements( google_ml.predict_row( model_id => 'gemini-1.5',
request_body => CONCAT('{
"contents": [
{ "role": "user",
"parts":
[ { "text": "Read this user search text: ', user_text, ' Compare it against the product inventory data set: ', content, ' Return a response with 3 values: 1) MATCH: if the 2 contexts are at least 85% matching or not: YES or NO 2) PERCENTAGE: percentage of match, make sure that this percentage is accurate 3) DIFFERENCE: A clear short easy description of the difference between the 2 products. Remember if the user search text says that some attribute should not be there, and the record has it, it should be a NO match."
} ]
}
] }'
)::json))-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'
AS LLM_RESPONSE
FROM (
SELECT
id || ' - ' || pdt_desc AS literature,
pdt_desc AS content,
'I want womens tops, pink casual only pure cotton.' user_text
FROM
apparels
ORDER BY
embedding <=> embedding('text-embedding-004',
'I want womens tops, pink casual only pure cotton.')::vector
LIMIT
5 ) AS xyz ) AS X;
雖然這可能仍令人卻步,但希望您能對這項功能有更深入的瞭解。結果會指出是否有相符項目、相符程度,以及分數的相關說明。
請注意,Gemini 模型預設為開啟串流功能,因此實際回應會分散在多行中:
10. 將應用程式發布到網路
準備好將這個應用程式移至網路了嗎?請按照下列步驟,使用 Cloud Run 函式建構無伺服器知識引擎:
- 前往 Google Cloud 控制台的 Cloud Run 函式頁面,建立新的 Cloud Run 函式,或使用以下連結:https://console.cloud.google.com/functions/add。
- 選取「Cloud Run 函式」做為環境。請提供「retail-engine」做為函式名稱,並選擇「us-central1」做為地區。將「驗證」設為「允許未經驗證的叫用」,然後按一下「NEXT」。選擇「Java 17」做為執行階段,並為原始碼選擇「Inline Editor」。
- 根據預設,系統會將進入點設為「
gcfv2.HelloHttpFunction
」。請分別將 Cloud Run 函式的HelloHttpFunction.java
和pom.xml
中的預留位置程式碼,替換為 Java 檔案和 XML 中的程式碼。 - 請記得將 Java 檔案中的 $PROJECT_ID 預留位置和 AlloyDB 連線憑證,改為您的值。AlloyDB 憑證是我們在本程式碼研究室一開始時使用的憑證。如果您使用了不同的值,請在 Java 檔案中進行相同的修改。
- 按一下「Deploy」。
部署完成後,我們會建立 VPC 連接器,讓 Cloud 函式可以存取 AlloyDB 資料庫執行個體。
重要步驟:
設定部署作業後,您應該會在 Google Cloud Run 函式控制台中看到函式。搜尋新建立的函式 (retail-engine
),然後按一下該函式,接著點選「編輯」,然後變更下列項目:
- 前往「執行階段、建構作業、連線和安全性設定」
- 將逾時時間提高至 180 秒
- 前往「連線設定」分頁:
- 在「Ingress」設定下方,確認已選取「Allow all traffic」(允許所有流量)。
- 在「Egress」設定下,按一下「Network」下拉式選單,然後選取「Add New VPC Connector」選項,並按照彈出式對話方塊中的操作說明進行:
- 請為 VPC 連接器提供名稱,並確認區域與執行個體相同。將「Network」值保留為預設值,並將「Subnet」設為「Custom IP Range」,IP 範圍為 10.8.0.0 或可用的類似值。
- 展開「顯示縮放設定」,並確認設定已正確設為下列項目:
- 按一下「建立」,這個連接器現在應該會列在輸出設定中。
- 選取新建的連接器
- 選擇將所有流量轉送至這個虛擬私有雲連接器。
- 依序點選「NEXT」和「DEPLOY」。
11. 測試應用程式
更新後的 Cloud Function 部署完成後,您應該會看到以下格式的端點:
https://us-central1-YOUR_PROJECT_ID.cloudfunctions.net/retail-engine
您可以透過 Cloud Shell 終端機執行下列指令來測試:
gcloud functions call retail-engine --region=us-central1 --gen2 --data '{"search": "I want some kids clothes themed on Disney"}'
您也可以按照下列步驟測試 Cloud Run 函式:
PROJECT_ID=$(gcloud config get-value project)
curl -X POST https://us-central1-$PROJECT_ID.cloudfunctions.net/retail-engine \
-H 'Content-Type: application/json' \
-d '{"search":"I want some kids clothes themed on Disney"}' \
| jq .
結果如下:
大功告成!在 AlloyDB 資料上使用嵌入模型執行相似度向量搜尋,就這麼簡單。
建構對話式服務專員!
這個實驗室的第二部分會說明如何建構服務專員。
12. 清理
如果您打算完成本實驗室的第 2 部分,請略過這個步驟,因為這會刪除目前的專案。
如要避免系統向您的 Google Cloud 帳戶收取這篇文章所用資源的費用,請按照下列步驟操作:
13. 恭喜
恭喜!您已成功使用 AlloyDB、pgvector 和向量搜尋功能執行相似度搜尋。結合 AlloyDB、Vertex AI 和 Vector Search 的功能,我們已大幅提升內容和向量搜尋的易用性、效率和意義。本實驗室的下一節將介紹建立服務項目的步驟。