📣

Amazon DocumentDB とDynamoDBにてVector Searchができるようになったアップデートについて

2023/11/30に公開

概要

re:Invent 2023のSwamiのKeynoteでこんなAmazon DocumentDB とDynamoDBにてVector Searchができるようなったアップデートが出たのでまとめてみた記事になります。

https://aws.amazon.com/jp/blogs/aws/vector-search-for-amazon-documentdb-with-mongodb-compatibility-is-now-generally-available/

Vector SearchとしてAmazon DocumentDBとAmazon DynamoDBが対応

そもそもVector Searchってなーに?

  • ChatGPTやBedrockで提供されている大規模言語モデル (LLM) が話題になっている中で、LLMを使用し社内向けのAIシステムを構築しようとした際に、LLMが学習していない社内データを使用したい、そんなシチュエーションがあると思います。
  • そういった時に、LLMそのものをfine tuningする方法と、LangChainを使ってVector MatchingさせるRetrieval Augmented Generation (RAG) の2つがあります。
  • ただ、LLMのfine tuningは現実味がなく、膨大な大きな計算リソースと学習のための作業が必要になります。
  • そのため、大体のユーザがRAGを選択し、以下のようなアーキテクチャを組むのが主流となっています。

  • この時に学習させたい情報のEmbeddingを取り、その内容を保存するのにVector Databaseが必要になってきます。
  • 全体の動きとしては、LLMに質問をしたとき、LLMはDBを参照しながら回答を作成する動きとなります。

開発者が必要なこと

主に開発者が必要なことは以下の二つとなります。

Vector DBの構築

学習させたい情報のデータセットに対し、Embeddingし、その情報をVector DBに保存、もちろんVector DBも用意が必要です。

LLMとVector DBの接続

プロンプトを使用し、質問をEmbeddingさせVector DBと類似性検索をさせます。
その後、情報の類似度の高いものをVectorDBから抽出し、その情報とLLMが学習している情報を使用して応答します。

今回、発表があったのは、そのVector DBやVector Searchの部分を既存でAWSが提供しているDatadaseサービスであるDocumentDBとDynamoDBで対応したというものです。

機能の紹介

  • KeynoteではDocumentDBとDynamoDBで対応したようだが、DynamoDBのドキュメントが見つからなかったので、一旦DocumentDBでの使用感について見ていきます。

https://docs.aws.amazon.com/documentdb/latest/developerguide/vector-search.html

  • DocumentDBのベクトル検索では、既存で利用できたJSONベースのドキュメントデータベースのメリットもえられつつ、Embeddingさせたデータを保存、検索することができるようです。

  • Amazon DocumentDB でのベクトル検索をするには、Amazon DocumentDB 5.0 インスタンスベースのクラスターで利用できるようです。
    当たり前だが、インスタンスベースなので、DocumentDBを使用するさいにクラスターの管理やインスタンスの面倒は開発者が見ることになる。

①: titan-embed-text-v1を使用して、embeddingしてみよう。

  • 下記にtitan-embed-text-v1を使用してembeddingしたコードを置いておきます。
  • こんな感じで、検索したい情報をembeddingし、出力されたものをVector Databaseに格納して使用します。
import json
import os
import sys

import boto3

bedrock = boto3.client('bedrock-runtime')

prompt = "I love dog and cat."
response = bedrock.invoke_model(
    body= json.dumps({"inputText": prompt}), 
    modelId='amazon.titan-embed-text-v1', 
    accept='application/json', 
    contentType='application/json'
)
response_body = json.loads(response['body'].read())
embedding = response_body.get('embedding')

# 埋め込みベクトルを表示
print(embedding)
[1.53125, -0.55078125, 0.14550781, 0.60546875, -0.05126953, -0.23535156, ・・・・]

②: embeddingをぶっ込みベクトルインデックスを作成

  • Amazon DocumentDBのコレクションに追加したいドキュメントのリストを指定して、insertMany( [{},...,{}] ) オペレーションを使って、生成されたベクトル埋め込みを追加します。

  • DocumentDでの検証前のセットアップはこちらをご参照ください。
    https://docs.aws.amazon.com/documentdb/latest/developerguide/get-started-guide.html

  • 下記がインサートするデータの例になります。

db.collection.insertMany([{"product_name": "I love a dog and cat.", "vectorField": [1.53125, -0.55078125, 0.14550781, 0.60546875, -0.05126953, -0.23535156, 0.03515625, -0.001121521, 0.84765625, -0.33984375, 0.33398438, 0.35351562, 0.19335938, -0.5546875, -0.071777344, -0.75, 0.36132812, -0.828125, -0.328125, 0.47265625, 0.49414062, -0.14746094, -0.3359375, 0.8203125, 0.16015625, -0.19726562, 1.2734375, -0.38085938, -0.28515625, -0.73828125, 0.87890625, 1.1953125, -0.03564453, -0.33984375, 0.04321289, -0.53125, -0.42578125, 0.038330078, 0.29492188, -0.12988281, -0.20703125, 0.53125, 0.53515625, 0.118652344, 0.13085938, 0.625, 0.09082031, 1.28125, 0.36914062, -0.15429688, 0.11669922, 0.21191406, 0.59375, -0.22949219, -0.08935547, 0.35351562, -0.5078125, 0.51953125, -1.1953125, -0.049560547, 0.734375, 0.068847656, 0.16894531, 1.03125, 0.43945312, -0.004547119, 0.36914062, 0.14355469, -0.70703125, -1.0234375, 0.03955078, -0.041503906, 0.6015625, 0.040039062, 0.8515625, 0.3515625, 0.22070312, -0.21191406, 0.36328125, -0.052734375, 0.14453125, 0.30078125, -0.0031738281, 0.13183594, -0.64453125, 0.30273438, 0.55078125, -0.018920898, 0.00012111664, 0.14160156, -0.42382812, -0.36523438, 0.28515625, 0.37695312, -0.20703125, 0.17285156, 0.24316406, -0.66015625, -0.06738281, 1.2890625]}]);

成功すると下記がレスポンスされます。

{
        "acknowledged" : true,
        "insertedIds" : [
                ObjectId("65679bcd05b737c230621cc0")
        ]
}

③: createIndexコマンドを利用して、vector indexを作成

  • createIndex コマンドを使用してベクトルインデックスを作成できます。
  • DocumentDBは、IVFFLAT(inverted file with flat compression)ベクトルインデックスを使用して、近似最近傍(ANN)検索を実行するようです。
db.collection.createIndex({ "vectorField": "vector" },{ "name": "myIndex","vectorOptions": {"dimensions": 100,"similarity": "euclidean","lists":1}});

こんなレスポンスが返ってきます。

{
        "ok" : 0,
        "operationTime" : Timestamp(1701288945, 1),
        "code" : 85,
        "errmsg" : "Index already exists with different options"
}

④: DocumentDBからvector embeddingsを検索します

これで、ドキュメント内の類似ベクトルを検索できるようになりました
"I like pets "を以下のコードで検索します。

db.collection.aggregate({$search: {"vectorSearch": {"vector": [1.53125, -0.55078125, 0.14550781, 0.60546875, -0.05126953, -0.23535156, 0.03515625, -0.001121521, 0.84765625, -0.33984375, 0.33398438, 0.35351562, 0.19335938, -0.5546875, -0.071777344, -0.75, 0.36132812, -0.828125, -0.328125, 0.47265625, 0.49414062, -0.14746094, -0.3359375, 0.8203125, 0.16015625, -0.19726562, 1.2734375, -0.38085938, -0.28515625, -0.73828125, 0.87890625, 1.1953125, -0.03564453, -0.33984375, 0.04321289, -0.53125, -0.42578125, 0.038330078, 0.29492188, -0.12988281, -0.20703125, 0.53125, 0.53515625, 0.118652344, 0.13085938, 0.625, 0.09082031, 1.28125, 0.36914062, -0.15429688, 0.11669922, 0.21191406, 0.59375, -0.22949219, -0.08935547, 0.35351562, -0.5078125, 0.51953125, -1.1953125, -0.049560547, 0.734375, 0.068847656, 0.16894531, 1.03125, 0.43945312, -0.004547119, 0.36914062, 0.14355469, -0.70703125, -1.0234375, 0.03955078, -0.041503906, 0.6015625, 0.040039062, 0.8515625, 0.3515625, 0.22070312, -0.21191406, 0.36328125, -0.052734375, 0.14453125, 0.30078125, -0.0031738281, 0.13183594, -0.64453125, 0.30273438, 0.55078125, -0.018920898, 0.00012111664, 0.14160156, -0.42382812, -0.36523438, 0.28515625, 0.37695312, -0.20703125, 0.17285156, 0.24316406, -0.66015625, -0.06738281, 1.2890625], "path":"vectorField", "similarity":"euclidean", "k": 2, "probes": 1}}});

そうするとちゃんと検索が走りレスポンスが返ってきましたね!

{ "_id" : ObjectId("65679bcd05b737c230621cc0"), "sentence" : "I love a dog and cat.", "vectorField" : [ 1.53125, -0.55078125, 0.14550781, 0.60546875, -0.05126953, -0.23535156, 0.03515625, -0.001121521, 0.84765625, -0.33984375, 0.33398438, 0.35351562, 0.19335938, -0.5546875, -0.071777344, -0.75, 0.36132812, -0.828125, -0.328125, 0.47265625, 0.49414062, -0.14746094, -0.3359375, 0.8203125, 0.16015625, -0.19726562, 1.2734375, -0.38085938, -0.28515625, -0.73828125, 0.87890625, 1.1953125, -0.03564453, -0.33984375, 0.04321289, -0.53125, -0.42578125, 0.038330078, 0.29492188, -0.12988281, -0.20703125, 0.53125, 0.53515625, 0.118652344, 0.13085938, 0.625, 0.09082031, 1.28125, 0.36914062, -0.15429688, 0.11669922, 0.21191406, 0.59375, -0.22949219, -0.08935547, 0.35351562, -0.5078125, 0.51953125, -1.1953125, -0.049560547, 0.734375, 0.068847656, 0.16894531, 1.03125, 0.43945312, -0.004547119, 0.36914062, 0.14355469, -0.70703125, -1.0234375, 0.03955078, -0.041503906, 0.6015625, 0.040039062, 0.8515625, 0.3515625, 0.22070312, -0.21191406, 0.36328125, -0.052734375, 0.14453125, 0.30078125, -0.0031738281, 0.13183594, -0.64453125, 0.30273438, 0.55078125, -0.018920898, 0.00012111664, 0.14160156, -0.42382812, -0.36523438, 0.28515625, 0.37695312, -0.20703125, 0.17285156, 0.24316406, -0.66015625, -0.06738281, 1.2890625 ] }
{ "_id" : ObjectId("65679ccb05b737c230621cc1"), "sentence" : "I love a dog and cat.", "vectorField" : [ 1.53125, -0.55078125, 0.14550781, 0.60546875, -0.05126953, -0.23535156, 0.03515625, -0.001121521, 0.84765625, -0.33984375, 0.33398438, 0.35351562, 0.19335938, -0.5546875, -0.071777344, -0.75, 0.36132812, -0.828125, -0.328125, 0.47265625, 0.49414062, -0.14746094, -0.3359375, 0.8203125, 0.16015625, -0.19726562, 1.2734375, -0.38085938, -0.28515625, -0.73828125, 0.87890625, 1.1953125, -0.03564453, -0.33984375, 0.04321289, -0.53125, -0.42578125, 0.038330078, 0.29492188, -0.12988281, -0.20703125, 0.53125, 0.53515625, 0.118652344, 0.13085938, 0.625, 0.09082031, 1.28125, 0.36914062, -0.15429688, 0.11669922, 0.21191406, 0.59375, -0.22949219, -0.08935547, 0.35351562, -0.5078125, 0.51953125, -1.1953125, -0.049560547, 0.734375, 0.068847656, 0.16894531, 1.03125, 0.43945312, -0.004547119, 0.36914062, 0.14355469, -0.70703125, -1.0234375, 0.03955078, -0.041503906, 0.6015625, 0.040039062, 0.8515625, 0.3515625, 0.22070312, -0.21191406, 0.36328125, -0.052734375, 0.14453125, 0.30078125, -0.0031738281, 0.13183594, -0.64453125, 0.30273438, 0.55078125, -0.018920898, 0.00012111664, 0.14160156, -0.42382812, -0.36523438, 0.28515625, 0.37695312, -0.20703125, 0.17285156, 0.24316406, -0.66015625, -0.06738281, 1.2890625 ] }

まとめ

  • 今回追加されたAmazon DocumentDBのVector Searchについて試してみました。
  • ただ、どうしてもDocumentDBの世界なので、クラスターの管理やインスタンスの管理があるのが私としてはうーんという感じだったのですが、mongo勢が今勢いがあるとのことで、この機能追加で喜ぶユーザもいるんだろうなと感じてます。
  • まだ、ドキュメント上ではDynamoDBのVector Searchについては公開されていないので、こちらは公開され次第記事にしていきたいと思います!

https://x.com/yoshii0110/status/1729929595699523955?s=20

Discussion