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 요청은 전용 벡터 검색 엔드포인트를 사용합니다. 이는 벡터 인덱스를 생성 및 관리(예: CreateTable, UpdateTableDescribeTable 사용)하기 위해 사용하는 표준 DynamoDB 엔드포인트와는 다릅니다. AWS SDK 및 AWS CLI는 자동으로 SearchVectors 요청을 올바른 엔드포인트로 라우팅합니다. 애플리케이션 코드에서 엔드포인트를 구성하거나 재정의할 필요가 없습니다.

AWS SDK 없이 바로 DynamoDB API를 직접적으로 호출하는 사용자 지정 HTTP 클라이언트를 구축하는 경우 다음 벡터 검색 엔드포인트 중 하나를 사용하여 account-idregion을 적절하게 바꿉니다.

  • account-id.search-ddb.region.amazonaws.com - 계정 기반 엔드포인트

  • search-dynamodb.region.api.aws - IPv4 및 IPv6 모두와 호환되는 듀얼 스택 엔드포인트

벡터 임베딩 생성

DynamoDB는 벡터 임베딩을 저장하고 검색하지만 생성하지는 않습니다. Amazon Bedrock Titan Text Embeddings 또는 Cohere Embed 모델과 같은 임베딩 모델이나 직접 운영하는 임베딩 모델을 사용하여 임베딩을 생성합니다. 그런 다음 결과 벡터를 DynamoDB 항목에 저장하고 쿼리 벡터를 SearchVectors에 전달합니다.

쿼리 벡터와 저장된 벡터는 동일한 모델을 사용해야 합니다.

SearchVectors에 전달하는 쿼리 벡터와 항목에 저장된 벡터는 동일한 임베딩 모델로 생성되어야 하며 벡터 인덱스와 동일한 수의 차원을 가져야 합니다. 모델을 혼용하거나 인덱스가 생성된 차원과 다른 수의 차원으로 쿼리하면 의미 없는 결과 또는 유효성 검사 오류가 발생합니다.

일반적인 흐름은 다음과 같습니다.

  1. 소스 콘텐츠(예: 제품 설명)를 임베딩 모델로 보내고 벡터를 받습니다.

  2. 해당 벡터를 DynamoDB 항목에서 벡터 인덱스의 VectorAttribute로 지정된 속성에 숫자(N) 목록(L)으로 저장합니다.

  3. 쿼리 시 동일한 모델을 사용하여 검색 텍스트에서 벡터를 생성하고 SearchVector로 전달합니다.

인덱스를 생성하기 전에 임베딩 모델을 선택

벡터 인덱스를 생성하기 전에 임베딩 모델을 선택합니다. 모델이 차원 수를 결정하기 때문입니다. 일반적인 임베딩 모델은 384, 768, 1024, 1536 또는 3072차원을 생성합니다. DynamoDB는 최대 4,096차원을 지원합니다. 요구 사항 및 제한 사항을(를) 참조하세요.

선택한 거리 함수는 모델이 임베딩을 생성하는 방식과 상호 작용합니다. COSINE은 방향을 비교하고 크기를 무시하므로 임베딩의 정규화 여부에 관계없이 작동합니다. DOT_PRODUCT는 크기에 민감합니다. 즉, 임베딩이 단위 길이로 정규화되지 않은 경우 방향에 관계없이 더 큰 벡터가 더 높은 점수를 받게 됩니다. DOT_PRODUCT를 사용하면서 방향 기반 유사성을 원하는 경우 임베딩을 저장하기 전에 단위 길이로 정규화합니다. 거리 함수가 결과의 순위를 매기는 방법을(를) 참조하세요.

벡터 인덱스 생성

벡터 인덱스를 새 테이블과 함께 생성하거나 기존 테이블에 추가할 수 있습니다.

벡터 인덱스가 있는 테이블 생성

CreateTable API를 VectorIndexes 파라미터와 함께 사용하여 벡터 인덱스가 있는 테이블을 생성합니다. 다음 AWS CLI 예제에서는 ProductEmbeddingIndex라는 이름의 벡터 인덱스가 있는 Products 테이블을 생성합니다.

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\" } ]"

이 예시는 다음과 같이 설정되어 있습니다.

  • VectorAttributeEmbedding을 벡터 데이터를 포함하는 속성으로 지정합니다.

  • SearchSchemaCategory를 벡터 인덱스 파티션 키(HASH)로 정의합니다. 이 키는 스케일링을 위해 인덱스를 범주별로 분할합니다. 또한 BrandINLINE_FILTER로 정의합니다. 이를 통해 검색 결과를 스토리지 계층에서 브랜드 기준으로 필터링할 수 있습니다. CategoryBrand는 모두 SearchSchema에서 참조되므로 AttributeDefinitions에서도 키 속성이 글로벌 보조 인덱스에 대해 선언되는 것과 동일한 방식으로 선언되어야 합니다.

  • Dimensions는 일반적인 임베딩 모델의 출력과 일치하는 1536으로 설정됩니다.

  • DistanceFunctionCOSINE으로 설정되며, 점수가 낮을수록 유사성이 높음을 나타냅니다.

기존 테이블에 벡터 인덱스 추가

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는 DescribeTable 응답의 두 필드, 즉 IndexStatus 값과 별도의 Backfilling 부울을 통해 인덱스 진행 상황을 보고합니다.

  1. IndexStatusCREATING인 경우 - DynamoDB가 인덱스 인프라를 설정하고 있습니다.

  2. IndexStatusACTIVE이고 Backfillingtrue로 설정된 경우 - DynamoDB가 기본 테이블의 기존 데이터로 인덱스를 채우고 있습니다. 이 단계에서는 기본 테이블에 대한 새 쓰기도 인덱스에 복제됩니다. 벡터 인덱스가 백필되는 동안 SearchVectors는 오류를 반환합니다. Backfillingfalse가 될 때까지 기다렸다가 검색합니다.

  3. IndexStatusACTIVE이고 Backfillingfalse로 설정된(또는 없는) 경우 - 인덱스가 완전히 채워지고 검색 작업을 수행할 준비가 되었습니다.

인덱스가 백필되는 동안에는 검색할 수 없습니다.

SearchVectors는 벡터 인덱스가 백필되는 동안 오류를 반환합니다. DescribeTable을 사용하여 IndexStatusBackfilling 플래그를 모두 확인하고 IndexStatusACTIVE이고 Backfillingfalse가 될 때까지 기다렸다가 검색합니다. BACKFILLING 인덱스 상태 값은 없습니다.

벡터 데이터로 항목 작성

표준 DynamoDB 쓰기 API(PutItem, UpdateItem, BatchWriteItem, TransactWriteItems)를 사용하여 벡터 데이터로 항목을 작성합니다. 벡터 임베딩을 숫자 목록(N 요소가 포함된 L 유형)으로 저장합니다.

벡터에는 많은 값이 포함되어 있으므로 항목을 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에서 벡터는 ProductEmbeddingIndex에 설정한 Dimensions와 일치하도록 1,536개의 값을 포함해야 합니다. 차원 수가 잘못된 벡터 쓰기는 거부됩니다.

DynamoDB는 벡터 인덱스가 있는 테이블에 항목을 쓸 때 벡터 데이터를 검증합니다. 다음 표는 검증 동작에 대한 설명입니다.

Condition 동작
벡터 속성의 차원 수가 잘못됨 쓰기가 거부됩니다.
벡터 인덱스 파티션 키 속성이 누락됨 기본 테이블에서 쓰기가 성공하지만 항목이 벡터 인덱스에 복제되지 않습니다.
벡터 인덱스 파티션 키 속성 유형이 인덱스 스키마와 일치하지 않음 쓰기가 거부됩니다.
인라인 필터 속성이 누락됨 쓰기가 성공하고 항목이 벡터 인덱스에 복제됩니다.
벡터 값의 정밀도가 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의 의미는 인덱스를 생성할 때 선택한 거리 함수에 따라 달라집니다. COSINEEUCLIDEAN의 경우 점수가 낮을수록 유사성이 높음을 나타냅니다. DOT_PRODUCT의 경우 점수가 높을수록 유사성이 높음을 나타냅니다.

SearchConditionExpression을 사용하여 필터링

SearchConditionExpression를 사용하여 SearchSchema에 정의된 벡터 인덱스 파티션 키 및 인라인 필터 속성을 기반으로 검색 결과를 필터링합니다. 이 표현식은 다른 DynamoDB 표현식 파라미터와 동일한 구문을 사용합니다.

다음 예시에서는 Brand 인라인 필터를 사용하여 Electronics 범주(벡터 인덱스 파티션 키)의 항목을 검색합니다.

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 권한이 있는 모든 보안 주체는 모든 파티션 키 값을 검색할 수 있습니다. dynamodb:LeadingKeys와 같은 세분화된 액세스 제어(FGAC) 조건 키는 SearchVectors에 적용되지 않으므로 IAM 정책 수준에서 개별 파티션 키 값에 대한 액세스를 제한할 수 없습니다. 워크로드에 데이터 계층에서 엄격한 테넌트 격리가 필요한 경우 각 테넌트에 대해 고유한 IAM 권한이 있는 별도의 테이블 또는 인덱스를 사용합니다.

ProjectionExpression 사용

ProjectionExpression을 사용하여 검색 결과에서 특정 속성만 반환하도록 합니다. 이렇게 하면 프로젝션된 속성이 모두 필요하지 않을 때 응답 크기를 줄일 수 있습니다. ProductEmbeddingIndex는 SearchSchema에서 벡터 인덱스 파티션 키(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가 인덱스와 그 모든 데이터를 제거합니다. 이 작업은 기본 테이블 또는 해당 항목에 영향을 주지 않습니다.