Optimizing vector search using Cohere compressed embeddings
출처: 문서
본문
Cohere 압축 임베딩을 사용한 벡터 검색 최적화하기
이 튜토리얼에서는 Cohere 압축 임베딩을 사용하여 벡터 검색을 최적화하는 방법을 알려줘요. 이러한 임베딩은 벡터 표현을 더 효율적으로 저장하고 더 빠르게 검색할 수 있게 해 주어 대규모 검색 애플리케이션에 이상적이에요.
이 튜토리얼은 버전 2.17 이상과 호환되지만, Step 4: 인덱스 검색의 템플릿 쿼리와 검색 파이프라인 사용은 버전 2.19 이상이 필요해요.
이 튜토리얼은 Amazon Bedrock에서 Cohere Embed Multilingual v3 모델을 사용해요. Amazon Bedrock에서 Cohere 압축 임베딩을 사용하는 방법에 대한 자세한 내용은 이 블로그 게시물을 참조하세요.
이 튜토리얼에서는 다음 OpenSearch 구성 요소를 사용할 거예요:
your_ 접두사로 시작하는 플레이스홀더를 자신의 값으로 바꿔 주세요.
{: .note}
Step 1: 임베딩 모델 구성하기
다음 단계에 따라 Amazon Bedrock에 연결하여 Cohere Embed 모델에 액세스하는 커넥터를 만들어요.
Step 1.1: 커넥터 만들기
이 블루프린트를 사용하여 임베딩 모델용 커넥터를 만들어요. 커넥터 생성에 대한 자세한 내용은 커넥터를 참조하세요.
이 튜토리얼에서는 ML 인퍼런스 프로세서를 사용하기 때문에 커넥터에 전처리나 후처리 함수를 지정할 필요가 없어요. {: .note}
커넥터를 만들려면 다음 요청을 보내세요. "embedding_types": ["int8"] 매개변수는 Cohere 모델의 8비트 정수 양자화 임베딩을 지정해요. 이 설정은 임베딩을 32비트 부동소수점에서 8비트 정수로 압축하여 저장 공간을 줄이고 계산 속도를 향상시켜요. 정밀도가 약간 떨어지지만 검색 작업에서는 일반적으로 무시할 수 있는 수준이에요. 이러한 양자화 임베딩은 바이트 벡터를 지원하는 OpenSearch의 knn_index와 호환돼요:
POST _plugins/_ml/connectors/_create
{
"name": "Amazon Bedrock Connector: Cohere embed-multilingual-v3",
"description": "Test connector for Amazon Bedrock Cohere embed-multilingual-v3",
"version": 1,
"protocol": "aws_sigv4",
"credential": {
"access_key": "your_aws_access_key",
"secret_key": "your_aws_secret_key",
"session_token": "your_aws_session_token"
},
"parameters": {
"region": "your_aws_region",
"service_name": "bedrock",
"truncate": "END",
"input_type": "search_document",
"model": "cohere.embed-multilingual-v3",
"embedding_types": ["int8"]
},
"actions": [
{
"action_type": "predict",
"method": "POST",
"headers": {
"x-amz-content-sha256": "required",
"content-type": "application/json"
},
"url": "https://bedrock-runtime.${parameters.region}.amazonaws.com/model/${parameters.model}/invoke",
"request_body": "{ \"texts\": ${parameters.texts}, \"truncate\": \"${parameters.truncate}\", \"input_type\": \"${parameters.input_type}\", \"embedding_types\": ${parameters.embedding_types} }"
}
]
}
{% include copy-curl.html %}
모델 매개변수에 대한 자세한 내용은 Cohere 문서와 Amazon Bedrock 문서를 참조하세요.
응답에는 커넥터 ID가 포함돼요:
{
"connector_id": "AOP0OZUB3JwAtE25PST0"
}
커넥터 ID를 기록해 두세요. 다음 단계에서 사용할 거예요.
Step 1.2: 모델 등록하기
다음으로, 이전 단계에서 만든 커넥터를 사용하여 모델을 등록해요. interface 매개변수는 선택 사항이에요. 모델에 특정 인터페이스 구성이 필요하지 않으면 이 매개변수를 빈 객체로 설정하세요: "interface": {}
POST _plugins/_ml/models/_register?deploy=true
{
"name": "Bedrock Cohere embed-multilingual-v3",
"version": "1.0",
"function_name": "remote",
"description": "Bedrock Cohere embed-multilingual-v3",
"connector_id": "AOP0OZUB3JwAtE25PST0",
"interface": {
"input": "{\n \"type\": \"object\",\n \"properties\": {\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"texts\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"embedding_types\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\"float\", \"int8\", \"uint8\", \"binary\", \"ubinary\"]\n }\n },\n \"truncate\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\"NONE\", \"START\", \"END\"]\n }\n },\n \"input_type\": {\n \"type\": \"string\",\n \"enum\": [\"search_document\", \"search_query\", \"classification\", \"clustering\"]\n }\n },\n \"required\": [\"texts\"]\n }\n },\n \"required\": [\"parameters\"]\n}",
"output": "{\n \"type\": \"object\",\n \"properties\": {\n \"inference_results\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"output\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"dataAsMap\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"format\": \"uuid\"\n },\n \"texts\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"embeddings\": {\n \"type\": \"object\",\n \"properties\": {\n \"binary\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"number\"\n }\n }\n },\n \"float\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"number\"\n }\n }\n },\n \"int8\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"number\"\n }\n }\n },\n \"ubinary\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"number\"\n }\n }\n },\n \"uint8\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"number\"\n }\n }\n }\n }\n },\n \"response_type\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\"embeddings\"]\n }\n },\n \"required\": [\"name\", \"dataAsMap\"]\n }\n },\n \"status_code\": {\n \"type\": \"integer\"\n }\n },\n \"required\": [\"output\", \"status_code\"]\n }\n }\n },\n \"required\": [\"inference_results\"]\n}"
}
}
{% include copy-curl.html %}
자세한 내용은 모델 인터페이스 문서를 참조하세요.
응답에는 모델 ID가 포함돼요:
{
"task_id": "COP0OZUB3JwAtE25yiQr",
"status": "CREATED",
"model_id": "t64OPpUBX2k07okSZc2n"
}
모델을 테스트하려면 다음 요청을 보내세요:
POST _plugins/_ml/models/t64OPpUBX2k07okSZc2n/_predict
{
"parameters": {
"texts": ["Say this is a test"],
"embedding_types": [ "int8" ]
}
}
{% include copy-curl.html %}
응답에는 생성된 임베딩이 포함돼요:
{
"inference_results": [
{
"output": [
{
"name": "response",
"dataAsMap": {
"id": "db07a08c-283d-4da5-b0c5-a9a54ef35d01",
"texts": [
"Say this is a test"
],
"embeddings": {
"int8": [
[
-26.0,
31.0,
...
]
]
},
"response_type": "embeddings_by_type"
}
}
],
"status_code": 200
}
]
}
Step 2: 수집 파이프라인 만들기
수집 파이프라인을 사용하면 문서를 인덱싱하기 전에 처리할 수 있어요. 여기서는 데이터의 title 및 description 필드에 대한 임베딩을 생성하는 데 사용할 거예요.
파이프라인을 설정하는 두 가지 방법이 있어요:
title과description에 대해 모델을 별도로 호출: 이 옵션은 각 필드에 대해 별도의 요청을 보내 독립적인 임베딩을 생성해요.title과description을 결합하여 모델을 한 번 호출: 이 옵션은 필드를 단일 입력으로 연결하고 하나의 요청을 보내 두 필드를 모두 나타내는 단일 임베딩을 생성해요.
옵션 1: title과 description에 대해 모델을 별도로 호출
PUT _ingest/pipeline/ml_inference_pipeline_cohere
{
"processors": [
{
"ml_inference": {
"tag": "ml_inference",
"description": "This processor is going to run ml inference during ingest request",
"model_id": "t64OPpUBX2k07okSZc2n",
"input_map": [
{
"texts": "$..title"
},
{
"texts": "$..description"
}
],
"output_map": [
{
"title_embedding": "embeddings.int8[0]"
},
{
"description_embedding": "embeddings.int8[0]"
}
],
"model_config": {
"embedding_types": ["int8"]
},
"ignore_failure": false
}
}
]
}
{% include copy-curl.html %}
옵션 2: title과 description을 결합하여 모델을 한 번 호출
PUT _ingest/pipeline/ml_inference_pipeline_cohere
{
"description": "Concatenate title and description fields",
"processors": [
{
"set": {
"field": "title_desc_tmp",
"value": [
"{{title}}",
"{{description}}"
]
}
},
{
"ml_inference": {
"tag": "ml_inference",
"description": "This processor is going to run ml inference during ingest request",
"model_id": "t64OPpUBX2k07okSZc2n",
"input_map": [
{
"texts": "title_desc_tmp"
}
],
"output_map": [
{
"title_embedding": "embeddings.int8[0]",
"description_embedding": "embeddings.int8[1]"
}
],
"model_config": {
"embedding_types": ["int8"]
},
"ignore_failure": true
}
},
{
"remove": {
"field": "title_desc_tmp"
}
}
]
}
{% include copy-curl.html %}
다음 시뮬레이션 요청을 보내 파이프라인을 테스트해요:
POST _ingest/pipeline/ml_inference_pipeline_cohere/_simulate
{
"docs": [
{
"_index": "books",
"_id": "1",
"_source": {
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald",
"description": "A novel of decadence and excess in the Jazz Age, exploring themes of wealth, love, and the American Dream.",
"publication_year": 1925,
"genre": "Classic Fiction"
}
}
]
}
{% include copy-curl.html %}
응답에는 생성된 임베딩이 포함돼요:
{
"docs": [
{
"doc": {
"_index": "books",
"_id": "1",
"_source": {
"publication_year": 1925,
"author": "F. Scott Fitzgerald",
"genre": "Classic Fiction",
"description": "A novel of decadence and excess in the Jazz Age, exploring themes of wealth, love, and the American Dream.",
"title": "The Great Gatsby",
"title_embedding": [
18,
33,
...
],
"description_embedding": [
-21,
-14,
...
]
},
"_ingest": {
"timestamp": "2025-02-25T09:11:32.192125042Z"
}
}
}
]
}
Step 3: 벡터 인덱스 생성 및 데이터 수집
다음으로, 벡터 인덱스를 만들어요:
PUT books
{
"settings": {
"index": {
"default_pipeline": "ml_inference_pipeline_cohere",
"knn": true,
"knn.algo_param.ef_search": 100
}
},
"mappings": {
"properties": {
"title_embedding": {
"type": "knn_vector",
"dimension": 1024,
"data_type": "byte",
"space_type": "l2",
"method": {
"name": "hnsw",
"engine": "lucene",
"parameters": {
"ef_construction": 100,
"m": 16
}
}
},
"description_embedding": {
"type": "knn_vector",
"dimension": 1024,
"data_type": "byte",
"space_type": "l2",
"method": {
"name": "hnsw",
"engine": "lucene",
"parameters": {
"ef_construction": 100,
"m": 16
}
}
}
}
}
}
{% include copy-curl.html %}
인덱스에 테스트 데이터를 수집해요:
POST _bulk
{"index":{"_index":"books"}}
{"title":"The Great Gatsby","author":"F. Scott Fitzgerald","description":"A novel of decadence and excess in the Jazz Age, exploring themes of wealth, love, and the American Dream.","publication_year":1925,"genre":"Classic Fiction"}
{"index":{"_index":"books"}}
{"title":"To Kill a Mockingbird","author":"Harper Lee","description":"A powerful story of racial injustice and loss of innocence in the American South during the Great Depression.","publication_year":1960,"genre":"Literary Fiction"}
{"index":{"_index":"books"}}
{"title":"Pride and Prejudice","author":"Jane Austen","description":"A romantic novel of manners that follows the character development of Elizabeth Bennet as she learns about the repercussions of hasty judgments and comes to appreciate the difference between superficial goodness and actual goodness.","publication_year":1813,"genre":"Romance"}
{% include copy-curl.html %}
Step 4: 인덱스 검색
인덱스에서 벡터 검색을 실행하는 방법은 다음과 같아요:
템플릿 쿼리와 검색 파이프라인 사용
먼저, 검색 파이프라인을 만들어요:
PUT _search/pipeline/ml_inference_pipeline_cohere_search
{
"request_processors": [
{
"ml_inference": {
"model_id": "t64OPpUBX2k07okSZc2n",
"input_map": [
{
"texts": "$..ext.ml_inference.text"
}
],
"output_map": [
{
"ext.ml_inference.vector": "embeddings.int8[0]"
}
],
"model_config": {
"input_type": "search_query",
"embedding_types": ["int8"]
}
}
}
]
}
{% include copy-curl.html %}
다음으로, 템플릿 쿼리를 사용하여 검색을 실행해요:
GET books/_search?search_pipeline=ml_inference_pipeline_cohere_search&verbose_pipeline=false
{
"query": {
"template": {
"knn": {
"description_embedding": {
"vector": "${ext.ml_inference.vector}",
"k": 10
}
}
}
},
"ext": {
"ml_inference": {
"text": "American Dream"
}
},
"_source": {
"excludes": [
"title_embedding", "description_embedding"
]
},
"size": 2
}
{% include copy-curl.html %}
각 검색 프로세서의 입력과 출력을 보려면 요청에 &verbose_pipeline=true를 추가하세요. 이는 검색 파이프라인이 쿼리를 어떻게 수정하는지 디버깅하고 이해하는 데 유용해요. 자세한 내용은 검색 파이프라인 디버깅을 참조하세요.
검색 파이프라인에서 쿼리 다시 작성
쿼리를 다시 작성하는 다른 검색 파이프라인을 만들어요:
PUT _search/pipeline/ml_inference_pipeline_cohere_search2
{
"request_processors": [
{
"ml_inference": {
"model_id": "t64OPpUBX2k07okSZc2n",
"input_map": [
{
"texts": "$..match.description.query"
}
],
"output_map": [
{
"query_vector": "embeddings.int8[0]"
}
],
"model_config": {
"input_type": "search_query",
"embedding_types": ["int8"]
},
"query_template": """
{
"query": {
"knn": {
"description_embedding": {
"vector": ${query_vector},
"k": 10
}
}
},
"_source": {
"excludes": [
"title_embedding",
"description_embedding"
]
},
"size": 2
}
"""
}
}
]
}
{% include copy-curl.html %}
이제 이 파이프라인을 사용하여 벡터 검색을 실행해요:
GET books/_search?search_pipeline=ml_inference_pipeline_cohere_search2
{
"query": {
"match": {
"description": "American Dream"
}
}
}
{% include copy-curl.html %}
응답에는 일치하는 문서가 포함돼요:
{
"took": 96,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": 7.271585e-7,
"hits": [
{
"_index": "books",
"_id": "U640PJUBX2k07okSEMwy",
"_score": 7.271585e-7,
"_source": {
"publication_year": 1925,
"author": "F. Scott Fitzgerald",
"genre": "Classic Fiction",
"description": "A novel of decadence and excess in the Jazz Age, exploring themes of wealth, love, and the American Dream.",
"title": "The Great Gatsby"
}
},
{
"_index": "books",
"_id": "VK40PJUBX2k07okSEMwy",
"_score": 6.773544e-7,
"_source": {
"publication_year": 1960,
"author": "Harper Lee",
"genre": "Literary Fiction",
"description": "A powerful story of racial injustice and loss of innocence in the American South during the Great Depression.",
"title": "To Kill a Mockingbird"
}
}
]
}
}
Step 5 (선택 사항): 바이너리 임베딩 사용
이 섹션에서는 설정을 확장하여 바이너리 임베딩을 지원해요. 바이너리 임베딩은 더 효율적인 저장과 더 빠른 검색을 제공하며, 저장 요구 사항을 크게 줄이고 검색 속도를 향상시켜 대규모 애플리케이션에 이상적이에요.
커넥터나 모델을 수정할 필요는 없어요. 벡터 인덱스, 수집 파이프라인, 검색 파이프라인만 업데이트하면 돼요.
Step 5.1: 수집 파이프라인 만들기
Step 2와 동일한 구성을 사용하되 int8을 모두 binary로 바꿔서 ml_inference_pipeline_cohere_binary라는 새 수집 파이프라인을 만들어요.
옵션 1: title과 description에 대해 모델을 별도로 호출
PUT _ingest/pipeline/ml_inference_pipeline_cohere
{
"processors": [
{
"ml_inference": {
"tag": "ml_inference",
"description": "This processor is going to run ml inference during ingest request",
"model_id": "t64OPpUBX2k07okSZc2n",
"input_map": [
{
"texts": "$..title"
},
{
"texts": "$..description"
}
],
"output_map": [
{
"title_embedding": "embeddings.binary[0]"
},
{
"description_embedding": "embeddings.binary[0]"
}
],
"model_config": {
"embedding_types": ["binary"]
},
"ignore_failure": false
}
}
]
}
{% include copy-curl.html %}
옵션 2: title과 description을 결합하여 모델을 한 번 호출
PUT _ingest/pipeline/ml_inference_pipeline_cohere
{
"description": "Concatenate title and description fields",
"processors": [
{
"set": {
"field": "title_desc_tmp",
"value": [
"{{title}}",
"{{description}}"
]
}
},
{
"ml_inference": {
"tag": "ml_inference",
"description": "This processor is going to run ml inference during ingest request",
"model_id": "t64OPpUBX2k07okSZc2n",
"input_map": [
{
"texts": "title_desc_tmp"
}
],
"output_map": [
{
"title_embedding": "embeddings.binary[0]",
"description_embedding": "embeddings.binary[1]"
}
],
"model_config": {
"embedding_types": ["binary"]
},
"ignore_failure": true
}
},
{
"remove": {
"field": "title_desc_tmp"
}
}
]
}
{% include copy-curl.html %}
Step 5.2: 벡터 인덱스 생성 및 데이터 수집
바이너리 벡터 필드를 포함하는 새 벡터 인덱스를 만들어요:
PUT books_binary_embedding
{
"settings": {
"index": {
"default_pipeline": "ml_inference_pipeline_cohere_binary",
"knn": true
}
},
"mappings": {
"properties": {
"title_embedding": {
"type": "knn_vector",
"dimension": 1024,
"data_type": "binary",
"space_type": "hamming",
"method": {
"name": "hnsw",
"engine": "faiss"
}
},
"description_embedding": {
"type": "knn_vector",
"dimension": 1024,
"data_type": "binary",
"space_type": "hamming",
"method": {
"name": "hnsw",
"engine": "faiss"
}
}
}
}
}
{% include copy-curl.html %}
인덱스에 테스트 데이터를 수집해요:
POST _bulk
{"index":{"_index":"books_binary_embedding"}}
{"title":"The Great Gatsby","author":"F. Scott Fitzgerald","description":"A novel of decadence and excess in the Jazz Age, exploring themes of wealth, love, and the American Dream.","publication_year":1925,"genre":"Classic Fiction"}
{"index":{"_index":"books_binary_embedding"}}
{"title":"To Kill a Mockingbird","author":"Harper Lee","description":"A powerful story of racial injustice and loss of innocence in the American South during the Great Depression.","publication_year":1960,"genre":"Literary Fiction"}
{"index":{"_index":"books_binary_embedding"}}
{"title":"Pride and Prejudice","author":"Jane Austen","description":"A romantic novel of manners that follows the character development of Elizabeth Bennet as she learns about the repercussions of hasty judgments and comes to appreciate the difference between superficial goodness and actual goodness.","publication_year":1813,"genre":"Romance"}
{% include copy-curl.html %}
Step 5.3: 검색 파이프라인 만들기
Step 2와 동일한 구성을 사용하되 int8을 모두 binary로 바꿔서 ml_inference_pipeline_cohere_search_binary라는 새 검색 파이프라인을 만들어요.
embeddings.int8[0]를embeddings.binary[0]로 바꾸세요."embedding_types": ["int8"]를"embedding_types": ["binary"]로 바꾸세요.
템플릿 쿼리와 검색 파이프라인 사용
먼저, 검색 파이프라인을 만들어요:
PUT _search/pipeline/ml_inference_pipeline_cohere_search_binary
{
"request_processors": [
{
"ml_inference": {
"model_id": "t64OPpUBX2k07okSZc2n",
"input_map": [
{
"texts": "$..ext.ml_inference.text"
}
],
"output_map": [
{
"ext.ml_inference.vector": "embeddings.binary[0]"
}
],
"model_config": {
"input_type": "search_query",
"embedding_types": ["binary"]
}
}
}
]
}
{% include copy-curl.html %}
검색 파이프라인에서 쿼리 다시 작성
쿼리를 다시 작성하는 다른 검색 파이프라인을 만들어요:
PUT _search/pipeline/ml_inference_pipeline_cohere_search_binary2
{
"request_processors": [
{
"ml_inference": {
"model_id": "t64OPpUBX2k07okSZc2n",
"input_map": [
{
"texts": "$..match.description.query"
}
],
"output_map": [
{
"query_vector": "embeddings.binary[0]"
}
],
"model_config": {
"input_type": "search_query",
"embedding_types": ["binary"]
},
"query_template": """
{
"query": {
"knn": {
"description_embedding": {
"vector": ${query_vector},
"k": 10
}
}
},
"_source": {
"excludes": [
"title_embedding",
"description_embedding"
]
},
"size": 2
}
"""
}
}
]
}
{% include copy-curl.html %}
그런 다음 Step 4에 설명된 대로 검색 파이프라인을 사용하여 벡터 검색을 실행할 수 있어요.