<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[関連性 - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[関連性 - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/jp/search-labs/blog/category/relevance</link>
    </image>
    <link>https://www.elastic.co/jp/search-labs/blog/category/relevance</link>
    <atom:link href="https://www.elastic.co/jp/search-labs/rss/category/relevance.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[jp]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 12:01:23 GMT</lastBuildDate>
  <item>
    <title><![CDATA[最小スコアで意味的精度を確保]]></title>
    <description><![CDATA[最小スコアしきい値を採用することで意味的精度を向上させます。この記事にはセマンティック検索とハイブリッド検索の具体的な例が含まれています。 ]]></description>
    <content:encoded><![CDATA[<p>セマンティック検索は、検索の関連性を高めるための無限の機会をもたらしました。ELSER、E5、Jina Embedding v4などの高品質な高密度・低密度モデルは、キーワードの一致ではなく、単語の意味に基づいて関連性の高い結果を返します。ただし、セマンティック検索では、テールで無関係な結果が返されたり、インデックス内に関連する結果がないクエリに対して無関係な結果が返されることがあります。この低密度モデルと高密度モデルの特性により、ユーザーを混乱させたり、大規模言語モデル（LLM）の貴重なトークンを無駄にしたりする可能性があります。</p><p>この記事では、最小スコアパラメータを使用して、セマンティック検索結果の精度を高める方法を学びます。このブログ記事で示された例を試したい場合は<a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/ensuring-semantic-precision-with-minimum-score/ensuring_semantic_precision_with_minimum_score.ipynb">関連するJupyterノートブック</a>をご覧ください。</p><h2>背景：精度と再現率</h2><p>検索の関連性において、<em>精度</em>と<em>再現率</em>は重要な概念です。まだご存知でない読者の方は、これについて一読されることをおすすめします。以下は要約です。</p><ul><li><p><strong>精度：</strong>返される検索結果のうち、ユーザーに関連するものの割合。</p></li><li><p><strong>再現率：</strong>コーパス内のすべての関連ドキュメントのうち、検索結果セットに含まれるドキュメントの割合。</p></li></ul><p>つまり、言い換えれば、精度とは関連する結果<strong>のみ</strong>を返すことであり、再現率は<strong>すべての</strong>関連する結果を返すことです。ご想像のとおり、これらは競合する要件であることが多いです。セマンティック検索は再現率が非常に高い傾向がありますが、精度に問題が生じる可能性があります。以下では、この特性について説明します。</p><h2>最小スコアパラメーターの導入</h2><p>「min_score」パラメーターを使用すると、最小スコアを設定して精度を向上させることができます。これにより、定義されたしきい値未満のスコアを持つ一致が削除され、結果セットが切り捨てられます。以下は簡単な例です。</p>GET search-movies/_search
{
  "retriever": {
    "linear": {
      "min_score": 4,
      "retrievers": [
        ...
      ]
    }
  }
}<h2>スコアの正規化</h2><p>最小スコアを設定するのは良いことですが、すべてのセマンティックモデルが静的しきい値に適したスコアを返すわけではありません。例えば、ELSERは無制限のスコアを返します。<a href="https://huggingface.co/intfloat/e5-small#faq">一部の</a>高密度モデルのスコアは密集してクラスター化されており、特定のクエリのコンテキストでのみ意味を持ちます。</p><p>ほとんどのセマンティック検索では、「min_score」を適用する前に正規化アプローチを使用することをお勧めします。正規化により、ドキュメントのスコアが定義された範囲内に収まるようになります。Elasticsearchレトリバーは、「l2_norm」と「minmax」という2つの<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers/linear-retriever#linear-retriever-normalizers">正規化機能</a>を提供します。最もよく使用されるのは「minmax」です。これは理解しやすく、多くのシナリオでうまく機能するためです。「minmax」の主な特性は次のとおりです。</p><ul><li><p>ドキュメントのスコアは0から1の間で配分されます。</p></li><li><p>最も高いスコアを持つドキュメントには常に1のスコアが付けられます。</p></li><li><p>最も低いスコアを持つドキュメントには常に0のスコアが付けられます。</p><ul><li><p>これにより、キーワード検索に適さなくなる可能性があります。詳細については「ハイブリッド検索」セクションをご覧ください。</p></li></ul></li></ul><p>以下は、 <code>min_score</code>を使用した正規化されたセマンティッククエリの例です。ランクウィンドウのサイズが500に増え、100から始まるより長い検索結果のリストを返すことができます。</p>GET search-movies/_search
{
  "size": 100,
  "_source": [
    "title", "overview"
  ],
  "retriever": {
    "linear": {
      "rank_window_size": 500,
      "min_score": 0.25,
      "retrievers": [
        {
          "normalizer": "minmax",
          "retriever": {
            "standard": {
              "query": {
                "semantic": {
                  "field": "overview_vector",
                  "query": "superhero movie"
                }
              }
            }
          }
        }
      ]
    }
  }
}<p>サイズは、通常の本番環境で見られるサイズよりも高い値に設定されています。これは、検索結果の品質を検査し、結果を調整できるようにするためです。</p><h2>線形レトリバーを使用したハイブリッド検索</h2><p>ハイブリッド検索の場合、最も簡単な方法は、すべてのスコアを正規化し、重みを割り当て、最小スコアを適用することです。合計が1になる重みを選択すると、合計スコアが0～1の範囲内に保たれることに注意してください。これにより、最終スコアの理解や<code>min_score</code>のチューニングが容易になります。以下はその例です。</p>GET search-movies/_search
{
  "size": 100,
  "_source": ["title", "overview","keywords"],
  "retriever": {
    "linear": {
      "rank_window_size": 500,
      "min_score": 0.25,
      "retrievers": [
        {
          "weight": 0.6,
          "normalizer": "minmax",
          "retriever": {
            "standard": {
              "query": {
                "semantic": {
                  "field": "overview_vector",
                  "query": "superhero movie"
                }
              }
            }
          }
        },
        {
          "weight": 0.4,
          "normalizer": "minmax",
          "retriever": {
            "standard": {
              "query": {
                "multi_match": {
                  "query": "superhero movie",
                  "fields": ["overview","keywords", "title"],
                  "type": "cross_fields",
                  "minimum_should_match": "2"
                }
              }
            }
          }
        }
      ]
    }
  }
}<h2>RRFを使用したハイブリッド検索</h2><p>BM25では、多くの場合、 <code>AND</code>演算子や<code>minimum_should_match</code>を使用するなど、他の手段で精度を制御します。さらに、単一で、正確で、まれな用語からなるクエリは、自然に検索結果の少ない検索結果を引き起こし、多くの場合、すべてが非常に関連性の高いものです。これにより、次のことが発生する可能性があります。</p><ul><li><p>絶対的なBM25スコアが最大スコアのヒットに近い場合でも、結果内のさらに後ろの結果にはBM25レトリバーで低い正規化スコアが割り当てられます。</p></li><li><p>非常に低いBM25スコアをセマンティックスコアに追加すると、合計がセマンティックスコアとして近似されます。</p></li><li><p>BM25スコアの寄与が不足すると、ドキュメントが<code>min_score threshold</code>によって破棄される可能性があります。</p></li></ul><p>解決策として、BM25とセマンティック結果を組み合わせるために、逆順位融合（RRF）を使用することができます。RRFは、各結果セット内の位置に焦点を当てることで、異なる検索アルゴリズムのスコアを比較するという課題を回避します。この場合、<code>min_score</code>はセマンティックレトリバーにのみ適用されます。</p>GET search-movies/_search
{
  "_source": ["title", "overview","keywords"],
  "retriever": {
    "rrf": {
      "rank_window_size": 500,
      "retrievers": [
        {
          "linear": {
            "rank_window_size": 500,
            "min_score": 0.25,
            "retrievers": [
              {
                "normalizer": "minmax",
                "retriever": {
                  "standard": {
                    "query": {
                      "semantic": {
                        "field": "overview_vector",
                        "query": "superhero movie"
                      }
                    }
                  }
                }
              }
            ]
          }
        },
        {
          "standard": {
            "query": {
              "multi_match": {
                "query": "superhero movie",
                "fields": ["overview", "keywords","title"],
                "type": "cross_fields",
                "minimum_should_match": "2"
              }
            }
          }
        }
      ]
    }
  }
}<h2>まとめ</h2><p><code>min_score</code>を使用することで、セマンティック検索アルゴリズムの高い再現率によって引き起こされる結果セット内の誤検出の数を減らす方法を示しました。レトリバーの詳細については、こちらの<a href="https://www.elastic.co/search-labs/blog/elasticsearch-retrievers">ブログ記事</a>と<a href="https://www.elastic.co/docs/solutions/search/retrievers-overview">Elasticsearchのドキュメント</a>をご覧ください。</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/semantic-precision-minimum-score</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/semantic-precision-minimum-score</guid>
    <category><![CDATA[関連性]]></category>
    <category><![CDATA[ハイブリッド検索]]></category>
    <dc:creator><![CDATA[Mattias Brunnert]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4a3fba607900049/6a170e0fcdacbf8fe17d2a7a/8b3b5910abfe16d48d309341a0027008b16c4340-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 20 Feb 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[判断リストによる検索クエリの関連性の評価]]></title>
    <description><![CDATA[Elasticsearchで検索クエリの関連性を客観的に評価し、リコールなどのパフォーマンス指標を改善するための判断リストの構築方法を探ります。スケーラブルな検索のテストの拡張性についても学びます。]]></description>
    <content:encoded><![CDATA[<p>検索エンジンに取り組んでいる開発者は、同じ問題によく遭遇します。それは、検索結果の上位に表示されると予想していたドキュメントが結果リストの3番目か4番目に表示されるため、ビジネスチームが特定の検索に満足してくれないという問題です。</p><p>ただし、この 1 つの問題を修正すると、すべてのケースを手動でテストすることができないため、他のクエリが誤って壊れてしまいます。しかし、1つのクエリの変更が他のクエリに波及効果をもたらすかどうかを、開発者やQAチームはどのようにテストできるでしょうか。さらに重要なのは、変更によってクエリが実際に改善されたことをどうやって確認できるかということです。</p><h2>体系的な評価に向けて</h2><p>ここで役に立つのが判断リストです。変更を加えるたびに手動の主観的なテストに頼るのではなく、ビジネスケースに関連するクエリの固定セットと、関連する結果を定義できます。</p><p>このセットが基準となります。変更を実装するたびに、それを使用して検索が実際に改善されたかどうかを評価します。</p><p>このアプローチの価値は、次の点にあります。</p><ul><li><p><strong>不確実性の排除</strong>：変更が他のクエリに影響を与えるかどうかを心配する必要はなくなり、データが教えてくれます。</p></li><li><p><strong>手動テストの停止</strong>：判断セットが記録されると、テストは自動化されます。</p></li><li><p><strong>変更を支援</strong>：変更のメリットを裏付ける明確な指標を示すことができます。</p></li></ul><h2>判断リストの作成方法</h2><p>最も簡単な方法の1つは、代表的なクエリを取得して、関連するドキュメントを手動で選択することです。このリストを作成するには2つの方法があります。</p><ul><li><p><strong>バイナリ判定：</strong>クエリに関連付けられた各ドキュメントに<em>関連</em>（通常「1」のスコア）とと非関連（「0」）の<strong>シンプルなタグ</strong>が付けられます。</p></li><li><p><strong>段階的な判断：</strong>ここでは、各ドキュメントに異なるレベルのスコアが付けられます。例えば、0から4の尺度を設定します。これは<a href="https://en.wikipedia.org/wiki/Likert_scale">ライカート尺度</a>に似ており、0は「全く関連しない」、4は「完全に関連する」を意味し、「関連する」、「やや関連する」などのバリエーションがあります。</p></li></ul><p>検索意図に明確な制限がある場合、つまり「このドキュメントは結果に含まれるべきかどうか」という場合には、バイナリ判断がうまく機能します。</p><p>段階的な判断は、グレーゾーンがある場合により役立ちます。一部の結果は他の結果よりも優れているため、「非常に良い」、「良い」、「役に立たない」という結果を取得し、結果の順序とユーザーのフィードバックを評価する指標を使用できます。ただし、段階的な評価尺度には欠点もあります。評価者によってスコアリングレベルの使い方が異なり、判断の一貫性が失われることがある点です。また、評価基準では高得点により重み付けされるため、小さな変更（評価を4ではなく3にするなど）でも、レビュー担当者の意図よりもはるかに大きな変化が評価基準に生じる可能性があります。この主観性が加わることで、段階的な判断はノイズが多くなり、時間の経過とともに管理が難しくなります。</p><h2>書類を自分で分類する必要がありますか？</h2><p>必ずしもそうとは限りません。なぜなら、判断リストを作成する方法はいくつかあり、それぞれに利点と欠点があるからです。</p><ul><li><p><strong>明示的な判断：</strong>ここでは、SMEが各クエリやドキュメントに目を通し、関連性があるかどうか（あるいはどの程度関連性があるか）を手動で判断します。これにより品質と管理は提供されますが、拡張性は低くなります。</p></li><li><p><strong>暗黙的な判断：</strong>この方法では、クリック、直帰率、購入などの実際のユーザーの行動に基づいて関連するドキュメントを推測します。このアプローチにより、データを自動的に収集できますが、バイアスがかかる可能性があります。例えば、ユーザーは関連性がなくても上位の結果をクリックする傾向があります。</p></li><li><p><strong>AI生成の判断：</strong>この最後のオプションでは、モデル（LLMなど）を使用してクエリとドキュメントを自動的に評価します。これは、<a href="https://en.wikipedia.org/wiki/LLM-as-a-Judge">LLM審査員</a>とも呼ばれます。スケーリングは高速かつ簡単ですが、データの品質は、使用しているモデルの品質と、LLMトレーニングデータがビジネス上の<a href="http://interests.as/">利益</a>とどの程度一致しているかによって異なります。人間の採点者と同様に、LLM審査員も独自のバイアスや不整合を導入する可能性があるため、信頼できる判断の小さなセットに対してその出力を検証することが重要です。LLMモデルは本質的に確率的であるため、 <a href="https://www.ibm.com/think/topics/llm-temperature">温度</a> パラメータを0に設定しても同じ結果に対して異なる評価を与えるLLMモデルがよく見られます。</p></li></ul><p>判断セットを作成するための最適な方法を選択するための推奨事項を以下に示します。</p><ul><li><p>ユーザーのみが適切に判断できる特徴（価格、ブランド、言語、スタイル、製品詳細など）の重要性を決定します。これらが重要な場合は、<strong>判断リスト</strong>の少なくとも一部について<em>明示的な判断が</em>必要です。</p></li><li><p>検索エンジンにすでに十分なトラフィックがある場合は、<strong>暗黙的な判断</strong>を使用して、クリック、コンバージョン、滞在時間の指標を使用して使用傾向を検出できます。これらの結果は人間が注意深く解釈し、明示的な判断セットと対比させて、バイアスを防御する必要があります（例：ユーザーは、たとえ低いランクの結果がより関連性が高くても、上位にランクされた結果をクリックする傾向があります）。</p></li></ul><p>これに対処するために、位置バイアス除去技術はクリックデータを調整または再重み付けして、実際のユーザーの関心をより適切に反映します。アプローチには以下のようなものがあります。</p><ul><li><p><strong>結果のシャッフル</strong>：一部のユーザーの検索結果の順序を変更し、位置がクリックにどのように影響するかを推定します。</p></li><li><p><strong>クリックモデルには</strong><a href="https://wiki.math.uwaterloo.ca/statwiki/index.php?title=a_Dynamic_Bayesian_Network_Click_Model_for_web_search_ranking">ダイナミックベイジアンネットワーク</a><a href="https://wiki.math.uwaterloo.ca/statwiki/index.php?title=a_Dynamic_Bayesian_Network_Click_Model_for_web_search_ranking"><strong>（DBN）、</strong></a><a href="https://rsrikant.com/papers/kdd10.pdf">ユーザーブラウジングモデル</a><a href="https://rsrikant.com/papers/kdd10.pdf"><strong>（UBM）が含まれます。</strong></a>これらの統計モデルは、スクロール、滞在時間、クリックシーケンス、結果ページへの戻りなどのパターンを使用して、クリックが単なる位置ではなく実際の関心を反映している可能性を推定します。</p></li></ul><h2>例：映画評価アプリ</h2><h3>要件</h3><p>この例を実行するには、稼働しているElasticsearch 8.xクラスター、<a href="https://www.elastic.co/downloads/elasticsearch">ローカル</a>または<a href="https://www.elastic.co/cloud/cloud-trial-overview">Elastic Cloud</a>（HostedまたはServerless）、<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis">REST API</a>またはKibanaへのアクセスが必要です。</p><p>ユーザーが映画についての意見をアップロードしたり、見たい映画を検索したりできるアプリを考えてみてください。ユーザー自身がテキストを書くため、タイプミスや表現の多様性がある可能性があります。そのため、検索エンジンがその多様性を解釈し、ユーザーにとって有益な結果を提供できることが不可欠です。</p><p>全体的な検索動作に影響を与えずにクエリを反復処理できるようにするために、会社のビジネスチームは、最も頻繁に実行される検索に基づいて、次のバイナリ判定セットを作成しました。</p><p>クエリ</p><p>DocID</p><p>テキスト</p><p>ディカプリオの演技</p><p>doc1</p><p>『レヴェナント：蘇えりし者』でのディカプリオの演技は息を呑むほど素晴らしかった。</p><p>ディカプリオの演技</p><p>doc2</p><p>『インセプション』ではレオナルド・ディカプリオが最も象徴的な役柄の一つを演じています。</p><p>ディカプリオの演技</p><p>doc3</p><p>ブラッド・ピットはこの犯罪スリラーで堅実な演技を見せています。</p><p>ディカプリオの演技</p><p>doc4</p><p>見事な視覚効果を備えたアクション満載の冒険。</p><p>泣ける悲しい映画</p><p>doc5</p><p>何時間も泣いてしまった、愛と喪失の悲痛な物語。</p><p>泣ける悲しい映画</p><p>doc6</p><p>史上最も悲しい映画の1つです。ティッシュが必須。</p><p>泣ける悲しい映画</p><p>doc7</p><p>笑える軽快なコメディ</p><p>泣ける悲しい映画</p><p>doc8</p><p>アクションと興奮に満ちたSF大作。</p><p>インデックスの作成：</p>PUT movies
{
  "mappings": {
    "properties": {
      "text": {
        "type": "text"
      }
    }
  }
}<p>一括リクエスト：</p>POST /movies/_bulk
{ "index": { "_id": "doc1" } }
{ "text": "DiCaprio performance in The Revenant was breathtaking." }
{ "index": { "_id": "doc2" } }
{ "text": "Inception shows Leonardo DiCaprio in one of his most iconic roles." }
{ "index": { "_id": "doc3" } }
{ "text": "Brad Pitt delivers a solid performance in this crime thriller." }
{ "index": { "_id": "doc4" } }
{ "text": "An action-packed adventure with stunning visual effects." }
{ "index": { "_id": "doc5" } }
{ "text": "A heartbreaking story of love and loss that made me cry for hours." }
{ "index": { "_id": "doc6" } }
{ "text": "One of the saddest movies ever made -- bring tissues!" }
{ "index": { "_id": "doc7" } }
{ "text": "A lighthearted comedy that will make you laugh." }
{ "index": { "_id": "doc8" } }
{ "text": "A science-fiction epic full of action and excitement." }<p>以下は、このアプリが使用しているElasticsearchクエリです。</p>GET movies/_search
{
 "query": {
   "match": {
     "text": {
       "query": "DiCaprio performance",
       "minimum_should_match": "100%"
     }
   }
 }
}<h3>判断から指標へ</h3><p>判断リスト自体は、多くの情報を提供しません。これは、クエリから得られる結果の期待値にすぎません。これらが真価を発揮するのは、検索パフォーマンスを測定するための客観的な指標の計算に使用するときです。</p><p>現在、人気の指標のほとんどには以下が含まれます。</p><ul><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#k-precision"><strong>精度</strong></a><strong>：</strong>すべての検索結果の中で本当に関連性の高い結果の割合を測定します。</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#k-recall"><strong>リコール</strong></a><strong>：</strong>検索エンジンがx件の結果の中で見つけた関連する結果の割合を測定します。</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#_discounted_cumulative_gain_dcg"><strong>割引累積利得（DCG）</strong></a><strong>：</strong>最も関連性の高い結果が上位にあるべきであることを考慮して、結果のランキングの品質を測定します。</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#_mean_reciprocal_rank"><strong>平均逆順位（MRR）：</strong></a>最初の関連結果の位置を測定します。リストの上位にあるほど、スコアも高くなります。</p></li></ul><p>同じ映画評価アプリを例に使い、リコール指標を計算して、クエリに抜け落ちている情報がないかを確認します。</p><p>Elasticsearchでは、<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval">Ranking Evaluation API</a>を通じて<em>判断リスト</em>を使って指標を計算できます。このAPIは、判断リスト、クエリ、および評価する指標をインプットとして受け取り、クエリ結果と判断リストを比較した値を返します。</p><p>次の2つのクエリの判断リストを実行してみましょう。</p>POST /movies/_rank_eval
{
 "requests": [
   {
     "id": "dicaprio-performance",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "DiCaprio performance",
             "minimum_should_match": "100%"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc1",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc2",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc3",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc4",
         "rating": 0
       }
     ]
   },
   {
     "id": "sad-movies",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "sad movies that make you cry",
             "minimum_should_match": "100%"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc5",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc6",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc7",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc8",
         "rating": 0
       }
     ]
   }
 ],
 "metric": {
   "recall": {
     "k": 10,
     "relevant_rating_threshold": 1
     }
 }
}<p>_rank_evalには 2 つのリクエストを使用します。1つはディカプリオクエリ用、もう1つは悲しい映画用です。各リクエストには、クエリと判断リスト（評価）が含まれています。評価に含まれていない文書は判断対象外とみなされるため、すべての文書に等級を付ける必要はありません。計算を行うために、リコールは評価において関連性があると見なされるドキュメントである「関連セット」のみを考慮します。</p><p>この場合、ディカプリオのクエリのリコールは1ですが、悲しい映画のリコールは0です。つまり、最初のクエリでは関連する結果をすべて取得できましたが、2 番目のクエリでは何も取得できませんでした。したがって、平均リコールは0.5です。</p>{
 "metric_score": 0.5,
 "details": {
   "dicaprio-performance": {
     "metric_score": 1,
     "unrated_docs": [],
     "hits": [
       {
         "hit": {
           "_index": "movies",
           "_id": "doc1",
           "_score": 2.4826927
         },
         "rating": 1
       },
       {
         "hit": {
           "_index": "movies",
           "_id": "doc2",
           "_score": 2.0780432
         },
         "rating": 1
       }
     ],
     "metric_details": {
       "recall": {
         "relevant_docs_retrieved": 2,
         "relevant_docs": 2
       }
     }
   },
   "sad-movies": {
     "metric_score": 0,
     "unrated_docs": [],
     "hits": [],
     "metric_details": {
       "recall": {
         "relevant_docs_retrieved": 0,
         "relevant_docs": 2
       }
     }
   }
 },
 "failures": {}
}<p>クエリ内の単語の100%がドキュメント内で見つかることを要求することで、おそらく関連する結果が除外されるため、<strong>minimum_should_match</strong>パラメータを厳しすぎるのかもしれません。<strong>minimum_should_match</strong>パラメーターを削除して、クエリで1つの単語しか見つかっていない文書が関連性があると見なされるようにしましょう。</p>POST /movies/_rank_eval
{
 "requests": [
   {
     "id": "dicaprio-performance",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "DiCaprio performance"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc1",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc2",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc3",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc4",
         "rating": 0
       }
     ]
   },
   {
     "id": "sad-movies",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "sad movies that make you cry"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc5",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc6",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc7",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc8",
         "rating": 0
       }
     ]
   }
 ],
 "metric": {
   "recall": {
     "k": 10,
     "relevant_rating_threshold": 1
     }
 }
}<p>ご覧のように、2つのクエリのうちの1つで<strong>minimum_should_match</strong>パラメーターを削除すると、両方のクエリの平均リコール率は1になります。</p>{
  "metric_score": 1,
  "details": {
    "dicaprio-performance": {
      "metric_score": 1,
      "unrated_docs": [],
      "hits": [
        {
          "hit": {
            "_index": "movies",
            "_id": "doc1",
            "_score": 2.0661702
          },
          "rating": 1
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc3",
            "_score": 0.732218
          },
          "rating": 0
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc2",
            "_score": 0.6271719
          },
          "rating": 1
        }
      ],
      "metric_details": {
        "recall": {
          "relevant_docs_retrieved": 2,
          "relevant_docs": 2
        }
      }
    },
    "sad-movies": {
      "metric_score": 1,
      "unrated_docs": [],
      "hits": [
        {
          "hit": {
            "_index": "movies",
            "_id": "doc7",
            "_score": 2.1307156
          },
          "rating": 0
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc5",
            "_score": 1.3160692
          },
          "rating": 1
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc6",
            "_score": 1.190063
          },
          "rating": 1
        }
      ],
      "metric_details": {
        "recall": {
          "relevant_docs_retrieved": 2,
          "relevant_docs": 2
        }
      }
    }
  },
  "failures": {}
}<p>要約すると、minimum_should_match: 100%句を削除すると、両方のクエリで完璧なリコールが得られます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaf4f08a8a2915180/6a170df61949f76cbfe7aaba/24d055da4348c63827ba7046fe8cafb6f47cadd8-546x628.png" alt="" /><p>これで完了でしょうか？</p><p>安心するのはまだ早いです。</p><p>リコールを改善することで、より幅広い結果を得る道が開かれます。ただし、それぞれの調整にはトレードオフが伴います。だからこそ、完全なテストケースを定義し、異なる指標を使って変更を評価することが重要です。</p><p>判断リストと指標を使用すると、変更をバックアップするデータが得られるため、変更を行うときに盲目的に変更を行うことがなくなります。検証は手動で繰り返し行う必要がなくなり、変更を1つのユースケースだけでなく複数のユースケースでテストできるようになります。さらに、A/Bテストでは、どの構成がユーザーやビジネスケースに最適かをライブでテストできるため、技術的な指標と実際の指標から完全に把握できます。</p><h2>判断リストの使用に関する最終的な推奨事項</h2><p>判断リストを扱うことは、単に測定することだけでなく、自信を持って反復作業を行うためのフレームワークを作ることでもあります。これを実現するには、次の推奨事項に従ってください。</p><ol><li><p><strong>規模にこだわらずとにかく始める</strong>。それぞれ50個の判断リストを持つ10,000個のクエリを用意する必要はありません。ビジネスケースの最も重要な5〜10個のクエリを特定し、結果の冒頭にどの文書が表示されたいかを定義するだけで十分です。これですでに基礎が整いました。通常は、上位クエリと結果なしのクエリから始めるのが望ましいです。また、精度のような設定が簡単な指標でテストを開始し、複雑さを上げていくこともできます。</p></li><li><p><strong>ユーザーとともに検証する。</strong>本番環境でのA/Bテストで数値を補完します。こうすることで、指標で良さそうに見える変更が実際に効果を生んでいるかどうかを知ることができます。</p></li><li><p><strong>リストをアクティブに保つ。</strong>ビジネスケースは進化し、重要な問い合わせも進化していきます。新たなニーズを反映するために、定期的に判断を更新してください。</p></li><li><p><strong>フローの一部に組み込む。</strong>判断リストを開発パイプラインに統合しましょう。各構成の変更、同義語、またはテキスト分析が基本リストに対して自動的に検証されることを確認します。</p></li><li><p><strong>技術的な知識と戦略を結び付ける。</strong>精度やリコールなどの技術的な指標の測定にとどまらず、評価結果をビジネスの成果に役立てましょう。</p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/judgment-lists-search-query-relevance-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/judgment-lists-search-query-relevance-elasticsearch</guid>
    <category><![CDATA[関連性]]></category>
    <category><![CDATA[Elastic内部の実情]]></category>
    <dc:creator><![CDATA[Jhon Guzmán]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcadfd2fb1cc95b4c/6a170df7acf0887798be9bd0/25478d0ffb228afd5d65d82312998ec1c299c565-700x490.png" length="0" type="image/png"/>
    <pubDate>Thu, 11 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[面倒な手間を省いたハイブリッド検索：リトリーバーによるハイブリッド検索の簡素化]]></title>
    <description><![CDATA[線形および RRF リトリーバーのマルチフィールド クエリ形式を使用して Elasticsearch でのハイブリッド検索を簡素化する方法と、Elasticsearch インデックスに関する事前の知識なしでクエリを作成する方法について説明します。]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/what-is/hybrid-search">ハイブリッド検索は</a>、<a href="https://www.elastic.co/search-labs/blog/lexical-and-semantic-search-with-elasticsearch#lexical-search---sparse-retrieval">語彙検索</a>の精度と速度と<a href="https://www.elastic.co/what-is/semantic-search">セマンティック検索</a>の自然言語機能を組み合わせた強力な検索アプローチとして広く認識されています。ただし、実際に適用するのは難しい場合があり、インデックスに関する深い知識と、単純ではない構成での詳細なクエリの構築が必要になることがよくあります。このブログでは、<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers#multi-field-query-format">リニア リトリーバーと RRF リトリーバーのマルチフィールド クエリ形式によって</a>ハイブリッド検索がよりシンプルで使いやすくなり、よくある問題点が解消され、より簡単にその全機能を活用できるようになる方法について説明します。また、マルチフィールド クエリ形式を使用すると、インデックスに関する事前の知識がなくてもハイブリッド検索クエリを実行できる方法についても説明します。</p><h2>スコア範囲の問題</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3521a6558cd477ca/6a17f174445de94d3c4d0225/c8b49153c47d2cdc233c0d2e440db04711d48ca5-1600x1600.jpg" alt="" /><p>まず最初に、ハイブリッド検索が困難になる主な理由の 1 つである、スコア範囲の多様性について確認しましょう。私たちの古い友人<a href="https://www.elastic.co/elasticon/conf/2016/sf/improved-text-scoring-with-bm25">BM25</a>は無制限のスコアを生成します。言い換えれば、BM25 は 0 に近い値から (理論的には) 無限大までの範囲のスコアを生成できます。対照的に、 <code>dense_vector</code>フィールドに対するクエリでは、0 から 1 の範囲のスコアが生成されます。この問題をさらに悪化させるのは、 <code>semantic_text</code>埋め込みのインデックス作成に使用されるフィールド タイプが難読化されるため、インデックスと推論エンドポイントの構成に関する詳細な知識がない限り、クエリのスコアの範囲がどうなるかを判断するのが難しい場合があることです。これは、語彙検索結果と意味検索結果をインターリーブしようとするときに、意味検索結果の関連性が高い場合でも、語彙検索結果が意味検索結果よりも優先される可能性があるため、問題が発生します。この問題に対する一般的に受け入れられている解決策は、結果をインターリーブする前にスコアを正規化することです。Elasticsearch には、これを実行するためのツールとして、<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers/linear-retriever">線形リトリーバー</a>と<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers/rrf-retriever">RRF</a>リトリーバーの 2 つがあります。
</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt09ed6bf3d25066bd/6a17f1750b0bedbd70dd3686/264481268c8b6ac259e3c257b85431b513f16672-1077x586.png" alt="線形/RRFを使用した場合と使用しない場合の検索結果の比較" /><p><strong>RRF</strong>リトリーバーは、ドキュメントのランクを関連性の尺度として使用し、スコアを破棄して、 <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion">RRF アルゴリズム</a>を適用します。スコアは考慮されないため、スコア範囲の不一致は問題になりません。</p><p><strong>線形</strong>リトリーバーは線形結合を使用してドキュメントの最終スコアを決定します。これには、ドキュメントの各コンポーネント クエリのスコアを取得し、それを正規化し、合計して合計スコアを生成することが含まれます。数学的には、この操作は次のように表現できます。</p>Total Score = 𝚺(N(Sx))<p>ここで、 <code>N</code>は正規化関数であり、SX はクエリ X のスコアです。ここで重要なのは正規化関数です。正規化関数は各クエリのスコアを同じ範囲を使用するように変換します。リニア リトリーバーの詳細については、<a href="https://www.elastic.co/search-labs/blog/linear-retriever-hybrid-search">こちらを</a>ご覧ください。</p><h2>詳しく見てみる</h2><p>ユーザーはこれらのツールを使用して効果的なハイブリッド検索を実装できますが、インデックスに関するある程度の知識が必要です。線形リトリーバーを使用して、2 つのフィールドを持つインデックスをクエリする例を見てみましょう。</p>PUT linear_retriever_example
{
  "mappings": {
    "properties": {
      "semantic_text_field": { &lt;1&gt;
        "type": "semantic_text",
        "inference_id": ".multilingual-e5-small-elasticsearch"
      },
      "text_field": { &lt;2&gt;
        "type": "text"
      }
    }
  }
}<p>1. <code>semantic_text_field</code>は、テキスト埋め込みモデルである<a href="https://www.elastic.co/docs/explore-analyze/machine-learning/nlp/ml-nlp-e5">E5</a>を使用する<code>semantic_text</code>フィールドです。</p><p>2. <code>text_field</code>は標準の<code>text</code>フィールドです</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "retrievers": [
        {
          "retriever": {
            "standard": {
              "query": {
                "match": { &lt;1&gt;
                  "semantic_text_field": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        },
        {
          "retriever": {
            "standard": {
              "query": {
                "match": {
                  "text_field": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        }
      ]
    }
  }
}<p>1. <a href="https://www.elastic.co/search-labs/blog/semantic-search-match-knn-sparse-vector#we-made-match-happen-in-semantic-search!">Elasticsearch 8.18/9.0でサポートされた</a><code>semantic_text</code>フィールドで<code>match</code>クエリを使用します。</p><p>
クエリを構築するときは、 <code>semantic_text_field</code>テキスト埋め込みモデルを使用するため、このクエリでは 0 から 1 の間のスコアが生成されることに留意する必要があります。また、 <code>text_field</code>は標準の<code>text</code>フィールドであるため、これに対するクエリによって無制限のスコアが生成されることも知っておく必要があります。適切な関連性を持つ結果セットを作成するには、クエリ スコアを結合する前に正規化するリトリーバーを使用する必要があります。この例では、 <code>minmax</code>正規化を備えた線形リトリーバーを使用して、各クエリのスコアを 0 から 1 の間の値に正規化します。</p><p>この例のクエリ構築は、関係するフィールドが 2 つだけなので、非常に簡単です。ただし、さまざまなタイプのフィールドが追加されると、すぐに複雑になる可能性があります。これは、効果的なハイブリッド検索クエリを記述するには、クエリ対象のインデックスに関するより深い知識が必要になることが多く、組み合わせる前にコンポーネント クエリ スコアが適切に正規化される必要があることを示しています。これは、ハイブリッド検索のより広範な導入の障害となります。</p><h3>クエリのグループ化</h3><p>例を拡張してみましょう。1 つの<code>text</code>フィールドと 2 つの<code>semantic_text</code>フィールドをクエリしたい場合はどうなるでしょうか。次のようなクエリを作成できます。</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "retrievers": [
        {
          "retriever": {
            "standard": {
              "query": {
                "semantic": {
                  "field": "semantic_text_field_1",
                  "query": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        },
        {
          "retriever": {
            "standard": {
              "query": {
                "semantic": {
                  "field": "semantic_text_field_2",
                  "query": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        },
        {
          "retriever": {
            "standard": {
              "query": {
                "match": {
                  "text_field": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        }
      ]
    }
  }
}<p>表面的には良さそうですが、潜在的な問題があります。これで、 <code>semantic_text</code>フィールドの一致が合計スコアの 2/3 を占めることになります。</p>Total Score = N(semantic_text_field_1 score) + N(semantic_text_field_2 score) + N(text_field score)<p>これは、不均衡なスコアを作成するため、おそらく望ましい結果ではありません。この例のようにフィールドが 3 つしかない場合、影響はそれほど顕著ではないかもしれませんが、より多くのフィールドをクエリすると問題が生じます。例えば、ほとんどの索引には意味フィールド（つまり<code>dense_vector</code> 、 <code>sparse_vector</code> 、または<code>semantic_text</code> )。上記のパターンを使用して、9 つの語彙フィールドと 1 つの意味フィールドを持つインデックスをクエリするとどうなるでしょうか?語彙の一致がスコアの 90% を占めることになり、意味検索の有効性が鈍ってしまいます。</p><p>これに対処する一般的な方法は、クエリを語彙と意味のカテゴリにグループ化し、その 2 つに均等に重み付けすることです。これにより、どちらかのカテゴリーが合計スコアを支配することが防止されます。</p><p>それを実践してみましょう。この例では、線形リトリーバーを使用する場合、グループ化されたクエリのアプローチはどのようになるでしょうか?</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "retrievers": [
        {
          "retriever": {
            "linear": {
              "retrievers": [
                {
                  "retriever": {
                    "standard": {
                      "query": {
                        "semantic": {
                          "field": "semantic_text_field_1",
                          "query": "foo"
                        }
                      }
                    }
                  },
                  "normalizer": "minmax"
                },
                {
                  "retriever": {
                    "standard": {
                      "query": {
                        "semantic": {
                          "field": "semantic_text_field_2",
                          "query": "foo"
                        }
                      }
                    }
                  },
                  "normalizer": "minmax"
                }
              ]
            }
          },
          "normalizer": "minmax"
        },
        {
          "retriever": {
            "standard": {
              "query": {
                "match": {
                  "text_field": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        }
      ]
    }
  }
}<p>うわー、これは冗長になってきましたね!クエリ全体を確認するには、上下に何度もスクロールする必要があったかもしれません。ここでは、2 つのレベルの正規化を使用してクエリ グループを作成します。数学的には次のように表現できます。</p>Total Score = N(N(semantic_text_field_1 score) + N(semantic_text_field_2 score)) + N(text_field score)<p>この 2 番目のレベルの正規化により、 <code>semantic_text</code>フィールドと<code>text</code>フィールドに対するクエリが均等に重み付けされるようになります。この例では、語彙フィールドが 1 つしかないため、 <code>text_field</code>の 2 番目のレベルの正規化を省略し、冗長性を<em>さらに</em>軽減していることに注意してください。</p><p>このクエリ構造はすでに扱いにくく、クエリするフィールドは 3 つだけです。より多くのフィールドをクエリするにつれて、熟練した検索実践者にとっても管理がますます困難になります。</p><h2>複数フィールドのクエリ形式</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5d9007d279f0da29/6a17f17714d90c39cf79b6f5/dd04e1686076a574b717c1460acfe4eb79299208-1600x1600.jpg" alt="" /><p>これらすべてを簡素化するために、Elasticsearch 8.19、9.1、 サーバーレスの 線形および RRF リトリーバーに<a href="https://www.elastic.co/cloud/serverless"> マルチフィールド</a><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers#multi-field-query-format"> クエリ形式</a> を追加しました。次のようにするだけで、上記と同じクエリを実行できます。</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "fields": [ "semantic_text_field_1", "semantic_text_field_2", "text_field" ],
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>これにより、クエリが 55 行から 9 行に短縮されます。Elasticsearch はインデックス マッピングを自動的に使用して次の処理を実行します。</p><ul><li><p>クエリされた各フィールドのタイプを決定する</p></li><li><p>各フィールドを語彙または意味のカテゴリにグループ化します</p></li><li><p>最終スコアでは各カテゴリーを均等に重み付けする</p></li></ul><p>これにより、使用されるインデックスや推論エンドポイントの詳細を知らなくても、誰でも効果的なハイブリッド検索クエリを実行できるようになります。</p><p>RRF を使用する場合、ランクは関連性の代理として使用されるため、 <code>normalizer</code>を省略できます。</p>GET rrf_retriever_example/_search
{
  "retriever": {
    "rrf": {
      "fields": [ "semantic_text_field_1", "semantic_text_field_2", "text_field" ],
      "query": "foo"
    }
  }
}<h2>フィールドごとのブースティング</h2><p>リニア リトリーバーを使用する場合、フィールドごとにブーストを適用して、特定のフィールドでの一致の重要度を調整できます。たとえば、2 つの<code>semantic_text</code>フィールドと 2 つの<code>text</code>フィールドの 4 つのフィールドをクエリするとします。</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "fields": [ "semantic_text_field_1", "semantic_text_field_2", "text_field_1", "text_field_2" ],
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>デフォルトでは、各フィールドはグループ内（語彙または意味）で均等に重み付けされます。スコアの内訳は次のようになります。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdc6e197e5ff7b68d/6a17f179505ac32834ad8c46/ba31c76189e3a1e5b1638437ccf0528aafec2598-1600x549.png" alt="クエリグループとフィールドスコアの比較" /><p>つまり、各フィールドは合計スコアの 25% を占めます。</p><p><code>field^boost</code>構文を使用して、任意のフィールドにフィールドごとのブーストを追加できます。<code>semantic_text_field_1</code>と<code>text_field_1</code>に2のブーストを適用してみましょう。</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "fields": [ "semantic_text_field_1^2", "semantic_text_field_2", "text_field_1^2", "text_field_2" ]
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>スコアの内訳は次のようになります。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltccc9ed7d6e865a5e/6a17f17abe6086a31d004882/de20e555d52f914bf483a048d056f54f4fece757-1600x549.png" alt="refとハイブリッド検索でフィールドの重みを変更しました" /><p>各クエリ グループの重みは均等ですが、グループ内のフィールドの重みは次のように変更されました。</p><ul><li><p><code>semantic_text_field_1</code> セマンティッククエリグループスコアの66％、合計スコアの33％</p></li><li><p><code>text_field_1</code> 語彙質問グループスコアの66％、総スコアの33％</p></li></ul><p>ℹ️ フィールドごとのブーストを適用しても、合計スコアの範囲は変更されないことに注意してください。これはスコア正規化の意図された副作用であり、語彙クエリスコアと意味クエリスコアが互いに直接比較可能のままになることを保証します。</p><p>ℹ️ フィールドごとのブースティングは、Elasticsearch 9.2 以降の RRF リトリーバーでも使用できます。</p><h3>ワイルドカード解決</h3><p>複数のフィールドを一致させるには、 <code>fields</code>パラメータで<code>*</code>ワイルドカードを使用できます。上記の例を続けると、このクエリは機能的には<code>emantic_text_field_1</code> 、 <code>semantic_text_field_2</code> 、 <code>text_field_1</code>明示的にクエリすることと同等です。</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "fields": [ "semantic_text_field_*", "*_field_1" ],
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>興味深いことに、 <code>*_field_1</code>パターンは<code>text_field_1</code>と<code>semantic_text_field_1</code>の両方に一致します。これは自動的に処理され、各フィールドが明示的にクエリされたかのようにクエリが実行されます。<code>semantic_text_field_1</code>が両方のパターンに一致することも問題ありません。すべてのフィールド名の一致は、クエリの実行前に重複が排除されます。</p><p>ワイルドカードはさまざまな方法で使用できます。</p><ul><li><p>プレフィックス一致（例： <code>*_text_field</code> ）</p></li><li><p>インラインマッチング（例： <code>semantic_*_field</code> ）</p></li><li><p>サフィックス一致（例： <code>semantic_text_field_*</code> ）</p></li></ul><p><code>*_text_field_*</code>のように、複数のワイルドカードを使用して上記の組み合わせを適用することもできます。</p><h3>デフォルトのクエリフィールド</h3><p>マルチフィールド クエリ形式を使用すると、何も知らないインデックスをクエリすることもできます。<code>fields</code>パラメータを省略すると、 <a href="https://www.elastic.co/docs/reference/elasticsearch/index-settings/index-modules">index.query.default_field インデックス設定</a>で指定されたすべてのフィールドがクエリされます。</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>デフォルトでは、 <code>index.query.default_field</code>は<code>*</code>に設定されています。このワイルドカードは、用語クエリをサポートするインデックス内のすべてのフィールド タイプ (ほとんど) に解決されます。例外は次のとおりです:</p><ul><li><p><code>dense_vector</code> フィールド</p></li><li><p><code>rank_vector</code> フィールド</p></li><li><p>ジオメトリフィールド: <code>geo_point</code> 、 <code>shape</code></p></li></ul><p>この機能は、サードパーティが提供するインデックスに対してハイブリッド検索クエリを実行する場合に特に便利です。マルチフィールド クエリ形式を使用すると、適切なクエリを簡単な方法で実行できます。<code>fields</code>パラメータを除外するだけで、該当するすべてのフィールドが照会されます。</p><h2>まとめ</h2><p>スコア範囲の問題により、特にクエリ対象のインデックスや使用中の推論エンドポイントに関する情報が限られている場合、効果的なハイブリッド検索の実装が困難になる可能性があります。リニア リトリーバーと RRF リトリーバーのマルチフィールド クエリ形式では、自動化されたクエリ グループ化ベースのハイブリッド検索アプローチをシンプルで使いやすい API にパッケージ化することで、この煩わしさを軽減します。フィールドごとのブースト、ワイルドカード解決、デフォルトのクエリ フィールドなどの追加機能により、機能が拡張され、多くのユース ケースをカバーできます。</p><h2>今すぐマルチフィールドクエリ形式をお試しください</h2><p>無料トライアル では、完全に管理された Elasticsearch<a href="https://www.elastic.co/cloud/serverless"> Serverless</a> プロジェクトで、マルチフィールド<a href="https://www.elastic.co/docs/deploy-manage/deploy/elastic-cloud/create-serverless-project"> クエリ形式を使用した線形リトリーバーと RRF</a> リトリーバーを試すことができます。8.19 および 9.1 以降のスタック バージョンでも利用できます。</p><p>1 つのコマンドでローカル環境で数分以内に開始できます。</p>curl -fsSL https://elastic.co/start-local | sh<p></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/hybrid-search-multi-field-query-retrievers-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/hybrid-search-multi-field-query-retrievers-elasticsearch</guid>
    <category><![CDATA[ハイブリッド検索]]></category>
    <category><![CDATA[関連性]]></category>
    <dc:creator><![CDATA[Mike Pellegrini]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt89e066372c549595/6a17f17c3e9e457c38ba1583/4494f98ae3958bbdbc6171df9677fc4d65ec5640-1536x1024.png" length="0" type="image/png"/>
    <pubDate>Thu, 27 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[コンテキストのためのYou Know - パート1：ハイブリッド検索とコンテキストエンジニアリングの進化]]></title>
    <description><![CDATA[ハイブリッド検索とコンテキスト エンジニアリングが語彙の基礎からどのように進化し、次世代のエージェント AI ワークフローを可能にしたかを探ります。]]></description>
    <content:encoded><![CDATA[<h2>私たちの新しいエージェントAIの世界</h2><p>私たちの多くと同じように、私も AI の能力が進化している速さに興奮すると同時に驚いています。大規模言語モデル (LLM) とベクトル検索によって、キーワードで検索する必要がなくなったセマンティック革命が初めて実現しました。その後、LLM は、チャット インターフェースを使用して自然言語によるリクエストを応答に変換し、膨大な知識ベースから簡単に利用できる要約を抽出するなど、データと対話する新しい方法を教えてくれました。私たちは今（すでに！）「エージェント AI」ワークフローの形で自動化された LLM 駆動型ロジックが始まります。このワークフローは、受信したリクエストを意味的に理解し、実行する手順を推論し、利用可能なツールから選択してアクションを反復的に実行し、目標を達成します。</p><p>エージェント AI の可能性により、私たちは、主に「プロンプト エンジニアリング」を使用して生成 AI のインタラクションを形成することから、エージェント ツールが LLM が応答を生成する際に考慮する必要がある最も関連性の高い効率的な追加情報を取得できるようにする方法に重点を置くように進化することを余儀なくされています。つまり、「コンテキスト エンジニアリング」が次のフロンティアです。ハイブリッド検索は、関連するコンテキストを明らかにするための最も強力で柔軟な手段であり、Elastic の Search AI プラットフォームは、コンテキストエンジニアリングに役立つデータを活用するまったく新しい方法を実現します。この記事では、LLM が情報検索の世界をどのように変えたかを 2 つの角度から説明し、さらに、LLM がどのように連携してより優れた成果を上げることができるかについて説明します。カバーすべき領域はかなり広いです…</p><h2>パート1: LLMが検索に与えた影響</h2><p>まず、LLM が情報にアクセスし取得する方法をどのように変えたかという観点から始めましょう。</p><h3>私たちの語彙の遺産</h3><p>私たちは皆、長い間、ある程度制限された語彙検索の世界で（できるだけうまく）生きてきました。検索は、調査をしたり新しいプロジェクトを開始したりするときに最初に使用するツールであり、最近まで、語彙検索エンジンが理解できる方法でクエリを言い表すのは私たち次第でした。語彙検索は、コンテンツが構造化されているか非構造化されているかに関係なく、何らかの形式のクエリ用語をドキュメント コーパスで見つかったキーワードと一致させることに依存します。語彙検索で文書がヒットとして返されるためには、そのキーワードに一致している必要があります (または、概念的なつながりを作るために同義語リストや辞書などの制御された語彙が必要です)。</p>POST my-index/_search
{
  "size": 10,
  "query": {
    "semantic": {
      "query": "machine learning applications",
      "field": "semantic-content-field"
    }
  }
}<p><em>語彙の</em><a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-multi-match-query"><em> 複数一致</em></a><em> クエリの 例</em></p><p>少なくとも検索エンジンには、関連性スコア付きのヒットを返す機能があります。検索エンジンは、インデックスされたデータを効果的にターゲットするための豊富なクエリ構文オプションと、ユーザーのクエリ構文の意図に応じて結果をスコア付けする組み込みの関連性アルゴリズムを提供します。検索エンジンは、関連性ランキング アルゴリズムの数十年にわたる進歩の恩恵を受けており、クエリとの関連性に基づいてスコア付けされ、並べ替えられた結果を提供できる効率的なデータ検索プラットフォームとなっています。データを取得する主な方法として SQL を使用するデータベースやその他のシステムは、ここでは不利です。データベース クエリには関連性の概念がなく、せいぜいアルファベット順または数字順に結果を並べ替えることしかできないからです。良いニュースとしては、これらのキーワードでヒットするものがすべて得られる (リコール) ことですが、それらは必ずしも、検索を求めた<em>理由</em>に対して役立つ順序 (精度) になっているわけではありません。これは重要なポイントです。すぐにわかります…</p><h3>（意味論的）ドラゴンの登場</h3><p>キーワード検索の代替として情報のベクトル表現の可能性は<a href="https://www.elastic.co/search-labs/blog/introduction-to-vector-search">、かなり長い間</a>研究されてきました。ベクトルは、キーワードのみのコンテンツ一致モードから抜け出すことができるため、大きな可能性を秘めています。ベクトルは用語と重みの数値表現であるため、トレーニング領域で用語が互いにどのように関連しているかについての言語モデルの理解に基づいて、概念を数学的に近づけることができます。汎用ベクトル検索の長い遅延は、モデルが主に特定のドメインに限定されていたためであり、異なるコンテキスト内で用語が表す可能性のあるさまざまな概念を十分に理解できるほどモデルが大きくなかったのです。</p><p>ベクトル検索が実用的になったのは、数年前に大規模言語モデル (LLM) が登場し、<a href="https://en.wikipedia.org/wiki/Transformer_(deep_learning_architecture)">トランスフォーマー</a>と<a href="https://en.wikipedia.org/wiki/Attention_(machine_learning)">アテンション</a>を使用してはるかに大量のデータをトレーニングできるようになったときでした。LLM のサイズと深さにより、ベクトルは最終的に十分なニュアンスを保存できるようになり、実際に意味を捉えることができるようになりました。理解の深さが突然増加したことにより、LLM は、以前はロックされていた多数の自然言語処理 (NLP) 機能を提供できるようになり、おそらく最も影響力があるのは、これまでのシーケンスの内容に基づいて、シーケンス内で最も可能性の高い次の用語を推測する機能です。推論は、生成 AI に人間に近いテキスト生成能力を与えるプロセスです。AI によって生成されたテキストは、LLM がトレーニング データ内で用語がどのように関連しているかを理解した上で生成され、また、リクエストのフレーズを使用して、用語が出現する可能性のあるさまざまなコンテキスト間の曖昧さを解消します。</p><p>生成 AI は魔法のようですが、LLM には品質と精度のエラー (一般に幻覚と呼ばれる) を引き起こす制限<em>があります</em>。幻覚は、LLM が真実に基づいた回答をするための情報にアクセスできない (または正しいコンテキストに誘導されない) 場合に発生します。そのため、LLM は役に立とうとして、代わりに自信に満ちたもっともらしい応答をでっち上げで生成します。原因の一部は、LLM が多様な情報の大規模な領域内で言語の使用法を学習する一方で、ある時点でトレーニングを停止する必要があるため、理解に適時性の要素があることです。つまり、モデルはトレーニングを停止した時点までの正確さしか認識できないということです。幻覚を引き起こすもう 1 つの要因は、モデルが非公開データ (パブリック インターネットで利用できないデータ) を認識しないことです。これは、データに特定の用語や命名法が含まれている場合に特に重要です。</p><h3>ベクターデータベース</h3><p>LLM は、テキスト埋め込みと呼ばれる手法を使用してコンテンツをモデル空間にベクトル化します。テキスト<a href="https://www.elastic.co/search-labs/blog/hybrid-search-multiple-embeddings">埋め込み</a>とは、受信したトレーニングに基づいて、モデルの世界観内にコンテンツの意味を埋め込む、つまりマッピングすることを指します。埋め込み用のコンテンツを準備して処理するには、<a href="https://www.elastic.co/search-labs/blog/chunking-strategies-elasticsearch">チャンク化</a>とトークン化（および<a href="https://www.kaggle.com/code/danishmahdi/subword-tokenization-bpe-wordpiece-and-unigram">サブワードトークン化</a>）など、いくつかの手順が必要です。結果は通常、ベクトル空間内でのコンテンツ チャンクの意味に関するモデルの理解を表す密なベクトルのセットになります。チャンキングは、埋め込みを生成するためのモデルの処理制約の制限内にコンテンツを収めることを目的とした不正確なプロセスであり、文や段落のインジケーターなどのセマンティック構造を使用して関連するテキストをチャンクにグループ化しようとします。</p><p>チャンク化の必要性により、埋め込まれたドキュメントでは、個々のチャンクが同じドキュメントの他のチャンクと完全に関連付けられていないため、多少の意味的損失が生じる可能性があります。ニューラル ネットワークの本質的な不透明性により、この損失が悪化する可能性があります。LLM はまさに「ブラック ボックス」であり、トレーニング中に作成された用語と概念間の接続は非決定論的であり、人間が解釈することはできません。これにより、説明可能性、再現性、無意識の偏見に関する問題が発生し、信頼性と正確性が失われる可能性があります。それでも、クエリ時に特定のキーワードに縛られずにアイデアを意味的に結び付ける機能は非常に強力です。</p>POST my-index/_search 
{
  "size": 10, 
  "query": {
    "semantic": {
      "query": "machine learning applications",
      "field": "semantic-content-field"
    }
  }
} <p><a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-semantic-query"><em>セマンティック</em></a><em> クエリの 例</em></p><p>ベクター データベースに関して考慮すべきもう 1 つの問題があります。ベクター データベースは検索エンジンではなく、データベースなのです。<a href="https://www.elastic.co/search-labs/blog/introduction-to-vector-search">ベクトル類似性検索を</a>実行すると、クエリ用語がエンコードされ、モデルのベクトル空間内の一連の (埋め込み) 座標が検索されます。これらの座標は、ブルズアイとして使用され、ブルズアイに「最も近い」近傍にあるドキュメントが検索されます。つまり、ドキュメントのランク (または結果の配置) は、クエリの座標からのそのドキュメントの座標の計算された類似<em>距離</em>によって決まります。ランキングはどの方向を優先すべきでしょうか、考えられるコンテキストのうちどれがユーザーの意図に最も近いでしょうか?私がこれを例えると、映画<a href="https://www.youtube.com/watch?v=x3h7xz558EY&amp;start=3&amp;end=86">「スターゲイト</a>」のワンシーンになります。そのシーンでは、交差する 6 つの座標点が目的地 (的) を示しますが、ユーザーの主観的な意図を表す出発点の座標である「7 番目のシンボル」を知らないとそこに到達できません。したがって、ベクトルの相対的なランキングが常に拡大し区別のない類似性の領域に基づくのではなく、表現構文と関連性スコアリングを通じてクエリの主観的な意図を考慮することによって、段階的な主観的関連性の<em>円筒</em>に似たものを得ることができます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb49ae330d3de1fc1/6a17053ee8fbce089639fb46/1ddfaae0c1496d08d7d30419e6d2aeaeacfc0ea2-1600x544.png" alt="段階的な主観的関連性の円筒。" /><p>LLM の推論機能は、クエリ<em>に対して</em>最も可能性の高いコンテキストを識別するのに役立つ可能性がありますが、問題は<em>、支援がなければ、</em>着信クエリの座標はモデルが最初にトレーニングされた方法によって<em>のみ</em>決定できることです。</p><p>ある意味、ベクトル類似性は厳密なキーワード一致とは正反対の極限にあると言えます。その強みは用語の不一致の問題を克服する能力にありますが、それは<a href="https://medium.com/data-science/vector-embeddings-are-lossy-heres-what-to-do-about-it-4f9a8ee58bb7">ほとんど欠点で</a>もあります。LLM は関連する概念を区別するのではなく、統合する傾向があります。ベクトル類似性により、コンテンツを意味的に一致させる能力は向上しますが、モデルによって十分に明確にされていない正確なキーワードや具体的な詳細を見落とす可能性があるため、精度は保証されません。ベクトル類似性検索はそれ自体強力ですが、ベクトル データベースから取得した結果と他の取得方法の結果を相関させる方法が必要です。</p><h3>再ランキング手法</h3><p>ここで、結果セットを統一されたランク順に再スコアリングまたは正規化する、再ランク付けと呼ばれる一般的な手法について説明するのが良いでしょう。再ランク付けが必要になるのは、複数のソースからの結果や、ランク付け/スコアリング メカニズムが異なる (または SQL の場合はまったくメカニズムがない) 検索方法による場合です。また、非セマンティック ソースからの結果をユーザーのクエリに意味的に合わせるために再ランク付けを使用する場合もあります。再ランキングは第2段階の操作であり、何らかの<em>初期検索</em>方法（つまり、その後、検索クエリ (SQL、語彙検索、ベクトル検索) は、異なるスコアリング方法で並べ替えられます。</p><p>利用可能なアプローチはいくつかありますが、その中には<a href="https://www.elastic.co/docs/solutions/search/ranking/learning-to-rank-ltr">Learning-To-Rank (LTR)</a>や<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion">Reciprocal Rank Fusion (RRF)</a>などがあります。LTR は、検索結果の特徴 (いいね、評価、クリックなど) をキャプチャし、それらを使用して結果にスコアを付けたり、結果をブーストしたり、バイアスをかけたりするのに役立ちます。RRFは、異なるクエリモダリティから返された結果をマージするのに最適です（例：語彙データベース検索とベクトルデータベース検索を 1 つの結果リストにまとめます。Elastic は、<a href="https://www.elastic.co/search-labs/blog/linear-retriever-hybrid-search">線形再ランキング</a>方式を使用してスコアを調整する柔軟性も提供します。</p><p>ただし、最も効果的な再ランキング手法の 1 つは、<a href="https://www.elastic.co/docs/solutions/search/ranking/semantic-reranking">セマンティック再ランキング</a>です。これは、LLM のセマンティック理解を使用して、クエリと結果の両方のベクトル埋め込みを分析し、関連性スコアリング/再スコアリングを適用して最終的な順序を決定します。もちろん、セマンティック再ランク付けには再ランク付けモデルへの接続が必要です 。Elasticsearch は、組み込みモデル (<a href="https://www.elastic.co/docs/explore-analyze/machine-learning/nlp/ml-nlp-rerank"> Elastic Rerank</a> )、<a href="https://www.elastic.co/docs/reference/elasticsearch/clients/eland/machine-learning"> インポートされた</a> サードパーティモデル、または<a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-cohere"> Cohere</a> や<a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-googlevertexai"> Google Vertex AI</a><strong> などの外部でホストされるサービスを活用する 再ランク付け</strong> エンドポイントを作成できる推論<a href="https://www.elastic.co/docs/api/doc/elasticsearch/group/endpoint-inference"> API</a> を提供します。次に、<a href="https://www.elastic.co/docs/solutions/search/retrievers-overview">リトリーバー</a>クエリ抽象化構文を使用して再ランク付けを実行できます。</p>POST my-index/_search 
{
  "size": 10,
  "retriever": {
    "text_similarity_reranker": {
      "retriever": {
        "rrf": {
          "retrievers": [
            {
              "standard": {
                "query": {
                  "multi_match": {
                    "query": "machine learning applications",
                    "fields": ["title", "content"]
                  }
                }
              }
            },
            {
              "knn": {
                "field": "semantic-content-field",
                "k": 10,
                "num_candidates": 100,
                "query_vector_builder": {
                  "text_embedding": {
                    "model_id": "my-text-embedding-model",
                    "model_text": "machine learning applications"
                  }
                }
              }
            }
          ],
          "rank_window_size": 50,
          "rank_constant": 20
        }
      }
    },
    "field": "content",
    "inference_id": "my-reranker",
    "inference_text": "machine learning applications",
    "rank_window_size": 20
  }
}<p><em>多段階リトリーバー再ランキング操作の例</em></p><p>素晴らしいですね。さまざまなソースからの結果の再ランキングを実行し、あらゆる種類のコンテンツの意味的理解に近づくことができます。意味的再ランキングは、計算コストと必要な処理時間の両方でコストがかかる可能性があり、そのため、意味的再ランキングは限られた数の結果に対してのみ実行できます。つまり、最初の結果を<em>どのように</em>取得するかが重要になります。</p><h3>文脈検索方法が重要</h3><p>主観的な意図は、結果の正確性を判断し、関連性を評価する上で重要な要素です。クエリを実行するユーザーの意図（柔軟な構文または第 2 段階の再ランク付けによって表現される）を考慮する機能がなければ、モデル空間内にすでにエンコードされている既存のコンテキストから選択することしかできません。このコンテキストの欠如に対処する一般的な方法は、<a href="https://en.wikipedia.org/wiki/Retrieval-augmented_generation">検索拡張生成 (RAG)</a>などの手法を使用することです。RAG の仕組みは、文脈的に関連するデータの事前クエリから返された追加の関連用語を含めることで、クエリの座標を効果的にシフトすることです。そのため、追加のコンテキストを提供するエンジンと、検索を実行するため<em>の</em>初期方法が、コンテキストの正確さにとってさらに重要になります。</p><p>さまざまなコンテキスト取得方法と、それが RAG 操作にどのように役立つか、または悪影響を与えるかを確認しましょう。</p><ul><li><p><strong>検索エンジンを使用しないハイブリッド検索では、依然として主観的な関連性が欠けています。</strong>RAG を提供するプラットフォームが主に SQL ベースである場合 (ほとんどの「データ レイク」プラットフォームが含まれます)、最初の検索段階で関連性スコアリングが欠如しています。多くのデータ レイク プラットフォームは、独自のハイブリッド検索 (検索ではない) を提供しており、通常は SQL ベースの検索とベクター データベースの結果にセマンティック リランキングや RRF などの再ランキング手法を組み合わせています。単純なソートは主観的なランキング付けには明らかに不十分ですが、第 2 段階のセマンティック リランキング操作の基礎として使用した場合でも、第 1 段階の検索としての SQL では、セマンティック リランキングが「上位 k」のヒットに対してのみ実行される場合に問題が生じます。検索時に結果にスコアを付ける方法がなければ、<em>最善の</em>結果が実際に上位の結果にあるという保証はありません。</p></li><li><p><strong>ベクトルの類似性だけでは RAG には不十分です</strong>。これは実際には、一連の問題が複合的に絡み合った結果です。つまり、埋め込みの損失、単純なチャンク化方法、類似性の計算方法、そして主観的な意図という重要な要素が欠落しているという問題です。RAG の主な目標の 1 つは、生成 AI のインタラクションを客観的な真実に基づいて確立することです。これにより、幻覚を防ぐと同時に、トレーニング中に認識されなかったプライベート情報を LLM に通知します。RAG を通じて提供される追加のコンテキストを使用して、手近の質問に答えるために最も重要であることがわかっている接続と詳細を考慮するように LLM を制限および指示できます。そのためには、意味論的アプローチと語彙的アプローチの<em>両方</em>を使用する必要があります。</p></li><li><p><strong>ファイルベースの grep/regex RAG。</strong>エージェント AI の世界では、外部の検索プラットフォームではなく、RAG の grep と regex を介してローカル ファイルにアクセスする、大幅に拡大されたコンテキスト ウィンドウの使用を指摘する<a href="https://www.nicolasbustamante.com/p/the-rag-obituary-killed-by-agents">声</a>も上がっています。その考え方は、はるかに大きなコンテキスト ウィンドウを利用できることで、LLM が、関連情報を収集するために断片的な情報や複数の検索方法/プラットフォームに頼るのではなく、独自の思考空間内で概念的なつながりを構築できるようになるというものです。理論上は、文書全体があれば文書セグメントよりも完全な画像が得られるというのは本当ですが、これは小さなデータドメインでのみ機能します (または、たとえば、 <a href="https://en.wikipedia.org/wiki/Vibe_coding">vibecoding</a>にファイルを提供する場合)。また、その場合でも、最初の検索方法は、キーワードのみが一致するすべての文書をスキャンすることです。</p></li></ul><p><strong>検索は単なる回収以上のもの</strong></p><p>検索エンジンは、クエリを可能な限り高速かつ柔軟に実行することを目的として構築されています。内部的には、さまざまな種類のデータをそれらのデータ型に適した方法で保存および取得するための特殊なデータ構造を利用します。Elasticsearchは、非構造化/全文語彙検索（一致、フレーズ、近接、複数一致）、高速キーワード（完全一致）マッチングとフィルタリング、数値範囲、日付、IPアドレスなど、基本的にすべてのタイプのデータの最適化された保存とクエリを提供し、ドキュメント構造（例：ネストされたドキュメントやフラット化されたドキュメントなど)。Elasticsearch は、スパース ベクトル タイプと密ベクトル タイプの両方を保存およびクエリできるネイティブ ベクトル データベースでもあり、ベクトル化されたコンテンツに関連する速度、スケーラビリティ、コストを改善しながら検索の忠実度を維持するための革新的な方法 ( <a href="https://www.elastic.co/search-labs/blog/better-binary-quantization-lucene-elasticsearch">Better Binary Quantization (BBQ)</a>や<a href="https://www.elastic.co/search-labs/blog/diskbbq-elasticsearch-introduction">DiskBBQ</a>など) を継続的に模索しています。Elasticsearch プラットフォームには、組み込みのデータ回復力と高可用性も備わっており、<a href="https://www.elastic.co/docs/deploy-manage/tools/snapshot-and-restore/searchable-snapshots">検索可能なスナップショット</a>などのデータライフサイクル管理機能も含まれています。検索可能なスナップショットを使用すると、アクセス頻度の低いデータや長期保存データをコスト効率の高いオブジェクトストレージに保存しながらも、完全に検索可能です。</p><h3>ハイブリッド検索はあらゆる面で最高です</h3><p><a href="https://www.elastic.co/what-is/hybrid-search">ハイブリッド検索</a>(単なるハイブリッド取得ではありません!)従来の語彙検索の長所と、LLM の意味理解およびベクトル類似性検索を組み合わせます。この相乗効果により、検索エンジンが提供する柔軟なクエリ構文オプション（意図主導型の構文オプションと関連性スコアリング、マルチモーダル データ検索、フィルタリング、集約、バイアスなど）を通じて、<em>検索</em>段階で関連性の高い結果をターゲットにすることができます。<a href="https://www.elastic.co/docs/reference/query-languages/esql">ES|QL</a>やマルチステージ<a href="https://www.elastic.co/docs/solutions/search/retrievers-overview">リトリーバー</a>などの検索構文を使用すると、従来の検索とセマンティック検索、フィルター、複数の再ランキング手法をすべて 1 つのリクエストで柔軟に組み合わせることができます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6ee9512910856ee3/6a17053fcdacbf2ea97d291e/f25180cb430414b99ae553d3b8eb161dbccea4d4-1920x1080.png" alt="ハイブリッド検索の仕組み" /><p>ハイブリッド検索の最大の利点の 1 つは、クエリで複数の異なるデータ タイプに同時に特殊な構文を使用できることです。これらのさまざまなクエリ構文は、結果の<em>検索</em>だけでなく、結果<em>の</em>フィルターや集計としても使用できます。たとえば、他の構文と頻繁に組み合わせられる最も一般的なクエリ タイプの 1 つは、<a href="https://www.elastic.co/docs/explore-analyze/geospatial-analysis">地理空間分析</a>です。特定のポイントから指定された距離内の地理座標を持つ結果をクエリしたり、地域別に結果の集計を要求したり、ゾーンへの出入りの動きを追跡してアラートを発する集計を実行したりできます。ハイブリッド検索を使用すると、構文を柔軟に組み合わせて、最も正確な方法で結果をターゲットにし、コンテキストに最も近いコンテンツを取得できます。</p><h2>休憩</h2><p>この最初の部分では、ベクトル検索によってデータの取得方法がどのように変化したかを説明し、LLM がデータの操作に使用するクエリ メカニズムにもたらした変化の基礎を説明します。LLM がコンテキストを失うことなく理解できるように、これを複数の部分に分割する必要があったと仮定します... ;-)<em>これがなぜ重要なのか</em>については<a href="https://www.elastic.co/search-labs/blog/context-engineering-llm-evolution-agentic-ai">、パート II: エージェント AI とコンテキスト エンジニアリングの必要性</a>で詳しく説明し、パート III ではハイブリッド検索について再び説明します。</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-evolution-agentic-ai</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-evolution-agentic-ai</guid>
    <category><![CDATA[ハイブリッド検索]]></category>
    <category><![CDATA[関連性]]></category>
    <dc:creator><![CDATA[Woody Walton]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc49e39872984c8eb/6a1705410e2e49e42c419fd5/7e59a0671aa9ea32d68188a693936a66ebf48625-1000x628.png" length="0" type="image/png"/>
    <pubDate>Wed, 12 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[ハイブリッド検索の再考: Elasticsearch の線形リトリーバーの導入!]]></title>
    <description><![CDATA[線形リトリーバーが加重スコアと MinMax 正規化を活用してハイブリッド検索を強化し、より正確で一貫性のあるランキングを実現する方法を確認し、その使用方法を学びます。]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/jp/search-labs/blog/elasticsearch-retrievers-ga-8.16.0">前回のブログ</a>投稿では、複雑なランキング パイプラインの作成を可能にする、ゼロから再設計されたリトリーバー フレームワークを紹介しました。また、Reciprocal Rank Fusion (RRF) リトリーバーが、異なるクエリの結果を結合してハイブリッド検索を可能にする方法についても調査しました。RRF は簡単に実装できますが、実際のスコアを無視して相対的なランクのみに焦点を当てるという、顕著な制限があります。これにより、微調整と最適化が困難になります。</p><h2>リニアレトリーバーに会いましょう！</h2><p>この投稿では、ハイブリッド検索をサポートするために最近追加された<a href="https://www.elastic.co/jp/docs/solutions/search/retrievers-overview#retrievers-overview-types"><code>linear</code></a><a href="https://www.elastic.co/jp/docs/solutions/search/retrievers-overview#retrievers-overview-types">リトリーバー</a>を紹介します。<code>rrf</code>とは異なり、 <code>linear</code>リトリーバーはドキュメントに一致したすべてのクエリの加重合計を計算します。このアプローチにより、結果セット内の各ドキュメントの相対的な重要度が維持され、各クエリが最終スコアに与える影響を正確に制御できるようになります。その結果、ハイブリッド検索を微調整するためのより直感的で柔軟な方法が提供されます。</p><p>最終スコアが次のように計算される線形リトリーバーを定義します。</p><p>それは次のように簡単です:</p>GET linear_retriever_blog/_search
{
   "retriever": {
       "linear": {
           "retrievers": [
               {
                   "retriever": {
                       "knn": {
                          ...
                        }
                    },
                   "weight": 5
               },
                  {
                   "retriever": {
                       "standard": {
                          ...
                        }
                    },
                   "weight": 1.5
               },


           ]
        }
     }
}<p>いかにシンプルで直感的であるかに気づきましたか?（そして<code>rrf</code>と本当に似ています！）この構成により、相対的な順位のみに依存する<code>rrf</code>とは異なり、各クエリ タイプが最終的な順位にどの程度寄与するかを正確に制御できます。</p><p>注意点が 1 つあります: 使用される類似度メトリックに応じて、 <code>knn</code>スコアは厳密に制限される場合があります。たとえば、コサイン類似度または単位正規化ベクトルのドット積では、スコアは常に<code>[0, 1]</code>範囲内になります。対照的に、 <code>bm25</code>スコアは予測しにくく、明確に定義された境界がありません。</p><h2>スコアのスケーリング：kNN vs BM25</h2><p>ハイブリッド検索の課題の 1 つは、異なるリトリーバーが異なるスケールでスコアを生成することです。たとえば、次のシナリオを考えてみましょう。</p><p>クエリAのスコア:</p><p></p><p>ドキュメント1</p><p>ドキュメント2</p><p>ドキュメント3</p><p>ドキュメント4</p><p>わかる</p><p>0.347</p><p>0.35</p><p>0.348</p><p>0.346</p><p>bm25</p><p>100</p><p>1.5</p><p>1</p><p>0.5</p><p>クエリBのスコア:</p><p></p><p>ドキュメント1</p><p>ドキュメント2</p><p>ドキュメント3</p><p>ドキュメント4</p><p>わかる</p><p>0.347</p><p>0.35</p><p>0.348</p><p>0.346</p><p>bm25</p><p>0.63</p><p>0.01</p><p>0.3</p><p>0.4</p><p>上記の差異を見ると、 <code>kNN</code>スコアは 0 から 1 の範囲であるのに対し、 <code>bm25</code>スコアは大きく変動する可能性があります。この違いにより、結果を組み合わせるための静的な最適な重みを設定することが難しくなります。</p><h2>正規化による救済：MinMax正規化</h2><p>この問題を解決するために、次の数式を使用して、クエリごとに独立してスコアを<code>[0, 1]</code>範囲にスケーリングするオプションの<code>minmax</code>ノーマライザーを導入しました。</p><p>これにより、クエリの結果セット内の各ドキュメントの相対的な重要度が保持され、異なるリトリーバーからのスコアを簡単に組み合わせることができます。正規化すると、スコアは次のようになります。</p><p>クエリAのスコア:</p><p></p><p>ドキュメント1</p><p>ドキュメント2</p><p>ドキュメント3</p><p>ドキュメント4</p><p>わかる</p><p>0.347</p><p>0.35</p><p>0.348</p><p>0.346</p><p>bm25</p><p>1.00</p><p>0.01</p><p>0.005</p><p>0.000</p><p>クエリBのスコア:</p><p></p><p>ドキュメント1</p><p>ドキュメント2</p><p>ドキュメント3</p><p>ドキュメント4</p><p>わかる</p><p>0.347</p><p>0.35</p><p>0.348</p><p>0.346</p><p>bm25</p><p>1.00</p><p>0.000</p><p>0.465</p><p>0.645</p><p>すべてのスコアが<code>[0, 1]</code>範囲内に収まるようになり、絶対スコアではなく結果の (クエリに対する相対的な) 重要度を取得し、クエリ間で一貫性を維持できるようになったため、加重合計の最適化がはるかに簡単になりました。</p><h2>リニアリトリーバーの例 </h2><p>ここで例を見て、上記がどのようになっているか、また<code>linear</code>リトリーバーが<code>rrf</code>の欠点のいくつかをどのように解決しているかを見てみましょう。RRF は相対的なランクのみに依存し、実際のスコアの違いは考慮しません。たとえば、次のスコアがあるとします。</p><p></p><p>ドキュメント1</p><p>ドキュメント2</p><p>ドキュメント3</p><p>ドキュメント4</p><p>わかる</p><p>0.347</p><p>0.35</p><p>0.348</p><p>0.346</p><p>bm25</p><p>100</p><p>1.5</p><p>1</p><p>0.5</p><p>rrfスコア</p><p>0.03226</p><p>0.03252</p><p>0.03200</p><p>0.03125</p><p>rrf はドキュメントを次のようにランク付けします。</p><p>ただし、doc1 は他のものと比べて<code>bm25</code>スコアが大幅に高くなっていますが、 <code>rrf</code>相対的な順位のみを見ているため、これを捕捉できません。<code>linear</code>リトリーバーは正規化と組み合わせることで、スコアとその差異の両方を正しく考慮し、より意味のあるランキングを生成します。</p><p></p><p>ドキュメント1</p><p>ドキュメント2</p><p>ドキュメント3</p><p>ドキュメント4</p><p>わかる</p><p>0.347</p><p>0.35</p><p>0.348</p><p>0.346</p><p>bm25</p><p>1</p><p>0.01</p><p>0.005</p><p>0</p><p>上記のように、doc1 の優れたランキングと<code>bm25</code>の<code>score</code>が適切に考慮され、最終スコアに反映されています。さらに、すべてのスコアが<code>[0, 1]</code>範囲内にあるため、より直感的な方法でスコアを比較および組み合わせることができます (さらに、オフラインの最適化プロセスを構築することもできます)。</p><h2>すべてをまとめると</h2><p>正規化を伴う<code>linear</code>リトリーバーを最大限に活用するには、検索リクエストは次のようになります。</p>GET linear_retriever_blog/_search
{
   "retriever": {
       "linear": {
           "retrievers": [
               {
                   "retriever": {
                       "knn": {
                          ...
                        }
                    },
                   "weight": 5
               },
                  {
                   "retriever": {
                       "standard": {
                          ...
                        }
                    },
                   "weight": 1.5,
                   "normalizer": "minmax"
               },


           ]
       }
   }
}<p>このアプローチは、両方の長所を組み合わせたものです。つまり、 <code>linear</code>リトリーバーの柔軟性と直感的なスコアリングを維持しながら、MinMax 正規化による一貫したスコア スケーリングを保証します。</p><p>すべてのリトリーバーと同様に、 <code>linear</code>リトリーバーは、説明可能性、一致の強調表示、フィールドの折りたたみなどをサポートし、階層的なリトリーバー ツリーの任意のレベルに統合できます。</p><h2>リニアレトリーバーを選ぶべきタイミングとそれが重要な理由</h2><p><code>linear</code>レトリーバー:</p><ul><li><p>ランクだけでなく実際のスコアを活用して相対的な重要性を維持します。</p></li><li><p>さまざまなクエリからの重み付けされた寄与による微調整を可能にします。</p></li><li><p>正規化を使用して一貫性を強化し、ハイブリッド検索をより堅牢かつ予測可能にします。</p></li></ul><h2>まとめ</h2><p><code>linear</code>リトリーバーは、Elasticsearch Serverless、8.18 および 9.0 リリースですでに利用可能です。その他の例と構成パラメータについては、ドキュメントでも参照できます。ぜひお試しいただき、ハイブリッド検索エクスペリエンスがどのように改善されるかをご確認ください。皆様からのフィードバックをお待ちしております。楽しい検索を！</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/linear-retriever-hybrid-search</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/linear-retriever-hybrid-search</guid>
    <category><![CDATA[関連性]]></category>
    <category><![CDATA[ハイブリッド検索]]></category>
    <dc:creator><![CDATA[Panagiotis Bailis]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte58a751cbcc1153d/6a17e3c76317305c4f585a10/7a07e27e3095463ff93b4cb7f8a0cf3b8e44eab0-1777x1000.png" length="0" type="image/png"/>
    <pubDate>Wed, 28 May 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Quepidでジャッジメントリストを作成する]]></title>
    <description><![CDATA[Quepidで人間の評価者が協力して判定リストを作成する方法、ベンチマークを使用して関連性を調整する方法を学びます。]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/search-labs/blog/judgment-lists">判断リスト</a>の作成は、検索結果の品質を最適化する上で重要なステップですが、複雑で困難な作業になる場合があります。判断リストは、対応する結果の関連性評価と組み合わせた検索クエリの厳選されたセットであり、テスト コレクションとも呼ばれます。このリストを使用して計算されたメトリックは、検索エンジンのパフォーマンスを測定するためのベンチマークとして機能します。判断リストの作成プロセスを効率化するために、 <a href="https://opensourceconnections.com/">OpenSource Connections</a>チームは<a href="https://quepidapp.com/">Quepid を</a>開発しました。判断は明示的なものでも、ユーザーからの暗黙的なフィードバックに基づくものでも構いません。このブログでは、あらゆる判断リストの基礎となる明示的な判断を人間の評価者が効果的に行えるように、Quepid で共同作業環境を設定する方法について説明します。</p><p>Quepid は、検索品質評価プロセスにおいて検索チームをサポートします。</p><ul><li><p>クエリセットを構築する</p></li><li><p>判断リストを作成する</p></li><li><p>検索品質指標を計算する</p></li><li><p>計算された検索品質指標に基づいて、さまざまな検索アルゴリズム/ランカーを比較します</p></li></ul><p>私たちのブログでは、映画レンタル店を運営しており、検索結果の品質を向上させることを目標としていると仮定しましょう。</p><h2>要件</h2><p>このブログでは<a href="https://github.com/o19s/es-tmdb">、es-tmdb リポジトリ</a>のデータとマッピングを使用します。データは<a href="https://www.themoviedb.org/">The Movie Database</a>から取得されています。手順に沿って、マッピングを使用して tmdb というインデックスを設定し、データにインデックスを付けます。ローカルインスタンスをセットアップするか、Elastic Cloud デプロイメントを使用するかは問題ではありません。どちらでも問題なく動作します。このブログでは、Elastic Cloud のデプロイメントを想定しています。データのインデックス作成方法については<a href="https://github.com/o19s/es-tmdb/blob/master/README.md">、es-tmdb リポジトリの README を</a>参照してください。</p><p>検索するデータがあることを確認するには、 <code>rocky</code>のタイトル フィールドで単純な一致クエリを実行します。</p>GET tmdb/_search
{
 "query": {
   "match": {
     "title": "rocky"
   }
 }
}<p>8 件の結果が表示されます。</p>{
 "took": 2,
 "timed_out": false,
 "_shards": {
   "total": 1,
   "successful": 1,
   "skipped": 0,
   "failed": 0
 },
 "hits": {
   "total": {
     "value": 8,
     "relation": "eq"
   }
…
}<h2>Quepidにログイン</h2><p><a href="https://github.com/o19s/quepid">Quepid は</a>、ユーザーが検索結果の品質を測定し、オフライン実験を実行して品質を向上できるようにするツールです。</p><p>Quepid は 2 つの方法で使用できます: <a href="https://app.quepid.com">https://app.quepid.com</a>で公開されている無料のホストバージョンを使用するか、または、アクセスできるマシンに Quepid をセットアップします。この投稿では、無料のホスト バージョンを使用していることを前提としています。ご使用の環境に Quepid インスタンスを設定する場合は、<a href="https://github.com/o19s/quepid/wiki/Installation-Guide">インストール ガイド</a>に従ってください。</p><p>どちらの設定を選択する場合でも、まだアカウントをお持ちでない場合はアカウントを作成する必要があります。</p><h2>Quepidケースの設定方法</h2><p>Quepid は「ケース」を中心に構成されています。ケースには、関連性調整設定と検索エンジンへの接続を確立する方法とともにクエリが保存されます。</p><ul><li><p>初めて使用する場合は、 <strong>「最初の関連性ケースを作成する」</strong>を選択します。</p></li><li><p>再度アクセスしたユーザーは、トップレベルのメニューから<strong>[関連性ケース]</strong>を選択し、 <strong>[+ ケースを作成] を</strong>クリックできます。</p></li></ul><p>ベースライン検索の測定と改善を開始するため、ケースに説明的な名前を付けます (例:「映画検索ベースライン」)。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte2913d344c42cd24/6a17e6477b54f906b48b38bd/8f9e480d9aae0d706cfc5371e41f19c706dd452a-594x251.png" alt="Quepidケースの設定" /><p><strong>[続行]</strong>を選択して名前を確認します。</p><p>次に、Quepid から検索エンジンへの接続を確立します。Quepid は、Elasticsearch を含むさまざまな検索エンジンに接続できます。</p><p>構成は、Elasticsearch と Quepid の設定によって異なります。Quepid を Elastic Cloud デプロイメントに接続するには、Elastic Cloud デプロイメントに対して CORS を有効にして構成し、API キーを用意する必要があります。詳細な手順は、 <a href="https://quepid-docs.dev.o19s.com/2/quepid/49/how-to-connect-quepid-to-elastic-cloud">Quepid ドキュメントの対応するハウツー</a>に記載されています。</p><p>Elasticsearch エンドポイント情報 ( <code>https://YOUR_ES_HOST:PORT/tmdb/_search</code> ) と接続に必要な追加情報 (<strong>詳細</strong>設定オプションの Elastic Cloud デプロイメントの場合は API キー) を入力し、 <strong>ping</strong>をクリックして接続をテストし、 <strong>[続行</strong>] を選択して次のステップに進みます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcc068309bdc094ae/6a17e6480b0bed14cddd356a/267339dfaecae2740eb2ee2739bdc971608bdb5f-588x1169.png" alt="QuepidでElasticsearchエンドポイントを設定します。" /><p>ここで、ケースに表示するフィールドを定義します。人間の評価者が後で特定のクエリに対するドキュメントの関連性を評価するのに役立つものをすべて選択します。</p><p><code>title</code><em>タイトル フィールド</em>として設定し、 <code>_id</code> <em>ID フィールド</em>のままにして、 <code>overview, tagline, cast, vote_average, thumb:poster_path</code><em>追加表示フィールド</em>として追加します。最後のエントリには、結果内の映画の小さなサムネイル画像が表示され、私たちと人間の評価者に視覚的にガイドします。</p><p><strong>[続行]</strong>ボタンを選択して表示設定を確認します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc910bdf5aa7680b3/6a17e64ae8fbce710b3a1906/02c58aae8c2ebb6d31f538b27462b4c65428fdc3-594x493.png" alt="Quepidの人間評価者向けに、ケースで表示するフィールドを定義します。" /><p>最後のステップは、ケースに検索クエリを追加することです。入力フィールドから<em>「スターウォーズ」</em> 、 <em>「ハリソンフォード」</em> 、 <em>「ベストアクション映画」の</em>3 つのクエリを 1 つずつ追加し、 <strong>「続行」をクリックします</strong>。</p><p>理想的には、ケースには実際のユーザークエリを表し、さまざまな種類のクエリを示すクエリが含まれます。現時点では、<em>スターウォーズは</em>映画のタイトルのすべてのクエリを表すクエリ、<em>ハリソンフォードは</em>キャストメンバーのすべてのクエリを表すクエリ、<em>ベストアクション映画は</em>特定のジャンルの映画を検索するすべてのクエリを表すクエリであると想像できます。これは通常、クエリ セットと呼ばれます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt46122bb45e1063e4/6a17e64b505ac36510ad8af8/baccfe96766319aa7255e9bff08913ac87d1517f-595x326.png" alt="Quepidケースに検索クエリを追加する" /><p>実稼働シナリオでは、<a href="https://opensourceconnections.com/blog/2022/10/13/how-to-succeed-with-explicit-relevance-evaluation-using-probability-proportional-to-size-sampling/">確率比例サイズサンプリング</a>などの統計手法を適用してイベント トラッキング データからクエリをサンプリングし、これらのサンプリングされたクエリを Quepid にインポートして、頻度に応じて先頭 (頻繁に発生するクエリ) と末尾 (発生頻度の低いクエリ) のクエリを含めます。つまり、まれなクエリを除外することなく、より頻度の高いクエリに偏向させるということです。</p><p>最後に、 <strong>「完了」</strong>を選択すると、定義された 3 つのクエリが表示されるケース インターフェイスに移動します。</p><h2>クエリと情報ニーズ</h2><p>判断リストという全体的な目標に到達するには、人間の評価者が特定のクエリに対する検索結果 (通常はドキュメント) を判断する必要があります。これはクエリ/ドキュメント ペアと呼ばれます。</p><p>場合によっては、クエリを見るとユーザーが何を望んでいたかが簡単にわかるようです。クエリ<code>harrison ford</code>の目的は、俳優のハリソン・フォードが主演する映画を見つけることです。クエリ<code>action</code>についてはどうでしょうか?ユーザーの意図はアクション ジャンルに属する映画を見つけることだと言いたくなるでしょう。でもどれですか？最新のもの、最も人気のあるもの、ユーザーの評価による最高のものはありますか?あるいは、ユーザーは「アクション」と呼ばれるすべての映画を見つけたいのでしょうか?<a href="https://www.themoviedb.org/search/movie?query=Action">映画データベースには「アクション」というタイトルの映画が少なくとも 12 本 (!) あり</a>、それらの名前は主にタイトルに含まれる感嘆符の数によって異なります。</p><p>意図が不明瞭なクエリの場合、2 人の評価者の間で解釈に違いが生じる可能性があります。情報ニーズの登場:<a href="https://en.wikipedia.org/wiki/Information_needs">情報ニーズ</a>とは、情報に対する意識的または無意識的な欲求のことです。情報ニーズを定義すると、人間の評価者がクエリに対して文書を判断するのに役立つため、判断リストを構築するプロセスで重要な役割を果たします。専門ユーザーまたは主題の専門家は、情報ニーズを指定するのに適しています。検索結果はユーザーのニーズを満たす必要があるため、ユーザーの視点から情報ニーズを定義することをお勧めします。</p><p>「映画検索ベースライン」のケースのクエリに必要な情報:</p><ol><li><p><strong>スターウォーズ</strong>: ユーザーはスターウォーズシリーズの映画や番組を見つけたいと考えています。関連性がある可能性があるのは、スターウォーズに関するドキュメンタリーです。</p></li><li><p><strong>ハリソン・フォード</strong>: ユーザーは俳優ハリソン・フォードが主演する映画を見つけたいと考えています。関連性がある可能性があるのは、ハリソン・フォードがナレーターなどの別の役割を担っている映画です。</p></li><li><p><strong>最高のアクション映画</strong>: ユーザーはアクション映画、できれば平均ユーザー投票数の多い映画を見つけたいと考えています。</p></li></ol><h2>Quepidで情報ニーズを定義する方法</h2><p>Quepid で情報ニーズを定義するには、ケース インターフェースにアクセスします。</p><p>1. クエリ (たとえば、<em>スターウォーズ</em>) を開き、 <em>[Toggle Notes] を選択します。</em></p><p>2. 最初のフィールドに情報ニーズを入力し、2 番目のフィールドに追加のメモを入力します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte57395f64f6e5fab/6a17e64d6864a40fd6b68771/e01d3d5242a350d8797faa665eb3170039f5dfa2-1483x559.png" alt="Quepidで情報とクエリのニーズを定義します。" /><p>3. <strong>「保存」</strong>をクリックします。</p><p>少数のクエリの場合、このプロセスは適切です。ただし、ケースを 3 クエリから 100 クエリに拡張する場合 (Quepid のケースでは、多くの場合、クエリは 50 ～ 100 クエリの範囲です)、Quepid の外部で (たとえば、スプレッドシートで) 情報ニーズを定義し、それを<strong>[インポート</strong>] からアップロードして<strong>[情報ニーズ] を選択する必要がある</strong>場合があります。</p><h2>Quepidでチームを作成し、ケースを共有する</h2><p>共同判断により関連性評価の品質が向上します。チームを設定するには:</p><p>1. 最上位メニューの<strong>「Teams」</strong>に移動します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt45c51d1a0e05a80d/6a17e64fe8fbcede793a190f/797706e8d130b474a95d30b6fa22ecaf36f98c03-613x58.png" alt="Quepidでチームを作成します。" /><p>2. <strong>[+ 新規追加]</strong>をクリックし、チーム名 (例:「検索関連性評価者」) を入力して、 <strong>[作成] を</strong>クリックします。</p><p>3. メールアドレスを入力し、 <strong>「ユーザーの追加」</strong>をクリックしてメンバーを追加します。</p><p>4. ケースインターフェースで、 <strong>「ケースの共有」</strong>を選択します。</p><p>5. 適切なチームを選択して確認します。</p><h2>Quepidで判定ブックを作成する</h2><p>Quepid のブックでは、複数の評価者がクエリ/ドキュメントのペアを体系的に評価できます。作成するには:</p><p>1. ケースインターフェースの<strong>「判決」</strong>に移動し、 <strong>「+ ブックを作成」</strong>をクリックします。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3543c00e0b834b3f/6a17e650e9ea87f57fa9c598/6a077f26225961150b7414463d7db04f090b68d6-896x365.png" alt="Quepidで判定ブックを作成します。" /><p>2. ブックにわかりやすい名前を付けてチームに割り当て、採点方法 (DCG@10 など) を選択し、選択戦略 (単一または複数の評価者) を設定します。ブックには次の設定を使用します。</p><ul><li><p><strong>名称</strong>：「映画検索0-3スケール」</p></li><li><p><strong>この本を共有するチーム</strong>: 作成したチームのボックスにチェックを入れます</p></li><li><p><strong>得点者</strong>: DCG@10</p></li></ul><p>3. <strong>「ブックを作成」をクリックします。</strong></p><p>名前は説明的で、検索対象（「映画」）に関する情報と、評価のスケール（「0～3」）が含まれています。選択したスコアラー DCG@10 によって、検索メトリックの計算方法が決まります。「DCG」は<a href="https://en.wikipedia.org/wiki/Discounted_cumulative_gain">「Discounted Cumulative Gain」</a>の略で、「@10」は指標を計算する際に考慮される上位からの結果の数です。</p><p>この場合、情報ゲインを測定し、それを位置の重み付けと組み合わせるメトリックを使用しています。他にもユースケースに適した検索メトリックが存在する可能性があり、<a href="https://opensourceconnections.com/blog/2020/02/28/choosing-your-search-relevance-metric">適切なものを選択すること自体が課題となります</a>。</p><h2>クエリとドキュメントのペアをブックに入力する</h2><p>関連性評価のためにクエリ/ドキュメントのペアを追加するには、次の手順に従います。</p><p>1.ケース インターフェースで、「判決」に移動します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0e98583138535cc3/6a17e6520b0bed4f51dd3571/d717c5b06ae6cb42ed2b9e771486a12f738a9890-1041x218.png" alt="Quepidでクエリとドキュメントのペアをブックに入力します。" /><p>2. 作成したブックを選択します。</p><p>3. 「ブックに入力」をクリックし、「ブックのクエリ/ドキュメント ペアを更新」を選択して確認します。</p><p>このアクションにより、各クエリの上位の検索結果に基づいてペアが生成され、チームによる評価の準備が整います。</p><h2>人間の評価チームに判断させる </h2><p>これまでに完了した手順は、かなり技術的かつ管理的なものでした。必要な準備が完了したので、審査員チームに作業を任せることができます。本質的に、審査員の仕事は、与えられたクエリに対する特定の文書の関連性を評価することです。このプロセスの結果は、判断されたクエリ ドキュメント ペアのすべての関連性ラベルを含む判断リストです。次に、このプロセスとそのインターフェースについてさらに詳しく説明します。</p><h3>人間評価インターフェースの概要</h3><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt553afb07d8080421/6a17e654505ac30514ad8afc/be3016091b49655dab3354d84e6dc638f3468390-1283x664.png" alt="Quepidの人間評価インターフェースが文書やクエリにある情報を判断する方法。" /><p>Quepidの人間評価インターフェースは、効率的な評価ができるように設計されています。</p><ul><li><p><strong>クエリ:</strong>検索用語を表示します。</p></li><li><p><strong>情報ニーズ:</strong>ユーザーの意図を示します。</p></li><li><p><strong>採点ガイドライン:</strong>一貫した評価を行うための指示を提供します。</p></li><li><p><strong>ドキュメント メタデータ:</strong>ドキュメントに関する関連詳細を表示します。</p></li><li><p><strong>評価ボタン:</strong>評価者は対応するキーボード ショートカットを使用して判断を割り当てることができます。</p></li></ul><h3>人間評価インターフェースを使用する</h3><p>人間の評価者として、私は本の概要からインターフェースにアクセスします。</p><p>1. ケース インターフェイスに移動し、 <strong>[判決]</strong>をクリックします。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0e98583138535cc3/6a17e6520b0bed4f51dd3571/d717c5b06ae6cb42ed2b9e771486a12f738a9890-1041x218.png" alt="Quepid人間評価インターフェースを使用する " /><p>2. <strong>「より多くの判断が必要です!」</strong>をクリックします。</p><p>システムはまだ評価されておらず、追加の判断が必要なクエリ/ドキュメントのペアを提示します。これは、ブックの選択戦略によって決まります。</p><ul><li><p><em>単一の評価者</em>: クエリ/ドキュメントのペアごとに 1 つの判断。</p></li><li><p><em>複数の評価者</em>: クエリ/ドキュメントのペアごとに最大 3 つの判断。</p></li></ul><h3>クエリとドキュメントのペアを評価する</h3><p>いくつかの例を見てみましょう。このガイドに従うと、さまざまな映画が表示される可能性が高くなります。ただし、評価の原則は変わりません。</p><p>最初の例は、映画「Heroes」でクエリ<em>「harrison ford」</em>を検索するものです。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta248e787b5e0a670/6a17e656ec0f89612d5a65ee/c1e14b0d8b04dd579471932dbe4ff72ae5692a02-981x571.png" alt="Quepidでブックにクエリとドキュメントペアを入力する方法" /><p>まずクエリを確認し、次に情報ニーズを確認し、最後に指定されたメタデータに基づいて映画を判断します。</p><p>この映画は、ハリドソン・フォードが出演しているため、私たちの検索に関連する結果です。私たちは主観的には最近の映画の方が関連性が高いと考えるかもしれませんが、これは私たちの情報ニーズには含まれません。したがって、この文書は当社の評価尺度で 3 に相当する「完璧」と評価されます。</p><p>次の例は、映画「フォードvsフェラーリ」のクエリ<em>「harrison ford」</em>です。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf5d86aac918a1e96/6a17e657414c64833e945152/052af7894506d7a765af156ba8e26ceec3559973-981x789.png" alt="Quepidのクエリ「harrison ford」に対する映画「フォード対フェラーリ」の例。" /><p>同じ慣例に従い、クエリ、情報ニーズ、そしてドキュメントのメタデータが情報ニーズにどの程度一致しているかを見て、このクエリ/ドキュメントを判断します。</p><p>これは悪い結果です。この結果は、おそらく、クエリ用語の 1 つである「ford」がタイトルに一致していることを示していると思われます。しかし、ハリソン・フォードはこの映画でも他の役でも何の役も演じていない。したがって、この文書は「悪い」と評価され、これは当社の評価尺度では 0 に相当します。</p><p>3番目の例は、クエリ<em>「ベストアクション映画</em>」に対する映画「アクションジャクソン」です。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2cee335ddd1e6a92/6a17e6596df731d1f40a0ed7/247ab862fbc7435537709f8c96619cb331133d09-985x606.png" alt="クエリ「best action movie」に対する「アクション・ジャクソン」の例。" /><p>これはアクション映画のように見えるので、情報ニーズは少なくとも部分的に満たされています。しかし、投票平均は10点満点中5.4点です。そのため、この映画はおそらく私たちのコレクションの中で最高のアクション映画ではないでしょう。したがって、審査員である私としては、この文書を「普通」と評価します。これは、当社の評価尺度では 1 です。</p><p>これらの例は、特に Quepid を使用してクエリ/ドキュメントのペアを評価するプロセスを、高レベルと全般にわたって示しています。</p><h2>人間評価者の最適な活用のヒント</h2><p>示された例を見ると、明確な判断に至るのは簡単そうに思えるかもしれません。しかし、信頼できる人間による評価プログラムを構築するのは簡単なことではありません。これは、データの品質を簡単に損なう可能性のある課題に満ちたプロセスです。</p><ul><li><p>人間の評価者は反復的な作業で疲れてしまうことがあります。</p></li><li><p>個人的な好みにより判断が歪む可能性があります。</p></li><li><p>分野の専門知識のレベルは裁判官によって異なります。</p></li><li><p>評価者は多くの場合、複数の責任を同時にこなします。</p></li><li><p>ドキュメントの認識された関連性は、クエリに対する実際の関連性と一致しない場合があります。</p></li></ul><p>これらの要因により、一貫性のない低品質の判断が生じる可能性があります。しかし、心配する必要はありません。これらの問題を最小限に抑え、より堅牢で信頼性の高い評価プロセスを構築するのに役立つ、実証済みのベスト プラクティスがあります。</p><ul><li><p><strong>一貫した評価:</strong>クエリ、情報ニーズ、ドキュメント メタデータを順番に確認します。</p></li><li><p><strong>ガイドラインを参照してください:</strong>一貫性を保つためにスコアリング ガイドラインを使用します。採点ガイドラインには、どのグレードをいつ適用するかの例など、審査プロセスを示すものが含まれます。最初の一連の判断の後に人間の評価者とチェックインすることは、困難なエッジケースや追加のサポートが必要な場所を知るための良い方法であることが証明されました。</p></li><li><p><strong>オプションを活用する:</strong>不明な場合は、「後で判断します」または「わかりません」を使用し、必要に応じて説明を加えます。</p></li><li><p><strong>休憩を取る:</strong>定期的に休憩を取ると判断力を維持するのに役立ちます。Quepid は、人間の評価者が一連の判定を終えるたびに紙吹雪を飛ばして、定期的な休憩を促します。</p></li></ul><p>これらの手順に従うことで、Quepid で判断リストを作成するための構造化された共同アプローチを確立し、検索関連性の最適化の取り組みの有効性を高めることができます。</p><h2>今後の見通し</h2><p>ここからどこへ行くのでしょうか?判断リストは、検索結果の品質を向上させるための基本的なステップの 1 つにすぎません。次の手順は次のとおりです。</p><h3>指標を計算して実験を始める</h3><p>判断リストが利用可能になると、その判断を活用して<a href="https://opensourceconnections.com/blog/2020/02/28/choosing-your-search-relevance-metric/">検索品質メトリック</a>を計算するのは自然な流れになります。Quepid は、判断が可能な場合、現在のケースに対して構成されたメトリックを自動的に計算します。メトリックは「スコアラー」として実装されており、サポートされているメトリックにお気に入りのメトリックが含まれていない場合は、独自のメトリックを提供できます。</p><p>ケース インターフェイスに移動し、 <strong>[スコアラーの選択]</strong>に移動して、 <em>DCG@10</em>を選択し、 <strong>[スコアラーの選択]</strong>をクリックして確認します。Quepid はクエリごとに DCG@10 を計算し、全体的なクエリの平均も計算して、ケースの検索結果の品質を定量化します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0d059c959b842139/6a17e65be8fbceb29b3a1913/0ff3b9918342071744d681a43d542102e927abd3-1163x551.png" alt="Quepidで検索結果の品質を定量化する方法。 " /><p>検索結果の品質が定量化されたので、最初の実験を実行できます。実験は仮説を立てることから始まります。評価を行った後のスクリーンショットの 3 つのクエリを見ると、検索品質メトリックの点から見ると 3 つのクエリのパフォーマンスが大きく異なることが明らかです。 <em>「スターウォーズ」</em>のパフォーマンスはかなり良好で、 <em>「ハリソンフォード」</em>も悪くありませんが、最も大きな可能性を秘めているのは<em>「ベストアクション映画」です</em>。</p><p>このクエリを拡張すると、その結果が表示され、細かい詳細まで掘り下げて、ドキュメントが一致した理由やスコアに影響を与えるものを調べることができます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt35227761f4524a1e/6a17e65cb1e11325c579f25a/c45c6cae085a492198c0f8b7060a1a7204e3724e-1131x691.png" alt="さまざまなクエリを試して、Quepidのさまざまな検索指標でどのように機能するかを確認しています。" /><p>「クエリの説明」をクリックして「解析」タブに入ると、クエリが<em>キャスト</em>、<em>概要</em>、<em>タイトルの</em>3つのフィールドを検索するDisjunctionMaxxQueryであることがわかります。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0966653b9ab3cc9c/6a17e65efaa913171f93c84c/4a1e1bb2a9cd28e9c48e0ba16357d17ed9d3a5cf-894x557.png" alt="クエリの解析を説明しています" /><p>通常、検索エンジニアとして私たちは、検索プラットフォームに関するドメイン固有の情報をある程度知っています。この場合、<em>ジャンル</em>フィールドがあることが分かります。これをクエリに追加して、検索品質が向上するかどうかを確認しましょう。</p><p><strong>ケース インターフェースで[関連性の調整]</strong> を選択すると開く<strong> クエリ サンドボックス</strong> を使用します。検索する<em>ジャンル</em>フィールドを追加して、これを探索してみましょう。</p>{
  "query": {
    "multi_match": {
      "query": "#$query##",
      "type": "best_fields",
      "fields": [
        "title^10",
        "overview",
        "cast",
        "genres"
      ]
    }
  }
}<p>「検索を再実行」をクリックしてください。そして結果を確認します。彼らは変わったのでしょうか？残念ながらそうではありません。現在、探索できるオプションは多数あり、基本的には Elasticsearch が提供するすべてのクエリ オプションがあります。</p><ul><li><p>ジャンルフィールドのフィールドウェイトを増やすことができます。</p></li><li><p>投票平均によってドキュメントをブーストする関数を追加できます。</p></li><li><p>ジャンルの一致が強い場合にのみ投票平均によってドキュメントをブーストする、より複雑なクエリを作成することもできます。</p></li><li><p>…</p></li></ul><p>これらすべてのオプションを Quepid で検討することの最大の利点は、改善しようとしている 1 つのクエリだけでなく、この場合のすべてのクエリへの影響を定量化できる点です。これにより、他のクエリの検索結果の品質を犠牲にして、パフォーマンスの低いクエリを改善することが防止されます。リスクなしで迅速かつ安価に反復して仮説の価値を検証できるため、オフライン実験はすべての検索チームの基本的な機能になります。</p><h3>評価者間の信頼性を測定する</h3><p>タスクの説明、情報のニーズ、そして Quepid が提供するような人間の評価者インターフェースがあっても、人間の評価者の間で意見の相違が生じる可能性があります。</p><p>意見の相違自体は悪いことではありません。むしろその逆です。意見の相違を測定することで、取り組むべき問題が明らかになることがあります。関連性は主観的である可能性があり、クエリはあいまいであり、データは不完全または不正確である可能性があります。<a href="https://en.wikipedia.org/wiki/Fleiss%27_kappa">Fleiss の Kappa</a>は評価者間の一致を測る統計的尺度であり、Quepid には使用できるサンプルノートブックがあります。これを見つけるには、最上位のナビゲーションで[ノートブック]を選択し、 例の<strong> フォルダーにあるノートブック Fleiss Kappa.ipynb</strong> を選択します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt92d52b30f1fb19c1/6a17e660abe0f2224bdfe9bb/f0669ae96371368ef4d84bb28669560ef09d755c-624x61.png" alt="Quepidで、評価者間の一致度を測定するFleissのKappa統計指標のノートブックを見つける方法。" /><h2>まとめ</h2><p>Quepid は、最も複雑な検索関連性の課題にも対処できるようにし、進化し続けています。<a href="https://github.com/o19s/quepid/blob/main/CHANGELOG.md#800----2024-02-14">バージョン 8 では、Quepid は AI 生成の判断をサポートしており</a>、これは判断生成プロセスを拡大したいチームにとって特に便利です。</p><p>Quepid ワークフローを使用すると、スケーラブルな判断リストを効率的に作成できるため、最終的にはユーザーのニーズを真に満たす検索結果が得られます。判断リストを確立すると、検索の関連性を測定し、改善を繰り返し、ユーザー エクスペリエンスを向上させるための強固な基盤が得られます。</p><p>先に進む際には、関連性の調整は継続的なプロセスであることを忘れないでください。判断リストを使用すると進捗状況を体系的に評価できますが、実験、メトリック分析、反復的な改善と組み合わせると最も強力になります。</p><h2>参考資料</h2><ul><li><p>Quepid ドキュメント:</p><ul><li><p><a href="https://quepid-docs.dev.o19s.com/2/quepid/32/relevancy-is-a-team-sport">関連性はチームスポーツ</a></p></li><li><p><a href="https://quepid-docs.dev.o19s.com/2/quepid/18/quepid-for-human-raters">人間の評価者のためのQuepid</a></p></li><li><p><a href="https://quepid-docs.dev.o19s.com/2/quepid/49/how-to-connect-quepid-to-elastic-cloud">QuepidをElastic Cloudに接続する方法</a></p></li></ul></li><li><p><a href="https://github.com/o19s/quepid">Quepid Githubリポジトリ</a></p></li><li><p><a href="https://opensourceconnections.com/blog/2020/07/07/meet-pete-the-e-commerce-search-product-manager/">電子商取引の検索を改善するブログシリーズ「Pete」</a></p></li><li><p><a href="https://opensourceconnections.com/slack">関連性Slack</a> ：#quepidチャンネルに参加する</p></li></ul><p><a href="https://opensourceconnections.com/"><strong>Open Source Connections</strong></a> と提携して 検索機能と AI 機能を変革し、チームが継続的に進化できるようにします。当社の実績は世界中に広がっており、クライアントは一貫して検索品質、チーム能力、ビジネス パフォーマンスの劇的な改善を達成しています。詳細については、<a href="https://opensourceconnections.com/contact/">今すぐお問い合わせください</a>。</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/quepid-judgement-lists</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/quepid-judgement-lists</guid>
    <category><![CDATA[関連性]]></category>
    <dc:creator><![CDATA[Daniel Wrigley]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte6779c72c7a42a5a/6a17e6623e9e45acf0ba146b/307c1774bd31f92bb4aa7b69e1a6796240465100-1600x914.png" length="0" type="image/png"/>
    <pubDate>Mon, 26 May 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[MLを使用したフィルターとファセットの生成]]></title>
    <description><![CDATA[ML モデルを使用した検索エクスペリエンスにおけるフィルターとファセットの作成を自動化することと、従来のハードコードされたアプローチを比較して、長所と短所を検討します。]]></description>
    <content:encoded><![CDATA[<p>フィルターとファセットは、検索結果を絞り込むために使用されるメカニズムであり、ユーザーが関連するコンテンツや製品をより迅速に見つけるのに役立ちます。従来のアプローチでは、ルールは手動で定義されます。たとえば、映画カタログでは、フィルターやファセットで使用するためにジャンルなどの属性が事前定義されています。一方、AI モデルを使用すると、映画の特徴から新しい属性を自動的に抽出できるため、プロセスはより動的かつパーソナライズされたものになります。このブログでは、それぞれの方法の長所と短所を検討し、その応用と課題に焦点を当てます。</p><h2>フィルターとファセットの違い</h2><p>始める前に、フィルターとファセットとは何かを定義しましょう。<strong>フィルターは</strong>、結果セットを制限するために使用される定義済みの属性です。たとえば、マーケットプレイスでは、検索を実行する前でもフィルターを利用できます。ユーザーは、<strong> 「PS5」</strong> を検索する前に<strong> 「ビデオゲーム」</strong> などのカテゴリを選択し、データベース全体ではなく、より具体的なサブセットに検索を絞り込むことができます。これにより、より関連性の高い結果を得られる可能性が大幅に高まります。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0a77b38aae238938/6a170b821949f72a52e7aa51/5ed8868fa5017d034e1273e35c884a5430afdf3c-1600x937.png" alt="各種フィルター" /><p><strong>ファセットは</strong>フィルターと同様に機能しますが、検索を実行した後にのみ使用できます。つまり、検索によって結果が返され、それに基づいて絞り込みオプションの新しいリストが生成されます。たとえば、PS5 コンソールを検索する場合、ストレージ<strong>容量</strong>、<strong>送料</strong>、<strong>色</strong>などの側面が表示され、ユーザーが理想的な製品を選択できるようになります。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt166e356b80d423ef/6a170b840e2e494ca341a10f/c5633fcc5b6fbb916110faf32144d8d43572e33a-1600x937.png" alt="ファセット " /><p>フィルターとファセットを定義したので、次に、従来のアプローチと機械学習 (ML) ベースのアプローチがそれらの実装と使用に与える影響について説明しましょう。それぞれの方法には、検索効率に影響する利点と課題があります。</p><h2>フィルターとファセットに対する従来のアプローチ</h2><p>このアプローチでは、フィルターとファセットは事前定義されたルールに基づいて手動で定義されます。つまり、検索を絞り込むために使用できる属性は、カタログ構造とユーザーのニーズを考慮して事前に固定され、計画されています。</p><p>たとえば、マーケットプレイスでは、「エレクトロニクス」や「ファッション」などのカテゴリに、ブランド、フォーマット、価格帯などの特定のフィルターがある場合があります。これらのルールは静的に作成されるため、検索エクスペリエンスの一貫性は確保されますが、新しい製品やカテゴリが登場するたびに手動で調整する必要があります。</p><p>このアプローチでは、表示されるフィルターとファセットの予測可能性と制御が可能になりますが、動的な改良を必要とする新しいトレンドが生まれた場合には制限される可能性があります。</p><p><strong>長所:</strong></p><ul><li><p><strong>予測可能性と制御:</strong>フィルターとファセットは手動で定義されるため、管理が容易になります。</p></li><li><p><strong>複雑さが低い:</strong>モデルをトレーニングする必要はありません。</p></li><li><p><strong>メンテナンスの容易さ:</strong>ルールが事前に定義されているため、調整や修正を迅速に行うことができます。</p></li></ul><p><strong>短所</strong>:</p><ul><li><p><strong>新しいフィルターには再インデックスが必要です:</strong>新しい属性をフィルターとして使用する必要がある場合は、ドキュメントにこの情報が含まれていることを確認するために、データセット全体のインデックスを再作成する必要があります。</p></li><li><p><strong>動的適応の欠如:</strong>フィルターは静的であり、ユーザーの行動の変化に自動的に適応しません。</p></li></ul><h3>フィルター/ファセットの実装 – 古典的なアプローチ</h3><p><strong>開発ツールの Kibana</strong>では、<strong>従来のアプローチ</strong>を使用してフィルター/ファセットのデモを作成します。</p><p>まず、インデックスを構造化するためのマッピングを定義します。</p>PUT videogames
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "brand": { "type": "keyword" },
      "storage": { "type": "keyword" },
      "price": { "type": "float" },
      "description": { "type": "text" }
    }
  }
}<p><strong>ブランド</strong>および<strong>ストレージ</strong>フィールドは<strong>キーワード</strong>として設定されており、集計 (<strong>ファセット</strong>) で直接使用できます。<strong>価格</strong>フィールドは<strong>float</strong>型であり、<strong>価格範囲</strong>の作成を可能にします。</p><p>次のステップでは、製品データがインデックス化されます。</p>POST videogames/_bulk
{ "index": { "_id": 1 } }
{ "name": "Play Station 5", "brand": "Sony", "storage": "1TB", "price": 499.99, "description": "Stunning Gaming: Marvel at stunning graphics and experience the features of the new PS5. Breathtaking Immersion: Discover a deeper gaming experience with support for haptic feedback, adaptive triggers, and 3D Audio technology. Slim Design: With the PS5 Digital Edition, gamers get powerful gaming technology in a sleek, compact design. 1TB of Storage: Have your favorite games ready and waiting for you to play with 1TB of built-in SSD storage. Backward Compatibility and Game Boost: The PS5 console can play over 4,000 PS4 games. With Game Boost, you can even enjoy faster, smoother frame rates in some of the best PS4 console games." }
{ "index": { "_id": 2 } }
{ "name": "Xbox Series X", "brand": "Microsoft", "storage": "1TB", "price": 499.99, "description": "Fastest, most powerful Xbox console ever. Play thousands of titles: Every game looks and plays better on Xbox Series X. At the heart of Series X is the Xbox Velocity. Architecture, which combines a custom SSD and built-in software to significantly reduce load times in and out of game. Switch between multiple games in an instant with Quick Resume. Explore new worlds and experience the action like never before with an unparalleled 12 teraflops of graphics processing power. Enjoy 4K gaming at up to 120 frames per second, premium advanced 3D sound, and more. 4K at 120 FPS: requires compatible content and display X version - with disc drive" }
{ "index": { "_id": 3 } }
{ "name": "Nintendo Switch", "brand": "Nintendo", "storage": "512GB", "price": 299.99, "description": "SHARPER, VIBRANT VISUALS. The new 7-inch screen on the Nintendo Switch OLED takes your gaming to the next level: vibrant colors with sharp contrasts for every moment. INTEGRATED GAMEPLAY. Enjoy the console's many multiplayer modes and connect with other players. Online or locally, the fun on the Nintendo Switch is guaranteed. ENJOY IMMERSION FOR LONGER. In addition to delivering an unparalleled experience, thanks to its improved audio, the Nintendo Switch has a rechargeable battery while you play. From 4.5 hours to 9 hours of battery life. INCLUDES SUPER MARIO BROS. WONDER. Transform your world with the phenomenal flowers in this new Mario game, full of amazing adventures, power-ups and new abilities. NINTENDO SWITCH ONLINE SUBSCRIPTION. Access online games, play with friends and enjoy the exclusive benefits of the Nintendo Switch Online subscription." }
{ "index": { "_id": 4 } }
{ "name": "Steam Deck", "brand": "Valve", "storage": "512GB", "price": 399.99, "description": "You can save games, apps, photos and videos without worrying about space. High-Level Performance: The 4-core processor and graphics ensure a dynamic experience and fast responses. High-Definition Images: Smooth transitions and sharp images provide complete immersion in the game. Wireless Connectivity: Wi-Fi technology allows you to play wherever you want, without wires or cables limiting your fun" }
{ "index": { "_id": 5 } }
{ "name": "Nintendo Switch Lite", "brand": "Nintendo", "storage": "512GB", "price": 299.99, "description": "MADE TO BE PORTABLE. Nintendo Switch Lite is designed specifically for portable gaming. The console lets you jump into your favorite games wherever you are. COMPACT AND LIGHTWEIGHT. With its sleek, lightweight design, this console is ready to hit the road wherever you are. COMPATIBLE GAMES. The Nintendo Switch Lite system plays the library of Nintendo Switch games that work in handheld mode. A WORLD OF COLOR TO CHOOSE FROM. Available in a variety of vibrant and unique colors, Nintendo Switch Lite lets you bring even more personality wherever you go." }<p>ここで、ブランド、ストレージ、価格帯別に結果をグループ化して、クラシック ファセットを取得してみましょう。クエリでは、size:0 が定義されました。このシナリオでは、クエリに対応するドキュメントを含めずに、集計結果のみを取得することが目標です。</p>POST videogames/_search
{
  "size": 0,
  "aggs": {
    "brands": {
      "terms": { "field": "brand" }
    },
    "storage_sizes": {
      "terms": { "field": "storage" }
    },
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 300 },   
          { "from": 300, "to": 500 },  
          { "from": 500 }  
        ]
      }
    }
  }
}<p>応答には、 <strong>Brand</strong> 、 <strong>Storage</strong> 、 <strong>Price</strong>のカウントが含まれ、フィルターとファセットの作成に役立ちます。</p>"aggregations": {
   "brands": {
     "doc_count_error_upper_bound": 0,
     "sum_other_doc_count": 0,
     "buckets": [
       {
         "key": "Microsoft",
         "doc_count": 1
       },
       {
         "key": "Nintendo",
         "doc_count": 1
       },
       {
         "key": "Sony",
         "doc_count": 1
       },
       {
         "key": "Valve",
         "doc_count": 1
       }
     ]
   },
   "storage_sizes": {
     "doc_count_error_upper_bound": 0,
     "sum_other_doc_count": 0,
     "buckets": [
       {
         "key": "1TB",
         "doc_count": 2
       },
       {
         "key": "512GB",
         "doc_count": 2
       }
     ]
   },
   "price_ranges": {
     "buckets": [
       {
         "key": "*-300.0",
         "to": 300,
         "doc_count": 1
       },
       {
         "key": "300.0-500.0",
         "from": 300,
         "to": 500,
         "doc_count": 3
       },
       {
         "key": "500.0-*",
         "from": 500,
         "doc_count": 0
       }
     ]
   }
 }<h2>フィルターとファセットに対する機械学習/AIベースのアプローチ</h2><p>このアプローチでは、人工知能 (AI) 技術を含む機械学習 (ML) モデルがデータ属性を分析して、関連するフィルターとファセットを生成します。ML/AI は、事前定義されたルールに依存するのではなく、インデックス化されたデータ特性を活用します。これにより、新しいファセットとフィルターを動的に検出できるようになります。</p><p><strong>長所</strong>:</p><ul><li><p><strong>自動更新:</strong>新しいフィルターとファセットは自動的に生成され、手動で調整する必要はありません。</p></li><li><p><strong>新しい属性の検出:</strong><strong>これまで考慮されていなかった</strong>データ特性をフィルターとして識別し、検索エクスペリエンスを充実させることができます。</p></li><li><p><strong>手作業の削減:</strong> AI が利用可能なデータから学習するため、チームはフィルタリング ルールを継続的に定義および更新する必要がありません。</p></li></ul><p><strong>短所:</strong></p><ul><li><p><strong>メンテナンスの複雑さ:</strong>モデルを使用する場合、生成されたフィルターの一貫性を確保するために事前検証が必要になる場合があります。</p></li><li><p><strong>ML と AI の専門知識が必要:</strong>このソリューションでは、モデルのパフォーマンスを微調整および監視する資格のある専門家が必要です。</p></li><li><p><strong>無関係なフィルターのリスク:</strong>モデルが適切に調整されていない場合、ユーザーにとって役に立たないファセットが生成される場合があります。</p></li><li><p><strong>コスト:</strong> ML および AI の使用にはサードパーティのサービスが必要になる場合があり、運用コストが増加する可能性があります。</p></li></ul><p>適切に調整されたモデルと適切に作成されたプロンプトを使用しても、生成されたファセットはレビュー手順を経る必要があることに注意してください。この検証は手動で行うことも、モデレーション ルールに基づいて行うこともできます。これにより、コンテンツが適切かつ安全であることが保証されます。必ずしも欠点ではありませんが、ファセットをユーザーに提供する前に、その品質と適合性を確認することは重要な考慮事項です。</p><h3>フィルター/ファセットの実装 - AIアプローチ</h3><p>このデモでは、AI モデルを使用して製品の特性を自動的に分析し、関連する属性を提案します。適切に構造化されたプロンプトを使用して、カタログから情報を抽出し、それをフィルターとファセットに変換します。以下に、プロセスの各ステップを紹介します。</p><p>最初に、 <strong>Inference API を</strong>使用して、ML サービスとの統合のためのエンドポイントを登録します。以下は<strong>OpenAI のサービス</strong>との統合の例です。</p>PUT _inference/completion/generate_filter_ia
{
   "service": "openai",
   "service_settings": {
       "api_key": "your-key",
       "model_id": "gpt-4o-mini"
   }
}<p>ここで、プロンプトを実行し、モデルによって生成された新しいフィルターを取得するためのパイプラインを定義します。</p>PUT /_ingest/pipeline/generate_filter_ai
{
   "processors": [
     {
       "script": {
         "source": """ctx.prompt = "You are an expert in data organization for search and product categorization. Your task is to analyze the following product and identify the best dynamic facets that can be used in an e-commerce search experience. Product: " + ctx.name + "description: " + ctx.description + "Instructions: - Analyze the product name and description. - Extract only the dynamic facets (technological features or product characteristics that can be inferred from the description, try to create max 3 facets by characteristics found). Put the values into an array. Using key and value, e.g. dynamic_facets: [{ \"name\": \"Gaming Experience\", \"value\": \"Haptic Feedback\" },{ \"name\": \"Gaming Experience\", \"value\": \"Adaptive Triggers\" } - Return only a JSON."
         """
       }
     },
     {
       "inference": {
         "model_id": "generate_filter_ia",
         "input_output": {
           "input_field": "prompt",
           "output_field": "result"
         }
       }
     },
     {
       "gsub": {
         "field": "result",
         "pattern": "```json",
         "replacement": ""
       }
     },
     {
       "json" : {
         "field" : "result",
         "strict_json_parsing": false,
         "add_to_root" : true
       }
     },
     {
       "remove": {
         "field": "result"
       }
     },
     {
       "remove": {
         "field": "prompt"
       }
     }
   ]
}<p>「PlayStation 5」製品用にこのパイプラインのシミュレーションを実行すると、次のようになります。</p><p><em>驚異的なゲーム体験: 驚異的なグラフィックスに驚嘆し、新しい PS5 の機能を体験してください。</em></p><p><em>息を呑むような没入感: 触覚フィードバック、アダプティブ トリガー、3D オーディオ テクノロジーのサポートにより、より奥深いゲーム体験を体験できます。</em></p><p><em>スリムなデザイン: PS5 デジタル エディションでは、洗練されたコンパクトなデザインで強力なゲーミング テクノロジーをゲーマーに提供します。</em></p><p><em>1TB のストレージ: 1TB の内蔵 SSD ストレージで、お気に入りのゲームをいつでもプレイできます。</em></p><p><em>下位互換性とゲームブースト: PS5 コンソールは 4,000 以上の PS4 ゲームをプレイできます。Game Boost を使用すると、最高の PS4 コンソール ゲームの一部で、より高速でスムーズなフレーム レートを楽しむことができます。</em></p><p>このシミュレーションから生成されたプロンプト出力を観察してみましょう。</p>{
 "docs": [
   {
     "doc": {
       "_index": "index",
       "_version": "-3",
       "_id": "1",
       "_source": {
         "name": "Play Station 5",
         "result": """```json
{
 "dynamic_facets": [
   { "name": "Storage Capacity", "value": "1TB SSD" },
   { "name": "Graphics Technology", "value": "Stunning Graphics" },
   { "name": "Audio Technology", "value": "3D Audio" }
 ]
}
```""",
         "description": "Stunning Gaming: Marvel at stunning graphics and experience the features of the new PS5. Breathtaking Immersion: Discover a deeper gaming experience with support for haptic feedback, adaptive triggers, and 3D Audio technology. Slim Design: With the PS5 Digital Edition, gamers get powerful gaming technology in a sleek, compact design. 1TB of Storage: Have your favorite games ready and waiting for you to play with 1TB of built-in SSD storage. Backward Compatibility and Game Boost: The PS5 console can play over 4,000 PS4 games. With Game Boost, you can even enjoy faster, smoother frame rates in some of the best PS4 console games.",
         "model_id": "generate_filter_ia",
         "prompt": """You are an expert in data organization for search and product categorization. Your task is to analyze the following product and identify the best dynamic facets that can be used in an e-commerce search experience. Product: Play Station 5description: Stunning Gaming: Marvel at stunning graphics and experience the features of the new PS5. Breathtaking Immersion: Discover a deeper gaming experience with support for haptic feedback, adaptive triggers, and 3D Audio technology. Slim Design: With the PS5 Digital Edition, gamers get powerful gaming technology in a sleek, compact design. 1TB of Storage: Have your favorite games ready and waiting for you to play with 1TB of built-in SSD storage. Backward Compatibility and Game Boost: The PS5 console can play over 4,000 PS4 games. With Game Boost, you can even enjoy faster, smoother frame rates in some of the best PS4 console games.Instructions: - Analyze the product name and description. - Extract only the dynamic facets (technological features or product characteristics that can be inferred from the description, try create max 3 facets by characteristics found). Put the values like arrays. Using key and value, e.g. dynamic_facets: [{ "name": "Gaming Experience", "value": "Haptic Feedback" },{ "name": "Gaming Experience", "value": "Adaptive Triggers" } - Return only a JSON."""
       },
       "_ingest": {
         "timestamp": "2025-03-19T22:14:32.0161803Z"
       }
     }
   }
 ]
}<p>これで、AI によって生成されたファセットを保存するための新しいフィールド<strong>dynamic_facets</strong>が新しいインデックスに追加されます。</p>PUT videogames_1
{
 "mappings": {
   "properties": {
     "name": { "type": "text" },
     "brand": { "type": "keyword" },
     "storage": { "type": "keyword" },
     "price": { "type": "float" },
     "description": { "type": "text" },
     "dynamic_facets": { "type": "nested",
     "properties": { "name": { "type": "keyword" },
                     "value": { "type": "keyword" } } }
   }
 }
}<p><strong>Reindex API</strong> を使用して、プロセス中に<strong> generate_filter_ai</strong> パイプラインを適用し、<strong> videogames</strong> インデックスを<strong> videogames_1</strong> に再インデックスします。このパイプラインは、インデックス作成中に動的ファセットを自動的に生成します。</p>POST _reindex?wait_for_completion=false
{
 "source": {
   "index": "videogames"
 },
 "dest": {
   "index": "videogames_1",
   "pipeline": "generate_filter_ai"
 }
}<p>ここで、検索を実行して新しいフィルターを取得します。</p>GET videogames_1/_search
{
 "size": 0,
 "query": {
   "match": {
     "name": "nintendo"
   }
 },
 "aggs": {
   "dynamic_facets": {
     "nested": {
       "path": "dynamic_facets"
     },
     "aggs": {
       "facets": {
         "terms": {
           "field": "dynamic_facets.name"
         },
         "aggs": {
           "facets": {
             "terms": {
               "field": "dynamic_facets.value"
             }
           }
         }
       }
     }
   }
 }
}<p>結果：</p>"aggregations": {
   "dynamic_facets": {
     "doc_count": 3,
     "facets": {
       "doc_count_error_upper_bound": 0,
       "sum_other_doc_count": 0,
       "buckets": [
         {
           "key": "Frame Rate",
           "doc_count": 1,
           "facets": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
               {
                 "key": "120 FPS",
                 "doc_count": 1
               }
             ]
           }
         },
         {
           "key": "Gaming Resolution",
           "doc_count": 1,
           "facets": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
               {
                 "key": "4K",
                 "doc_count": 1
               }
             ]
           }
         },
         {
           "key": "Graphics Processing Power",
           "doc_count": 1,
           "facets": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
               {
                 "key": "12 Teraflops",
                 "doc_count": 1
               }
             ]
           }
         }
       ]
     }
   }
 }<p>ファセットの実装を象徴するシンプルなフロントエンドを以下に示します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb0d6aa40caf7a91a/6a170b86ab7f0839afdb9eb6/12b6d9d4f4d0985848d92841545fd22b7253ae6d-1600x1288.png" alt="ファセットの実装" /><p>提示された UI コードは<a href="https://gist.github.com/andreluiz1987/06d9ec1b381e942e9def0e969bd811a0">ここに</a>あります。</p><h2>まとめ</h2><p>フィルターとファセットを作成する両方のアプローチには、利点と注意点があります。手動ルールに基づく従来のアプローチでは、制御が可能になりコストも削減されますが、継続的な更新が必要となり、新しい製品や機能に動的に適応することができません。</p><p>一方、AI と機械学習ベースのアプローチでは、ファセット抽出が自動化されるため、検索がより柔軟になり、手動による介入なしに新しい属性を発見できるようになります。ただし、このアプローチは実装と維持が複雑になる可能性があり、一貫した結果を確保するために調整が必要になります。</p><p>従来のアプローチと AI ベースのアプローチのどちらを選択するかは、ビジネスのニーズと複雑さによって異なります。データ属性が安定していて予測可能な、より単純なシナリオでは、従来のアプローチの方が効率的で保守が容易になり、インフラストラクチャと AI モデルによる不必要なコストを回避できます。一方、ML/AI を使用してファセットを抽出すると、検索エクスペリエンスが向上し、フィルタリングがよりインテリジェントになるため、大きな価値が付加されます。</p><p>重要なのは、自動化が投資を正当化するかどうか、あるいはより従来型のソリューションがすでにビジネス ニーズを効果的に満たしているかどうかを評価することです。</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/filters-facets-using-ml</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/filters-facets-using-ml</guid>
    <category><![CDATA[関連性]]></category>
    <category><![CDATA[MLの調査]]></category>
    <dc:creator><![CDATA[Andre Luiz]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4084864dcdaa25d3/6a170b880c485781f901aaa9/6f196643d573614fe5124705c7e4db9bfce004b0-1200x628.png" length="0" type="image/png"/>
    <pubDate>Thu, 03 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[同義語APIを使用して同義語を自動化し、アップロードする方法]]></title>
    <description><![CDATA[LLM を使用して同義語を自動的に識別および生成し、用語をプログラムで Elasticsearch 同義語 API に読み込むことができる方法について説明します。]]></description>
    <content:encoded><![CDATA[<p>効率的なユーザー エクスペリエンスを提供するには、検索結果の品質を向上させることが不可欠です。検索を最適化する 1 つの方法は、同義語を通じて検索対象の用語を自動的に拡張することです。これにより、クエリをより広範囲に解釈できるようになり、言語のバリエーションをカバーして結果の一致が向上します。</p><p>このブログでは、大規模言語モデル (LLM) を使用して同義語を自動的に識別および生成し、これらの用語をプログラムで Elasticsearch の同義語 API に読み込むことができる方法について説明します。</p><h2>同義語はいつ使用すればよいですか?</h2><p>同義語を使用すると、ベクトル検索に比べて高速かつコスト効率の高いソリューションになります。埋め込みに関する深い知識や複雑なベクトル取り込みプロセスを必要としないため、実装はより簡単です。</p><p>さらに、ベクトル検索ではインデックス作成と検索を埋め込むために大きなストレージ容量とメモリが必要になるため、リソースの消費量が少なくなります。</p><p>もう一つの重要な側面は、検索の地域化です。同義語を使用すると、現地の言語や習慣に応じて用語を適応させることができます。これは、埋め込みが地域的な表現や国固有の用語と一致しない可能性がある場合に役立ちます。たとえば、一部の単語や頭字語は地域によって意味が異なる場合がありますが、現地のユーザーにとっては当然同義語として扱われます。ブラジルでは、これはかなり一般的です。「アバカシ」と「アナナス」は同じ果物（パイナップル）ですが、北東部の一部の地域では後者の用語の方が一般的に使用されています。同様に、南東部でよく知られている「pão francês」は、北東部では「pão careca」として知られている場合があります。</p><h2>LLM を使用して同義語を生成するにはどうすればよいでしょうか?</h2><p>同義語を自動的に取得するには、用語のコンテキストを分析して適切なバリエーションを提案する LLM を使用できます。このアプローチにより、同義語を動的に拡張できるため、固定辞書に依存せずに、より広範で正確な検索が可能になります。</p><p>このデモでは、LLM を使用して電子商取引製品の同義語を生成します。多くの検索では、検索語句のバリエーションにより、結果がほとんど返されないか、まったく返されません。同義語を使用すると、この問題は解決できます。たとえば、「スマートフォン」を検索すると、さまざまな種類の携帯電話が検索されるため、ユーザーは探している製品を見つけることができます。</p><h3>要件</h3><p>始める前に、環境を設定し、必要な依存関係を定義する必要があります。Elastic が提供するソリューションを使用して、 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html">Elasticsearch と Kibana を Docker でローカルに実行します</a>。コードは Python v3.9.6 で記述され、次の依存関係があります。</p>pip install openai==1.59.8 elasticsearch==8.15.1<h3>製品インデックスの作成</h3><p>最初は、同義語をサポートしない製品のインデックスを作成します。これにより、クエリを検証し、同義語を含むインデックスと比較できるようになります。</p><p>インデックスを作成するには、Kibana DevTools で次のコマンドを使用して製品データセットを一括ロードします。</p>POST _bulk
{"index": {"_index": "products", "_id": 10001}}
{"category": "Electronics", "name": "iPhone 14 Pro"}
{"index": {"_index": "products", "_id": 10007}}
{"category": "Electronics", "name": "MacBook Pro 16-inch"}
{"index": {"_index": "products", "_id": 10013}}
{"category": "Electronics", "name": "Samsung Galaxy Tab S8"}
{"index": {"_index": "products", "_id": 10037}}
{"category": "Electronics", "name": "Apple Watch Series 8"}
{"index": {"_index": "products", "_id": 10049}}
{"category": "Electronics", "name": "Kindle Paperwhite"}
{"index": {"_index": "products", "_id": 10067}}
{"category": "Electronics", "name": "Samsung QLED 4K TV"}
{"index": {"_index": "products", "_id": 10073}}
{"category": "Electronics", "name": "HP Spectre x360 Laptop"}
{"index": {"_index": "products", "_id": 10079}}
{"category": "Electronics", "name": "Apple AirPods Pro"}
{"index": {"_index": "products", "_id": 10115}}
{"category": "Electronics", "name": "Amazon Echo Show 10"}
{"index": {"_index": "products", "_id": 10121}}
{"category": "Electronics", "name": "Apple iPad Air"}
{"index": {"_index": "products", "_id": 10127}}
{"category": "Electronics", "name": "Apple AirPods Max"}
{"index": {"_index": "products", "_id": 10151}}
{"category": "Electronics", "name": "Sony WH-1000XM4 Headphones"}
{"index": {"_index": "products", "_id": 10157}}
{"category": "Electronics", "name": "Google Pixel 6 Pro"}
{"index": {"_index": "products", "_id": 10163}}
{"category": "Electronics", "name": "Apple MacBook Air"}
{"index": {"_index": "products", "_id": 10181}}
{"category": "Electronics", "name": "Google Pixelbook Go"}
{"index": {"_index": "products", "_id": 10187}}
{"category": "Electronics", "name": "Sonos Beam Soundbar"}
{"index": {"_index": "products", "_id": 10199}}
{"category": "Electronics", "name": "Apple TV 4K"}
{"index": {"_index": "products", "_id": 10205}}
{"category": "Electronics", "name": "Samsung Galaxy Watch 4"}
{"index": {"_index": "products", "_id": 10211}}
{"category": "Electronics", "name": "Apple MacBook Pro 16-inch"}
{"index": {"_index": "products", "_id": 10223}}
{"category": "Electronics", "name": "Amazon Echo Dot (4th Gen)"}<h3>LLMによる同義語の生成</h3><p>このステップでは、LLM を使用して同義語を動的に生成します。これを実現するために、OpenAI API を統合し、適切なモデルとプロンプトを定義します。LLM は製品のカテゴリと名前を受け取り、同義語が文脈的に適切であることを確認します。</p>import json
import logging

from openai import OpenAI

def call_gpt(prompt, model):
    try:
        logging.info("generate synonyms by llm...")
        response = client.chat.completions.create(
            model=model,
            messages=[{"role": "user", "content": prompt}],
            temperature=0.7,
            max_tokens=1000
        )
        content = response.choices[0].message.content.strip()
        return content
    except Exception as e:
        logging.error(f"Failed to use model: {e}")
        return None

def generate_synonyms(category, products):
   synonyms = {}

   for product in products:
       prompt = f"You are an expert in generating synonyms for products. Based on the category and product name provided, generate synonyms or related terms. Follow these rules:\n"
       prompt += "1. **Format**: The first word should be the main item (part of the product name, excluding the brand), followed by up to 3 synonyms separated by commas.\n"
       prompt += "2. **Exclude the brand**: Do not include the brand name in the synonyms.\n"
       prompt += "3. **Maximum synonyms**: Generate a maximum of 3 synonyms per product.\n\n"
       prompt += f"The category is: **{category}**, and the product is: **{product}**. Return only the synonyms in the requested format, without additional explanations."

       response = call_gpt(prompt, "gpt-4o")
       synonyms[product] = response

   return synonyms<p>作成された製品インデックスから、「エレクトロニクス」カテゴリ内のすべてのアイテムを取得し、その名前を LLM に送信します。予想される出力は次のようになります。</p>{
  "iPhone 14 Pro": ["iPhone", "smartphone", "mobile", "handset"],
  "MacBook Pro 16-inch": ["MacBook", "Laptop", "Notebook", "Ultrabook"],
  "Samsung Galaxy Tab S8": ["Tab", "Tablet", "Slate", "Pad"],
  "Bose QuietComfort 35 Headphones": ["Headphones", "earphones", "earbuds", "headset"]
}<p>生成された同義語は、Synonyms API を使用して Elasticsearch に登録できます。</p><h3>Synonyms API による同義語の管理</h3><p>シノニム API は、システム内でシノニム セットを直接管理する効率的な方法を提供します。各同義語セットは同義語ルールで構成され、検索では単語のグループが同等として扱われます。</p><p><strong>同義語セットの作成例</strong></p>PUT _synonyms/my-synonyms-set
{
  "synonyms_set": [
    {
      "id": "rule-1",
      "synonyms": "hello, hi"
    },
    {
      "synonyms": "bye, goodbye"
    }
  ]
}<p>
これにより、「my-synonyms-set」というセットが作成され、そこでは「hello」と「hi」が「bye」と「goodbye」と同様に同等として扱われます。</p><h2>製品カタログの同義語作成の実装</h2><p>以下は、同義語セットを構築して Elasticsearch に挿入するメソッドです。同義語ルールは、LLM によって提案された同義語のマッピングに基づいて生成されます。各ルールには、スラッグ形式の製品名に対応する ID と、LLM によって計算された同義語のリストがあります。</p>import json
import logging

from elasticsearch import Elasticsearch
from slugify import slugify

es = Elasticsearch(
    "http://localhost:9200",
    api_key="your_api_key"
)

def mount_synonyms(results):
   synonyms_set = [{"id": slugify(product), "synonyms": synonyms} for product, synonyms in
                   results.items()]

   try:
       response = es.synonyms.put_synonym(id="products-synonyms-set",
                                                 synonyms_set=synonyms_set)

       logging.info(json.dumps(response.body, indent=4))
       return response.body
   except Exception as e:
       logging.error(f"Error create synonyms: {str(e)}")
       return None<p>以下は、同義語セットを作成するためのリクエスト ペイロードです。</p>{
   "synonyms_set":[
      {
         "id": "iphone-14-pro",
         "synonyms": "iPhone, smartphone, mobile, handset"
      },
      {
         "id": "macbook-pro-16-inch",
         "synonyms": "MacBook, Laptop, Notebook, Computer"
      },
      {
         "id": "samsung-galaxy-tab-s8",
         "synonyms": "Tablet, Slate, Pad, Device"
      },
      {
         "id": "garmin-forerunner-945",
         "synonyms": "Forerunner, smartwatch, fitness watch, GPS watch"
      },
      {
         "id": "bose-quietcomfort-35-headphones",
         "synonyms": "Headphones, Earphones, Headset, Cans"
      }
   ]
}<p>クラスターにシノニム セットが作成されたら、次のステップに進み、定義したセットを使用してシノニムをサポートする新しいインデックスを作成します。</p><p>LLM によって生成された同義語と、Synonyms API によって定義された同義語セットの作成を含む完全な Python コードは次のとおりです。</p>import json
import logging

from elasticsearch import Elasticsearch
from openai import OpenAI
from slugify import slugify

logging.basicConfig(level=logging.INFO)

client = OpenAI(
   api_key="your-key",
)

es = Elasticsearch(
    "http://localhost:9200",
    api_key="your_api_key"
)


def call_gpt(prompt, model):
   try:
       logging.info("generate synonyms by llm...")
       response = client.chat.completions.create(
           model=model,
           messages=[{"role": "user", "content": prompt}],
           temperature=0.7,
           max_tokens=1000
       )
       content = response.choices[0].message.content.strip()
       return content
   except Exception as e:
       logging.error(f"Failed to use model: {e}")
       return None


def generate_synonyms(category, products):
   synonyms = {}

   for product in products:
       prompt = f"You are an expert in generating synonyms for products. Based on the category and product name provided, generate synonyms or related terms. Follow these rules:\n"
       prompt += "1. **Format**: The first word should be the main item (part of the product name, excluding the brand), followed by up to 3 synonyms separated by commas.\n"
       prompt += "2. **Exclude the brand**: Do not include the brand name in the synonyms.\n"
       prompt += "3. **Maximum synonyms**: Generate a maximum of 3 synonyms per product.\n\n"
       prompt += f"The category is: **{category}**, and the product is: **{product}**. Return only the synonyms in the requested format, without additional explanations."

       response = call_gpt(prompt, "gpt-4o")
       synonyms[product] = response

   return synonyms


def get_products(category):
   query = {
       "size": 50,
       "_source": ["name"],
       "query": {
           "bool": {
               "filter": [
                   {
                       "term": {
                           "category.keyword": category
                       }
                   }
               ]
           }
       }
   }
   response = es.search(index="products", body=query)

   if response["hits"]["total"]["value"] &gt; 0:
       product_names = [hit["_source"]["name"] for hit in response["hits"]["hits"]]
       return product_names
   else:
       return []


def mount_synonyms(results):
   synonyms_set = [{"id": slugify(product), "synonyms": synonyms} for product, synonyms in
                   results.items()]

   try:
       es_client = get_client_es()
       response = es_client.synonyms.put_synonym(id="products-synonyms-set",
                                                 synonyms_set=synonyms_set)

       logging.info(json.dumps(response.body, indent=4))
       return response.body
   except Exception as e:
       logging.error(f"Erro update synonyms: {str(e)}")
       return None


if __name__ == '__main__':
   category = "Electronics"
   products = get_products("Electronics")
   llm_synonyms = generate_synonyms(category, products)
   mount_synonyms(llm_synonyms)<h3>同義語サポート付きのインデックスの作成</h3><p>新しいインデックスが作成され、 <code>products</code>インデックスのすべてのデータが再インデックスされます。このインデックスは、以前に作成された<code>products-synonyms-set</code>を適用する<code>synonyms_filter</code>を使用します。</p><p>以下はシノニムを使用するように構成されたインデックス マッピングです。</p>PUT products_02
{
  "settings": {
    "analysis": {
      "filter": {
        "synonyms_filter": {
          "type": "synonym",
          "synonyms_set": "products-synonyms-set",
          "updateable": true
        }
      },
      "analyzer": {
        "synonyms_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "synonyms_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "ID": {
        "type": "long"
      },
      "category": {
        "type": "keyword"
      },
      "name": {
        "type": "text",
        "analyzer": "standard",
        "search_analyzer": "synonyms_analyzer"
      }
    }
  }
}<h3><code>products</code>インデックスの再インデックス</h3><p>ここで、 <strong>Reindex API を</strong>使用して、 <code>products</code>インデックスからシノニムのサポートを含む新しい<code>products_02</code>インデックスにデータを移行します。Kibana DevTools で次のコードが実行されました。
</p>POST _reindex
{
  "source": {
    "index": "products"
  },
  "dest": {
    "index": "products_02"
  }
}<p>移行後、 <code>products_02</code>インデックスが作成され、構成された同義語セットを使用して検索を検証できるようになります。</p><h3>同義語による検索の検証</h3><p>2つのインデックス間の検索結果を比較してみましょう。両方のインデックスに対して同じクエリを実行し、結果を取得するために同義語が使用されているかどうかを検証します。</p><h4><code>products</code>インデックスで検索（同義語なし）</h4><p>Kibana を使用して検索を実行し、結果を分析します。「分析 &gt; 検出」メニューで、作成したインデックスのデータを視覚化するためのデータ ビューを作成します。</p><p>Discovery 内で、データ ビューをクリックし、名前とインデックス パターンを定義します。「 <strong>products</strong> 」インデックスでは、「 <strong>products</strong> 」パターンを使用します。次に、「<strong> products_02」</strong> パターンを使用して、「<strong> products_02</strong> 」インデックスの新しいデータ ビューを作成するプロセスを繰り返します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte826fd932cfeb9df/6a17fdffec0f8912aa5a6841/3ad4a6891a3905e96532a312932fdf3a8216aec2-1600x599.png" alt="" /><p>データ ビューを構成したら、分析 &gt; 検出に戻り、検証を開始できます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltba3729c60068e8a0/6a17fe01e9ea87ba2aa9c82a/422c4b2b51abae6580cad25085d1b8a365fc6b9e-1294x850.png" alt="" /><p>ここで、DataView 製品を選択し、「タブレット」という用語で検索を実行すると、「Kindle Paperwhite」や「Apple iPad Air」などの製品があることがわかっているにもかかわらず、結果は表示されません。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2c6a383dd4cb0157/6a17fe02577262671d1bce0c/e4ae3a785fdd93f48d7c7d204185ded149126f2c-1600x862.png" alt="" /><h4><code>products_02</code>インデックスで検索 (同義語をサポート)</h4><p>シノニムをサポートする「 <strong>products_synonyms</strong> 」データ ビューで同じクエリを実行すると、製品が正常に取得されました。これは、構成された同義語セットが正しく機能していることを示しており、検索された用語のさまざまなバリエーションが期待どおりの結果を返すことが保証されています。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt986b4706e2f70014/6a17fe043e9e454edbba16d3/e609749c39e90d5c82fa846af6124679dd62bcb8-1600x526.png" alt="" /><p>同じクエリを Kibana DevTools で直接実行することで、同じ結果を得ることができます。Elasticsearch Search API を使用して、products_02 インデックスを検索するだけです。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbe829a3c4d7aac60/6a17fe05e8fbce03d73a1bd7/504d0d1f96dcfbceb309063dc0716bcee64ad2f8-1600x870.png" alt="" /><h2>まとめ</h2><p>Elasticsearch に同義語を実装することで、製品カタログ検索の精度と範囲が向上しました。主な差別化要因は<strong>LLM</strong>の使用であり、これにより同義語が自動的かつ文脈に応じて生成され、事前定義されたリストの必要性がなくなりました。モデルは製品名とカテゴリを分析し、電子商取引に関連する同義語を確保しました。</p><p>さらに、<strong>同義語 API により</strong>辞書管理が簡素化され、同義語セットを動的に変更できるようになりました。このアプローチにより、検索はより柔軟になり、さまざまなユーザーのクエリ パターンに適応できるようになりました。</p><p>このプロセスは、新しいデータとモデルの調整によって継続的に改善され、ますます効率的な研究体験を保証します。</p><h2>参照資料</h2><p><strong>Elasticsearchをローカルで実行する</strong></p><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html</a></p><p><strong>同義語API</strong></p><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/synonyms-apis.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/synonyms-apis.html</a></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-synonyms-automate</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-synonyms-automate</guid>
    <category><![CDATA[関連性]]></category>
    <category><![CDATA[基本]]></category>
    <dc:creator><![CDATA[Andre Luiz]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0f0247b9bc1d1ccd/6a17fe07ec0f891c745a6845/05a3cfeaa387561d5334ca3f1609035ddfff7481-1200x628.png" length="0" type="image/png"/>
    <pubDate>Thu, 27 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elasticsearchでの後期相互作用モデルのスケーリング - パート 2]]></title>
    <description><![CDATA[この記事では、後期相互作用ベクトルを大規模な本番環境のワークロードに適したものにするための技術を探ります。これには、ディスク容量の使用を減らし、計算効率を向上させることが含まれます。]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/search-labs/blog/elastiacsearch-colpali-document-search">前回のColPaliブログ</a>では、Elasticsearchを使ってビジュアル検索アプリケーションを作成する方法を探りました。ColPaliなどのモデルがアプリケーションにもたらす価値に主に焦点を当てましたが、E5などのバイエンコーダーを使ったベクトル検索に比べてパフォーマンス上の欠点があります。</p><p>このブログでは、<a href="https://www.elastic.co/search-labs/blog/elastiacsearch-colpali-document-search">パート1</a>の例を基に、後期相互作用ベクトルを大規模な本番ワークロードに対応させるために、さまざまなテクニックとElasticsearchの強力なベクトル検索ツールキットをどのように使用するかを説明します。</p><p>完全なコード例は<a href="https://github.com/elastic/elasticsearch-labs/tree/main/supporting-blog-content/colpali">GitHub</a>にあります。</p><h2>後期相互作用モデルの課題</h2><p>ColPaliは、インデックス内のドキュメントに対してページごとに1000を超えるベクトルを作成します。</p><p>これにより、後期相互作用ベクトルを扱う際に2つの課題が生じます。</p><ol><li><p>ディスク容量：これらのベクトルをすべてディスクに保存すると、大量のストレージ使用量が発生し、規模が大きくなるとコストが高くなります。</p></li><li><p>計算：ドキュメントのランキングを行う際に、<code>maxSimDotProduct()</code>比較を使用すると、各ドキュメントのすべてのベクトルをクエリのN個のベクトルと比較する必要があります。</p></li></ol><p>これらの問題に対処するためのいくつかの手法を見てみましょう。</p><h2>後期相互作用モデルを最適化する技術</h2><h3>ビットベクトル</h3><p>ディスク容量を減らすために、画像をビットベクトルに圧縮することができます。Pythonの簡単な関数を使用して、マルチベクトルをビットベクトルに変換できます。</p>def to_bit_vectors(embeddings: list) -&gt; list:
    return [
        np.packbits(np.where(np.array(embedding) &gt; 0, 1, 0))
        .astype(np.int8)
        .tobytes()
        .hex()
        for embedding in embeddings
    ]<p>この関数の基本的な概念は単純で、0より大きい値は1に、0より小さい値は0になり、これが0と1の配列となり、それをビットベクトルを表す16進数の文字列に変換するというものです。</p><p>インデックスマッピングでは、<code>element_type</code>パラメータを<code>bit</code>に設定します。</p>mappings = {
    "mappings": {
        "properties": {
            "col_pali_vectors": {
                "type": "rank_vectors",
                "element_type": "bit"
            }
        }
    }
}

es.indices.create(index=INDEX_NAME, body=mappings)<p>新しいビットベクトルをすべてインデックスに書き込んだら、次のコードを使ってビットベクトルをランク付けします。</p>query = "What do companies use for recruiting?"
query_vector = to_bit_vectors(create_col_pali_query_vectors(query))
es_query = {
    "_source": False,
    "query": {
        "script_score": {
            "query": {
                "match_all": {}
            },
            "script": {
                "source": "maxSimInvHamming(params.query_vector, 'col_pali_vectors')",
                "params": {
                    "query_vector": query_vector
                }
            }
        }
    },
    "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcaf0c8f999d68701/6a17f46696142a6f46eb1c56/51b989446e4099745971e1eac27d147a78d13e0a-1600x480.png" alt="" /><p>精度を少し犠牲にすることで、ハミング距離（<code>maxSimInvHamming(...)</code>）を使用することができます。これにより、ビットマスク、SIMDなどの最適化を活用できます。ビットベクトルとハミング距離について詳しくは<a href="https://www.elastic.co/search-labs/blog/bit-vectors-in-elasticsearch">ブログをご覧ください</a>。</p><p>あるいは、クエリベクトルをビットベクトルに変換せずに、完全な忠実度の後期相互作用ベクトルで検索することもできます。</p>query = "What do companies use for recruiting?"
query_vector = create_col_pali_query_vectors(query)
es_query = {
    "_source": False,
    "query": {
        "script_score": {
            "query": {
                "match_all": {}
            },
            "script": {
                "source": "maxSimDotProduct(params.query_vector, 'col_pali_vectors')",
                "params": {
                    "query_vector": query_vector
                }
            }
        }
    },
    "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2fa6c89fb451b6e0/6a17f468af47b65da9cde0d9/89f3c795c6dc44b2f7d46801320288316b47e1b2-1600x488.png" alt="ビットベクトルを用いた後期相互作用モデルの最適化結果" /><p>これにより、非対称類似関数を用いてベクトルを比較します。</p><p></p><p>2つのビットベクトル間の通常のハミング距離について考えてみましょう。以下のドキュメントベクトル<em>D</em>と</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4b6ece1ec4dedac/6a17f4694b055d248143234e/366a70a23e37d403788327b7aefc873fd4482f5e-1235x86.png" alt="" /><p>クエリベクトル<em>Q</em>があると仮定します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7721df9c8f0d84f1/6a17f46b3e03d77cf54f2dcb/978ec31e0afbc0eaebf548a015b628c0cad84625-1247x84.png" alt="" /><p></p><p>シンプルなバイナリ量子化では、ベクトル<em>D</em>を <code>10101101</code>に、<em>Q</em>を<code>11111011</code>に変換します。ハミング距離を見つけるには、直接ビット計算が必要ですが、これは非常に高速です。この場合、ハミング距離は <code>01010110</code>であり、ビット数は4です。したがって、得点はそのハミング距離の逆数になります。類似するベクトルほどハミング距離は小さくなるため、これを反転すると類似するベクトルに高いスコアが付けられるようになります。特にここで、スコアは1/4 = <code>0.25</code>となります。</p><p>ただし、各次元の大きさが失われることに注意してください。<code>1</code>は<code>1</code>です。ですから、<em>Qについては</em>、<code>0.01</code> と<code>0.79</code> の違いはなくなります。単純に<code>&gt;0</code>に従って量子化しているので、Qベクトルが量子化されない小さなトリックを実行できます。これではビット単位の超高速演算はできませんが、Dが量子化されたままなので、ストレージコストは低く抑えられます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blted50315518e2d599/6a17f46c414c6463709452d3/508e8498ba969534d2a0131d431c75735fc27cb9-1399x611.png" alt="" /><p>つまり、これにより<em>Q</em>で提供される情報が保持され、距離推定の品質が向上し、ストレージが小さく抑えられます。</p><p>ビットベクトルを使用することで、ディスク容量とクエリ時の計算負荷を大幅に節約できます。しかし、できることはまだあります。</p><h3>平均ベクトル</h3><p>数十万、数百万のドキュメントにわたって検索をスケールするには、ビットベクトルがもたらすパフォーマンスの恩恵でさえ十分ではないでしょう。このようなタイプのワークロードにスケールするには、ElasticsearchのHNSWインデックス構造をベクトル検索に活用したいと思うでしょう。</p><p>ColpAliはドキュメントごとに約1000ベクトルを生成しますが、これは多すぎ、HNSWグラフに追加することはできません。したがって、ベクトルの数を減らす必要があります。これを行うには、画像を埋め込むときにColPaliによって生成されたすべてのドキュメントベクトルの平均を取得して、ドキュメントの意味の単一の表現を作成します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc053425fbfcf8de8/6a17f46f148009faf1b488aa/7c3b4dffb70bd95f67deb35f8c01e73c5286c2ab-1476x1102.png" alt="すべての遅延相互作用ベクトルの平均ベクトル" /><p>現時点では、これはElastic自体では不可能であり、Elasticsearchに取り込む前にベクトルを前処理する必要があります。 </p><p>Logstashまたは取り込みパイプラインでこれを行うことができますが、ここでは単純なPython関数を使用します。</p>def to_avg_vector(vectors):
    vectors_array = np.array(vectors)
    
    avg_vector = np.mean(vectors_array, axis=0)
    
    norm = np.linalg.norm(avg_vector)
    if norm &gt; 0:
        normalized_avg_vector = avg_vector / norm
    else:
        normalized_avg_vector = avg_vector

    return normalized_avg_vector.tolist()<p>また、ドット積類似度を使用できるようにベクトルを正規化しています。</p><p>ColPaliのベクトルをすべて平均ベクトルに変換したら、それらをdense_vectorフィールドにインデックスできます。</p>mappings = {
    "mappings": {
        "properties": {
            "avg_vector": {
                "type": "dense_vector",
                "dims": 128,
                "index": True,
                "similarity": "dot_product"
            },
            "col_pali_vectors": {
                "type": "rank_vectors",
                "element_type": "bit"
            }
        }
    }
}

es.indices.create(index=INDEX_NAME, body=mappings)<p>これによって、後期相互作用ベクトルとともにさらに多くの情報が保存されるため、合計ディスク使用量が増加することを考慮する必要があります。さらに、HNSWグラフを保持するために追加のRAMを使用して、何十億ものベクトルにわたって検索をスケールできるようにします。RAMの使用を減らすために、人気の <a href="https://www.elastic.co/search-labs/blog/optimized-scalar-quantization-elasticsearch">BBQ機能</a>を活用できます。その結果、通常では不可能な膨大なデータセットに対して高速な検索結果が得られます。</p><p>knnクエリで検索するだけで最も関連性の高いドキュメントを見つけられるようになりました。</p>query = "What do companies use for recruiting?"
query_vector = to_avg_vector(create_col_pali_query_vectors(query))
es_query = {
    "_source": False,
    "knn": {
        "field": "avg_vector",
        "query_vector": query_vector,
        "k": 10,
        "num_candidates": 100
    },
    "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf4ac6b7fd444f935/6a17f471a29299d76ad02dc0/a500f9907020f032c3b1c7a48ed8c759dc2a1dd4-1600x498.png" alt="" /><p>以前最高だったマッチは残念ながら3位に落ちました。</p><p>この問題を解決するために、多段階の取得を行うことができます。最初の段階では、knnクエリを使って数百万件の文書からクエリに最適な候補を検索します。第2段階では、ColPaliの後期相互作用ベクトルの忠実度が高い上位k（ここでは10）のみを再ランクしています。</p>query = "What do companies use for recruiting?"
col_pali_vector = create_col_pali_query_vectors(query)
avg_vector = to_avg_vector(col_pali_vector)
es_query = {
  "_source": False,
  "retriever": {
    "rescorer": {
      "retriever": {
        "knn": {
          "field": "avg_vector",
          "query_vector": avg_vector,
          "k": 10,
          "num_candidates": 100
        }
      },
      "rescore": {
        "window_size": 10,
        "query": {
          "rescore_query": {
            "script_score": {
              "query": {
                "match_all": {}
              },
              "script": {
                "source": "maxSimDotProduct(params.query_vector, 'col_pali_vectors')",
                "params": {
                  "query_vector": col_pali_vector
                }
              }
            }
          }
        }
      }
    }
  },
  "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt265edd5f37be40b7/6a17f4733e9e45583dba15e6/797f490860af87fcf29f34668a5c4511419c6fd0-1600x501.png" alt="後期相互作用モデルを最適化するための平均ベクトル使用の結果" /><p>ここでは、8.18で導入された<a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.18/retriever.html#rescorer-retriever">リスコアリトリーバー</a>を使用して結果を再ランク付けしています。再採点後、ベストマッチが再び1位になったことがわかります。 </p><p>注：本番環境では、maxSim関数が以前として相対的に高パフォーマンスであるため、10よりはるかに高いkを使うことができます。</p><h3>トークンプーリング</h3><p>トークンプーリングは、白い背景のパッチなどの冗長な情報をプールすることで、マルチベクトル埋め込みのシーケンスの長さを短縮します。この技術により、ページのシグナルの大部分を維持しながら埋め込みの数を減らすことができます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3d643e6ac908f640/6a17f4754b055d3783432352/09eae0b768f4b450e555d7e53e57561bd52de2c0-1412x1056.png" alt="後期相互作用モデルの最適化のためのトークンプーリング" /><p>トークンプーリングは、クラスタリングアルゴリズムを使用して、ドキュメント内の類似したトークン埋め込みをクラスターにグループ化することによって機能します。次に、各クラスターのベクトルの平均を計算して、単一の集約表現を作成します。この集約されたベクトルはグループ内の元のトークンを置き換え、ドキュメントシグナルを大幅に失うことなくベクトルの合計数を削減します。</p><p>ColPaliの論文では、ほとんどのデータセットに対して初期プールファクター値を3とすることを提案しており、これにより元のパフォーマンスの97.8%を保持しつつ、ベクトルの総数を66.7%削減しています。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2d78a15c6944a1ea/6a17f477414c64a2929452d9/343cc9eaf54af8c7a125d4115838f3c7d5659de0-1600x1007.png" alt="後期相互作用モデル最適化のためのプール係数" /><p>しかし、注意も必要です。非常に密度が高く、テキストが多く、余白がほとんどない「Shift」データセットは、プールファクターが増加するにつれてパフォーマンスが急速に低下します。</p><p>プールされたベクトルを作成するには、colpali_engineライブラリを利用できます。</p>from colpali_engine.compression.token_pooling import HierarchicalTokenPooler

pooler = HierarchicalTokenPooler(pool_factor=3) # test on your data for a good pool_factor

def pool_vectors(embedding: list) -&gt; list:
    tensor = torch.tensor(embedding).unsqueeze(0)
    pooled = pooler.pool_embeddings(tensor)
    return pooled.squeeze(0).tolist()<p>これで、次元が約66.7%削減されたベクトルが得られました。通常通りにインデックス化し、<code>maxSimDotProduct()</code>機能で検索することができます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc460c14031814ede/6a17f4794202292bf629f72d/2412c5db7d79a590b96d42fe01f140c42f010612-1600x481.png" alt="後期相互作用モデルの結果" /><p>結果の精度が若干犠牲になりますが、良好な検索結果を得ることができます。</p><p>ヒント：pool_factorを高くすれば（100-200）、平均的なベクトルソリューションとここで説明したソリューションの中間を取ることもできます。ドキュメントあたり5-10ベクトル程度であれば、HNSWインデックスを活用するためにネストされたフィールドでインデックスを作成することが可能になります。</p><h2>クロスエンコーダー、後期相互作用とバイエンコーダーの比較</h2><p>これまでに学んだことを踏まえて、ColPaliやColBERTなどの後期相互作用モデルを他のAI検索手法と比較すると、どのような位置づけになるでしょうか。</p><p>maxSim関数はクロスエンコーダーと比較して安価ですが、クエリとドキュメントのペアごとに2つのベクトルを比較するだけのバイエンコーダーを使用したベクトル検索よりも、依然として多くの比較と計算を必要とします。 </p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbfd97f3bba3e5b17/6a17f47be31791b0052d5943/75e1fc9e601aa7a6e88f137565c1919166c7a71c-1480x458.png" alt="クロスエンコーダー、後期相互作用モデルとバイエンコーダーの比較" /><p>このため、後期相互作用モデルについては、一般的にトップkの検索結果のリランキングにのみ使用することを推奨します。また、フィールドタイプの名前であるrank_vectorsにもこれを反映しています。</p><p>では、クロスエンコーダーはどうでしょうか。クエリ時に実行するコストが安いため、後期相互作用モデルの方が優れているのでしょうか。これもまた、状況によります。クロスエンコーダーは一般的に高品質な結果を生成しますが、クエリとドキュメントのペアが変換器モデルを通して完全に処理する必要があるため、多くの計算リソースを必要とします。また、ベクトルのインデキシングを必要とせず、ステートレスな方法で動作できるという利点もあります。その結果は次のようになります。</p><ul><li><p>使用ディスク容量の削減</p></li><li><p>よりシンプルなシステム</p></li><li><p>検索結果の品質向上</p></li><li><p>レイテンシが高いため、深いリランキングが困難</p></li></ul><p>一方、後期相互作用モデルでは、この計算の一部をインデックス時にオフロードできるため、クエリのコストが削減されます。その代償として、ベクトルをインデックスする必要があり、インデックスパイプラインがより複雑になり、これらのベクトルを保存するためにより多くのディスク領域が必要になります。</p><p>特にColPaliの場合、画像には大量のデータが含まれているため、画像からの情報の分析は非常に高価です。この場合、クエリ時にこの情報を評価するとリソースが大量に消費され、処理が遅くなるため、トレードオフはColPaliなどの後期相互作用モデルを使用する方に傾きます。 </p><p>ColBertのように、ほとんどのクロスエンコーダーのようにテキストデータを処理する後期相互作用モデル（例：elastic-rerank-v1）では、ディスクの節約とシンプルさのメリットを享受するためにクロスエンコーダーを使用する方が有利になる可能性があります。</p><p>ユースケースに合わせてこれらの長所と短所を比較検討し、最適な検索アプリケーションを構築するためにElasticsearchが提供するさまざまなツールを試してみることをお勧めします。</p><h2>まとめ</h2><p>このブログでは、ColpAliのような後期相互作用モデルをElasticsearchの大規模ベクトル検索用に最適化するさまざまな手法を紹介しました。後期相互作用モデルは検索効率とランキング品質の間の強力なバランスを実現しますが、ストレージと計算に関連する課題ももたらします。</p><p>これらの課題に対処するために、私たちは次の点を検討しました。</p><ul><li><p>ハミング距離や非対称最大類似度などの効率的な類似度計算を活用しながら、ディスク容量を大幅に削減する<strong>ビットベクトル</strong>。</p></li><li><p>複数の埋め込みを単一の密な表現に圧縮する<strong>平均ベクトル</strong>。これにより、HNSW インデックスによる効率的な検索が可能になります。</p></li><li><p>冗長な埋め込みを賢明にマージしながら意味の整合性を保守し、クエリ時の演算処理の負担を軽減する<strong>トークンプーリング</strong>。</p></li></ul><p>Elasticsearchは、ニーズに基づいて検索アプリケーションをカスタマイズおよび最適化するための強力なツールキットを提供します。検索速度、ランキング品質、ストレージ効率のどれを優先するかに関係なく、これらのツールとテクニックを使用すると、実際のアプリケーションのニーズに応じてパフォーマンスと品質のバランスをとることができます。</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/late-interaction-model-colpali-scale</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/late-interaction-model-colpali-scale</guid>
    <category><![CDATA[関連性]]></category>
    <category><![CDATA[Vector Database]]></category>
    <dc:creator><![CDATA[Peter Straßer,Benjamin Trent]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt97a536033e6b0a56/6a17f47dfbc5f88c86491c0d/c780b78a07573f2df1cfef8b29a7109f839b0ab3-1200x628.png" length="0" type="image/png"/>
    <pubDate>Thu, 20 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>