본문 바로가기
WIKI 기술 지식 베이스

Using custom configurations for neural sparse search

원문 보기 위키 갱신

출처: 문서

본문

neural sparse 검색에 사용자 지정 구성 사용하기

자동으로 생성된 벡터 임베딩을 사용하는 neural sparse 검색은 doc-only와 bi-encoder 두 가지 모드로 동작해요. 자세한 내용은 스파스 벡터 임베딩 자동 생성하기를 참조하세요.

쿼리 시점에는 다음과 같은 방법으로 사용자 지정 모델을 사용할 수 있어요.

  • Bi-encoder 모드: 배포한 sparse encoding 모델을 사용해 쿼리 텍스트로부터 임베딩을 생성해요. 이때는 수집 시점에 사용한 것과 동일한 모델이어야 해요.

  • 사용자 지정 토크나이저를 사용하는 doc-only 모드: 배포한 토크나이저 모델을 사용해 쿼리 텍스트를 토큰화해요. 토큰 가중치는 미리 계산된 룩업 테이블에서 가져와요.

다음은 neural sparse 검색에 사용자 지정 모델을 사용하는 전체 예제예요.

1단계: sparse encoding 모델/토크나이저 구성하기

bi-encoder 모드와 사용자 지정 토크나이저를 사용하는 doc-only 모드, 두 모드 모두에서 수집에 사용할 sparse encoding 모델을 구성해야 해요. bi-encoder 모드는 검색에도 같은 모델을 사용하고, doc-only 모드는 검색에 별도의 토크나이저를 사용해요.

1(a)단계: 검색 모드 선택하기

검색 모드와 적절한 모델/토크나이저 조합을 선택하세요:

  • Bi-encoder: 수집과 검색 모두에서 amazon/neural-sparse/opensearch-neural-sparse-encoding-v2-distill 모델을 사용해요.

  • 사용자 지정 토크나이저를 사용하는 Doc-only: 수집 시에는 amazon/neural-sparse/opensearch-neural-sparse-encoding-doc-v3-distill 모델을, 검색 시에는 amazon/neural-sparse/opensearch-neural-sparse-tokenizer-v1 토크나이저를 사용해요.

다음 표는 두 검색 모드의 사용 가능한 모든 조합에 대한 검색 관련성을 비교한 것이니, 사용 사례에 가장 적합한 조합을 선택할 때 참고하세요.

영어 모델

모드 수집 모델 검색 모델 BEIR 평균 검색 관련성 모델 파라미터
Doc-only amazon/neural-sparse/opensearch-neural-sparse-encoding-doc-v1 amazon/neural-sparse/opensearch-neural-sparse-tokenizer-v1 0.49 133M
Doc-only amazon/neural-sparse/opensearch-neural-sparse-encoding-doc-v2-distill amazon/neural-sparse/opensearch-neural-sparse-tokenizer-v1 0.504 67M
Doc-only amazon/neural-sparse/opensearch-neural-sparse-encoding-doc-v2-mini amazon/neural-sparse/opensearch-neural-sparse-tokenizer-v1 0.497 23M
Doc-only amazon/neural-sparse/opensearch-neural-sparse-encoding-doc-v3-distill amazon/neural-sparse/opensearch-neural-sparse-tokenizer-v1 0.517 67M
Doc-only amazon/neural-sparse/opensearch-neural-sparse-encoding-doc-v3-gte amazon/neural-sparse/opensearch-neural-sparse-tokenizer-v1 0.546 133M
Bi-encoder amazon/neural-sparse/opensearch-neural-sparse-encoding-v1 amazon/neural-sparse/opensearch-neural-sparse-encoding-v1 0.524 133M
Bi-encoder amazon/neural-sparse/opensearch-neural-sparse-encoding-v2-distill amazon/neural-sparse/opensearch-neural-sparse-encoding-v2-distill 0.528 67M

다국어 모델

모드 수집 모델 검색 모델 MIRACL 평균 검색 관련성 모델 파라미터
Doc-only amazon/neural-sparse/opensearch-neural-sparse-encoding-multilingual-v1 amazon/neural-sparse/opensearch-neural-sparse-tokenizer-multilingual-v1 0.629 168M

1(b)단계: 모델/토크나이저 등록하기

두 모드 모두 sparse encoding 모델을 등록해야 해요. 사용자 지정 토크나이저를 사용하는 doc-only 모드에서는 sparse encoding 모델 외에 사용자 지정 토크나이저도 등록해야 해요.

Bi-encoder 모드

bi-encoder 모드를 사용할 때는 amazon/neural-sparse/opensearch-neural-sparse-encoding-v2-distill 모델만 등록하면 돼요.

sparse encoding 모델을 등록하세요:

POST /_plugins/_ml/models/_register?deploy=true
{
  "name": "amazon/neural-sparse/opensearch-neural-sparse-encoding-v2-distill",
  "version": "1.0.0",
  "model_format": "TORCH_SCRIPT"
}

{% include copy-curl.html %}

모델 등록은 비동기 작업이에요. OpenSearch는 등록하는 모델마다 작업 ID를 반환해요:

{
  "task_id": "aFeif4oB5Vm0Tdw8yoN7",
  "status": "CREATED"
}

Get ML Task API를 호출하면 작업 상태를 확인할 수 있어요:

GET /_plugins/_ml/tasks/aFeif4oB5Vm0Tdw8yoN7

{% include copy-curl.html %}

작업이 완료되면 작업 상태가 COMPLETED로 바뀌고, ML Tasks API 응답에 등록된 모델의 모델 ID가 포함돼요:

{
  "model_id": "<bi-encoder model ID>",
  "task_type": "REGISTER_MODEL",
  "function_name": "SPARSE_ENCODING",
  "state": "COMPLETED",
  "worker_node": [
    "4p6FVOmJRtu3wehDD74hzQ"
  ],
  "create_time": 1694358489722,
  "last_update_time": 1694358499139,
  "is_async": true
}

생성한 모델의 model_id를 기록해 두세요. 이후 단계에서 필요해요.

사용자 지정 토크나이저를 사용하는 doc-only 모드

사용자 지정 토크나이저를 사용하는 doc-only 모드에서는 수집 시점에 사용할 amazon/neural-sparse/opensearch-neural-sparse-encoding-doc-v3-distill 모델과 검색 시점에 사용할 amazon/neural-sparse/opensearch-neural-sparse-tokenizer-v1 토크나이저를 등록해야 해요.

sparse encoding 모델을 등록하세요:

POST /_plugins/_ml/models/_register?deploy=true
{
  "name": "amazon/neural-sparse/opensearch-neural-sparse-encoding-doc-v3-distill",
  "version": "1.0.0",
  "model_format": "TORCH_SCRIPT"
}

{% include copy-curl.html %}

토크나이저를 등록하세요:

POST /_plugins/_ml/models/_register?deploy=true
{
  "name": "amazon/neural-sparse/opensearch-neural-sparse-tokenizer-v1",
  "version": "1.0.1",
  "model_format": "TORCH_SCRIPT"
}

{% include copy-curl.html %}

bi-encoder 모드와 마찬가지로 Get ML Task API를 사용해 등록 작업 상태를 확인하세요. ML Tasks API 응답이 오면 작업 상태가 COMPLETED로 바뀌어요. 생성한 모델과 토크나이저의 model_id를 기록해 두세요. 이후 단계에서 필요해요.

2단계: 데이터 수집하기

bi-encoder 모드와 doc-only 모드 모두 수집 시점에 sparse encoding 모델을 사용해 스파스 벡터 임베딩을 생성해요.

2(a)단계: ingest 파이프라인 만들기

스파스 벡터 임베딩을 생성하려면 문서 필드의 텍스트를 벡터 임베딩으로 변환하는 sparse_encoding 프로세서가 포함된 ingest 파이프라인을 만들어야 해요. 프로세서의 field_map은 벡터 임베딩을 생성할 입력 필드와 임베딩을 저장할 출력 필드를 결정해요.

다음 예제 요청은 passage_text의 텍스트가 스파스 벡터 임베딩으로 변환되어 passage_embedding에 저장되는 ingest 파이프라인을 만들어요. 요청에 등록한 모델의 모델 ID를 입력하세요:

PUT /_ingest/pipeline/nlp-ingest-pipeline-sparse
{
  "description": "An sparse encoding ingest pipeline",
  "processors": [
    {
      "sparse_encoding": {
        "model_id": "<bi-encoder or doc-only model ID>",
        "prune_type": "max_ratio",
        "prune_ratio": 0.1,
        "field_map": {
          "passage_text": "passage_embedding"
        }
      }
    }
  ]
}

{% include copy-curl.html %}

긴 텍스트를 여러 passage로 나누려면 sparse_encoding 프로세서 앞에 text_chunking ingest 프로세서를 사용하세요. 자세한 내용은 Text chunking을 참조하세요.

2(b)단계: 수집용 인덱스 만들기

파이프라인에 정의한 sparse encoding 프로세서를 사용하려면 rank features 인덱스를 만들고, 이전 단계에서 만든 파이프라인을 기본 파이프라인으로 추가해야 해요. field_map에 정의된 필드가 올바른 타입으로 매핑되어 있는지 확인하세요. 예제를 이어서 보면, passage_embedding 필드는 rank_features로 매핑해야 해요. 마찬가지로 passage_text 필드는 text로 매핑해야 해요.

다음 예제 요청은 기본 ingest 파이프라인으로 구성된 rank features 인덱스를 만들어요:

PUT /my-nlp-index
{
  "settings": {
    "default_pipeline": "nlp-ingest-pipeline-sparse"
  },
  "mappings": {
    "properties": {
      "id": {
        "type": "text"
      },
      "passage_embedding": {
        "type": "rank_features"
      },
      "passage_text": {
        "type": "text"
      }
    }
  }
}

{% include copy-curl.html %}

디스크 공간을 절약하려면 다음과 같이 소스에서 임베딩 벡터를 제외할 수 있어요:

PUT /my-nlp-index
{
  "settings": {
    "default_pipeline": "nlp-ingest-pipeline-sparse"
  },
  "mappings": {
    "_source": {
      "excludes": [
        "passage_embedding"
      ]
    },
    "properties": {
      "id": {
        "type": "text"
      },
      "passage_embedding": {
        "type": "rank_features"
      },
      "passage_text": {
        "type": "text"
      }
    }
  }
}

{% include copy-curl.html %}

<token, weight> 쌍이 소스에서 제외되면 다시 복구할 수 없어요. 이 최적화를 적용하기 전에 애플리케이션에서 <token, weight> 쌍이 필요하지 않은지 확인하세요. {: .important}

2(c)단계: 인덱스에 문서 수집하기

이전 단계에서 만든 인덱스에 문서를 수집하려면 다음 요청을 보내세요:

PUT /my-nlp-index/_doc/1
{
  "passage_text": "Hello world",
  "id": "s1"
}

{% include copy-curl.html %}

PUT /my-nlp-index/_doc/2
{
  "passage_text": "Hi planet",
  "id": "s2"
}

{% include copy-curl.html %}

문서가 인덱스에 수집되기 전에 ingest 파이프라인이 문서에 sparse_encoding 프로세서를 실행해 passage_text 필드의 벡터 임베딩을 생성해요. 색인된 문서에는 원본 텍스트가 담긴 passage_text 필드와 벡터 임베딩이 담긴 passage_embedding 필드가 포함돼요.

3단계: 데이터 검색하기

인덱스에서 neural sparse 검색을 수행하려면 Query DSL 쿼리에서 neural_sparse 쿼리 절을 사용하세요.

다음 예제 요청은 neural_sparse 쿼리를 사용해 원문 텍스트 쿼리로 관련 문서를 검색해요. bi-encoder 모드에서는 모델 ID를, 사용자 지정 토크나이저를 사용하는 doc-only 모드에서는 토크나이저 ID를 입력하세요:

GET my-nlp-index/_search
{
  "query": {
    "neural_sparse": {
      "passage_embedding": {
        "query_text": "Hi world",
        "model_id": "<bi-encoder or tokenizer ID>"
      }
    }
  }
}

{% include copy-curl.html %}

응답에는 일치하는 문서가 포함되어 있어요:

{
  "took" : 688,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 30.0029,
    "hits" : [
      {
        "_index" : "my-nlp-index",
        "_id" : "1",
        "_score" : 30.0029,
        "_source" : {
          "passage_text" : "Hello world",
          "passage_embedding" : {
            "!" : 0.8708904,
            "door" : 0.8587369,
            "hi" : 2.3929274,
            "worlds" : 2.7839446,
            "yes" : 0.75845814,
            "##world" : 2.5432441,
            "born" : 0.2682308,
            "nothing" : 0.8625516,
            "goodbye" : 0.17146169,
            "greeting" : 0.96817183,
            "birth" : 1.2788506,
            "come" : 0.1623208,
            "global" : 0.4371151,
            "it" : 0.42951578,
            "life" : 1.5750692,
            "thanks" : 0.26481047,
            "world" : 4.7300377,
            "tiny" : 0.5462298,
            "earth" : 2.6555297,
            "universe" : 2.0308156,
            "worldwide" : 1.3903781,
            "hello" : 6.696973,
            "so" : 0.20279501,
            "?" : 0.67785245
          },
          "id" : "s1"
        }
      },
      {
        "_index" : "my-nlp-index",
        "_id" : "2",
        "_score" : 16.480486,
        "_source" : {
          "passage_text" : "Hi planet",
          "passage_embedding" : {
            "hi" : 4.338913,
            "planets" : 2.7755864,
            "planet" : 5.0969057,
            "mars" : 1.7405145,
            "earth" : 2.6087382,
            "hello" : 3.3210192
          },
          "id" : "s2"
        }
      }
    ]
  }
}

검색용 기본 모델 구성하기

사용자 지정 모델을 사용할 때는 인덱스 수준에서 기본 모델 ID를 구성해 쿼리를 단순화할 수 있어요. 이렇게 하면 매 쿼리마다 model_id를 지정할 필요가 없어요.

먼저 neural_query_enricher 프로세서가 포함된 search 파이프라인을 만드세요:

PUT /_search/pipeline/neural_search_pipeline
{
  "request_processors": [
    {
      "neural_query_enricher" : {
        "default_model_id": "<bi-encoder model/tokenizer ID>"
      }
    }
  ]
}

{% include copy-curl.html %}

그다음 이 파이프라인을 인덱스의 기본 파이프라인으로 설정하세요:

PUT /my-nlp-index/_settings 
{
  "index.search.default_pipeline" : "neural_search_pipeline"
}

{% include copy-curl.html %}

기본 모델을 구성하고 나면 쿼리를 실행할 때 model_id를 생략할 수 있어요.

인덱스에 기본 모델을 설정하는 방법, 또는 특정 필드에 기본 모델을 설정하는 방법에 대한 자세한 내용은 인덱스 또는 필드에 기본 모델 설정하기를 참조하세요.

다음 단계

  • 튜토리얼을 살펴보고 AI 검색 애플리케이션을 만드는 방법을 알아보세요.

더 알아보기 (Learn more)