밀접 vs 희소 파이프라인
원본 보기튜토리얼: 인제스트 파이프라인을 사용하는 밀집 및 희소 워크플로
- Elastic Stack에서 시맨틱 검색을 수행하는 가장 쉬운 방법은
semantic_text엔드투엔드 튜토리얼을 참고하세요. - 이 튜토리얼은 inference 엔드포인트와
semantic_text필드 타입보다 먼저 작성되었습니다. 현재는 이 튜토리얼에서 설명하는 방식보다 더 간단하고 상위 수준의 시맨틱 검색 옵션이 있습니다. 대부분의 사용 사례에서는 semantic text 워크플로가 시맨틱 검색을 수행하는 권장 방식입니다.
이 가이드는 배포된 NLP 모델을 사용해 Elasticsearch에서 시맨틱 검색을 구현하는 방법을 모델 선택부터 인제스트 파이프라인 구성, 쿼리 실행까지 보여줍니다.
Elasticsearch는 밀집 및 희소 벡터 모델을 포함해 다양한 NLP 모델을 지원합니다. 좋은 관련성을 얻으려면 올바른 모델을 선택하는 것이 매우 중요합니다.
직접 만든 텍스트 임베딩 모델을 가져올 수도 있지만, 좋은 결과를 얻으려면 대개 튜닝과 평가가 필요합니다. 목록에서 성능이 검증된 서드파티 모델을 선택하는 것이 좋은 출발점입니다. BM25만 사용하는 것보다 더 나은 검색 결과를 얻으려면 자체 데이터로 모델을 학습시키는 것이 필수적입니다. 하지만 모델 학습 과정에는 데이터 과학자와 ML 전문가로 구성된 팀이 필요하므로 비용과 시간이 많이 듭니다.
밀집 임베딩과 희소 임베딩은 텍스트를 서로 다르게 표현하며, 각 방식은 서로 다른 검색 목표에 적합합니다. 다음 예시는 일반적인 선택 기준을 보여줍니다.
키워드 방식 검색 위에 의미 확장을 더하고 싶다면 희소 임베딩을 사용하세요. ELSER 같은 희소 모델은 쿼리와 문서를 가중치가 부여된 용어로 확장하므로, 사용자가 짧은 구문, 약어, 도메인 어휘로 검색할 때 도움이 됩니다. 희소 벡터는 대부분의 값이 0이고 소수의 토큰 가중치만 0이 아닌 고차원 벡터입니다.
일반적인 사용 사례는 다음과 같습니다.
- 업무 및 IT 검색: 사용자가 오류 코드, 서비스 이름, 팀별 전문 용어로 검색할 때 런북, 티켓, 사내 위키를 찾습니다.
- 보안 및 옵저버빌리티: 기술 용어와 자연어가 섞인 분석가 쿼리에서 관련 알림, 플레이북, 탐지 규칙을 찾아냅니다.
- 지원 및 셀프서비스: 쿼리에 문서에 그대로 등장하지 않는 제품 용어가 사용된 경우에도 고객 질문을 도움말 문서와 매칭합니다.
설명 가능한 결과가 필요하거나, 커스텀 모델을 학습시키지 않고도 영어 텍스트에서 강력한 관련성이 필요하거나, 전담 머신러닝 팀 없이 대규모 시맨틱 검색이 필요한 경우 희소 임베딩이 현실적인 기본 선택지입니다.
자세한 내용은 Elasticsearch의 희소 벡터 검색을 참고하세요.
겹치는 키워드가 아니라 벡터 공간에서의 전체적인 의미로 콘텐츠를 매칭하고 싶다면 밀집 임베딩을 사용하세요. 밀집 모델은 텍스트(및 기타 콘텐츠 유형)를 고정 길이 벡터로 매핑하여 개념적으로 유사한 항목이 서로 가깝게 위치하도록 합니다. 밀집 벡터는 임베딩 모델이 생성한 부동소수점 값의 조밀한 배열입니다.
일반적인 사용 사례는 다음과 같습니다.
- AI 에이전트를 위한 컨텍스트 엔지니어링: 검색, 도구, 지시문을 결합해 응답이 사용자의 데이터에 근거하도록 합니다. Agent Builder는 이 워크플로를 위한 즉시 사용 가능한 툴킷을 제공합니다.
- 검색 증강 생성(RAG): 질문과 원문이 서로 다른 단어를 사용하더라도 사용자의 질문에 답이 되는 문서 구절을 검색합니다.
- 자연어 Q&A: "비밀번호를 어떻게 재설정하나요?" 같은 질문을 FAQ 항목, 제품 문서, 정책 페이지와 매칭합니다.
- 추천 및 유사도: 관련 기사, 제품, 미디어를 찾습니다. 예를 들어 현재 보고 있는 기사와 비슷한 기사나 시각적으로 유사한 제품 이미지를 노출할 수 있습니다.
밀집 임베딩은 정확한 키워드 일치보다 검색어의 의미가 더 중요할 때 이상적입니다. 원본 쿼리의 동의어와 다른 표현을 기반으로 관련성 높은 결과를 검색해 사용자의 의도를 반영한 결과를 반환하는 데 뛰어납니다.
자세한 내용은 Elasticsearch의 밀집 벡터 검색을 참고하세요.
모델을 선택한 후에는 Elasticsearch에 배포합니다.
ELSER를 배포하려면 ELSER 다운로드 및 배포를 참고하세요.
서드파티 텍스트 임베딩 모델을 배포하려면 텍스트 임베딩 모델 배포를 참고하세요.
임베딩을 생성하기 전에 인덱스 매핑을 준비하세요. 매핑은 희소(ELSER) 모델을 사용하는지 밀집 모델을 사용하는지에 따라 달라집니다.
ELSER는 토큰-가중치 쌍을 출력합니다. 이를 저장하려면 sparse_vector 필드를 사용하세요.
ELSER 인덱스의 매핑을 생성하려면 튜토리얼의 인덱스 매핑 생성 섹션을 참고하세요.
토큰용 sparse_vector 필드와 원본 콘텐츠용 text 필드를 포함하는 매핑을 생성합니다. 예를 들면 다음과 같습니다.
PUT my-index
{
"mappings": {
"properties": {
"my_tokens": {
"type": "sparse_vector"
},
"my_text_field": {
"type": "text"
}
}
}
}
- ELSER가 생성한 토큰이 저장될 필드입니다.
- 토큰을 저장하는 필드는 반드시
sparse_vector필드여야 합니다. - 희소 벡터 표현을 만드는 데 사용되는 원본 필드입니다. 이 예시에서 필드 이름은
my_text_field입니다. - 이 예시에서 필드 타입은
text입니다.
밀집 벡터 모델은 숫자 임베딩을 출력합니다. 선택한 지원 서드파티 모델이 생성하는 밀집 벡터를 저장하려면 dense_vector 필드 타입을 사용하세요. 모델은 특정한 차원 수의 임베딩을 생성한다는 점에 유의하세요. dense_vector 필드는 dims 옵션으로 동일한 차원 수를 설정해야 합니다. 임베딩의 차원 수는 해당 모델 문서를 참고하세요.
NLP 모델용 인덱스 매핑을 확인하려면 관련 튜토리얼의 인제스트 추론 파이프라인에 텍스트 임베딩 모델 추가 섹션에 있는 매핑 코드 스니펫을 참고하세요. 이 예시는 모델 출력이 저장될 my_embeddings.predicted_value 필드를 dense_vector 필드로 정의하는 인덱스 매핑을 생성하는 방법을 보여줍니다.
PUT my-index
{
"mappings": {
"properties": {
"my_embeddings.predicted_value": {
"type": "dense_vector",
"dims": 384
},
"my_text_field": {
"type": "text"
}
}
}
}
- 모델이 생성한 임베딩이 저장될 필드의 이름입니다.
- 임베딩을 저장하는 필드는 반드시
dense_vector필드여야 합니다. - 모델은 특정한 차원 수의 임베딩을 생성합니다.
dense_vector필드는dims옵션으로 동일한 차원 수를 설정해야 합니다. 임베딩의 차원 수는 해당 모델 문서를 참고하세요. - 밀집 벡터 표현을 만드는 데 사용되는 원본 필드입니다. 이 예시에서 필드 이름은
my_text_field입니다. - 이 예시에서 필드 타입은
text입니다.
인제스트 시점에 임베딩을 생성하려면 inference 프로세서가 포함된 인제스트 파이프라인을 사용하세요. 인제스트 파이프라인은 입력 데이터를 처리해 대상 인덱스에 색인합니다. 색인 시점에 inference 인제스트 프로세서는 학습된 모델을 사용해 파이프라인을 통해 인제스트된 데이터에 대해 추론을 수행합니다. inference 프로세서가 포함된 인제스트 파이프라인을 생성한 후에는 이 파이프라인을 통해 데이터를 인제스트하여 모델 출력을 생성할 수 있습니다.
ELSER 모델을 사용하는 인제스트 파이프라인은 다음과 같이 생성합니다.
PUT _ingest/pipeline/my-text-embeddings-pipeline
{
"description": "Text embedding pipeline",
"processors": [
{
"inference": {
"model_id": ".elser_model_2",
"input_output": [
{
"input_field": "my_text_field",
"output_field": "my_tokens"
}
]
}
}
]
}
- 추론 과정의
input_field와 추론 결과가 저장될output_field를 정의하는 구성 객체입니다.
파이프라인을 통해 데이터를 인제스트하여 ELSER로 토큰을 생성하려면 튜토리얼의 inference 인제스트 파이프라인을 통한 데이터 인제스트 섹션을 참고하세요. 파이프라인으로 문서를 성공적으로 인제스트하면 인덱스에는 ELSER가 생성한 토큰이 저장됩니다. 토큰은 관련성을 포착하는 학습된 연관 관계이며 동의어가 아닙니다. 토큰이 무엇인지 자세히 알아보려면 이 페이지를 참고하세요.
텍스트 임베딩 모델을 사용하는 인제스트 파이프라인 예시입니다.
PUT _ingest/pipeline/my-text-embeddings-pipeline
{
"description": "Text embedding pipeline",
"processors": [
{
"inference": {
"model_id": "sentence-transformers__msmarco-minilm-l-12-v3",
"target_field": "my_embeddings",
"field_map": {
"my_text_field": "text_field"
}
}
}
]
}
- 사용하려는 텍스트 임베딩 모델의 모델 ID입니다.
field_map객체는 입력 문서의 필드 이름(이 예시에서는my_text_field)을 모델이 기대하는 필드 이름(항상text_field)에 매핑합니다.
파이프라인을 통해 데이터를 인제스트하여 선택한 모델로 텍스트 임베딩을 생성하려면 inference 인제스트 파이프라인에 텍스트 임베딩 모델 추가 섹션을 참고하세요. 이 예시는 inference 프로세서로 파이프라인을 생성하고 해당 파이프라인을 통해 데이터를 재색인하는 방법을 보여줍니다. 파이프라인으로 문서를 성공적으로 인제스트하면 인덱스에는 모델이 생성한 텍스트 임베딩이 저장됩니다.
이제 시맨틱 검색을 수행할 차례입니다.
배포한 모델 유형에 따라 희소 벡터 쿼리로 랭크 피처를 조회하거나, kNN 검색으로 밀집 벡터를 조회할 수 있습니다.
ELSER 텍스트 임베딩은 희소 벡터 쿼리로 조회할 수 있습니다. 희소 벡터 쿼리에서는 사용하려는 NLP 모델과 연결된 inference ID와 쿼리 텍스트를 제공하여 희소 벡터 필드를 조회할 수 있습니다.
GET my-index/_search
{
"query":{
"sparse_vector": {
"field": "my_tokens",
"inference_id": "my-elser-endpoint",
"query": "the query string"
}
}
}
밀집 벡터 모델이 생성한 텍스트 임베딩은 kNN 검색으로 조회할 수 있습니다. knn 절에는 밀집 벡터 필드의 이름과, 모델 ID 및 쿼리 텍스트를 담은 query_vector_builder 절을 제공합니다.
GET my-index/_search
{
"knn": {
"field": "my_embeddings.predicted_value",
"k": 10,
"num_candidates": 100,
"query_vector_builder": {
"text_embedding": {
"model_id": "sentence-transformers__msmarco-minilm-l-12-v3",
"model_text": "the query string"
}
}
}
}
어떤 상황에서는 어휘 검색이 시맨틱 검색보다 더 나은 성능을 낼 수 있습니다. 예를 들어 단일 단어나 제품 번호 같은 ID를 검색할 때가 그렇습니다.
상호 순위 융합(reciprocal rank fusion)을 사용해 시맨틱 검색과 어휘 검색을 하나의 하이브리드 검색 요청으로 결합하면 두 방식의 장점을 모두 얻을 수 있습니다. 그뿐 아니라 상호 순위 융합을 사용한 하이브리드 검색은 일반적으로 더 좋은 성능을 보이는 것으로 나타났습니다.
시맨틱 쿼리와 어휘 쿼리 간의 하이브리드 검색은 검색 요청에 rrf retriever를 포함하여 구현할 수 있습니다. rrf retriever의 standard retriever로 sparse_vector 쿼리와 전문 검색 쿼리를 제공하세요. rrf retriever는 상호 순위 융합을 사용해 상위 문서의 순위를 매깁니다.
GET my-index/_search
{
"retriever": {
"rrf": {
"retrievers": [
{
"standard": {
"query": {
"match": {
"my_text_field": "the query string"
}
}
}
},
{
"standard": {
"query": {
"sparse_vector": {
"field": "my_tokens",
"inference_id": "my-elser-endpoint",
"query": "the query string"
}
}
}
}
]
}
}
}
시맨틱 쿼리와 어휘 쿼리 간의 하이브리드 검색은 다음을 제공하여 구현할 수 있습니다.
- 상호 순위 융합으로 상위 문서의 순위를 매기는
rrfretriever - 전문 검색 쿼리를 담은
query절이 있는 하위 retriever로서의standardretriever - 밀집 벡터 필드를 조회하는 kNN 검색을 수행하는 하위 retriever로서의
knnretriever
GET my-index/_search
{
"retriever": {
"rrf": {
"retrievers": [
{
"standard": {
"query": {
"match": {
"my_text_field": "the query string"
}
}
}
},
{
"knn": {
"field": "text_embedding.predicted_value",
"k": 10,
"num_candidates": 100,
"query_vector_builder": {
"text_embedding": {
"model_id": "sentence-transformers__msmarco-minilm-l-12-v3",
"model_text": "the query string"
}
}
}
}
]
}
}
}