MilvusでJSONデータをベクトル化し、類似性検索を行う
この記事では、MilvusがJSONデータのベクトル化、取り込み、類似検索をどのように効率化するかを紹介する。
シリーズ全体を読む
- 楽々AIワークフロー:Hugging FaceとPyMilvusの初心者ガイド
- MilvusとHaystack 2.0によるRAGパイプラインの構築
- Milvusインスタンスでベクターインデックスを選ぶ方法:ビジュアルガイド
- MilvusとOpenAIによるセマンティック検索
- GCP KubernetesでMilvusを効率的にデプロイする:オープンソースデータベース管理ガイド
- 北極雪片とMilvus上のトランスフォーマーでRAGを作る
- MilvusでJSONデータをベクトル化し、類似性検索を行う
- Gemini 1.5、BGE-M3、Milvus Lite、LangChainによるマルチモーダルRAGの構築
JSONは、JavaScript Object Notationの略で、サーバーやウェブアプリケーション間でデータの保存や交換を行うためのテキストベースのフォーマットです。そのシンプルさ、柔軟性、互換性により、開発者はさまざまな業界やアプリケーションでJSONデータを使用しています。例えば、IoT(モノのインターネット)デバイスやセンサーは、JSONを介してウェブインターフェースとシームレスに通信します。
しかし、JSONの階層構造は便利な反面、保存、検索、分析などの作業には手間がかかります。JSONをベクトル化することで、このデータを効率的な処理、保存、検索、分析に最適化された形式に変換し、パフォーマンスと使いやすさを向上させます。
この記事では、MilvusベクトルデータベースがJSONデータのベクトル化、取り込み、類似検索をどのように効率化するかを探ります。さらに、Milvusを使用したJSONデータのベクトル化、取り込み、検索のステップバイステップのプロセスを詳細に説明したガイドを提供します。
JSONデータのベクトル化と取得をMilvusが効率化する方法
Milvusは、大量の高次元ベクトルデータを管理する、拡張性の高いオープンソースのベクトルデータベースである。検索拡張世代(RAG)、セマンティック検索、レコメンダーシステムなどのユースケースに役立つ。ここでは、Milvusがどのように効率的なJSONデータの処理と検索を促進するかを紹介する。
動的スキーマによるJSONデータのサポート
Milvusは、ユーザーのコレクション内でベクトルデータと共にJSONデータのシームレスな保存とクエリをサポートしています。この機能により、ユーザーはJSONデータを効率的に一括挿入し、JSONフィールドの値に基づいて高度なクエリとフィルタリングを実行できます。この機能は、動的なスキーマ変更を必要とするアプリケーションでの詳細なデータ分析と操作に不可欠です。
主流の埋め込みモデルとの統合
Milvusは、OpenAI Embedding API、sentence-transformer、BM25、Splade、BGE-M3、VoyageAIを含むPython SDK for MilvusであるPyMilvusを通して、主流のエンベッディングモデルと統合します。この統合により、ベクトルデータの準備が効率化され、追加のデータスタックを導入することなく、データパイプライン全体の複雑さが軽減されます。
| ------------------------------------------------------------------------------- | -------- | ----------------------- | | エンベッディング関数** | タイプ | APIまたはオープンソース | OpenAI | OpenAI|密|API|||。 | sentence-transformer | Dense | Open-sourced | | BM25 | BM25 | 疎な | オープンソース || BM25 | 疎な | オープンソース || BM25 | Splade | Sparse | Open-sourced | | BGE-M3 | BGE-M3 | ハイブリッド | オープンソース | | VoyageAI | VoyageAI](https://milvus.io/docs/embed-with-voyage.md)|密|API||。
エンベッディング生成と類似検索のためのMilvusの使い方
以下のセクションでは、一般的な埋め込みモデルと統合することで、Milvusを使用してベクトル埋め込みを生成し、JSONデータ全体の類似性検索を行う方法を説明します。このステップバイステップガイドの完全なコードについては、こちらのnotebookを参照してください。
ステップ1:JSONデータのインポート
インポート json
# JSONファイルへのパス
json_file_path = 'data.json'
# JSONデータを読み込む
with open(json_file_path, 'r') as file:
articles = json.load(ファイル)
# 正しく読み込まれたことを確認するためにデータを表示する
print(articles)
- JSON ライブラリをインポートします:この行には、JSONフォーマットのデータを扱うためのPython組み込みのJSONライブラリが含まれています。
- JSONファイルのパスを設定する:この行では、JSONファイルのパスを設定します。
- JSONデータの読み込みと印刷JSONファイルを読み込みモードで開き、データを記事変数にロードし、正しくロードされたことを確認するためにそれをプリントアウトする。with`ステートメントを使用することで、データを読み込んだ後にファイルが自動的にクローズされ、効率的かつ安全なアプローチとなる。
データは以下の形式である:
{
"title":"現代医療における機械学習のインパクト"、
"content":"機械学習は、診断と患者ケアを改善することで、ヘルスケア業界に革命をもたらしている。予測分析などの技術は、患者の転帰を予測し、パーソナライズされた治療計画を強化し、業務を合理化するために使用されている、
"metadata":{
"author":"Jane Doe"、
"views":5000,
"publication":「ヘルステック・ウィークリー
"拍手":150,
「回答数20,
「タグ":[機械学習", "ヘルスケア", "予測分析"]、
「reading_time":8
}
},...
ステップ2: PyMilvusで埋め込みを生成する
MilvusはPyMilvusを通して多くの一般的な埋め込みモデルとの統合を提供し、開発プロセスを効率化します。この例では、All-MiniLM-L6-v2
文型変換モデルである SentenceTransformerEmbeddingFunction
を使用します。
この埋め込み関数を使用するには、まずPyMilvusクライアントライブラリを model
サブパッケージとともにインストールする必要がある。
pip install "milvus[model]"
from pymilvus.model.dense import SentenceTransformerEmbeddingFunction # モデルライブラリからモデルを取得する。
# モデルライブラリからモデルを取得
model = SentenceTransformerEmbeddingFunction('all-MiniLM-L6-v2')
# 前処理されたテキストから特徴を抽出する
for article in articles:
# タイトルと内容の埋め込みを生成する
article['title_vector'] = model([article['タイトル'])[0])
article['content_vector'] = model([article['content'])[0]。
# ベクトルデータを追加した記事を表示する
print({key: articles[0][key] for key in articles[0].keys()})
ここでは、シンプルにするために、"title "と "content "のベクトル化だけに焦点を当てます。上記のコードを使って、データの2つのフィールドをベクトル化し、別々のフィールドとして保存しました。以下にステップの内訳を示します:
- model = SentenceTransformerEmbeddingFunction('all-MiniLM-L6-v2')`:この行は'all-MiniLM-L6-v2'モデルをロードします。'all-MiniLM-L6-v2'はPyMilvusのモデルライブラリを使って事前に学習されたモデルです。このモデルはテキスト入力に対して密なベクトル埋め込みを生成することで知られています。
- article['title_vector'] = model.encode(article['title'])とarticle['content_vector'] = model.encode(article['content'])`です:これらの行は、ロードされたSentence Transformerモデルを適用して、各記事のタイトルと内容をベクトル埋め込みにエンコードします。エンコード関数は、テキスト情報を意味的に類似したテキストベクトルがより近い高次元空間に変換します。この変換は、セマンティック検索、クラスタリング、情報検索のような、テキストの根本的なセマンティクスの理解に依存する多くの機械学習アプリケーションにとって極めて重要である。
- print({key: articles[0][key] for key in articles[0].keys()})`:この最後の行は、タイトルと内容のために新しく追加されたベクトルを含む、最初の記事のすべてのキーと値のペアを表示します。
- この出力は、テキストデータがどのように数値表現で補強されるかをわかりやすく視覚化し、データ駆動型アプリケーションのための充実したデータ構造を示している。
ステップ3:Milvusのセットアップ
ここで、Milvusベクトルデータベースを使って、テキストデータから得られるベクトル埋め込みを管理する。
from pymilvus import connections, CollectionSchema, FieldSchema, DataType, Collection, utility.
# Milvusへの接続
connections.connect(alias="default", host="localhost", port="19530")
# コレクションスキーマのフィールドを定義する
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True)、
FieldSchema(name="title_vector", dtype=DataType.FLOAT_VECTOR, dim=384)、
FieldSchema(name="content_vector", dtype=DataType.FLOAT_VECTOR, dim=384)
]
# コレクションスキーマを作成する
schema = CollectionSchema(fields, description="記事の埋め込みコレクション")
# Milvusでコレクションを作成する
コレクション名 = "articles"
if not utility.has_collection(collection_name):
collection = Collection(name=collection_name, schema=schema)
print(f "Collection '{collection_name}'が作成されました。")
else:
コレクション = コレクション(name=コレクション名)
print(f "コレクション '{コレクション名}' は既に存在します。")
もっと深く掘り下げてみよう:
さらに深く潜ってみましょう:
- connections.connect(alias="default", host="localhost", port="19530")`:この行はローカルマシン(localhost)のポート19530で動作しているMilvusサーバーへの接続を確立します。alias="default "パラメータは、この接続が以降の操作におけるデフォルト接続であることを意味します。このステップはアプリケーションとベクターデータベース間の通信を確立し、データ挿入、クエリ、管理などの操作を可能にします。
- フィールドスキーマとコレクションスキーマ`:Milvusにデータを格納するフィールドはFieldSchemaを使用して定義されます。各フィールドには特定の役割がある:
- id`:主キーとして設定され、各エントリに一意な識別子を自動的に割り当てるように設定された整数フィールド。
- title_vectorとcontent_vector
:これらのフィールドは浮動小数点数のベクトル(FLOAT_VECTOR)を格納し、それぞれ記事のタイトルとコンテンツの埋め込みを表す。dim=384
はこれらのベクトルの次元数を指定し、埋め込みモデルの出力サイズと一致させる。
- これらのフィールド定義は
CollectionSchema
にまとめられ、コレクションが保持するデータの構造と種類を記述する。 - コレクション名 = "articles"`:コレクションの名前を設定する。
ステップ4: データの挿入
# 挿入するデータを準備する
エンティティ = [{
"title_vector": article['title_vector']、
"content_vector": article['content_vector'].
for article in articles].
# データをコレクションに挿入する
insert_result = collection.insert(エンティティ)
print(f "Data inserted, number of rows:{len(insert_result.primary_keys)}")。
- リスト内包
entities = [{"title_vector": article['title_vector'], "content_vector": article['content_vector']} for article in articles]
は辞書のリストを構築し、各辞書はMilvusコレクションに挿入されるエンティティを表す。これらのベクタはMilvusコレクションスキーマで定義されたフィールド(title_vectorとcontent_vector
)と一致する形式で用意される。 - insert_result = collection.insert(entities)`の行は用意されたエンティティをコレクションに挿入する。この操作は、類似検索や機械学習モデルの入力など、様々な検索タスクのためのベクトルデータをMilvusデータベースに投入するために重要である。
print(f "Data inserted, number of rows:{len(insert_result.primary_keys)}")
:データ挿入後、この行は挿入に成功した行(エンティティ)の数を出力する。insert_result.primary_keys`は挿入された各レコードの一意な識別子を提供し、いくつのエントリが追加されたかを反映する。このフィードバックは、データがコレクションに正しく完全に格納されているかどうかを確認するために重要である。
ステップ 5: インデックスの作成
インデックス作成は、検索クエリのパフォーマンスに直接影響するため、どのデータベース管理シス テムにおいても非常に重要です。リアルタイムの分析と応答性が重要なAIアプリケーションでは、効率的なインデックス作成によってユーザーエクスペリエンスを大幅に向上させることができます。
# title_vector と content_vector のインデックスパラメータを定義する。
index_params = {
"index_type":"IVF_FLAT", # L2およびIP距離に適した反転ファイルシステム
"metric_type":"L2", # ユークリッド距離
"params":{"nlist":100} # クラスタ数
}
# title_vector' フィールドにインデックスを作成する。
collection.create_index(field_name="title_vector", index_params=index_params)
print("title_vector' にインデックスを作成しました。")
# content_vector' フィールドにインデックスを作成する
collection.create_index(フィールド名="content_vector", index_params=index_params)
print("インデックスが'content_vector'に作成されました。")
# 検索用にコレクションをメモリにロードする
collection.load()
print("コレクションをメモリにロードしました。")
ベクトル空間をクラスタリングすることで、IVF_FLAT
インデックスはクエリの検索空間を縮小し、特にデータセットが大きくなるにつれて検索速度を劇的に改善する。最終的には、コレクションをメモリにロードして運用効率を高める。IVF_FLATインデックスタイプを使用して、ベクトル空間を100のクラスタに分割し、ユークリッド距離計算に
L2メトリックを使用する。次に、
title_vectorと
content_vector` の両フィールドにインデックスを作成し、検索作業を高速化する。
ステップ6:類似検索の実行
# 検索パラメータを定義する
search_params = {
"metric_type":"L2",
"params":{"nprobe":10}
}
# 最初の記事のコンテンツベクタをクエリに使うと仮定する
query_vector = [エンティティ[0]["content_vector"]] とする。
# 'content_vector'フィールドで検索を実行する
search_results = collection.search(
data=query_vector、
anns_field="content_vector"、
param=search_params、
limit=5、
output_fields=["id"])
)
# 検索結果を表示する
for hits in search_results:
for hit in hits:
print(f "Hit: {hit}, ID: {hit.id}")
このプロセスは search_params
ディクショナリで検索パラメータを定義することから始まり、ベクトル間のユークリッド距離を測定するために L2
メトリックを利用する。クエリベクタは最初の記事の content_vector
を用いて準備され、コレクション内で類似した内容の記事を見つけることを目的としている。検索は content_vector
フィールドにこれらのパラメータを使用し、最も近い上位5件に結果を限定し、そのIDを返す。
最後に、ベクトル化されたコンテンツ表現に基づいて最初のクエリに最も類似した記事を特定することで、クエリの有効性を実証するために、各マッチとそのIDを表示して検索結果を反復する。
結論
ベクトルデータベースはJSONデータのベクトル化とクエリを最適化し、従来のデータベースの制約を超えた類似検索、複雑なパターン認識、リレーショナルクエリを可能にする。Milvusベクトルデータベースは、ベクトルデータと共にJSONデータの保存と検索をサポートし、ベクトル生成のための主流の埋め込みモデルと統合します。この統合により、開発者はデータスタックを追加することなく、JSONデータを簡単にベクトル化することができ、開発プロセスを大幅に効率化することができます。
さらに、JSONデータでは、すべてのキーがすべてのドキュメントに含まれていない場合にスパース性が発生し、情報の欠落やNULLを示す多くのゼロ値を持つベクトルが生成されます。これにより複雑な高次元ベクトル空間が形成され、処理やクエリが困難になります。Milvusの埋め込みモデルとの統合は、スパースな高次元データを効率的に管理するためのデータ構造とアルゴリズムを最適化する。例えば、多様なデータサイズやデータ型に適応可能な動的スキーマを採用し、複雑なJSON構造を最小限の前処理で効率的に保存・照会することができます。