為大型資料表生成及管理自動向量嵌入項目

選取文件版本:

您可以為整個資料表欄產生及管理向量嵌入,為大規模向量嵌入建立作業提供可擴充的解決方案。這項解決方案特別適合用來對文字內容執行語意搜尋和檢索增強生成 (RAG),包括:

  • 為新資料表建立初始向量嵌入
  • 匯入大量資料後產生嵌入內容
  • 在資料大幅變更後重新整理嵌入內容
  • 逐步維護嵌入

瞭解自動向量嵌入

AlloyDB Omni 的自動向量嵌入功能提供可擴充的方式,自動生成及維護資料的向量嵌入。您不必為每段新增或更新的文字手動產生嵌入,只要設定自動向量嵌入,系統就會為您處理這項程序。對於依賴最新嵌入內容進行語意搜尋、檢索增強生成 (RAG) 和其他 AI 輔助功能的應用程式而言,這項功能特別實用。

使用自動向量嵌入功能,您可以執行下列操作:

  • 初始化整個資料表的嵌入:使用單一指令,為資料表資料欄中的所有現有資料產生嵌入。
  • 保持嵌入內容同步:來源資料變更時,系統會自動更新嵌入內容,確保 AI 應用程式一律使用最新資訊。
  • 大規模生成嵌入:有效率地為數百萬列的大型資料表建立嵌入。
  • 呼叫每個嵌入資料欄的管理函式,即可設定及管理同一資料表中的多個資料欄嵌入。

這項功能會隱藏向量嵌入建立和維護作業的複雜性,簡化 AI 應用程式的開發和維護作業。

事前準備

如要為大型資料表產生及管理向量嵌入,請先按照下列步驟操作:

  • 檢查並提高 Vertex AI 配額:為確保最佳效能,並避免作業緩慢、QPS 偏低或多次重試,請檢查 Vertex AI 配額,並視需要提高配額。

    如要查看及提高配額,請按照下列步驟操作:

    1. 前往 Google Cloud 控制台的「配額」頁面。
    2. 篩選與模型和區域相關的下列指標:
      • 每分鐘要求數 (RPM):Regional online prediction requests per base model per minute per region per base_model
      • Gemini 權杖:Embed content input tokens per minute per region per base_model
    3. 如果目前的限制不足以容納表格大小,請找出要更新的配額值,然後勾選該配額旁邊的核取方塊。
    4. 點選「編輯」,「Quota changes」(配額變更) 對話方塊隨即顯示。

      詳情請參閱「要求調整配額」。

    如要瞭解 Vertex AI 嵌入模型限制,請參閱「Gemini 嵌入模型權杖限制」。

    如需完整配額清單,請參閱「Vertex AI 配額與限制」。

  • 使用 psqlpostgres 使用者身分連線至資料庫

  • 確認已安裝 google_ml_integration 擴充功能,且版本為 1.5.6 以上

  • 確認 google_ml_integration.enable_model_support 旗標和 google_ml_integration.enable_faster_embedding_generation 旗標已設為 on

  • 如要從 AlloyDB Omni 資料庫產生嵌入,必須先設定 AlloyDB Omni,才能與 Vertex AI 搭配使用。詳情請參閱「整合資料庫與 Vertex AI」。

  • 如要管理及監控自動產生嵌入內容,使用者預設擁有 Select 存取 google_ml.embed_gen_progressgoogle_ml.embed_gen_settings 資料表的權限。

    如要讓使用者管理自動產生嵌入內容的功能,請在 google_ml.embed_gen_progressgoogle_ml.embed_gen_settings 資料表上授予 INSERTUPDATEDELETE 權限:

    GRANT INSERT, UPDATE, DELETE ON google_ml.embed_gen_progress TO 'USER_NAME';
    

    更改下列內容:

    • USER_NAME:獲授權的使用者名稱。
  • 完成「生成文字嵌入」一文所述的初始設定。

  • 確認您使用的 PostgreSQL 用戶端中,AUTOCOMMIT 是否設為 ON

確認擴充功能版本

如要檢查 google_ml_integration 擴充功能的版本,請執行下列指令:

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

如要更新擴充功能,請執行下列指令:

ALTER EXTENSION google_ml_integration UPDATE;

確認資料庫旗標已設為 on

如要確認資料庫標記是否設定正確,請執行下列指令:

SHOW google_ml_integration.enable_model_support;
SHOW google_ml_integration.enable_faster_embedding_generation;

如果這些旗標設為 off,請參閱設定執行個體的資料庫旗標。如要進一步瞭解這些標記,請參閱「支援的資料庫標記」。

準備資料表

您必須先在資料表中建立欄,才能產生自動嵌入內容,並儲存產生的向量。這個資料欄通常會使用 vector(DIMENSION) 型別,且必須有 DEFAULT NULL 值。

舉例來說,如要將 768 維度嵌入的資料欄新增至名為 user_reviews 的資料表,請使用以下指令:

ALTER TABLE user_reviews ADD COLUMN IF NOT EXISTS content_embeddings vector(768) DEFAULT NULL;

初始化資料表的嵌入項目

管理自動向量嵌入的函式可在 aigoogle_ml 結構定義中使用。ai 架構提供簡化的介面,方便您使用 AlloyDB Omni 的最新 AI 功能。

使用 ai.initialize_embeddings() SQL 函式,為資料表的內容資料欄產生嵌入內容。這是封鎖呼叫,也就是說,資料庫工作階段會等待作業完成,然後傳回結果,並允許您在該工作階段中發出新指令。不過,資料庫的其他連線不會遭到封鎖,可以繼續使用資料表:

  • 如果函式傳回成功,表示向量嵌入建立作業已完成。
  • 這項函式會自動嘗試從暫時性問題 (例如模型配額錯誤) 中復原。只有在這些復原嘗試失敗時,系統才會傳回失敗訊息。如果問題持續發生,例如 batch_size 設定錯誤導致要求超出大小限制,或是作業遭到手動取消,您必須手動重新發出呼叫。

這項功能支援 Google 提供的模型 (例如 Vertex AI 的 text-embedding-005),以及您註冊的自訂模型。

執行批次生成作業

根據預設,AlloyDB Omni 會使用批次處理,在單一要求中為多個文字輸入內容生成嵌入項目,藉此提升效率。如果您未提供特定批量大小,AlloyDB Omni 會套用自動判斷的預設值。

提示批量大小

ai.initialize_embeddings 中的 batch_size 參數可讓您為直接支援的模型建議偏好的批量大小,引導 AlloyDB Omni 的查詢最佳化工具。AlloyDB Omni 可能會根據模型限制或配額動態縮減大小,但提示有助於影響查詢執行計畫。

CALL ai.initialize_embeddings(
    model_id => 'text-embedding-005',
    table_name => 'user_reviews',
    content_column => 'content',
    embedding_column => 'content_embeddings',
    batch_size => 50
);

使用支援批次的自訂嵌入模型

如要使用支援批次處理的自訂或外部支援模型,請定義批次轉換函式,並在建立模型時將這些函式指定為 model_batch_in_transform_fnmodel_batch_out_transform_fn。您也可以在 initialize_embeddings 呼叫中指定 batch_size。對於支援批次處理的模型,建議您使用大於 1 的 batch_size,以提升效能。

  1. 定義自訂模型的輸入、輸出和批次轉換函式。

    -- Scalar input transform functions
    CREATE OR REPLACE FUNCTION acme_text_input_transform(model_id TEXT, input TEXT) RETURNS JSON;
    CREATE OR REPLACE FUNCTION acme_text_output_transform(model_id TEXT, model_output JSON) RETURNS real[];
    CREATE OR REPLACE FUNCTION acme_generate_headers(model_id TEXT, input TEXT) RETURNS JSON;
    -- Batch input transform functions
    CREATE OR REPLACE FUNCTION acme_text_batch_input_transform(model_id TEXT, input TEXT[]) RETURNS JSON;
    CREATE OR REPLACE FUNCTION acme_text_batch_output_transform(model_id TEXT, model_output JSON) RETURNS real[][];
    
  2. 如要建立模型,請指定批次轉換函式。

    CALL
      ai.create_model(
        model_id => 'custom-embedding-model',
        model_request_url => 'https://acme.com/models/text/embeddings/v1',
        model_type => 'text_embedding',
        model_in_transform_fn => 'acme_text_input_transform',
        model_out_transform_fn => 'acme_text_output_transform',
        generate_headers_fn => 'acme_generate_headers',
        model_batch_in_transform_fn => 'acme_text_batch_input_transform',
        model_batch_out_transform_fn => 'acme_text_batch_output_transform'
      );
    
  3. 使用自訂模型生成向量嵌入。

    CALL
      ai.initialize_embeddings(
        model_id => 'custom-embedding-model',
        table_name => 'user_reviews',
        content_column => 'content',
        embedding_column => 'content_embeddings',
        batch_size => 10
    );
    

您也可以搭配不支援批次的自訂模型使用自動嵌入功能。如要這麼做,您仍須定義批次轉換函式 model_batch_in_transform_fnmodel_batch_out_transform_fn。如果是非批次處理模型,請定義這些函式,一次處理輸入陣列中的單一輸入。呼叫這個模型的 ai.initialize_embeddings 時,請將 batch_size 設為 1

使用自訂維度 (支援批次作業)

如要搭配 OUTPUT_DIMENSIONALITY 參數使用自訂批次輸入轉換函式,您可以定義函式,在要求參數中指定所選維度。這項功能有助於針對支援可變輸出大小的模型,最佳化嵌入生成作業。

舉例來說,下列函式會為輸出維度為 768 的模型定義自訂批次輸入轉換:

CREATE OR REPLACE FUNCTION google_ml.vertexai_text_embedding_batch_input_transform_with_768_dims(model_id VARCHAR(100), input_list TEXT[])
RETURNS JSON
LANGUAGE SQL
AS $$
  SELECT pg_catalog.json_build_object(
    'instances',
    pg_catalog.json_agg(pg_catalog.json_build_object('content', content)),
    'parameters',
    pg_catalog.json_build_object('outputDimensionality', 768)
  ) FROM unnest(input_list) AS content;
$$;

使用自訂模型進行 JSONB 最佳化

您可以在自訂輸出轉換函式中使用 JSONB 資料型別,提升效能。使用批次支援功能建立自訂模型時,google_ml_integration 擴充功能會自動尋找並使用轉換函式的 JSONB 變體。

這項最佳化措施可大幅提升自動產生嵌入內容的效能,因為 JSONB 是更有效率的二進位格式,可在 PostgreSQL 中儲存及處理 JSON 資料。

如要使用這項功能,您需要提供另一個版本的轉換函式,該函式接受 JSONB 引數,而不是 JSON

舉例來說,假設您有下列簽章的批次輸出轉換函式:

CREATE OR REPLACE FUNCTION my_batch_output_transform(model_id TEXT, model_output JSON) RETURNS real[][];

您可以建立如下所示的 JSONB 變體:

CREATE OR REPLACE FUNCTION my_batch_output_transform(model_id TEXT, model_output JSONB) RETURNS real[][];

擴充功能會自動偵測函式的 JSONB 版本,並用於批次處理。如果您已建立使用 JSON 轉換函式的模型註冊,則無須更新 ai.create_model 呼叫。只要新 JSONB 函式與現有 JSON 函式使用完全相同的名稱,擴充功能就會自動偵測並使用 JSONB 變體進行批次處理。

逐步重新整理嵌入

重新整理嵌入內容時,系統會根據輸入內容資料欄中的最新值重新產生嵌入內容。

為方便您控管一致性和效能,AlloyDB Omni 支援多種模式,可逐步重新整理嵌入內容。您可以在 ai.initialize_embeddings() 中使用 incremental_refresh_mode 列舉引數選取模式。以下列出可能的模式:

  • transactional:在更新內容資料欄的交易中,一併重新整理嵌入內容。這個程序通常會使用類似資料庫觸發程序的機制,在內容欄更新時自動產生嵌入內容,但可能會造成額外負擔,並減緩更新作業。導入的額外負荷是為了維持交易語意,並確保嵌入內容與內容同步。這個模式會依據模型的純量轉換函式,因此您必須在建立模型時定義 model_in_transform_fnmodel_out_transform_fn。如要使用 transactional 模式,您必須具備表格的擁有者角色

    CALL
      ai.initialize_embeddings(
        model_id => 'text-embedding-005',
        table_name => 'user_reviews',
        content_column => 'content',
        embedding_column => 'content_embeddings',
        batch_size => 10,
        incremental_refresh_mode => 'transactional'
    );
    

    transactional 模式中,系統會使用觸發條件自動保持嵌入內容同步,因此 ai.refresh_embeddings() 函式會停用。如要為整個資料表重新產生嵌入內容,或從這個模式中中斷的 ai.initialize_embeddings() 呼叫復原,請先使用 ai.drop_embedding_config() 函式捨棄設定,然後重新發出 ai.initialize_embeddings() 呼叫。

    如果資料集或表格不大,且插入和更新的資料量相較於初始載入量較少 (例如,一百萬列的表格每天更新幾百列),就適合使用這種自動模式進行示範。如果維護即時資料一致性比更新作業期間產生的額外延遲更重要,就適合使用這項功能。

  • manual:這是預設模式。在這個模式下,系統會在表格中新增布林追蹤資料欄,追蹤過時的嵌入。呼叫 ai.refresh_embeddings() 函式會執行定期增量重新整理,只為新的或更新的資料列產生嵌入內容。如果使用者需要進一步控管效能,尤其是在初始載入後處理大量插入或更新作業時,建議使用這個模式。如果優先要盡量縮短寫入延遲時間,且可接受暫時過時或空值的嵌入,直到使用 ai.refresh_embeddings 觸發定期增量重新整理為止,就適合使用這項功能。如要更新過時或新的資料列,請按照「重新整理資料表的所有嵌入內容」一節的說明使用 ai.refresh_embeddings() 函式。

選擇重新整理模式

下表比較這兩種累加式重新整理模式,協助您為應用程式選擇最合適的方法。

模式 說明 一致性和效能 適用情境
transactional 系統會使用類似觸發程序的機制,在資料庫交易中更新嵌入內容。請注意,ai.refresh_embeddings() 在這個模式下會停用。 立即保持一致性。每次 INSERTUPDATE 都會觸發嵌入生成作業,導致寫入延遲時間過長。 示範、小型資料集或資料一致性至關重要的資料表。
manual (預設) 使用布林追蹤資料欄監控過時或新的資料列。您必須呼叫 ai.refresh_embeddings(),才能觸發定期增量重新整理。 最終一致性。可選擇一次大量生成嵌入內容,將寫入延遲時間降到最低。 大型資料集、寫入頻率高的實際工作環境,或對效能要求嚴苛的應用程式。

重新整理資料表的所有嵌入

使用 manual 增量重新整理模式成功執行資料表的 ai.initialize_embeddings() 後,即可定期增量重新整理嵌入內容,並使用 ai.refresh_embeddings 觸發這項作業。您可以透過重新整理作業,更新在初始 initialize_embeddings 呼叫期間同時修改的資料列嵌入內容,或執行定期增量重新整理。

如果手動模式的嵌入建立程序遭到中斷 (例如透過 pg_cancel),請呼叫 ai.refresh_embeddings() 函式,完成其餘資料列的生成作業。

重新整理函式會重複使用初始呼叫中的設定,因此您只需要指定表格和嵌入資料欄。您也可以提供選用的 batch_size 來覆寫預設值。

CALL ai.refresh_embeddings(
    table_name => 'user_reviews',
    embedding_column => 'content_embeddings',
    batch_size => 50  -- Optional override
);

在建立向量嵌入時處理表格資料

雖然 ai.initialize_embeddings() 是在執行階段中封鎖的呼叫,但其他連線仍可繼續使用資料表。自動向量嵌入程序會使用標準的資料列層級鎖定,分批更新資料列。也就是說,如果其他連線嘗試修改有效嵌入作業所指定的相同資料列,系統只會短暫封鎖並行資料修改語言 (DML) 作業 (例如 UPDATEDELETE)。不會封鎖非修改型 SELECT 查詢。

刪除自動向量嵌入設定

如要移除特定表格和嵌入資料欄組合的自動向量嵌入設定,請使用 ai.drop_embedding_config() 函式。這項函式可用於清理資料,或重新設定資料欄的嵌入管理功能。

CALL
  ai.drop_embedding_config(
    table_name => 'user_reviews',
    embedding_column => 'content_embeddings');

使用分區資料表

自動向量嵌入功能支援分區資料表。方便您有效管理大型分割資料集的嵌入內容。以下是使用分區資料表的常見用途。

初始化分區資料表的嵌入項目

您只能在資料表的根分區初始化嵌入內容。這項操作只需對整個分區資料表執行一次。

CALL ai.initialize_embeddings(
    model_id => 'text-embeddings-005',
    table_name => 'documents', -- This is the root partitioned table
    content_column => 'content',
    embedding_column => 'content_embeddings'
);

重新整理分區資料表的嵌入

初始化後,您可以重新整理任何分區的嵌入內容,包括根分區、子分區或個別葉分區。對於大型資料集,您可以從不同的資料庫連線,平行重新整理不同分割區的嵌入內容,藉此提升效能:

  • 如要重新整理整個表格,請執行下列指令:
CALL ai.refresh_embeddings(
    table_name => 'documents', -- This is the root partitioned table
    embedding_column => 'content_embeddings'
);
  • 如要重新整理單一資料分割,請執行下列指令:
CALL ai.refresh_embeddings(
    table_name => 'documents_eu',
    embedding_column => 'content_embeddings'
);

為新加入或附加的分割區重新整理嵌入內容

自動嵌入功能支援為併入主資料表的分割區產生嵌入內容,但須完成初始設定。具體步驟取決於您要新增完全新的分區,還是附加現有資料表。

  • 新加入的分區:如果將新分區加入資料表,可以對新分區呼叫 ai.refresh_embeddings,產生該分區的嵌入內容。
-- Add a new partition
CREATE TABLE documents_africa PARTITION OF documents
    FOR VALUES IN ('africa');

-- Refresh embeddings for the new partition
CALL ai.refresh_embeddings(
    table_name => 'documents_africa',
    embedding_column => 'content_embeddings'
);
  • 新附加的分區:如要將現有資料表附加為分區,請先使用 ai.embedding_prepare_partition 程序,確保資料表結構與分區資料表相容。自動嵌入功能支援在階層式分區設定的任何層級新增或附加分區。ai.embedding_prepare_partition 程序可確保結構定義與階層中的任何父項資料表相容。

如要將現有資料表附加為分區,請先使用 ai.embedding_prepare_partition 程序,確保資料表結構定義與分區資料表相容:

-- Prepare the table to be attached
CALL ai.embedding_prepare_partition(
    parent_table => 'documents',
    child_table => 'documents_misc'
);

-- Attach the partition
ALTER TABLE documents ATTACH partition documents_misc DEFAULT;

-- Refresh embeddings for the newly attached partition
CALL ai.refresh_embeddings(
    table_name => 'documents_misc',
    embedding_column => 'content_embeddings'
);

自動嵌入功能支援在階層式分區設定的任何層級新增或附加分區。ai.embedding_prepare_partition 程序可確保結構定義與階層中的任何父項資料表相容:

-- Prepare a sub-partition for a non-root parent table
CALL ai.embedding_prepare_partition(
    parent_table => 'documents_eu', -- An existing partition
    child_table => 'documents_eu_germany'
);

-- Attach the new sub-partition
ALTER TABLE documents_eu ATTACH PARTITION documents_eu_germany
    FOR VALUES IN ('germany');

-- Refresh embeddings for the new sub-partition
CALL ai.refresh_embeddings(
    table_name => 'documents_eu_germany',
    embedding_column => 'content_embeddings'
);

監控嵌入生成進度

您可以查詢 ai.embedding_progress_view,監控有效 initialize_embeddingsrefresh_embeddings 呼叫的即時狀態。這個檢視畫面會顯示作業進度詳細資料,包括完成百分比、經過時間和預估剩餘時間。

如要查看進度,請執行下列查詢:

SELECT
  table_name,
  content_column,
  embedding_column,
  model_id,
  percent_progress,
  status,
  elapsed_time,
  rows_processed,
  partition_root
FROM
  ai.embedding_progress_view;

這個檢視畫面提供下列資訊:

說明
table_name 正在處理的資料表或分區名稱。
content_column 含有嵌入來源內容的資料欄。
embedding_column 儲存嵌入內容的資料欄。
model_id 用於生成內容的模型。
percent_progress 作業完成的百分比。
status 作業的目前狀態 (例如執行中、成功)。
elapsed_time 作業開始後經過的時間。
rows_processed 目前處理的列數。
partition_root 根分區資料表的名稱。

自動生成嵌入的範例

本節提供範例,說明如何使用已註冊的模型端點,在自動模式中生成嵌入。

OpenAI 嵌入模型

如要使用 OpenAI 提供的已註冊的 text-embedding-3-small 模型端點生成嵌入,請執行下列陳述式:

CALL ai.initialize_embeddings(
    model_id => 'text-embedding-3-small',
    table_name => 'user_reviews',
    content_column => 'content',
    embedding_column => 'content_embeddings'
);

自訂嵌入模型

如果是您自己的模型或外部支援的模型,您必須定義輸入和輸出轉換函式,並向 ai.create_model 註冊。如果您打算使用自動嵌入功能,就必須同時指定純量轉換函式 (例如 acme_text_input_transformacme_text_output_transform) 和批次轉換函式 (例如 acme_text_batch_input_transformacme_text_batch_output_transform)。

後續步驟