Python 클라이언트 라이브러리와 함께 Azure Cosmos DB 벡터 검색을 사용합니다. 애플리케이션에서 벡터 데이터를 효율적으로 저장하고 쿼리합니다.
이 빠른 시작 가이드에서는 텍스트 임베딩-3-small 모델의 벡터와 함께 JSON 파일에 있는 샘플 호텔 데이터 세트를 사용합니다. 데이터 세트에는 호텔 이름, 위치, 설명 및 벡터 포함이 포함됩니다.
GitHub에서 리소스 프로비저닝을 사용하여 샘플 코드를 찾습니다.
필수 조건
Azure 구독
- Azure 구독이 없는 경우 체험 계정 만들기
기존 Azure Cosmos DB의 리소스 데이터 평면에 대한 접근
- 리소스가 없는 경우 새 리소스를 만듭니다.
- 클라이언트 IP 주소에 대한 액세스를 허용하도록 구성된 방화벽
- 할당된 RBAC(역할 기반 액세스 제어) 역할:
- Cosmos DB 기본 제공 데이터 기여자 (데이터 평면)
- 역할 ID:
00000000-0000-0000-0000-000000000002
-
- 구성된 사용자 지정 도메인
- 할당된 RBAC(역할 기반 액세스 제어) 역할:
- Cognitive Services OpenAI 사용자
- 역할 ID:
5e0bd9bd-7b93-4f28-af87-19fc36ad61bd
-
text-embedding-3-small배포된 모델
벡터를 사용하여 데이터 파일 만들기
호텔 데이터 파일에 대한 새 데이터 디렉터리를 만듭니다.
mkdir data벡터가 있는 raw 데이터 파일을
data디렉터리에 다운로드합니다.curl -o data/HotelsData_toCosmosDB_Vector.json https://raw.githubusercontent.com/Azure-Samples/cosmos-db-vector-samples/refs/heads/main/data/HotelsData_toCosmosDB_Vector.json
Python 프로젝트 만들기
데이터 디렉터리와 동일한 수준에서 프로젝트에 대한 새 형제 디렉터리를 만들고 Visual Studio Code에서 엽니다.
mkdir vector-search-quickstart code vector-search-quickstart터미널에서 Python 가상 환경을 만들고 활성화합니다.
python -m venv .venvsource .venv/bin/activate다음 콘텐츠를 사용하여
requirements.txt프로젝트 루트에 파일을 만듭니다.azure-cosmos>=4.7.0 azure-identity>=1.18.0 openai>=1.57.0 python-dotenv>=1.0.1필요한 패키지를 설치합니다.
pip install -r requirements.txt- azure-cosmos - 데이터베이스 작업을 위한 Azure Cosmos DB 클라이언트 라이브러리
- azure-identity - 암호 없는(관리 ID) 연결에 대한 인증 라이브러리 Azure
- openai - Azure OpenAI를 사용하여 임베딩을 생성하기 위한 OpenAI SDK
-
python-dotenv - 파일에서 환경 변수 로드
.env
환경 변수에
.env대한 파일을 프로젝트 루트에 만듭니다.# Identity for local developer authentication with Azure CLI AZURE_TOKEN_CREDENTIALS=AzureCliCredential # Azure OpenAI Embedding Settings AZURE_OPENAI_EMBEDDING_MODEL=text-embedding-3-small AZURE_OPENAI_EMBEDDING_API_VERSION=2024-08-01-preview AZURE_OPENAI_EMBEDDING_ENDPOINT= # Cosmos DB configuration AZURE_COSMOSDB_ENDPOINT= # Data file DATA_FILE_WITH_VECTORS=../data/HotelsData_toCosmosDB_Vector.json FIELD_TO_EMBED=Description EMBEDDED_FIELD=DescriptionVector EMBEDDING_DIMENSIONS=1536.env파일의 자리 표시자 값을 사용자 정보로 바꿉니다.-
AZURE_OPENAI_EMBEDDING_ENDPOINT: Azure OpenAI 리소스 엔드포인트 URL 주소 -
AZURE_COSMOSDB_ENDPOINT: Azure Cosmos DB의 끝점 URL
-
문서 스키마 이해
애플리케이션을 빌드하기 전에 벡터가 Azure Cosmos DB 문서에 저장되는 방법을 이해합니다. 각 호텔 문서에는 다음이 포함됩니다.
-
표준 필드:
HotelId,HotelName,DescriptionCategory등 -
벡터 필드:
DescriptionVector- 호텔 설명의 의미 체계적 의미를 나타내는 1536 부동 소수점 숫자의 배열입니다.
호텔 문서 구조의 간소화된 예는 다음과 같습니다.
{
"HotelId": "1",
"HotelName": "Stay-Kay City Hotel",
"Description": "This classic hotel is fully-refurbished...",
"Rating": 3.6,
"DescriptionVector": [
-0.04886505,
-0.02030743,
0.01763356,
...
// 1536 dimensions total
]
}
포함 저장에 대한 핵심 사항은 다음과 같습니다.
- 벡터 배열은 문서에 표준 JSON 배열로 저장됩니다.
-
벡터 정책은 경로(
/DescriptionVector), 데이터 형식(), 차원(float321536) 및 거리 함수(코사인)를 정의합니다. - 인덱싱 정책은 효율적인 유사성 검색을 위해 벡터 필드에 벡터 인덱스 만들기
- 삽입 성능을 최적화하려면 표준 인덱싱에서 벡터 필드를 제외해야 합니다.
이러한 정책은 이 샘플 프로젝트의 거리 메트릭 에 대한 Bicep 템플릿에 정의됩니다. 벡터 정책 및 인덱싱에 대한 자세한 내용은 Azure Cosmos DB의 벡터 검색을 참조하세요.
벡터 검색을 위한 코드 파일 만들기
Python 파일에 대한 src 디렉터리를 만듭니다. 벡터 검색 구현에 대해 다음 두 개의 파일을 vector_search.pyutils.py 추가합니다.
mkdir src
touch src/__init__.py
touch src/vector_search.py
touch src/utils.py
벡터 검색을 위한 코드 만들기
다음 코드를 파일에 붙여넣습니다 vector_search.py .
"""Azure Cosmos DB NoSQL Vector Search — main entry point.
Loads hotel data, bulk-inserts into the selected container (DiskANN or
QuantizedFlat), generates a query embedding via Azure OpenAI, and
executes a VectorDistance() similarity search.
"""
import os
import sys
from pathlib import Path
from dotenv import load_dotenv
sys.path.insert(0, str(Path(__file__).parent))
from utils import (
get_clients_passwordless,
get_clients,
insert_data,
print_search_results,
read_file_return_json,
validate_field_name,
get_query_activity_id,
)
# ---------------------------------------------------------------------------
# Load environment
# ---------------------------------------------------------------------------
load_dotenv()
ALGORITHM_CONFIGS: dict[str, dict[str, str]] = {
"diskann": {
"container_name": "hotels_diskann",
"algorithm_name": "DiskANN",
},
"quantizedflat": {
"container_name": "hotels_quantizedflat",
"algorithm_name": "QuantizedFlat",
},
}
def _build_config() -> dict[str, str | int]:
"""Build runtime configuration from environment variables."""
return {
"query": "quintessential lodging near running trails, eateries, retail",
"db_name": os.getenv("AZURE_COSMOSDB_DATABASENAME", "Hotels"),
"algorithm": os.getenv("VECTOR_ALGORITHM", "diskann").strip().lower(),
"data_file": os.getenv("DATA_FILE_WITH_VECTORS", "../data/HotelsData_toCosmosDB_Vector.json"),
"embedded_field": os.getenv("EMBEDDED_FIELD", "DescriptionVector"),
"embedding_dimensions": int(os.getenv("EMBEDDING_DIMENSIONS", "1536")),
"deployment": os.getenv("AZURE_OPENAI_EMBEDDING_MODEL", "text-embedding-3-small"),
"distance_function": os.getenv("VECTOR_DISTANCE_FUNCTION", "cosine"),
}
def main() -> None:
"""Run the vector search demonstration."""
config = _build_config()
# Try passwordless auth first, fall back to key-based
clients = get_clients_passwordless()
if not clients["ai_client"] or not clients["db_client"]:
clients = get_clients()
ai_client = clients["ai_client"]
db_client = clients["db_client"]
try:
algorithm = config["algorithm"]
if algorithm not in ALGORITHM_CONFIGS:
valid = ", ".join(ALGORITHM_CONFIGS)
raise ValueError(
f"Invalid algorithm '{algorithm}'. Must be one of: {valid}"
)
if not ai_client:
raise RuntimeError(
"Azure OpenAI client is not configured. "
"Please check your environment variables."
)
if not db_client:
raise RuntimeError(
"Cosmos DB client is not configured. "
"Please check your environment variables."
)
algo_cfg = ALGORITHM_CONFIGS[algorithm]
container_name = algo_cfg["container_name"]
database = db_client.get_database_client(config["db_name"])
print(f"Connected to database: {config['db_name']}")
container = database.get_container_client(container_name)
print(f"Connected to container: {container_name}")
print(f"\n📊 Vector Search Algorithm: {algo_cfg['algorithm_name']}")
print(f"📏 Distance Function: {config['distance_function']}")
# Verify the container exists
try:
container.read()
except Exception as e:
status_code = getattr(e, "status_code", None)
if status_code == 404:
raise RuntimeError(
f"Container or database not found. Ensure database "
f"'{config['db_name']}' and container '{container_name}' "
f"exist before running this script."
) from e
raise
data_path = Path(__file__).parent.parent / config["data_file"]
data = read_file_return_json(str(data_path))
insert_data(container, data)
embedding_response = ai_client.embeddings.create(
model=config["deployment"],
input=[config["query"]],
)
query_embedding = embedding_response.data[0].embedding
safe_field = validate_field_name(config["embedded_field"])
query_text = (
f"SELECT TOP 5 c.HotelName, c.Description, c.Rating, "
f"VectorDistance(c.{safe_field}, @embedding) AS SimilarityScore "
f"FROM c "
f"ORDER BY VectorDistance(c.{safe_field}, @embedding)"
)
print("\n--- Executing Vector Search Query ---")
print(f"Query: {query_text}")
print(
f"Parameters: @embedding (vector with {len(query_embedding)} dimensions)"
)
print("--------------------------------------\n")
results = list(
container.query_items(
query=query_text,
parameters=[{"name": "@embedding", "value": query_embedding}],
enable_cross_partition_query=True,
)
)
# Extract diagnostics
response_headers = container.client_connection.last_response_headers
activity_id = get_query_activity_id(response_headers)
if activity_id:
print(f"Query activity ID: {activity_id}")
request_charge_raw = response_headers.get("x-ms-request-charge", "0") if response_headers else "0"
try:
request_charge = float(request_charge_raw)
except (ValueError, TypeError):
request_charge = 0.0
print_search_results(results, request_charge)
except Exception as error:
print(f"App failed: {error}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
이 코드:
- 환경 변수를 통해
DiskANN벡터 알고리즘 또는quantizedFlat벡터 알고리즘을 구성합니다. - 암호 없는 인증을 사용하여 Azure OpenAI 및 Azure Cosmos DB에 연결합니다.
- JSON 파일에서 미리 벡터화된 호텔 데이터를 로드합니다.
- 적절한 컨테이너에 데이터를 삽입합니다.
- 자연어 쿼리(
quintessential lodging near running trails, eateries, retail)에 대한 포함을 생성합니다. - SQL 쿼리를
VectorDistance실행하여 유사성 점수로 순위가 가장 유사한 상위 5개 호텔을 검색합니다. - 누락된 클라이언트, 잘못된 알고리즘 선택 및 존재하지 않는 컨테이너/데이터베이스에 대한 오류를 처리합니다.
코드를 이해하기: Azure OpenAI를 사용하여 임베딩 생성
이 코드는 쿼리 텍스트에 대한 임베딩을 생성합니다.
embedding_response = ai_client.embeddings.create(
model=config["deployment"], # OpenAI embedding model, e.g. "text-embedding-3-small"
input=[config["query"]], # List of description strings to embed
)
query_embedding = embedding_response.data[0].embedding
client.embeddings.create에 대한 이 OpenAI API 호출은 "달리기 코스 근처의 이상적인 숙소"와 같은 텍스트를 그 의미를 포착하는 1536차원 벡터로 변환합니다. 포함 생성에 대한 자세한 내용은 Azure OpenAI embeddings 설명서를 참조하세요.
코드 이해: Azure Cosmos DB에 벡터 저장
벡터 배열이 있는 모든 문서는 함수를 upsert_item 사용하여 삽입됩니다.
for item in data:
doc = {"id": item["HotelId"], **item}
response = container.upsert_item(body=doc)
이렇게 하면 미리 생성된 DescriptionVector 배열을 포함한 호텔 문서가 컨테이너에 삽입됩니다. 각 문서는 id에서 HotelId로 매핑된 필드를 가지며, 이 함수는 문서를 안전하게 다시 삽입할 수 있도록 upsert를 처리합니다.
코드 이해: 벡터 유사성 검색 실행
이 코드는 함수를 사용하여 벡터 검색을 수행합니다.VectorDistance
query_text = (
f"SELECT TOP 5 c.HotelName, c.Description, c.Rating, "
f"VectorDistance(c.{safe_field}, @embedding) AS SimilarityScore "
f"FROM c "
f"ORDER BY VectorDistance(c.{safe_field}, @embedding)"
)
results = list(
container.query_items(
query=query_text,
parameters=[{"name": "@embedding", "value": query_embedding}],
enable_cross_partition_query=True,
)
)
이 코드는 VectorDistance 함수를 사용하여 쿼리의 포함 벡터(@embedding)를 각 문서의 저장된 벡터 필드(DescriptionVector)와 비교하여 이름 및 유사성 점수가 가장 유사한 상위 5개 호텔을 반환하는 매개 변수가 있는 SQL 쿼리를 작성합니다. 쿼리 포함은 삽입을 방지하기 위해 매개 변수로 전달되며 이전 Azure OpenAI embeddings.create 호출에서 가져옵니다.
이 쿼리에서 반환하는 내용:
- 벡터 거리를 기준으로 가장 유사한 호텔 상위 5개
- 호텔 속성:
HotelName,DescriptionRating -
SimilarityScore: 각 호텔이 쿼리와 얼마나 유사한지를 나타내는 숫자 값입니다. - 유사성 순으로 정렬된 결과
함수에 대한 VectorDistance 자세한 내용은 VectorDistance 설명서를 참조하세요.
유틸리티 함수 만들기
다음 코드를 utils.py에 붙여넣으세요.
"""Shared utilities for Azure Cosmos DB NoSQL vector search.
Provides client initialization (passwordless and key-based), JSON I/O,
bulk insert with RU tracking, field validation, and result formatting.
"""
import json
import os
import re
import time
from typing import Any, Optional
def get_clients() -> dict[str, Any]:
"""Get Azure OpenAI and Cosmos DB clients using key-based authentication.
Returns dict with 'ai_client' and 'db_client' (either may be None if
the required environment variables are missing).
"""
from azure.cosmos import CosmosClient
from openai import AzureOpenAI
ai_client = None
db_client = None
api_key = os.getenv("AZURE_OPENAI_EMBEDDING_KEY", "")
api_version = os.getenv("AZURE_OPENAI_EMBEDDING_API_VERSION", "")
endpoint = os.getenv("AZURE_OPENAI_EMBEDDING_ENDPOINT", "")
deployment = os.getenv("AZURE_OPENAI_EMBEDDING_MODEL", "")
if api_key and api_version and endpoint and deployment:
ai_client = AzureOpenAI(
api_key=api_key,
api_version=api_version,
azure_endpoint=endpoint,
azure_deployment=deployment,
)
cosmos_endpoint = os.getenv("AZURE_COSMOSDB_ENDPOINT", "")
cosmos_key = os.getenv("AZURE_COSMOSDB_KEY", "")
if cosmos_endpoint and cosmos_key:
db_client = CosmosClient(url=cosmos_endpoint, credential=cosmos_key)
return {"ai_client": ai_client, "db_client": db_client}
def get_clients_passwordless() -> dict[str, Any]:
"""Get Azure OpenAI and Cosmos DB clients using DefaultAzureCredential.
Uses managed identity / Azure CLI credentials for passwordless auth.
Returns dict with 'ai_client' and 'db_client' (either may be None).
"""
from azure.cosmos import CosmosClient
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
from openai import AzureOpenAI
ai_client = None
db_client = None
api_version = os.getenv("AZURE_OPENAI_EMBEDDING_API_VERSION", "")
endpoint = os.getenv("AZURE_OPENAI_EMBEDDING_ENDPOINT", "")
deployment = os.getenv("AZURE_OPENAI_EMBEDDING_MODEL", "")
if api_version and endpoint and deployment:
credential = DefaultAzureCredential()
token_provider = get_bearer_token_provider(
credential, "https://cognitiveservices.azure.com/.default"
)
ai_client = AzureOpenAI(
api_version=api_version,
azure_endpoint=endpoint,
azure_deployment=deployment,
azure_ad_token_provider=token_provider,
)
cosmos_endpoint = os.getenv("AZURE_COSMOSDB_ENDPOINT", "")
if cosmos_endpoint:
credential = DefaultAzureCredential()
db_client = CosmosClient(url=cosmos_endpoint, credential=credential)
return {"ai_client": ai_client, "db_client": db_client}
def read_file_return_json(file_path: str) -> list[dict[str, Any]]:
"""Read a JSON file and return its parsed contents."""
print(f"Reading JSON file from {file_path}")
try:
with open(file_path, "r", encoding="utf-8") as f:
return json.load(f)
except FileNotFoundError:
print(f"Error: File '{file_path}' not found")
raise
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON in file '{file_path}': {e}")
raise
def write_file_json(file_path: str, json_data: Any) -> None:
"""Serialize data to a JSON file."""
try:
with open(file_path, "w", encoding="utf-8") as f:
json.dump(json_data, f, indent=2, ensure_ascii=False)
print(f"Wrote JSON file to {file_path}")
except IOError as e:
print(f"Error writing to file '{file_path}': {e}")
raise
def _get_document_count(container: Any) -> int:
"""Return the number of documents in a Cosmos DB container."""
query = "SELECT VALUE COUNT(1) FROM c"
results = list(container.query_items(query=query, enable_cross_partition_query=True))
return results[0] if results else 0
def insert_data(
container: Any, data: list[dict[str, Any]]
) -> dict[str, Any]:
"""Bulk-insert documents into a Cosmos DB container.
Skips insertion if the container already has documents.
Each item gets an 'id' field mapped from 'HotelId'.
Returns a dict with total, inserted, failed, skipped, and requestCharge.
"""
existing_count = _get_document_count(container)
if existing_count > 0:
print(f"Container already has {existing_count} documents. Skipping insert.")
return {
"total": 0,
"inserted": 0,
"failed": 0,
"skipped": existing_count,
"requestCharge": 0.0,
}
print(f"Inserting {len(data)} items...")
inserted = 0
failed = 0
total_request_charge = 0.0
start_time = time.time()
for item in data:
doc = {"id": item["HotelId"], **item}
try:
response = container.upsert_item(body=doc)
inserted += 1
ru = _extract_ru_from_headers(container.client_connection.last_response_headers)
total_request_charge += ru
except Exception as e:
status_code = getattr(e, "status_code", None)
if status_code == 409:
inserted += 1
else:
failed += 1
print(f" Insert failed for item {item.get('HotelId', '?')}: {e}")
duration = time.time() - start_time
print(f"Bulk insert completed in {duration:.2f}s")
print(f"\nInsert Request Charge: {total_request_charge:.2f} RUs\n")
return {
"total": len(data),
"inserted": inserted,
"failed": failed,
"skipped": 0,
"requestCharge": total_request_charge,
}
def _extract_ru_from_headers(headers: Optional[dict[str, str]]) -> float:
"""Extract the request charge (RU) from Cosmos DB response headers."""
if not headers:
return 0.0
raw = headers.get("x-ms-request-charge", "0")
try:
return float(raw)
except (ValueError, TypeError):
return 0.0
def validate_field_name(field_name: str) -> str:
"""Validate a field name is a safe SQL identifier.
Prevents NoSQL injection when interpolating field names into queries.
Allows only letters, digits, and underscores; must start with a letter
or underscore.
Raises ValueError if the field name is invalid.
"""
pattern = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
if not pattern.match(field_name):
raise ValueError(
f'Invalid field name: "{field_name}". '
"Field names must start with a letter or underscore and "
"contain only letters, numbers, and underscores."
)
return field_name
def print_search_results(
search_results: list[dict[str, Any]],
request_charge: Optional[float] = None,
) -> None:
"""Print vector search results in a consistent format."""
print("\n--- Search Results ---")
if not search_results:
print("No results found.")
return
for i, result in enumerate(search_results, 1):
score = result.get("SimilarityScore", 0.0)
name = result.get("HotelName", "Unknown")
print(f"{i}. {name}, Score: {score:.4f}")
if request_charge is not None:
print(f"\nVector Search Request Charge: {request_charge:.2f} RUs")
print("")
def get_query_activity_id(response_headers: Optional[dict[str, str]]) -> Optional[str]:
"""Extract the activity ID from Cosmos DB query response headers."""
if not response_headers:
return None
return response_headers.get("x-ms-activity-id")
def get_bulk_operation_rus(headers: Optional[dict[str, str]]) -> float:
"""Extract total RU cost from Cosmos DB response headers."""
return _extract_ru_from_headers(headers)
이 유틸리티 모듈은 다음과 같은 주요 함수를 제공합니다.
-
get_clients_passwordless: 암호 없는 인증을 사용하여 Azure OpenAI 및 Azure Cosmos DB에 대한 클라이언트를 만들고 반환합니다. 두 리소스 각각에서 RBAC를 활성화하고 Azure CLI에 로그인하십시오. -
insert_data: Azure Cosmos DB 컨테이너에 데이터를 삽입하고 각 작업에 대한 RU(요청 단위)를 추적합니다. -
print_search_results: 점수 및 호텔 이름을 포함하여 벡터 검색 결과를 출력합니다. -
validate_field_name: 데이터에 필드 이름이 있는지 확인합니다. -
get_bulk_operation_rus: Azure Cosmos DB 응답 헤더에서 총 RU 비용을 추출합니다.
Azure CLI를 사용하여 인증
앱이 Azure 리소스에 안전하게 액세스할 수 있도록 애플리케이션을 실행하기 전에 Azure CLI에 로그인합니다.
az login
이 코드는 로컬 개발자 인증을 사용하여 Azure Cosmos DB와 Azure OpenAI에 액세스하고, get_clients_passwordlessutils.py의 함수를 활용합니다.
AZURE_TOKEN_CREDENTIALS=AzureCliCredential를 설정할 때 자격 증명 체인에서 DefaultAzureCredential이(가) 사용할 자격 증명을 명확히 선택합니다. 이 함수는 DefaultAzureCredential에서 azure-identity를 사용합니다. 순서가 지정된 자격 증명 공급자 체인을 차례로 검사하지만, 환경 변수에 의해 Azure CLI 자격 증명이 우선적으로 사용됩니다.
Azure ID 라이브러리를 사용하여 Azure 서비스에 Python 앱을 인증하는 방법에 대해 자세히 알아봅니다.
애플리케이션 실행
환경 변수를 VECTOR_ALGORITHM 사용하여 실행할 벡터 인덱스 구현을 선택합니다. 변수는 애플리케이션이 연결하는 Azure Cosmos DB 컨테이너를 제어합니다.
Linux/macOS:
VECTOR_ALGORITHM=diskann python -m src.vector_search
윈도우:
$env:VECTOR_ALGORITHM="diskann"; python -m src.vector_search
앱 로깅 및 출력은 다음을 보여줍니다.
- 컨테이너 연결 상태
- 데이터 삽입 상태
- 호텔 이름 및 유사성 점수가 있는 검색 결과
Connected to database: Hotels
Connected to container: hotels_diskann
📊 Vector Search Algorithm: DiskANN
📏 Distance Function: cosine
Reading JSON file from ..\data\HotelsData_toCosmosDB_Vector.json
Container already has 50 documents. Skipping insert.
--- Executing Vector Search Query ---
Query: SELECT TOP 5 c.HotelName, c.Description, c.Rating, VectorDistance(c.DescriptionVector, @embedding) AS SimilarityScore FROM c ORDER BY VectorDistance(c.DescriptionVector, @embedding)
Parameters: @embedding (vector with 1536 dimensions)
--------------------------------------
Query activity ID: <ACTIVITY_ID>
--- Search Results ---
1. Royal Cottage Resort, Score: 0.4991
2. Country Comfort Inn, Score: 0.4786
3. Nordick's Valley Motel, Score: 0.4635
4. Economy Universe Motel, Score: 0.4461
5. Roach Motel, Score: 0.4388
Vector Search Request Charge: 5.33 RUs
거리 메트릭
Azure Cosmos DB는 벡터 유사성을 위해 세 가지 거리 함수를 지원합니다.
| Distance 함수 | 점수 범위 | 해석 | 적합한 대상 |
|---|---|---|---|
| 코사인 (기본값) | 0.0에서 1.0까지 | 점수가 높을수록(1.0에 가까울수록) 더 큰 유사성을 나타냅니다. | 일반 텍스트 유사성, Azure OpenAI 임베딩(이 퀵스타트 가이드에서 사용) |
| 유클리단 (L2) | 0.0에서 ∞ | 낮을수록 더 유사함 | 공간 데이터( 크기가 중요한 경우) |
| 닷 제품 | -∞에서 +∞까지 | 더 높은 = 더 유사 | 벡터 크기가 정규화된 경우 |
거리 함수는 컨테이너를 만들 때 벡터 포함 정책에 설정됩니다. 이는 샘플 리포지토리의 인프라스트럭처에서 제공됩니다. 컨테이너 정의의 일부로 정의됩니다.
{
name: 'hotels_diskann'
partitionKeyPaths: [
'/HotelId'
]
indexingPolicy: {
indexingMode: 'consistent'
automatic: true
includedPaths: [
{
path: '/*'
}
]
excludedPaths: [
{
path: '/_etag/?'
}
{
path: '/DescriptionVector/*'
}
]
vectorIndexes: [
{
path: '/DescriptionVector'
type: 'diskANN'
}
]
}
vectorEmbeddingPolicy: {
vectorEmbeddings: [
{
path: '/DescriptionVector'
dataType: 'float32'
dimensions: 1536
distanceFunction: 'cosine'
}
]
}
}
이 Bicep 코드는 벡터 검색 기능을 사용하여 호텔 문서를 저장하기 위한 Azure Cosmos DB 컨테이너 구성을 정의합니다.
| 재산 | Description |
|---|---|
partitionKeyPaths |
HotelId을 기준으로 문서를 분할하여 분산 저장합니다. |
indexingPolicy |
쓰기 성능을 최적화하기 위해 시스템 /* 필드와 배열을 제외한 모든 문서 속성(_etag)에서 DescriptionVector 자동 인덱싱을 구성합니다. 벡터 필드는 특수 구성을 대신 사용하기 때문에 표준 인덱싱이 vectorIndexes 필요하지 않습니다. |
vectorIndexes |
효율적인 유사성 검색을 위해 경로에 /DescriptionVector DiskANN 또는 quantizedFlat 인덱스 중 하나를 만듭니다. |
vectorEmbeddingPolicy |
벡터 필드의 특성을 정의합니다: 1536차원의 데이터 유형(float32)는 모델 출력(text-embedding-3-small)과 일치하며 쿼리 수행 시 벡터 간 유사성을 측정하는 거리 함수로 코사인을 사용합니다. |
유사성 점수 해석
예제에서는 코사인 유사성을 사용하여 출력합니다.
- 0.4991 (로얄 코티지 리조트) - 가장 높은 유사성, "달리기 트레일, 식당, 소매 근처 숙박"에 대한 최고의 일치
- 0.4388 (바퀴벌레 모텔) - 유사성이 낮고 관련성이 낮지만 일치하는 항목이 적습니다.
- 1.0에 가까운 점수는 더 강력한 의미 체계 유사성을 나타냅니다.
- 0에 가까운 점수는 유사성이 거의 없음을 나타냅니다.
중요 참고 사항:
- 절대 점수 값은 포함 모델 및 데이터에 따라 달라집니다.
- 절대 임계값이 아닌 상대 순위 에 집중
- Azure OpenAI 임베딩은 코사인 유사성과 가장 잘 작동합니다.
거리 함수에 대한 자세한 내용은 거리 함수란?
Visual Studio Code에서 데이터 보기 및 관리
Visual Studio Code에서 Cosmos DB 확장을 선택하여 Azure Cosmos DB 계정에 연결합니다.
Hotels 데이터베이스에서 데이터 및 인덱스를 봅니다.
자원을 정리하세요
NoSQL 계정에 대한 API가 더 이상 필요하지 않은 경우 해당 리소스 그룹을 삭제할 수 있습니다.