搭配使用向量搜尋和 Spanner Graph

本頁說明如何在 Spanner 圖中使用向量搜尋功能,找出 K 近鄰 (KNN) 和近似近鄰 (ANN)。您可以使用向量距離函式執行 KNN 和 ANN 向量搜尋,用於相似度搜尋或檢索增強生成的生成式 AI 應用程式等用途。

Spanner Graph 支援下列距離函式,可執行 KNN 向量相似度搜尋

  • COSINE_DISTANCE():測量兩個向量之間的最短距離。
  • EUCLIDEAN_DISTANCE():測量兩個向量夾角的餘弦值。
  • DOT_PRODUCT():計算角的餘弦乘以對應向量大小的積。如果您知道資料集中的所有向量嵌入值都已標準化,就可以使用 DOT_PRODUCT() 做為距離函式。

如需更多資訊,請參閱「在 Spanner 中執行向量相似度搜尋,方法是找出 K 個最近鄰」。

Spanner Graph 也支援下列近似距離函式,用於執行 ANN 向量相似度搜尋

  • APPROX_COSINE_DISTANCE:測量兩個向量之間的近似最短距離。
  • APPROX_EUCLIDEAN_DISTANCE:測量兩個向量之間角度的近似餘弦值。
  • APPROX_DOT_PRODUCT:計算角度的近似餘弦值,再乘上對應向量大小的積。如果您知道資料集中的所有向量嵌入值都已標準化,則可以使用 DOT_PRODUCT() 做為距離函式。

詳情請參閱「找出近似最近鄰、建立向量索引,以及查詢向量嵌入」。

事前準備

如要執行本文中的範例,您必須先按照「設定及查詢 Spanner 圖」中的步驟執行以下操作:

  1. 建立執行個體
  2. 使用 Spanner Graph 結構定義建立資料庫
  3. 插入必要的圖表資料

插入必要的圖表資料後,請對資料庫進行下列更新。

在圖形資料庫中插入其他向量資料

如要對圖形資料庫進行必要更新,請執行下列操作:

  1. Account 輸入表格中新增資料欄 nick_name_embeddings

    ALTER TABLE Account
    ADD COLUMN nick_name_embeddings ARRAY<FLOAT32>(vector_length=>4);
    
  2. nick_name 欄中新增資料。

    UPDATE Account SET nick_name = "Fund for a refreshing tropical vacation" WHERE id = 7;
    UPDATE Account SET nick_name = "Fund for a rainy day!" WHERE id = 16;
    UPDATE Account SET nick_name = "Saving up for travel" WHERE id = 20;
    
  3. nick_name 欄中的文字建立嵌入項目,然後將這些項目填入新的 nick_name_embeddings 欄。

    如要在 Spanner Graph 中為營運資料產生 Vertex AI 嵌入資料,請參閱「取得 Vertex AI 文字嵌入資料」。

    為方便說明,我們在範例中使用人工的低維向量值。

    UPDATE Account SET nick_name_embeddings = ARRAY<FLOAT32>[0.3, 0.5, 0.8, 0.7] WHERE id = 7;
    UPDATE Account SET nick_name_embeddings = ARRAY<FLOAT32>[0.4, 0.9, 0.7, 0.1] WHERE id = 16;
    UPDATE Account SET nick_name_embeddings = ARRAY<FLOAT32>[0.2, 0.5, 0.6, 0.6] WHERE id = 20;
    
  4. AccountTransferAccount 輸入表格中新增兩個資料欄:notesnotes_embeddings

    ALTER TABLE AccountTransferAccount
    ADD COLUMN notes STRING(MAX);
    ALTER TABLE AccountTransferAccount
    ADD COLUMN notes_embeddings ARRAY<FLOAT32>(vector_length=>4);
    
  5. notes 欄中的文字建立嵌入項目,並將這些項目填入 notes_embeddings 欄。

    如要在 Spanner Graph 中為營運資料產生 Vertex AI 嵌入資料,請參閱「取得 Vertex AI 文字嵌入資料」。

    為方便說明,我們在範例中使用人工的低維向量值。

    UPDATE AccountTransferAccount
    SET notes = "for shared cost of dinner",
      notes_embeddings = ARRAY<FLOAT32>[0.3, 0.5, 0.8, 0.7]
    WHERE id = 16 AND to_id = 20;
    UPDATE AccountTransferAccount
    SET notes = "fees for tuition",
      notes_embeddings = ARRAY<FLOAT32>[0.1, 0.9, 0.1, 0.7]
    WHERE id = 20 AND to_id = 7;
    UPDATE AccountTransferAccount
    SET notes = 'loved the lunch',
      notes_embeddings = ARRAY<FLOAT32>[0.4, 0.5, 0.7, 0.9]
    WHERE id = 20 AND to_id = 16;
    
  6. AccountAccountTransferAccount 輸入表中新增資料欄後,請使用下列陳述式更新屬性圖表定義。詳情請參閱「更新現有的節點或邊定義」。

    CREATE OR REPLACE PROPERTY GRAPH FinGraph
    NODE TABLES (Account, Person)
    EDGE TABLES (
      PersonOwnAccount
        SOURCE KEY (id) REFERENCES Person (id)
        DESTINATION KEY (account_id) REFERENCES Account (id)
        LABEL Owns,
      AccountTransferAccount
        SOURCE KEY (id) REFERENCES Account (id)
        DESTINATION KEY (to_id) REFERENCES Account (id)
        LABEL Transfers
    );
    

尋找 K 個最近鄰

在以下範例中,使用 EUCLIDEAN_DISTANCE() 函式對圖形資料庫的節點和邊執行 KNN 向量搜尋。

對圖表節點執行 KNN 向量搜尋

您可以對 Account 節點的 nick_name_embeddings 屬性執行 KNN 向量搜尋。這個 KNN 向量搜尋會傳回帳戶擁有者的 name 和帳戶的 nick_name。在以下範例中,結果會顯示休閒旅遊和度假帳戶的前兩個最近鄰點,以 [0.2, 0.4, 0.9, 0.6] 向量嵌入表示。

GRAPH FinGraph
MATCH (p:Person)-[:Owns]->(a:Account)
RETURN p.name, a.nick_name
ORDER BY EUCLIDEAN_DISTANCE(a.nick_name_embeddings,
  -- An illustrative embedding for 'accounts for leisure travel and vacation'
  ARRAY<FLOAT32>[0.2, 0.4, 0.9, 0.6])
LIMIT 2;

結果

名稱 nick_name
Alex 儲蓄資金,享受清新的熱帶假期
Dana 存錢出國旅遊

針對圖形邊緣執行 KNN 向量搜尋

您可以對 Owns 邊緣的 notes_embeddings 屬性執行 KNN 向量搜尋。這個 KNN 向量搜尋會傳回帳戶擁有者的 name 和轉移的 notes。在以下範例中,結果會顯示「餐飲費」的兩個最相近的 K 個鄰居,以 [0.2, 0.4, 0.9, 0.6] 向量嵌入表示。

GRAPH FinGraph
MATCH (p:Person)-[:Owns]->(:Account)-[t:Transfers]->(:Account)
WHERE t.notes_embeddings IS NOT NULL
RETURN p.name, t.notes
ORDER BY EUCLIDEAN_DISTANCE(t.notes_embeddings,
  -- An illustrative vector embedding for 'food expenses'
  ARRAY<FLOAT32>[0.2, 0.4, 0.9, 0.6])
LIMIT 2;

結果

名稱 附註
Lee 晚餐分攤費用
Dana 午餐很棒

建立向量索引並找出近似最鄰近項目

如要執行 ANN 搜尋,您必須建立 專用向量索引,讓 Spanner Graph 用於加快向量搜尋速度。向量索引必須使用特定距離指標。您可以將 distance_type 參數設為 COSINEDOT_PRODUCTEUCLIDEAN 等其中一個,選擇最適合您用途的距離指標。詳情請參閱「向量索引語句」。

在下列範例中,您會使用 Account 輸入資料表的 nick_name_embedding 欄位,以歐氏距離類型建立向量索引:

CREATE VECTOR INDEX NickNameEmbeddingIndex
ON Account(nick_name_embeddings)
WHERE nick_name_embeddings IS NOT NULL
OPTIONS (distance_type = 'EUCLIDEAN', tree_depth = 2, num_leaves = 1000);

對圖形節點執行 ANN 向量搜尋

建立向量索引後,您就可以針對 Account 節點的 nick_name 屬性執行 ANN 向量搜尋。ANN 向量搜尋會傳回帳戶擁有者的 name 和帳戶的 nick_name。在以下範例中,結果會顯示休閒旅遊和度假帳戶的前兩個近似近鄰,由 [0.2, 0.4, 0.9, 0.6] 向量嵌入表示。

圖表提示會強制查詢最佳化工具在查詢執行計畫中使用指定的向量索引。

GRAPH FinGraph
MATCH (@{FORCE_INDEX=NickNameEmbeddingIndex} a:Account)
WHERE a.nick_name_embeddings IS NOT NULL
RETURN a, APPROX_EUCLIDEAN_DISTANCE(a.nick_name_embeddings,
  -- An illustrative embedding for 'accounts for leisure travel and vacation'
  ARRAY<FLOAT32>[0.2, 0.4, 0.9, 0.6],
  options => JSON '{"num_leaves_to_search": 10}') AS distance
ORDER BY distance
LIMIT 2

NEXT

MATCH (p:Person)-[:Owns]->(a)
RETURN p.name, a.nick_name;

結果

名稱 nick_name
Alex 儲蓄資金,享受清新的熱帶假期
Dana 存錢出國旅遊

後續步驟