View a markdown version of this page

建立和搜尋向量索引 - Amazon DynamoDB

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

建立和搜尋向量索引

本節說明如何建立和管理向量索引、使用向量資料寫入項目,以及使用 SearchVectors API 執行相似性搜尋。

開始之前

在使用向量索引之前,請先驗證下列項目:

  • 您的資料表使用隨需容量模式 (PAY_PER_REQUEST)。向量索引僅使用隨需容量模式,並且需要使用也使用隨需容量模式的資料表,因此您無法混合兩種容量模式。

  • 您的 AWS Identity and Access Management (IAM) 身分具有建立向量索引的 dynamodb:CreateTable或 dynamodb:UpdateTable許可。

  • 您的 IAM 身分具有向量索引資源執行搜尋的dynamodb:SearchVectors許可。資源 ARN 格式為 arn:aws:dynamodb:region:account-id:table/table-name/index/index-name。

SearchVectors 端點

SearchVectors 請求使用專用向量搜尋端點,這與您用來建立和管理向量索引的標準 DynamoDB 端點不同 (例如,使用 CreateTable、 UpdateTable和 DescribeTable)。 AWS SDKs 和 會自動將SearchVectors請求 AWS CLI 路由到正確的端點。您不需要在應用程式程式碼中設定或覆寫端點。

如果您要建置自訂 HTTP 用戶端,在沒有 AWS SDK 的情況下直接呼叫 DynamoDB API,請使用下列其中一個向量搜尋端點,視需要取代 account-id 和 region:

  • account-id.search-ddb.region.amazonaws.com — 以帳戶為基礎的端點。

  • search-dynamodb.region.api.aws — 雙堆疊端點,與 IPv4 和 IPv6 相容。

產生向量內嵌

DynamoDB 會儲存和搜尋向量內嵌,但不會產生它們。您可以使用內嵌模型產生內嵌,例如 Amazon Bedrock Titan Text Embeddings 或 Cohere Embed Model,或您操作的任何內嵌模型。然後,將產生的向量存放在 DynamoDB 項目中,並將查詢向量傳遞給 SearchVectors。

查詢向量和預存向量必須使用相同的模型

您傳遞至 的查詢向量SearchVectors和存放在項目中的向量必須由相同的內嵌模型產生,且必須具有與向量索引相同的維度。混合模型或使用與建立索引不同的維度進行查詢,會產生無意義的結果或驗證錯誤。

典型的流程是:

  1. 將您的來源內容 (例如產品描述) 傳送至內嵌模型並接收向量。

  2. 將該向量存放在 DynamoDB 項目中,以向量索引 (VectorAttribute) 命名的屬性中,做為數字 (L) 的清單 ()N。

  3. 在查詢時間,使用相同的模型從搜尋文字產生向量,並將其傳遞為 SearchVector。

在建立索引之前,選擇您的內嵌模型

在建立向量索引之前選擇內嵌模型,因為模型會決定維度數目。常見的內嵌模型會產生 384、768、1024、1536 或 3072 維度。DynamoDB 最多支援 4,096 個維度。請參閱 要求與限制。

您選擇的距離函數會與您的模型產生內嵌的方式互動。 會COSINE比較方向並忽略大小,因此它可與內嵌搭配使用,無論其是否標準化。 DOT_PRODUCT 對大小敏感:如果您的內嵌未標準化為單位長度,則無論方向為何,較大的向量都會獲得更高的分數。如果您使用 DOT_PRODUCT且想要以方向為基礎的相似性,請將內嵌標準化為單位長度,然後再存放。請參閱 距離函數如何排名結果。

建立向量索引

您可以在建立新資料表時建立向量索引,或將向量索引新增至現有資料表。

使用向量索引建立資料表

使用 CreateTable API 搭配 VectorIndexes 參數來建立具有向量索引的資料表。下列 AWS CLI 範例會建立名為 的向量索引Products資料表ProductEmbeddingIndex。

aws dynamodb create-table \ --table-name Products \ --attribute-definitions AttributeName=ProductId,AttributeType=S \ AttributeName=Category,AttributeType=S \ AttributeName=Brand,AttributeType=S \ --key-schema AttributeName=ProductId,KeyType=HASH \ --billing-mode PAY_PER_REQUEST \ --vector-indexes \ "[ { \"IndexName\": \"ProductEmbeddingIndex\", \"VectorAttribute\": {\"AttributeName\": \"Embedding\"}, \"SearchSchema\": [{\"AttributeName\":\"Category\",\"SearchSchemaElementType\":\"HASH\"}, {\"AttributeName\":\"Brand\",\"SearchSchemaElementType\":\"INLINE_FILTER\"}], \"Projection\": {\"ProjectionType\": \"ALL\"}, \"Dimensions\": 1536, \"DistanceFunction\": \"COSINE\" } ]"

在此範例中:

  • VectorAttribute 指定 Embedding為包含向量資料的屬性。

  • SearchSchema Category將 定義為向量索引分割區索引鍵 (HASH),依類別分割索引以進行擴展。它還將 Brand定義為 INLINE_FILTER,可讓您在儲存層依品牌篩選搜尋結果。由於 SearchSchema 中同時參考Brand了 Category和 ,因此它們也必須在 中宣告AttributeDefinitions,因此全域次要索引的金鑰屬性宣告方式相同。

  • Dimensions 設定為 1536,符合常見內嵌模型的輸出。

  • DistanceFunction 設定為 COSINE,其中分數越低表示相似度越大。

將向量索引新增至現有資料表

使用 UpdateTable API 搭配 VectorIndexUpdates 參數,將向量索引新增至現有資料表。此範例會將名為 的第二個獨立索引ProductEmbeddingIndexV2新增至相同的Products資料表。

aws dynamodb update-table \ --table-name Products \ --vector-index-updates \ "[ { \"Create\": { \"IndexName\": \"ProductEmbeddingIndexV2\", \"VectorAttribute\": {\"AttributeName\": \"Embedding\"}, \"Projection\": {\"ProjectionType\": \"ALL\"}, \"Dimensions\": 1536, \"DistanceFunction\": \"EUCLIDEAN\" } } ]"

當您將向量索引新增至現有資料表時,DynamoDB Backfilling 會報告DescribeTable回應中兩個欄位的索引進度: IndexStatus值和單獨的布林值。

  1. IndexStatus 為 Backfilling CREATING且不存在 或 false。DynamoDB 正在佈建索引基礎設施。

  2. IndexStatus 是 CREATING,而 Backfilling是 true。DynamoDB 正在從現有的基底資料表資料填入索引。在此階段,基底資料表的新寫入會複寫至索引。 SearchVectors會傳回 ValidationException。即使基底資料表包含極少的項目,此階段仍可能需要相當長的時間。

  3. IndexStatus 為 Backfilling ACTIVE且不再報告。索引已準備好進行搜尋。

您無法在索引回填時搜尋

SearchVectors ValidationException 當向量索引回填時, 會傳回 。使用 DescribeTable同時檢查 IndexStatus 和 Backfilling旗標,並等到 IndexStatus為 ACTIVE 且 Backfilling 不是 true再搜尋。沒有BACKFILLING索引狀態值;索引會以IndexStatusCREATINGBackfilling設為 的方式回填報告true。

新就緒的索引無法立即搜尋

SearchVectors 請求由專用搜尋端點提供,與提供 的端點分開DescribeTable。DescribeTable 第一次報告 IndexStatus 後ACTIVE,搜尋端點可能需要額外的時間,才能開始提供索引。在該間隔期間ValidationException, 通常會SearchVectors傳回 The table does not have the specified index。

在建立索引後,將第一個搜尋ValidationException上的 視為可重試,而非失敗。在觀察之後立即搜尋的程式碼ACTIVE可能似乎在一個環境中運作,並在另一個環境中失敗。間隔很短且不同。

對於不依賴於任一狀態欄位的整備檢查,請在重試迴圈中發出實際SearchVectors請求。將第一個成功回應視為索引已就緒的訊號。

您一次只能建立或刪除每個資料表的一個向量索引。此限制會與相同資料表上的全域次要索引建立共用。建立或刪除索引的第二個UpdateTable請求,而另一個索引操作正在進行失敗,並顯示 LimitExceededException: Subscriber limit exceeded: Only 1 online index can be created or deleted simultaneously per table。

這也適用於單一請求:在其VectorIndexUpdates參數中包含兩個Create動作的UpdateTable呼叫會失敗並出現相同的錯誤。一次建立一個向量索引,等待每個索引到達,ACTIVE再開始下一個。由於每個索引都必須完成回填,才能開始下一個索引,因此在一個資料表上建置多個向量索引需要比建置一個還要長。

CreateTable 請求可以一次定義多個向量索引,每個資料表上限為 5 個。超過該限制會失敗,並顯示 ValidationException: One or more parameter values were invalid: VectorIndex count exceeds the per-table limit of 5。

使用向量資料寫入項目

您可以使用標準 DynamoDB 寫入 APIs (PutItem、UpdateItem、BatchWriteItem、) 搭配向量資料寫入項目TransactWriteItems。將向量內嵌儲存為數字清單 (L 類型包含N元素)。

由於向量包含許多值,請將項目儲存至 等檔案item.json,然後將檔案傳遞至 AWS CLI。

{ "ProductId": { "S": "prod-123" }, "Category": { "S": "Electronics" }, "Title": { "S": "Wireless Headphones" }, "Embedding": { "L": [ { "N": "0.1234" }, { "N": "-0.5678" }, { "N": "0.9012" }, ... ] } }
aws dynamodb put-item \ --table-name Products \ --item file://item.json
向量長度必須符合索引維度

此處顯示的Embedding向量為縮寫。在 中item.json,它必須包含 1,536 個值,以符合Dimensions您在 上設定的 ProductEmbeddingIndex。寫入維度不正確的向量會遭到拒絕。

當您將項目寫入具有向量索引的資料表時,DynamoDB 會驗證向量資料。下表說明驗證行為。

條件 Behavior (行為)
向量屬性的維度數目錯誤 寫入遭拒。
缺少向量索引分割區索引鍵屬性 在基礎資料表上寫入成功,但項目不會複寫到向量索引。
向量索引分割區索引鍵屬性類型不符合索引結構描述 寫入遭拒。
缺少內嵌篩選條件屬性 寫入成功,且項目會複寫至向量索引。
向量值的精確度高於 32 位元浮點 (f32) 寫入成功。值會依原樣存放在基底資料表中,但在複寫至向量索引時失去精確度。
從項目中刪除向量屬性 向量索引中的對應項目會被刪除。
缺少分割區索引鍵會導致無提示取消索引

如果您的向量索引在 SearchSchema 中定義分割區索引鍵,而且您撰寫的項目沒有該屬性 (或使用 將其移除UpdateItem),則寫入會在基礎資料表上成功,但該項目會無提示地從向量索引中排除。即使基礎資料表項目及其向量內嵌仍然存在,它也不會出現在SearchVectors結果中。請確定您要搜尋的每個項目都包含向量索引分割區索引鍵屬性。

過時的內嵌會產生不正確的結果

DynamoDB 不會為您重新計算內嵌。如果您變更產生內嵌的來源內容 (例如,編輯產品描述),儲存的向量不會自動更新。您必須使用內嵌模型重新產生內嵌,並將新的向量寫入項目。否則,向量索引會根據舊的過時向量繼續傳回結果,這會無提示地產生不正確的相符項目。

使用 SearchVectors 搜尋

使用 SearchVectors API 在向量索引中尋找與查詢向量最相似的項目。結果會依相關性排序,最相似的項目優先。搜尋結果最終一致:寫入或更新向量之間可能會出現短暫的延遲,且顯示在搜尋結果中。如需詳細資訊,請參閱持續寫入同步。

基本搜尋

下列範例會搜尋ProductEmbeddingIndex索引中 10 個最相似的項目。由於此索引在其 SearchSchema 中已定義向量索引分割區索引鍵 (Category),因此 SearchConditionExpression必須包含向量索引分割區索引鍵值。

將查詢向量儲存到檔案,例如 query-vector.json,做為數值的純 JSON 陣列。

[ { "N": "0.1234" }, { "N": "-0.5678" }, { "N": "0.9012" }, ... ]
aws dynamodb search-vectors \ --table-name Products \ --index-name ProductEmbeddingIndex \ --search-vector file://query-vector.json \ --top-k 10 \ --search-condition-expression "Category = :cat" \ --expression-attribute-values "{\":cat\": {\"S\": \"Electronics\"}}"

回應包含SearchResults陣列。每個元素都包含相符項目Item和 Score,指出項目與查詢向量的相似度。

{ "SearchResults": [ { "Item": { "ProductId": { "S": "prod-456" }, "Category": { "S": "Electronics" }, "Title": { "S": "Bluetooth Speaker" } }, "Score": 0.0023 }, { "Item": { "ProductId": { "S": "prod-789" }, "Category": { "S": "Electronics" }, "Title": { "S": "Noise Cancelling Earbuds" } }, "Score": 0.0145 } ] }
根據預設,向量屬性會從結果中排除

根據預設,來自 的結果SearchVectors不包含向量屬性 (內嵌)。向量資料很大,通常在回應中不需要。結果包含其他投影屬性和 Score值。若要包含向量屬性,請使用 請求它ProjectionExpression。如需詳細資訊,請參閱使用 ProjectionExpression。

SearchVector 是純清單,不是 DynamoDB L 類型

SearchVector 請求參數是數字物件的純 JSON 陣列 ([{"N": "0.1234"}, ...])。請勿在 DynamoDB L類型中包裝它,就像在項目屬性中存放向量一樣。只有在項目屬性中寫入或讀取向量資料時,才會使用L包裝函式。

的意義Score取決於您在建立索引時選擇的距離函數。對於 COSINE和 EUCLIDEAN,分數越低表示相似度越高。對於 DOT_PRODUCT,分數越高表示相似性越大。

使用 SearchConditionExpression 篩選

使用 根據向量索引分割區索引鍵和 SearchSchema 中定義的內嵌篩選條件屬性來SearchConditionExpression篩選搜尋結果。此表達式使用與其他 DynamoDB 表達式參數相同的語法。

下列範例會使用內嵌篩選條件搜尋Electronics類別 (向量索引分割區索引鍵) Brand 中的項目。

aws dynamodb search-vectors \ --table-name Products \ --index-name ProductEmbeddingIndex \ --search-vector file://query-vector.json \ --top-k 10 \ --search-condition-expression "Category = :cat AND Brand = :brand" \ --expression-attribute-values "{\":cat\": {\"S\": \"Electronics\"}, \":brand\": {\"S\": \"Acme\"}}"

如果您的向量索引具有 SearchSchema 中定義的分割區索引鍵,則必須將其包含在 中SearchConditionExpression。內嵌篩選條件屬性是選用的。

中的向量索引分割區索引鍵和內嵌篩選條件屬性都支援等式運算子 SearchConditionExpression (=)。尚未提供比較、範圍和設定成員運算子 (<>、<、<=>、>=、IN)。

此篩選是您將相似性搜尋範圍限定為資料子集的方式,這是多租戶和擷取增強生成 (RAG) 應用程式的常見需求。例如,若要尋找類似查詢但僅在一個租用戶內的文件,請在 SearchSchema 中將租用戶屬性定義為向量索引分割區索引鍵 (HASH),並在每次搜尋中傳遞其值。這會將結果隔離到該租用戶。它也可以改善效能,因為搜尋只會檢查相關資料。將內嵌篩選條件屬性用於您希望在路由分割區中套用的其他相等性限制,例如文件類型或狀態。

分割區索引鍵範圍不是安全界限

使用分割區索引鍵將搜尋範圍限定為單一租用戶,是一種資料區域性和效能最佳化,而不是存取控制機制。擁有索引dynamodb:SearchVectors許可的任何主體都可以搜尋任何分割區索引鍵值。由於 等精細存取控制 (FGAC) 條件金鑰dynamodb:LeadingKeys不適用於 SearchVectors,因此您無法限制存取 IAM 政策層級的個別分割區金鑰值。如果您的工作負載需要在資料層進行嚴格的租用戶隔離,請使用單獨的資料表或索引,並為每個租用戶提供不同的 IAM 授權。

使用 ProjectionExpression

ProjectionExpression 使用 僅傳回搜尋結果中的特定屬性。當您不需要所有投影的屬性時,這可以減少回應大小。由於 在其 SearchSchema 中ProductEmbeddingIndex定義向量索引分割區索引鍵 (Category),因此此範例仍會包含 中的向量索引分割區索引鍵值SearchConditionExpression。

aws dynamodb search-vectors \ --table-name Products \ --index-name ProductEmbeddingIndex \ --search-vector file://query-vector.json \ --top-k 5 \ --search-condition-expression "Category = :cat" \ --expression-attribute-values "{\":cat\": {\"S\": \"Electronics\"}}" \ --projection-expression "ProductId, Title"
只能傳回投影的屬性

您只能傳回投影至向量索引的屬性。無法傳回不在索引投影中的屬性SearchVectors。

刪除向量索引

使用 UpdateTable API 搭配 VectorIndexUpdates 參數來刪除向量索引。

aws dynamodb update-table \ --table-name Products \ --vector-index-updates \ "[ {\"Delete\": {\"IndexName\": \"ProductEmbeddingIndex\"}} ]"

當您刪除向量索引時,DynamoDB 會移除索引及其所有資料。此操作不會影響基底資料表或其項目。