Gluegent Blog

Gluegent Blog

新機能でよりシンプルに!Elasticsearchでセマンティック検索

  • 技術

今回はElasticsearch 8.15 から登場したフィールドタイプであるsemantic_textとinference APIを使用してセマンティック検索をする方法を説明していきます。
セマンティック検索を行うために使用するエンベディングモデルは、Google Vertex AIとOpenAIを使用しました。

新機能でよりシンプルに!Elasticsearchでセマンティック検索

こんにちは。エンジニアの土屋です。
以前の私の記事ではElasticsearch環境に学習済みモデルをデプロイしてセマンティック検索を行う方法をご紹介しました。その後のElasticsearchのバージョンアップによって、以前に比べてかなりシンプルにセマンティック検索の実装が可能になりました。
今回は、Elasticsearchの新しい機能を使って、以前よりもさらに手軽にセマンティック検索を実現する方法をご紹介します。以前手間がかかった設定も、新しいバージョンでは非常にシンプルになっています。

使用したElastic環境

  • version8.17.7のElastic Deployment

1. Inference Endpointの作成

Inference APIではElastic環境にデプロイした機械学習モデルに加え、AmazonやGoogleやOpenAIなどの他サービスの学習済みモデルを指定することができます。Inference endpointで指定して登録した学習済みモデルは、semantic_textフィールドのインデクシングや検索に使用することができるようになります。

今回はGoogle Vertex AIとOpenAIを使用しました。その際のKibana Console Shellは以下のようになります。

PUT _inference/text_embedding/open_ai_embeddings
{
  "service": "openai",
  "service_settings": {
    "model_id": "text-embedding-3-small",
    "api_key": “openai-api-key"
  }
}

【▲OpenAIのInference endpointをopen_ai_embeddingsというidで作成】

PUT _inference/text_embedding/vertex_ai_embeddings
{
    "service": "googlevertexai",
    "service_settings": {
        "service_account_json": "${service_account_json}",
        "model_id": "text-multilingual-embedding-002",
        "location": "us-central1",
        "project_id": “gcp-project-id"
    }
}

【▲Google Vertex AIのInference endpointをvertex_ai_embeddingsというidで作成】

2. インデックスとドキュメントの作成

今回はOpenAIとVertex AIの両方のモデルを使ったセマンティック検索ができるようにフィールド名をopen_ai_textとvertex_ai_textとしてそれぞれ作成しました。

フィールドタイプはsemantic_textを指定し、Inference_idには「1. Inference Endpointの作成」で作成したidを指定します。

PUT /semantic_sample_index
{
  "mappings": {
    "properties": {
      "open_ai_text": {
        "type": "semantic_text",
        "inference_id": "open_ai_embeddings"
      },
      "vertex_ai_text": {
        "type": "semantic_text",
        "inference_id": "vertex_ai_embeddings"
      }
    }
  }
}

mappingの定義でsemantic_textを指定しているのでドキュメント登録時はtext type等と同様に文字列をフィールドの値とします。以前の方法だとIngest Pipelineを通して登録する等の手順が必要でしたがsemantic_textを使用することでこの手順が不要になっていました!

PUT semantic_sample_index/_doc/001
{
    "open_ai_text":"中間・期末テスト勉強法",
    "vertex_ai_text":"中間・期末テスト勉強法"
}
PUT semantic_sample_index/_doc/002
{
    "open_ai_text":"体系的に学ぶ!ユニットテスト入門",
    "vertex_ai_text":"体系的に学ぶ!ユニットテスト入門"
}
PUT semantic_sample_index/_doc/003
{
    "open_ai_text":"サルでもわかるリグレッションテスト",
    "vertex_ai_text":"サルでもわかるリグレッションテスト"
}
PUT semantic_sample_index/_doc/004
{
    "open_ai_text":"必ず当たる心理テスト",
    "vertex_ai_text":"必ず当たる心理テスト"
}
PUT semantic_sample_index/_doc/005
{
    "open_ai_text":"ITエンジニアリング-テストの基本",
    "vertex_ai_text":"ITエンジニアリング-テストの基本"
}

3. セマンティック検索を試す

検索の際はsemantic queryを使用して検索が可能です。基本的には以下のようにフィールド名とクエリ文字列の指定のみで検索ができます。

POST /semantic_sample_index/_search
{
  "query" : {
    "semantic": {
      "field": "open_ai_text",
      "query": "テストコードの書き方"
    }
  }
}

POST /semantic_sample_index/_search
{
  "query" : {
    "semantic": {
      "field": "vertex_ai_text",
      "query": "テストコードの書き方"
    }
  }
}

検索に関しても、以前の方法だとエンベディングモデルの指定等の複雑な設定が必要でしたが、semantic queryではtextやkeywordのmatch検索やterm検索と変わらないシンプルなクエリでセマンティック検索が可能になりました。

semantic_textの機能

ここまでご紹介した通り、semantic_textを使えば、シンプルな手順でセマンティック検索が可能になります。今回は本のタイトルを想定した十数文字程度の文字列を対象としましたが、長文に対してセマンティック検索を行う場合、エンベディングの際に「チャンク分け」をしないと検索精度が落ちる可能性があります。このチャンク分けも、semantic_textを使えば自動で行うことができます。

また、Elasticsearchのバージョン8.18からは、検索レスポンスにデフォルトでベクトル情報が付与されなくなりました。これにより、私たちはエンベディング処理を意識することなく、ドキュメントの登録と検索ができるようになっています。

今回は基本的にデフォルトの設定でsemantic_textを使用しましたが、チャンク分けの設定やインデックスと検索で異なるモデルを使用する設定などがあります。(詳細は公式ページ参照)

従来の方法との比較

【従来のdense_vectorフィールドタイプでのセマンティック検索】

  • 1. Ingest Pipelineの作成
    • エンベディングモデルの指定や対象フィールドの指定
  • 2. Indexのmapping設定
    • dense_vectorタイプの指定
  • 3. Documentsの登録
    • Ingest Pipelineの指定が必要
  • 4. kNN(ANN)クエリによる検索
    • エンベディングモデルの指定やknnパラメータの指定が必要

【semantic_textを使用したセマンティック検索】

  • 1. Inference Endpointの作成
    • エンベディングモデルの指定
  • 2. Indexのmapping設定
    • semantic_textタイプの指定
  • 3. Documentsの登録
    • セマンティック検索を意識せずにシンプルに登録可能
  • 4. semantic queryを使用した検索
    • フィールド名とクエリ文字列のみのシンプルなクエリで検索可能

それぞれの手順を書きましたが、semantic_textを使用することでIngest Pipelineの設定やクエリの書き方の面で大幅に簡略化されました。これによって、より手軽なセマンティック検索の実装が可能になってきていると感じました。

まとめ

Elasticsearch 8.15から導入された新フィールドタイプsemantic_textとInference APIを活用して、セマンティック検索を実装する方法を解説しました。特に、Google Vertex AIとOpenAIのエンベディングモデルを連携させ、より高度な検索を簡単な手順で実現できることがお分かりいただけたかと思います。

Gluegent製品への応用

弊社が提供するクラウドワークフローGluegent Flowでは、AIを活用した「ユーザーアシスト」機能を提供をしています。このユーザーアシストの機能向上や、セマンティックな理解に基づいた新たな機能の開発にも今後積極的に取り組んでいきたいと考えています。

最後まで読んで頂きありがとうございました

(土屋)