セマンティック検索

このページの項目

セマンティック検索とは

セマンティック検索とは、検索エンジンが人間のようにクエリと検索対象オブジェクト(テキスト・画像・動画・音声データなど)の 意味 を理解して行われる情報検索です。

検索対象オブジェクトとクエリの意味をベクトルで表現することで、セマンティック検索が実現されています。両者の意味をベクトルで捉えて検索することで、以下のようなメリットが生まれます。

  • 検索対象がテキストに限定されません。画像・動画・音声データなど、検索対象オブジェクトの意味をベクトルに変換できさえすれば、どんなオブジェクトでも、オブジェクトの種類が異なっていても検索可能です(マルチモーダル)。
  • 同じ理由で、他言語で書かれた文書を自言語で検索できます。たとえば、英語のマニュアルを(翻訳せずに)日本語のクエリで検索できます。
  • テキスト検索の場合、キーワードが一致していなくても意味が近いものが検索できます。そのため、類義語辞書のメンテナンスなどは一切不要です。
  • キーワードが一致していなくても検索できるため、検索対象文書執筆者(業務ドメインの専門家)と検索者(業務ドメインに詳しくない方)の間でボキャブラリーギャップがあっても検索できます。

セマンティック検索(セマンティックサーチ)は以下のように呼ばれることがありますが、すべて同じ技術です。本書ではセマンティック検索という呼称で統一します。

  • ベクトル検索(ベクトルサーチ)
  • 密ベクトル検索(密ベクトルサーチ)
  • ニューラル検索(ニューラルサーチ)

KandaSearchがサービス提供するApache Solrは、バージョン9.0以降でセマンティック検索をサポートしています。

Apache Solrのセマンティック検索機能

セマンティック検索を使うための、Apache Solrに必要な設定等について説明します。

スキーマ設定

managed-schema.xmlに、ベクトル値を保存するためのフィールドが必要です。以下に例を示します(次元数4、コサイン類似度、フィールド名vector)。

<fieldType name="knn_vector" class="solr.DenseVectorField" vectorDimension="4" similarityFunction="cosine"/>
<field name="vector" type="knn_vector" indexed="true" stored="true"/>
  • vectorDimensionで次元数を指定します(必須)。
  • similarityFunctionで関連度計算のために使用する関数を指定します(必須;euclidean、dot_product、cosineのいずれか)。

インデクシング

なんらかのモデルを使って、以下のような文書データを用意します。前述の通り、ベクトル値を保存するフィールド名をvectorとしたので、以下のJSONデータもvectorフィールドに4次元のベクトル値を持たせています。

[
  { "id": "1", "vector": [1.0, 2.5, 3.7, 4.1] },
  { "id": "2", "vector": [1.5, 5.5, 6.7, 65.1] }
]

このように用意したJSON(data.jsonとします)を以下のようにApache Solrに登録(インデクシング)します。

curl -X POST 'https://<subdomain>.c.kandasearch.com/solr/<collection>/update?commit=true' --data-binary @data.json -H 'Content-Type: text/json'

検索

インデクシング時に使用したのと同じモデルを使って、クエリベクトル(ここでは4次元)を用意し、以下のようにセマンティック検索を実行します。

curl https://<subdomain>.c.kandasearch.com/solr/<collection>/select?&q={!knn f=vector topK=10}[1.0, 2.5, 3.7, 4.1]&fl=id score
  • fでベクトルフィールド名を指定します(必須)。
  • topKで取得する最大ヒット件数を指定します(デフォルト10)。

KandaSearchのセマンティック検索機能

KandaSearchの場合、テキスト検索であれば、クエリ時と少量のインデクシング時ベクトル計算はKandaSearch内で実行できます。

KandaSearchのセマンティック検索のためのプラグイン

KandaSearchが提供する、セマンティック検索のためのApache Solrのプラグインはあらかじめ組み込まれています(別途拡張機能等をダウンロードする必要はありません)。ここではその組み込み済みのプラグインの使い方を説明します。

EmbeddingsProcessorFactory

EmbeddingsProcessorFactoryは、少量のインデクシング時ベクトル計算を行うのに向くApache SolrのUpdateRequestProcessorです。使用するには、以下の設定をsolrconfig.xmlに行います。

<updateRequestProcessorChain name="get-embeddings">
  <processor class="com.rondhuit.solr.update.dense.EmbeddingsProcessorFactory">
      <str name="clientType">COMMUNITY_JA</str>
      <str name="sourceField">body</str>
      <str name="targetField">body_vector</str>
  </processor>

  <processor class="solr.LogUpdateProcessorFactory"/>
  <processor class="solr.RunUpdateProcessorFactory"/>
</updateRequestProcessorChain>

パラメーターは以下の通りで、いずれも指定は必須です。

パラメーター名 説明
clientType 以下のいずれかを指定。
COMMUNITY_JA:日本語用モデル
COMMUNITY_EN:英語用モデル
COMMUNITY_MULT:Solrマニュアルモデル(多言語モデルから微調整)
SENTENCE_EMBEDDINGS:後述の「Hugging Faceで公開されているモデルを使う」を参照
sourceField ベクトル計算を行う対象のフィールド名
targetField ベクトル計算結果を保存するDenseVectorField型のフィールド名

このように設定したUpdateRequestProcessorChainは、 get-embeddings と名前が付与されているので、インデクシング時に次のように update.chain パラメーターに指定して呼び出すことができます。

curl -X POST 'https://<subdomain>.c.kandasearch.com/solr/<collection>/update?update.chain=get-embeddings&commit=true' --data-binary @yourfile.json -H 'Content-type: application/json'
DenseVectorSearchComponent

DenseVectorSearchComponentはApache SolrのSearchComponentであり、これを使うことで通常のキーワード検索のように、Solrにクエリテキストを送信することでセマンティック検索を実行することができます。使用するには、以下の設定をsolrconfig.xmlに行います。

<searchComponent name="dense-search" class="com.rondhuit.solr.handler.component.DenseVectorSearchComponent">
  <str name="clientType">COMMUNITY_JA</str>
</searchComponent>

<requestHandler name="/semantic" class="solr.SearchHandler">
  <lst name="defaults">
    <str name="echoParams">explicit</str>
    <str name="wt">json</str>
    <bool name="indent">true</bool>
    <bool name="_ks.dense">true</bool>
    <str name="_ks.dense.field">body_vector</str>
    <int name="_ks.dense.k">100</int>
  </lst>
  <arr name="first-components">
    <str>dense-search</str>
  </arr>
</requestHandler>
パラメーター名 説明
clientType 以下のいずれかを指定(必須)。
COMMUNITY_JA:日本語用モデル
COMMUNITY_EN:英語用モデル
COMMUNITY_MULT:Solrマニュアルモデル(多言語モデルから微調整)
SENTENCE_EMBEDDINGS:後述の「Hugging Faceで公開されているモデルを使う」を参照
_k.dense true(デフォルト)またはfalseを指定し、DenseVectorSearchComponentの機能のON/OFFを切り替える
_k.dense.field ベクトル検索対象フィールド名(必須)
_k.dense.k 検索結果として上位何件の文書を取得するかを指定(デフォルト:100)
Hugging Faceで公開されているモデルを使う

KandaSearch提供のEmbeddingsProcessorFactoryとDenseVectorSearchComponentは、前述のモデル(COMMUNITY_JA, COMMUNITY_EN, COMMUNITY_MULT)以外に、Hugging Faceで公開されているエンドポイントを使うことができます。以下は、EmbeddingsProcessorFactoryとDenseVectorSearchComponentに共通のパラメーターです。

パラメーター名 説明
clientType SENTENCE_EMBEDDINGSを指定して、Hugging Faceのエンドポイント利用を宣言
hostName Hugging Faceのエンドポイント
apiKey Hugging FaceのAPIキー

DenseVectorSearchComponentの場合、次のように使います。

<searchComponent name="dense-search" class="com.rondhuit.solr.handler.component.DenseVectorSearchComponent">
  <str name="hostName">{Your Hugging Face Endpoint}</str>
  <str name="clientType">SENTENCE_EMBEDDINGS</str>
  <str name="apiKey">{Your API Key}</str>
</searchComponent>

そして、Hugging Faceプロジェクトにて、エンドポイントを用意するために、カスタムハンドラーを実装します。そのカスタムハンドラーは、以下の形式のJSON(フィールド名が embeddings で値がfloatの配列)を返却するようにします。

{
  "embeddings":[
    -0.045720744878053665,-0.007091674953699112, ...
  ]
}

Livedoorニュースコーパス(embeddings)を使ったセマンティック検索の例

次にKandaSearch拡張機能ライブラリーで提供しているLivedoorニュースコーパス(embeddings)のデータを用いたセマンティック検索の実行例を通して、KandaSearchにおけるApache Solrのセマンティック検索の実行方法を見ていきます。

1. コレクションの作成

KandaSearchの拡張機能内のコンフィグを使ってコレクションを作成します。
操作方法は以下の通りです。

  1. 拡張機能ライブラリーより「Livedoorニュース(embeddings) configuration(Solr 9)」をプロジェクトに追加します。プロジェクトがない場合は作成します。
  2. プロジェクトビューの「拡張機能」より、1で追加したコンフィグをローカルPCへダウンロードします。
  3. プロジェクトオーバービューから、コレクションを追加するインスタンスへ移動します。インスタンスがない場合は作成します。コミュニティ(Community)プランは無償で作成できます。
  4. インスタンスビューの左サイドメニューから「コレクション」を選択します。
  5. コレクション画面内の「+コレクションを追加する」をクリックし、「インポートによる作成」から2でダウンロードしたファイルを指定し、インスタンスを作成します。
2. Livedoorニュースコーパス(embeddings)の登録

拡張機能ライブラリー内のベクトルデータが付与されたデータファイルを使ってコレクションに登録(インデクシング)します。
操作方法は以下の通りです。

  1. 拡張機能ライブラリーより、「Livedoorニュースコーパス(embeddings)」をプロジェクトに追加します。
  2. プロジェクトビューの「拡張機能」より、1で追加したデータをローカルPCへダウンロードし解凍します。JSON形式のファイルは約270MBです。
  3. データファイルが、インスタンスのオーバービューから登録できるサイズを超えているため、MacのターミナルやWindowsのWSLなどから、cURLコマンドを使って登録します。
curl -X POST 'https://<subdomain>.c.kandasearch.com/solr/<collection>/update?commit=true&indent=true' --data-binary @livedoor_embeddings.json -H 'Content-Type: text/json'
3. セマンティック検索の実行

データの登録が完了したら、検索UIからセマンティック検索を実行します。 操作方法は以下の通りです。

(1)インスタンスビューの左サイドメニューから「検索」を選択します。

(2)検索条件に以下のような指定(設定の例です)を行い「検索」をクリックします。

  • キーワード - 検索したいキーワードや調べたい内容の文章を指定します。例:「スマホ」「男性がもらって喜ぶもの」など。
  • コレクション - 上記の操作で作成したコレクション名を選択します。
  • リクエストハンドラ - /semantic と指定します。
  • ユニークキー - id が自動的に選択されます。
  • タイトル - title と指定します。
  • ボディ - body と指定します。
  • セマンティック検索を有効にする - チェックボックスをオンにします。
  • Dense Field - ベクトル値の格納されたフィールド名を指定します。body_vector と指定します。
  • Dense Top K - 返される検索結果件数を指定します。10 と指定します。
  • デフォルトフィールド - body と指定します。

(3)検索結果が表示されます。

4. データの追加や更新

前述のEmbeddingsProcessorFactoryを使うことで、少量のデータの追加や更新時のベクトル計算を行うことができます。試しに、次のようなJSONファイル sample.json を用意してKandaSearchのApache Solrに登録してみましょう。

$ cat sample.json
[
    {
    "id":"otani-san.txt",
    "url":"http://example.com/otani-san.html",
    "category":"sports-watch",
    "date":"2024-02-28T00:00:00Z",
    "title":"ドジャースの大谷翔平選手",
    "body":[
        "大谷翔平がドジャースのグラウンドに姿を現すと、出待ちしていたファンから大声援が起きた。"
    ]
    }
]

次のcurlコマンドを実行して登録します。

curl -X POST 'https://<subdomain>.c.kandasearch.com/solr/<collection>/update?update.chain=get-embeddings&commit=true' --data-binary @sample.json -H 'Content-type: application/json'

そして、前述と同じ設定でセマンティック検索を実行します。このとき、クエリを「ドジャースの大谷選手」などとします。すると、上記の追加データがヒットすることがわかります。

大量データのベクトル化

KandaSearchでの大量データのベクトル化は、GPSを設置して行います。詳しくはKandaSearchチームまでお問い合わせください。

セマンティック検索のデモ

ロンウイットのセマンティック検索デモサイトでさまざまなセマンティック検索の実行例をご覧いただけます。

関連する項目