Voyage AI 임베딩 모델은 유연한 차원과 양자화를 지원 벡터 기반 애플리케이션의 저장 및 검색 비용을 최적화하는 데 도움이 됩니다. 이 페이지에서는 이러한 기능을 사용하여 높은 검색 품질을 유지하면서 비용을 줄이는 방법에 대해 설명합니다.
개요
대규모 리포지토리에 대한 코드 검색과 같은 대규모 벡터 검색 애플리케이션으로 작업할 때는 저장 및 계산 비용이 상당할 수 있습니다. 이러한 비용은 다음 요인에 따라 선형적으로 확장하다 .
차원 포함: 각 벡터의 차원 수
정밀도: 벡터의 각 숫자를 인코딩하는 데 사용되는 비트 수
이러한 요소 중 하나 또는 둘 다를 줄이면 검색 품질에 큰 영향을 주지 않고 비용을 크게 낮출 수 있습니다. Voyage AI 모델은 이를 달성하기 위해 두 가지 보완 기술을 지원 .
마트료시카 임베딩: 더 적은 차원으로 잘라내어 더 작은 버전의 임베딩을 사용할 수 있습니다.
양자화: 임베딩에 포함된 각 숫자의 정밀도를 32비트 부동소수점에서 정밀도가 낮은 형식으로 줄입니다.
이러한 기술은 차원이 축소되거나 양자화된 값을 사용해도 품질을 유지하도록 모델을 훈련하는 마트료시카 학습 및 양자화 인식 교육 통해 구현됩니다.
마트료시카 임베딩
마트료시카 임베딩은 단일 벡터 내에 중첩된 크기가 다른 유효한 임베딩을 여러 개 포함하는 특수한 유형의 벡터 임베딩입니다. 이를 통해 성능과 비용 요구 사항의 균형을 가장 잘 맞추는 차원을 유연하게 선택할 수 있습니다.
최신 Voyage 임베딩 모델은 마트료시카 임베딩을 생성하고 output_dimension 매개변수를 통해 직접 여러 출력 차원을 지원 . 자세한 학습 은 모델 개요를 참조하세요.
마트료시카 임베딩의 작동 방식
마트료시카 학습을 사용하면 단일 임베딩에 다양한 길이의 중첩된 임베딩 패밀리가 포함됩니다. 예시 들어 2048차원의 Voyage 임베딩에는 더 짧은 길이의 유효한 임베딩이 여러 개 포함되어 있습니다.
첫 번째 256 차원은 유효한 256차원 임베딩을 형성합니다.
첫 번째 512 차원은 유효한 512차원 임베딩을 형성합니다.
첫 번째 1024 차원은 유효한 1024차원 임베딩을 형성합니다.
모든 2048 차원이 완전 충실도 임베딩을 형성합니다.
길이가 짧은 버전은 전체 임베딩보다 검색 품질이 약간 낮지만 저장 과 계산 리소스가 덜 필요합니다.
마트료시카 임베딩을 잘라내는 방법
차원의 선행 하위 집합을 유지하여 마트료시카 임베딩을 자릅니다. 다음 예시 1024차원 벡터를 256 차원으로 자르는 방법을 보여 줍니다.
import voyageai import numpy as np def embd_normalize(v: np.ndarray) -> np.ndarray: # Normalize rows of a 2D array to unit vectors row_norms = np.linalg.norm(v, axis=1, keepdims=True) if np.any(row_norms == 0): raise ValueError("Cannot normalize rows with a norm of zero.") return v / row_norms vo = voyageai.Client() # Generate 1024-dimensional embeddings embd = vo.embed(['Sample text 1', 'Sample text 2'], model='voyage-4-large').embeddings # Truncate to 256 dimensions and normalize short_dim = 256 resized_embd = embd_normalize(np.array(embd)[:, :short_dim]).tolist()
양자화
양자화는 고정밀 부동 소수점 숫자를 정밀도가 낮은 형식으로 변환하여 임베딩의 정밀도를 줄입니다. 이 프로세스 강력한 검색 품질을 유지하면서 저장 및 계산 비용을 크게 줄일 수 있습니다.
최신 Voyage 임베딩 모델은 양자화 인식 교육 사용하여 교육되므로, 양자화하더라도 높은 검색 품질을 유지합니다. 자세한 학습 은 모델 개요를 참조하세요.
참고
MongoDB 포함하여 벡터 저장 및 검색을 지원 하는 많은 데이터베이스가 양자화된 임베딩도 지원 . MongoDB Vector Search의 양자화에 대해 자세히 학습하려면 벡터 양자화를 참조하세요.
양자화 작동 방식
양자화는 표준 32비트 부동 소수점 형식보다 적은 수의 비트로 각 차원을 표현하여 임베딩의 정밀도를 줄입니다. 양자화된 임베딩은 차원당 4 바이트를 사용하는 대신 다음을 사용합니다.
8비트 정수 (차원당 1 바이트): 저장 4만큼 줄입니다.
바이너리 (차원당 1 비트): 저장 32x만큼 줄입니다.
이처럼 크기가 크게 감소했음에도 불구하고, 보이지(Voyage)와 같은 양자화 인식 학습 모델은 높은 검색 품질을 유지합니다. 지원되는 Voyage 모델을 사용하면 output_dtype 매개 변수를 사용하여 출력 데이터 유형 지정하여 양자화 활성화 .
데이터 유형 | 설명 |
|---|---|
| 반환된 각 임베딩은 32비트(4바이트) 단정밀도 부동 소수점 숫자 목록입니다. 이는 기본값 이며 가장 높은 정밀도와 검색 정확도를 제공합니다. |
| 반환된 각 임베딩은 각각 -128 ~ 127 및 0 ~ 255 범위의 8비트(1바이트) 정수 목록입니다. |
| 반환된 각 임베딩은 비트로 채워진 양자화된 단일 비트 임베딩 값을 나타내는 8비트 정수 목록( |
예시
이진 양자화 이해
다음과 같은 임베딩 값을 고려하세요.
-0.0396, 0.0062, -0.0745, -0.0390, 0.0046, 0.0003, -0.0850, 0.0399 이진 양자화는 다음 규칙을 사용하여 각 값을 단일 비트로 변환합니다.
0보다 작은 값은0(으)로 변환됩니다.0보다 크거나 같은 값은1(으)로 변환됩니다.
0, 1, 0, 0, 1, 1, 0, 1 8비트는 하나의 8비트 정수로 압축됩니다:
01001101. 이 정수는 10진수로77로 변환됩니다.최종 출력 유형으로 변환하려면 다음 변환을 적용 .
출력 유형변환 방법결과ubinaryuint8: 값을 부호 없는 정수로 직접 사용합니다.77binaryint8: 를 빼서 오프셋 이진법을128적용합니다.-51(77 - 128과 동일)
오프셋 바이너리
오프셋 바이너리 는 부호가 있는 정수를 바이너리 형식으로 표현하는 방법입니다. Voyage AI binary 출력 유형에 이 메서드를 사용하여 비트 팩 바이너리 임베딩을 부호 있는 정수(int8)로 인코딩합니다.
오프셋 바이너리 메서드는 오프셋 값을 더하거나 빼는 방식으로 작동합니다.
바이너리로 변환하는 경우: 인코딩하기 전에 부호가 있는 정수에
128를 추가합니다.바이너리에서 변환할 때: 디코딩 후 정수에서
128빼기
8비트 부호 있는 정수(-128 ~ 127 범위 )의 경우 오프셋은 항상 128입니다.
예시
부호 있는 정수를 이진수로
-32 을 8비트 이진수로 나타내려면 다음을 수행합니다.
오프셋(
128)을-32에 추가하면96가 됩니다.96를 바이너리로 변환합니다:01100000.
예시
이진법에서 부호 있는 정수로
8비트 이진수 01010101에서 부호가 있는 정수를 확인하려면 다음을 수행합니다.
정수로 직접 변환합니다:
85.85에서 오프셋(128)을 빼면-43가 됩니다.
Voyage AI 로 양자화를 사용하는 방법
부동 소수점 임베딩을 수동으로 바이너리 형식으로 변환하거나 바이너리 임베딩을 개별 비트로 다시 언팩할 수 있습니다. 다음 예시에서는 두 작업을 모두 보여줍니다.
import numpy as np import voyageai vo = voyageai.Client() # Generate float embeddings embd_float = vo.embed('Sample text 1', model='voyage-4-large', output_dimension=2048).embeddings[0] # Compute 512-dimensional bit-packed binary and ubinary embeddings from 2048-dimensional float embeddings embd_binary_calc = (np.packbits(np.array(embd_float) > 0, axis=0) - 128).astype(np.int8).tolist() # Quantize, binary offset embd_binary_512_calc = embd_binary_calc[0:64] # Truncate. Binary is 1/8 length of embedding dimension. embd_ubinary_calc = (np.packbits(np.array(embd_float) > 0, axis=0)).astype(np.uint8).tolist() # Quantize, binary offset embd_ubinary_512_calc = embd_ubinary_calc[0:64] # Truncate. Binary is 1/8 length of embedding dimension.
import numpy as np import voyageai vo = voyageai.Client() # Generate binary embeddings embd_binary = vo.embed('Sample text 1', model='voyage-4-large', output_dtype='binary', output_dimension=2048).embeddings[0] embd_ubinary = vo.embed('Sample text 1', model='voyage-4-large', output_dtype='ubinary', output_dimension=2048).embeddings[0] # Unpack bits embd_binary_bits = [format(x, f'08b') for x in np.array(embd_binary) + 128] # List of (bits) strings embd_binary_unpacked = [bit == '1' for bit in ''.join(embd_binary_bits)] # List of booleans embd_ubinary_bits = [format(x, f'08b') for x in np.array(embd_ubinary)] # List of (bits) strings embd_ubinary_unpacked = [bit == '1' for bit in ''.join(embd_ubinary_bits)] # List of booleans