Serverless Operations, inc

>_cd /blog/id_nfchr7n_v

title

OpenSearch の様々な検索 (3) : ハイブリッド検索を試してみる

第三回目はハイブリッド検索を試してみます。

ハイブリッド検索は、従来のキーワード検索と、このブログで見てきた意味的検索(ベクトル検索/ニューラル検索など) を組み合わせて利用する方式です。
キーワードが直接含まれる文の精度/解釈性と、意味や文脈を理解して類似度で拾うベクトル検索の柔軟性、双方の良さを取ることを目的としています

内部的にはキーワード検索とニューラル検索がそれぞれ行われ、正規化→結合→最終ランキング、として結果が結合されて戻されます。

normalization プロセッサ

キーワード検索とニューラル検索では、検索結果の一致度合いの指標が異なります。前者は検索に用いたキーワードの出現頻度や重要度どれほど含まれているかをスコア化し、ニューラル検索では検索に用いたベクトルの類似度(コサイン類似度、ユークリッド距離など)をスコア化し、どれほど類似しているか、をもとに結果が出力されます。

この2つの結果を結合するためにはその指標をそろえる必要があります。これを normalization と言います。検索用パイプラインを作成し、検索時にnormalization プロセッサが呼び出される用に設定を行うことで、2つの検索結果が結合されて出力されます。

さっそくやってみる

まずは前回の記事、OpenSearch の様々な検索 (2) : セマンティック検索 / ニューラル検索を試してみるを終わらせておきます。

検索パイプラインの作成

検索時にnormalizationプロセッサが起動されるように検索パイプラインを作成します。

PUT /_search/pipeline/nlp-search-pipeline
{
  "description": "Post processor for hybrid search",
  "phase_results_processors": [
    {
      "normalization-processor": {
        "normalization": {
          "technique": "min_max"
        },
        "combination": {
          "technique": "arithmetic_mean",
          "parameters": {
            "weights": [
              0.3,
              0.7
            ]
          }
        }
      }
    }
  ]
}

以下の部分がポイントです。キーワード検査のスコアを0.3, ニューラル検索のスコアを0.7で重み付けを行い結果を結合します。

        "combination": {
          "technique": "arithmetic_mean",
          "parameters": {
            "weights": [
              0.3,
              0.7
            ]

ハイブリッド検索の実行

では準備が整いましたのでハイブリッド検索を以下のコマンドで実行します。

GET /my-nlp-index/_search?search_pipeline=nlp-search-pipeline
{
  "_source": {
    "exclude": [
      "passage_embedding"
    ]
  },
  "query": {
    "hybrid": {
      "queries": [
        {
          "match": {
            "text": {
              "query": "cowboy rodeo bronco"
            }
          }
        },
        {
          "neural": {
            "passage_embedding": {
              "query_text": "wild west",
              "model_id": "JCLqTJkBck7QR77TNOSN",
              "k": 5
            }
          }
        }
      ]
    }
  }
}

ニューラル検索

キーワード検索

ハイブリッド検索

A man who is riding a wild horse in the rodeo is very near to falling off .

A rodeo cowboy , wearing a cowboy hat , is being thrown off of a wild white horse .

A rodeo cowboy , wearing a cowboy hat , is being thrown off of a wild white horse .

A wild animal races across an uncut field with a minimal amount of trees 

A West Virginia university women 's basketball team , officials , and a small gathering of fans are in a West Virginia arena .

A man who is riding a wild horse in the rodeo is very near to falling off .

A rodeo cowboy , wearing a cowboy hat , is being thrown off of a wild white horse .

A man who is riding a wild horse in the rodeo is very near to falling off .

A wild animal races across an uncut field with a minimal amount of trees .

検索結果は一致度が高い順に出力されます。ハイブリッド検索の結果はキーワード検索とニューラル検索の結果を重みづけで並び替えたものになっています。

たとえば、ある意味で検索を行いたいが検索結果に特定の文字は入っていてほしい、という場合以下の様にキーワード検索とニューラル検索のキーワードを変えることもできます。

GET /my-nlp-index/_search?search_pipeline=nlp-search-pipeline
{
  "_source": {
    "exclude": [
      "passage_embedding"
    ]
  },
  "query": {
    "hybrid": {
      "queries": [
        {
          "match": {
            "text": {
              "query": "cowboy rodeo bronco"
            }
          }
        },
        {
          "neural": {
            "passage_embedding": {
              "query_text": "wild west",
              "model_id": "JCLqTJkBck7QR77TNOSN",
              "k": 5
            }
          }
        }
      ]
    }
  }
}

まとめ

このようにハイブリッド検索を使用することでキーワード検索の精度とニューラル検索の意味理解の良さの両方の良さを享受することが出来ます。「特定の単語は必ず含めたいけれど、意味的に関連する内容も拾いたい」といったユースケースでは有効に働くでしょう。例えばECサイトの商品検索をする時に「赤いスニーカー」とユーザが入力した時に「赤」「スニーカー」という入力通りの検索結果は表示しつつ、関連する赤系の靴やランニングシューズなどの関連する商品を同時に表示することもできるでしょう。

社内FAQサイトに社員が「有給申請」と検索すると、正確にその言葉を含むマニュアルだけでなく、「休暇取得」「勤怠管理」など意味的に関連する資料を同時に表示することも可能になります。

ハイブリッド検索を理解しておくことでOpenSearchに実装されている検索アルゴリズムをうまく組み合わせて顧客の検索体験の向上に役立てることができると思います。

Written by
編集部

亀田 治伸

Kameda Harunobu

  • Facebook->
  • X->
  • GitHub->

Share

Facebook->X->
Back
to list
<-