ElasticsearchのRetrieverについて調べたので雑にメモ

Posted by johtani on Friday, December 27, 2024

目次

ElasticsearchにRetrieverという仕組みが8.16でGAしたので、ざっくり調べた時のメモを残しておこうかなと。

ElasticsearchのRetriever

Retrieverという検索の機能が8.16でGAリリースされた。

Retrieverとは?

これまでの検索処理(_serachエンドポイント)では、検索してsearch_afterで検索結果を絞り込む(Aggregationは最初の検索処理の結果)ことや、rescoreで検索結果の一部を別のクエリでスコアリングして並べ替えるといったことが可能でした。 しかし、複数の検索処理それぞれ実施してその結果を並べ替えたり、入れ子にした検索の処理を行ったりといった検索パイプラインのような処理はできませんでした。

8.16でリリースされたRetrieverは1回のリクエストで、複数のクエリを実行した結果をRRFで結合したり、rerankerでリランキングしたりといったことが可能になります。 rrfがリリースされたタイミング(8.8)では1つのパターンのみが考慮されていました。

queryが通常の転地インデックスを利用した検索、knnがベクトル検索、rankが2つの検索結果を統合するためにrrfを利用するという命令となります。

{
  "query": {
    "match": {
      "product": {
        "query": "brown shoes"
      }
    }
  },
  "knn": {
    "field": "product-vector",
    "query_vector": [54, 10, -2],
    "k": 20,
    "num_candidates": 75
  },
  "rank": {
     "rrf": {
        "window_size": 100,
        "rank_constant": 20
     }
  }
}

この形以外で検索結果を統合する自由度がありません。 また、rankについてもrrfのみのでGAしていません。 これらの拡張性を提供する形でRetrieverが提供されています。

上記のクエリは次のようなRetrieverとなります。

{
  "retriever": {
    "rrf": { 
      "retrievers": [ 
        {
          "standard": { 
            "query": {
              "match": {
                "product": {
                  "query": "brown shoes"
                }
              }
            }
          }
        },
        {
          "knn": { 
            "field": "product-vector",
            "query_vector": [54, 10, -2],
            "k": 20,
            "num_candidates": 75
          }
        }
      ],
      "rank_constant": 20, 
      "rank_window_size": 100  
    }
  }
}

それぞれ検索結果のリストを返すものを「Retriever」と呼び、rrfなどは、複数の検索結果を混ぜて返すため、入れ子で別のRetrieverを読んでいる形となります。

複数のretreiverをパイプライン処理のようにつなぎたい場合は、入れ子にしていくことで前段のretrieverの結果をもとに、後段のretrieverの処理を実施可能です。

GET retrievers_example/_search
{
    "retriever": {
        "text_similarity_reranker": {
            "retriever": {
                "text_similarity_reranker": {
                    "retriever": {
                        "knn": {
                            "field": "vector",
                            "query_vector": [
                                0.23,
                                0.67,
                                0.89
                            ],
                            "k": 3,
                            "num_candidates": 5
                        }
                    },
                    "rank_window_size": 100,
                    "field": "text",
                    "inference_id": "my-rerank-model",
                    "inference_text": "What are the state of the art applications of AI in information retrieval?"
                }
            },
            "rank_window_size": 10,
            "field": "text",
            "inference_id": "my-other-more-expensive-rerank-model",
            "inference_text": "Applications of Large Language Models in technology and their impact on user satisfaction"
        }
    },
    "_source": false
}

提供されているRetriever

  • standard: これまでの検索クエリの実行を行うretriever。
  • knn: knn検索のためのretriever。
  • rrf: RRFを用いて検索結果を生成するretriever。
    • 複数のRetrieverを呼び出せる。
  • text_similarity_reranker: NLPモデルを利用して検索結果の上位k件を並べ替えるretriever。
    • inference APIで登録してあるものを呼び出すもの。
    • 別のRetriever(1つだけ)の結果を指定したRerankerで並び変える
  • rule: クエリルールを利用して、特定のクエリに対して処理を実施する
    • 8.17時点では、pinnedとexcludeのみ

Text Similarity Re-ranker Retriever(8.17時点)

Create inference APIを利用して、text_similarity_rerankerのエンドポイントを設定。こちらは、テキストの類似性を計算できるもの。

現在利用できるRerankerは次の通り

Elandを利用するパターンはサポートされているモデルは現状2種類なので、あまり選択肢がないと思われる。 Vertex AIで定義したものがどのくらい自由度があるのかは別途調査する必要がある。 Enterpriseの契約でなければInference APIが利用できない。

使い方(例)

既存の検索の仕組みとの組み合わせの例などが記載してある(ハイライト、collapse、inner_hits、aggsなど)。

QueryのRescorerは?

Query Rescorerという仕組みが用意されており、通常の全文検索のqueryに対して、上位N件の結果を別のクエリを用いてスコア計算をする方法が用意されている。

このquery rescorerはretrieverでは現時点(8.17)では利用できない模様(Issue 118327) これに対し、すでにPRが作成され、次期バージョンに取り込まれるrescoreと呼ばれるretrieverが実装されている

ElasticのLtRとRetrieverの組み合わせはどうなるのか?

上記のPRが実装されることで、「おそらく」ElasticのLtRの検索もrescoreのretrieverで呼び出せるはず(要確認)。

O19nのLtRは?

こちらもRescoreで呼び出す形であれば、上記のPRで対応されるのでは(要確認)。

そのほかに気になる観点(そのうち調べるかも?)

  • 使えないクエリとかあるのか?
    • Retrieverと現在の_searchの組み合わせに関しては制限の記載あり
    • 個別のRetriever内部で制限があるかは未調査
  • Query Profileとかどうなるのか?
  • 分散トレーシングのSpanとかはどうなるのか?どのRetrieverがどのくらいの処理時間みたいなのがわかるのか?
  • SlowQueryはShardに対してなので、末端(葉)のクエリの処理での計測になるのか?
    • Fetchも同様か?
  • Fetchはどのタイミングで実行されるのか?一番最後?
  • Rescoreとの違い、組み合わせはどうなるのか?
    • そのうちなくなりそう、rescore?
  • クエリの実行順序を明確に指定できる形にできるから、処理早くしたりできる???
  • 複数Shardの場合の処理の流れってどんな感じ?

まとめ

とりあえず、雑に調べてたので、雑にメモに残しておきます。 まだちゃんとしたデータで動かしてないので、それは宿題かなぁ。


comments powered by Disqus

See Also by Hugo


Related by prelims-cli