Google Vertex AIのLLM GroundingにElasticsearchを使う

# はじめに
Google Vertex AIではLLM Groundingが行えます。
https://cloud.google.com/vertex-ai/generative-ai/docs/grounding/overview?hl=ja
RAGとほぼ同じではありますが、このGroundingを行う先としてElasticsearchを選べるようになっています。
https://cloud.google.com/vertex-ai/generative-ai/docs/grounding/grounding-with-elasticsearch?hl=ja

非常に簡単にRAGができるようになるのでその手順を解説します。

:::note info
2025/04/22の時点で本機能はPreviewです
:::

# 環境
Elasticsearch: v9.0.0
Gemini:gemini-2.0-flash-001（他のバージョンでも出来ます）

# 手順
## Elasticsearchの準備
Vertex AIからREST APIをElasticsearchに向けて投げるので、Vertex AIから届くところに立てる必要があります。Elastic Cloudで立てるのが楽でしょう。
少し古いですが、こちらに手順が説明されています。
https://qiita.com/tomo_s_el/items/3584d0b1fabb0bafa4fa

### ドキュメントの用意
gemini-2.0-flash-001がうまく回答できないけど、Groundingしたら応えられるようになるものを考えます。こういう場合、最新情報で行うのがわかりやすいです。

ElasticsearchにはBBQ (Better Binary Quantization)という機能が8.16からリリースされています。普通にやると所謂バーベキューの方の説明が出てきます。
そこをGroundingを使って回答を改善してみます。
BBQのリリースブログを一部日本語に翻訳した以下の文章を使ってみます。

`Elasticsearch 8.16は、BBQ（Better Binary Quantization）を導入しました。これは、ベクトル化されたデータを圧縮する革新的なアプローチで、従来の方法であるプロダクト量子化（PQ）を上回る性能を発揮します。Elasticは、このアプローチを実装し、実際の検索ワークロードでこの機能を利用できるようにし、必要なコンピューティングリソースを削減しながら、低クエリレイテンシーと高いランキング品質を維持する最初のベクトルデータベースベンダーです。このリリースでは、Reciprocal Rank Fusion（RRF）、Retrievers、およびオープンなInference APIの一般提供も開始され、ハイブリッド検索と検索強化生成（RAG）ベースのアプリケーションを構築するためのワークフローを簡素化する包括的なツールセットが提供されます。Elasticsearch 8.16は現在Elastic Cloudで利用可能です。これは、この最新リリースのすべての新機能を含む唯一のホスト型Elasticsearchオファリングです。これらの機能は、Elastic Cloudの完全管理型サーバーレスElasticsearchプロジェクトでも利用可能です。また、Elastic Stackやクラウドオーケストレーション製品であるElastic Cloud EnterpriseおよびElastic Cloud for Kubernetesをダウンロードして、セルフマネージド体験をすることもできます。ローカル開発でElasticsearchを始めるには、start-localスクリプトをチェックして、数分でノートパソコンにローカルデプロイメントを取得してください。```bashcurl -fsSL https://elastic.co/start-local | sh```Elastic 8.16のその他の新機能については、8.16の発表記事をご覧ください >>ElasticはBBQを導入しましたBetter Binary Quantization（BBQ）に出会いましょう。これは、ベクトルデータに対して最大32倍の圧縮効果を達成しながら、精度を損なわない最先端の最適化です。Elasticは、大規模なデータセットに依存するワークロードの削減とスケールのために、分散型でスケーラブルなElasticsearchベクトルデータベースのユーザーにこの機能を提供する最初の企業であることを誇りに思っています。これはまずElasticの顧客にのみ提供されますが、すぐにLuceneコミュニティに貢献され、すべてのベクトルストアの潜在的な能力を高めることになります。BBQは、スカラー量子化とほぼ同じ速度とストレージ効率を達成しながら、高いランキング品質を維持します。その高い圧縮レベルにより、組織は大規模なデータセットを効果的に管理し、ベクトルストレージと検索操作を手頃な価格でスケールすることができます。さらに、BBQはデータセットが拡大しても優れたリコールを維持しながら、メモリ使用量を95%以上削減します。また、Elasticsearch内の他の量子化方法と簡単に組み合わせることができ、最大の利益を得ることができます。`

### インデックス
インデックスを作って上記のドキュメントを投入します。
以下をDev Toolsで実行します。

```
POST test/_doc/
{
  "description": "Elasticsearch 8.16は、BBQ（Better Binary Quantization）を導入しました。これは、ベクトル化されたデータを圧縮する革新的なアプローチで、従来の方法であるプロダクト量子化（PQ）を上回る性能を発揮します。Elasticは、このアプローチを実装し、実際の検索ワークロードでこの機能を利用できるようにし、必要なコンピューティングリソースを削減しながら、低クエリレイテンシーと高いランキング品質を維持する最初のベクトルデータベースベンダーです。このリリースでは、Reciprocal Rank Fusion（RRF）、Retrievers、およびオープンなInference APIの一般提供も開始され、ハイブリッド検索と検索強化生成（RAG）ベースのアプリケーションを構築するためのワークフローを簡素化する包括的なツールセットが提供されます。Elasticsearch 8.16は現在Elastic Cloudで利用可能です。これは、この最新リリースのすべての新機能を含む唯一のホスト型Elasticsearchオファリングです。これらの機能は、Elastic Cloudの完全管理型サーバーレスElasticsearchプロジェクトでも利用可能です。また、Elastic Stackやクラウドオーケストレーション製品であるElastic Cloud EnterpriseおよびElastic Cloud for Kubernetesをダウンロードして、セルフマネージド体験をすることもできます。ローカル開発でElasticsearchを始めるには、start-localスクリプトをチェックして、数分でノートパソコンにローカルデプロイメントを取得してください。```bashcurl -fsSL https://elastic.co/start-local | sh```Elastic 8.16のその他の新機能については、8.16の発表記事をご覧ください >>ElasticはBBQを導入しましたBetter Binary Quantization（BBQ）に出会いましょう。これは、ベクトルデータに対して最大32倍の圧縮効果を達成しながら、精度を損なわない最先端の最適化です。Elasticは、大規模なデータセットに依存するワークロードの削減とスケールのために、分散型でスケーラブルなElasticsearchベクトルデータベースのユーザーにこの機能を提供する最初の企業であることを誇りに思っています。これはまずElasticの顧客にのみ提供されますが、すぐにLuceneコミュニティに貢献され、すべてのベクトルストアの潜在的な能力を高めることになります。BBQは、スカラー量子化とほぼ同じ速度とストレージ効率を達成しながら、高いランキング品質を維持します。その高い圧縮レベルにより、組織は大規模なデータセットを効果的に管理し、ベクトルストレージと検索操作を手頃な価格でスケールすることができます。さらに、BBQはデータセットが拡大しても優れたリコールを維持しながら、メモリ使用量を95%以上削減します。また、Elasticsearch内の他の量子化方法と簡単に組み合わせることができ、最大の利益を得ることができます。"
}
```

### Search Template
`Search Template`は検索の細かな設定をあらかじめ決めておくものです。
https://www.elastic.co/docs/solutions/search/search-templates
検索のアプリケーションを作る場合に、複雑なクエリを行うとアプリ側にその複雑なクエリ分を全部記載しないといけなくなるし、クエリ分を変更したい時にはソースコードに手を入れないといけなくなります。
Search Templateを利用するとparameterとして検索文などを渡すことができるので便利です。

今回のケースもVertex AIからはSearch Templateを使って検索を行ってGroundingをする仕組みになっています。

以下をDev Toolsで実行します。
```
PUT _scripts/vertexai_template
{
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "match": {
            "description": "{{query}}"
        }
      }
    }
  }
}
```

`{{query}`というのはmustacheという記法です。
https://mustache.github.io/mustache.5.html
これでパラメータとして定義することが出来ます。
このように使います。
 ```
 GET test/_search/template
{
  "id": "vertexai_template",
  "params": {
    "query": "elasticsearchのBBQについて"
  }
}
```
### API Keyの用意
ドキュメントはこちら
https://www.elastic.co/docs/deploy-manage/api-keys/elasticsearch-api-keys#create-api-key
`Stack Management` -> `Security` -> `API Keys`から右上の`Create API Key`をクリックして、名前だけ入れて、右下の`Create API Key`を押します。
![スクリーンショット 2025-04-23 8.57.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603229/9bcaac11-0693-40b2-baed-a31167b9bdc4.png)

API Keyが表示されるのでコピーしておきます。このKeyは再度表示することは出来ませんので、コピーし忘れたら別のKeyを作成しましょう。

![スクリーンショット 2025-04-23 8.58.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603229/4d3406c5-17d2-4324-a45b-81c71ad57888.png)

これでElasticsearch側の準備はできました。

## Vertex AI
AI Studioからプロンプトの作成の画面に移ります。
![スクリーンショット 2025-04-23 8.48.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603229/def3c973-7d6c-4dc3-96f3-736357ad26c0.png)

モデルは何でも良いと思いますが、gemini 2.0であれば以下のような面白い回答をしてくれます。
![スクリーンショット 2025-04-23 8.50.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603229/696532c9-cf60-44f4-847f-8db5cc839258.png)
勿論追加でBBQ=Better Binary Quantizationだと教えてあげれば正しい回答をします。

### Groundingの設定
ページの右側にグラウンディングが２つありますが、下側をクリックします。
![スクリーンショット 2025-04-23 9.03.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603229/ce405900-8ccc-46a9-b980-aaa526434b65.png)

Elasticsearchを選ぶと設定入力画面が出ます。
![スクリーンショット 2025-04-23 9.04.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603229/c8f5a3c4-9d1b-4a6f-afe4-869cc561fb61.png)

- Elasticsearch エンドポイント
![https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_2603229_ebf37746-bac5-4b3d-b83e-9ce3bcc7fab4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603229/d1728dc0-590d-47d2-a346-29b1c6df0a78.png)

- Elasticsearch API キー
    - 先ほど作成したAPIキーだが、頭に`ApiKey`とつける
    - 例えばAPI Keyが`hogehoge`なら
        - `ApiKey hogehoge`
- Elasticsearch インデックス
    - 今回だと`test`
- Elasticsearch 検索テンプレート
    - 今回だと`vertexai_template`

## Grounding
ではプロンプトに`ElasticsearchのBBQについて`と入れてみましょう
![スクリーンショット 2025-04-23 9.26.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603229/174e1b43-25ac-415d-8eb3-7530134b90e9.png)

Grounding Sourceにちゃんとインデックスしたドキュメントが表示されています。

# まとめ
Vertex AIから簡単にGroundingができるのは非常に便利です。
特にSearch Templateが使用できるので複雑な検索文も問題なく使用できます。
RAGでは回答のもととなるドキュメントが正しくないと意味がありません。正しい検索結果を返すための方法が豊富に用意されているElasticsearchを利用してみてください。