「Chroma DBガイド | 生成AI LLMのためのベクトルストア」

Chroma DB Guide | Vector Store for Generating AI LLM

イントロダクション

GPTやPaLMなどの生成型の大規模言語モデルは、大量のデータで訓練されます。これらのモデルはデータセットからそのままのテキストを取得するのではなく、コンピュータはテキストを理解することができないため、数値のみを理解できます。埋め込みは、テキストを数値形式で表現したものです。大規模言語モデルへの情報の出入りは、すべてこれらの埋め込みを介して行われます。これらの埋め込みに直接アクセスすることは時間がかかります。そのため、効率的なストレージと埋め込みの取得のために特別に設計されたベクトルデータベースと呼ばれるものが存在します。このガイドでは、広く使用されているオープンソースのベクトルストア/データベースであるChroma DBに焦点を当てます。

学習目標

  • ChromaDBと埋め込みモデルを使用した埋め込みの生成
  • Chromaベクトルストア内でのコレクションの作成
  • ドキュメント、画像、および埋め込みのコレクションへの保存
  • データの削除と更新、コレクションの名前変更などのコレクション操作の実行
  • 最後に、関連情報を抽出するためのクエリの実行

この記事はData Science Blogathonの一部として公開されました。

埋め込みの短い紹介

埋め込みまたはベクトル埋め込みは、データ(テキスト、画像、音声、ビデオなど)を数値形式で表現する方法です。正確には、n次元空間(数値ベクトル)内の数値の形式でデータを表現する方法です。この方法により、埋め込みを使用して似たデータをクラスタ化することができます。これらの入力を受け取り、ベクトルに変換するモデルが存在します。その一つの例はWord2Vecです。Googleが開発した人気のある埋め込みモデルで、単語をベクトルに変換します(ベクトルはn次元の点です)。すべての大規模言語モデルは、それぞれの埋め込みモデルを持ち、それらのLLMのための埋め込みを作成します。

これらの埋め込みは何に使用されるのですか?

単語をベクトルに変換することの利点は、それらを比較できることです。コンピュータは単語をそのまま比較することはできませんが、数値の形式で与えれば、つまりベクトル埋め込みとして与えれば比較できます。似たような埋め込みを持つ単語のクラスタを作成することができます。たとえば、”King”、”Queen”、”Prince”、”Princess”という単語は他の単語と関連しているため、同じクラスタに表示されます。

このように、埋め込みを使用することで、与えられた単語に類似した単語を取得することができます。これを文に組み込むこともできます。文を入力し、提供されたデータから関連する文を取得します。これはセマンティックサーチ、文の類似性、異常検出、チャットボットなど、さまざまなユースケースの基盤です。PDFやドキュメントからの質問応答を実行するために構築したチャットボットでは、この埋め込みの概念を利用しています。すべての生成型の大規模言語モデルは、与えられたクエリに類似した内容を取得するためにこのアプローチを使用します。

ベクトルストアとその必要性

先述のように、埋め込みは数値形式で表現されたデータの表現です。通常、非構造化データをn次元空間で表現します。では、これらをどこに保存するのでしょうか?伝統的なRDMS(リレーショナルデータベース管理システム)では、これらのベクトル埋め込みを保存することはできません。ここでベクトルストア/ベクトルデータベースが登場します。ベクトルデータベースは、ベクトル埋め込みを効率的に保存および取得するために設計されています。さまざまなベクトルストアが存在し、それらはサポートする埋め込みモデルや類似ベクトルを取得するために使用する検索アルゴリズムの種類によって異なります。

なぜそれが必要なのでしょうか?それは、必要なデータへの高速なアクセスを提供するためです。PDFに基づいたチャットボットを考えてみましょう。ユーザーがクエリを入力すると、まずはPDFから関連コンテンツを取得し、この情報をチャットボットにフィードする必要があります。そして、チャットボットはこのクエリに関連する情報を取得し、ユーザーに適切な回答を提供するためにこの情報を使用します。では、ユーザーのクエリに関連するPDFから関連コンテンツをどのように取得するのでしょうか?答えは簡単な類似度検索です。

データがベクトル埋め込みで表現されると、データの異なる部分間で類似性を見つけ、特定の埋め込みに類似したデータを抽出することができます。クエリはまず埋め込みモデルによって埋め込みに変換され、その後ベクトルストアはこのベクトル埋め込みを受け取り、データベース内に保存されている他の埋め込みとの類似性検索(検索アルゴリズムを介して)を実行し、関連するデータをすべて取得します。これらの関連するベクトル埋め込みは、最終的な回答を生成するチャットボットで使用される大規模言語モデルに渡されます。

Chroma DBとは何ですか?

Chromaは、Chromaという会社が提供するベクトルストア/ベクトルDBです。Chroma DBは他の多くのベクトルストアと同様に、ベクトル埋め込みの保存と検索が目的です。良い点は、Chromaが無料かつオープンソースのプロジェクトであるということです。これにより、世界中の他の優れた開発者が提案を行い、データベースの大幅な改善を行うことができます。さらに、オープンソースソフトウェアに関する問題に対しては、迅速な回答が期待できます。なぜなら、オープンソースコミュニティ全体が問題を確認し、解決するために存在しているからです。

現在、Chromaはホスティングサービスを提供していません。Chromaを利用したアプリケーションを作成する際には、データをローカルのファイルシステムに保存します。ただし、Chromaは近い将来、ホスティングサービスの構築を計画しています。Chroma DBでは、ベクトル埋め込みを保存する異なる方法を提供しています。メモリ内に保存したり、メモリに保存して読み込んだり、バックエンドサーバーに接続してChromaを実行することができます。全体的にChroma DBはAPIに4つの機能しかなく、それにより短く、シンプルで、簡単に始めることができます。

Chroma DBで始めましょう

このセクションでは、Chromaをインストールし、提供されるすべての機能を確認します。まず、pipコマンドを使用してライブラリをインストールします。

$ pip install chromadb

ChromaベクトルストアAPI

これにより、Python用のChromaベクトルストアAPIがダウンロードされます。このパッケージを使用すると、ベクトル埋め込みの保存、取得、および指定されたベクトル埋め込みに対する意味検索など、すべてのタスクを実行できます。

import chromadb
from chromadb.config import Settings


client = chromadb.Client(Settings(chroma_db_impl="duckdb+parquet",
                                    persist_directory="/content/"
                                ))

メモリデータベース

まず、永続性のあるインメモリデータベースを作成します。上記のコードにより、データベースが作成されます。クライアントを作成するには、Chroma DBからClient()オブジェクトを取得します。次に、インメモリデータベースを作成するために、次のパラメーターを使用してクライアントを設定します。

  • chroma_db_impl = “duckdb+parquet”
  • persist_directory = “/content/”

これにより、parquetファイル形式のインメモリDuckDBデータベースが作成されます。また、このデータを保存するディレクトリを指定します。ここでは、データベースを/content/フォルダに保存しています。したがって、この構成でChroma DBクライアントに接続すると、Chroma DBは指定されたディレクトリ内に既存のデータベースを探し、読み込みます。存在しない場合は作成します。接続を閉じると、データはこのディレクトリに保存されます。

次に、コレクションを作成します。ベクトルストアのコレクションは、ベクトル埋め込み、ドキュメント、および任意のメタデータを保存する場所です。ベクトルデータベースのコレクションは、リレーショナルデータベースのテーブルのようなものと考えることができます。

コレクションの作成とドキュメントの追加

次に、コレクションを作成し、ドキュメントを追加します。

collection = client.create_collection("my_information")


collection.add(
    documents=["これは車の情報を含むドキュメントです",
    "これは犬の情報を含むドキュメントです", 
    "このドキュメントには四輪車のカタログが含まれています"],
    metadatas=[{"source": "Car Book"},{"source": "Dog Book"},{'source':'Vechile Info'}],
    ids=["id1", "id2", "id3"]
)
  • まず、コレクションを作成します。ここではコレクションの名前を「my_information」とします。
  • このコレクションにドキュメントを追加します。ここでは3つのドキュメントを追加しています。私たちの場合、3つの文を3つのドキュメントとして追加しています。最初のドキュメントは車について、2番目のドキュメントは犬について、最後のドキュメントは四輪車についてです。
  • メタデータも追加しています。すべてのドキュメントに対してメタデータが提供されています。
  • 各ドキュメントには固有のIDが必要なため、それぞれにid1、id2、id3を割り当てています
  • これらはすべてコレクションのadd()関数の変数のようなものです
  • コードを実行した後、これらのドキュメントを「my_information」コレクションに追加します

ベクトルデータベース

ベクトルデータベースに格納される情報は、ベクトル埋め込みの形式であることを学びました。しかし、ここではテキスト/テキストファイル、つまりドキュメントを提供しています。では、それらをどのように格納するのでしょうか? Chroma DBはデフォルトで、all-MiniLM-L6-v2ベクトル埋め込みモデルを使用して、私たちのためにベクトル埋め込みを作成します。このモデルは、私たちのドキュメントを取り、それらをベクトル埋め込みに変換します。HuggingFaceやOpenAIの他のsentence-transformerモデルや埋め込みモデルなど、特定の埋め込み関数で作業したい場合は、embeddings_function=embedding_function_name変数名をcreate_collection()メソッド内で指定することができます。

ドキュメントを渡す代わりに、ベクトルストアに直接埋め込みを提供することもできます。 create_collectionのdocumentパラメータと同様に、embeddingパラメータがあり、ベクトルデータベースに格納する埋め込みを渡します。

これで、モデルは私たちの3つのドキュメントをベクトルストアにベクトル埋め込みの形で正常に格納しました。次に、それらから関連するドキュメントを取得する方法を見ていきましょう。クエリを渡し、それに関連するドキュメントを取得します。これに対する対応するコードは次のとおりです。

results = collection.query(
    query_texts=["Car"],
    n_results=2
)


print(results)

ベクトルストアのクエリ

  • ベクトルストアのクエリには、コレクションが提供するquery()関数があります。この関数を使用すると、関連するドキュメントのためにベクトルデータベースをクエリできます。この関数では、2つのパラメータを指定します
  • query_texts – このパラメータには、関連するドキュメントを抽出するためのクエリのリストを指定します。
  • n_results – このパラメータは、データベースが返す上位結果の数を指定します。この場合、クエリに関連する上位2つのドキュメントを返すようにコレクションを設定します
  • 結果を実行して表示すると、次の出力が得られます

ベクトルストアがid1id3に関連付けられた2つのドキュメントを返すことがわかります。 id1は車に関するドキュメントであり、id3は車に関連する四輪車に関するドキュメントです。したがって、クエリとして「car」を指定した場合、Chroma DBはクエリを最初に指定した埋め込みモデルを使用してベクトル埋め込みに変換します。その後、このベクトル埋め込みは、利用可能なすべてのドキュメントに対して意味的な検索(類似最近傍)を実行します。したがって、クエリに関しては「car」が最も関連性が高いため、以下のような結果が得られます。

これは、複数のドキュメントを含むチャットアプリケーションを構築しようとしている場合に非常に役立ちます。ベクトルストアを介して、意味的な検索を実行し、提供されたクエリに関連するドキュメントのみを最終的な生成AIモデルにフィードすることで、関連するドキュメントを取得することができます。その後、この関連するドキュメントを取り、提供されたクエリに対して応答を生成します。

データの更新と削除

常にすべての情報を一度にベクトルストアに追加するわけではありません。ほとんどの場合、最初は限られたデータ/ドキュメントしかなく、それらをそのままベクトルストアに追加します。後でより多くのデータを取得した場合、ベクトルストア内に存在する既存のデータ/ベクトル埋め込みを更新する必要があります。Chroma DBでデータを更新するためには、次の手順を実行します。

collection.update(
    ids=["id2"],
    documents=["これは猫に関する情報を含むドキュメントです"],
    metadatas=[{"source": "猫の本"}],
)

以前、id2に関連付けられたドキュメントの情報は犬についてでした。これを猫に変更します。この情報をベクトルストア内で更新するために、ドキュメントのID、更新されたドキュメント、および更新されたメタデータをコレクションのupdate()関数に渡します。これにより、以前は犬に関する情報であったid2が猫に更新されます。

データベース内のクエリ

results = collection.query(
    query_texts=["Felines"],
    n_results=1
)


print(results)

クエリとして「Felines」を指定してベクトルストアに対して検索を行います。猫はFelinesという哺乳類の家族に属しています。したがって、コレクションはクエリに対して関連するドキュメントとしてCatドキュメントを返す必要があります。出力では、まさに同じものが表示されます。ベクトルストアはクエリとドキュメントの内容の間で意味的な検索を実行し、提供されたクエリに対して完璧なドキュメントを返すことができました。

The Upset Function

update関数と同様の機能として、upsert()関数と呼ばれる類似の関数があります。update()関数とupsert()関数の唯一の違いは、update()関数で指定されたドキュメントIDが存在しない場合、update()関数はエラーを発生させますが、upsert()関数の場合、コレクションにドキュメントIDが存在しない場合、add()関数と同様に追加されます。

場合によっては、スペースを節約したり、不要な情報を削除したりするために、ベクトルストアのコレクションからいくつかのドキュメントを削除したいことがあります。

collection.delete(ids = ['id1'])


results = collection.query(
    query_texts=["Car"],
    n_results=2
)


print(results)

The Delete Function

コレクションからアイテムを削除するには、delete()関数を使用します。上記では、車に関する最初のドキュメント(id1)を削除しています。今度は、「car」というクエリでコレクションをクエリし、結果を確認します。車に最も近い4輪車に関するドキュメント(id2)と車に最も近いドキュメントである猫に関するドキュメント(id3)の2つのドキュメントが表示されますが、n_results = 2が指定されているため、id3も取得できます。delete()関数に変数を指定しない場合、そのコレクションからすべてのアイテムが削除されます。

コレクション関数

新しいコレクションを作成し、ドキュメントと埋め込みを追加する方法を見てきました。ベクトルストアに保存されているドキュメントからクエリに関連する情報を抽出する方法も見てきました。Chroma DBのコレクションオブジェクトには、他にも多くの便利な機能があります。

Chroma DBが提供する他の機能について見てみましょう

new_collections = client.create_collection("new_collection")


new_collections.add(
    documents=["This is Python Documentation",
               "This is a Javascript Documentation",
               "This document contains Flast API Cheatsheet"],
    metadatas=[{"source": "Python For Everyone"},
    {"source": "JS Docs"},
    {'source':'Everything Flask'}],
    ids=["id1", "id2", "id3"]
)


print(new_collections.count())
print(new_collections.get())

The Count Function

コレクションのcount()関数は、コレクションに存在するアイテムの数を返します。この場合、コレクションには3つのドキュメントが格納されているため、出力は3になります。get()関数は、コレクションに存在するすべてのアイテムを、、および(存在する場合)とともに返します。出力では、コレクションに含まれるすべてのアイテムがget()コマンドを介して取得されていることがわかります。次に、コレクション名を変更する方法を見てみましょう

collection.modify(name="new_collection_name")

変更関数

modify() 関数を使用して、コレクション作成時に指定された名前を変更します。実行すると、古い名前から modify() 関数の name 変数で指定された新しい名前にコレクション名を変更します。ここで、Vector Store には複数のコレクションがあると仮定します。特定のコレクションで作業する方法、つまり Vector Store から特定のコレクションを取得する方法と特定のコレクションを削除する方法について見ていきましょう。

my_collection = client.get_collection(name="my_information_2")

client.delete_collection(name="my_information_2")

コレクションの取得関数

get_collection() 関数は、Vector Store から name で指定された既存のコレクションを取得します。指定されたコレクションが存在しない場合、同じエラーが発生します。ここでは、get_collection()my_information_2 コレクションを取得し、それを変数 my_collection に割り当てます。既存のコレクションを削除するには、delete_collection() 関数があります。この関数は、パラメータとしてコレクション名(この場合は my_information)を取り、存在する場合に削除します。

結論

このガイドでは、オープンソースのベクトルデータベースである Chroma の使い方について説明しました。まず、ベクトル埋め込みとは何か、なぜジェネレーティブAIモデルに必要なのか、そしてベクトルストアがこれらのジェネレーティブ大規模言語モデルをサポートする方法について学びました。次に、Chroma のコレクション作成方法について詳しく説明しました。その後、ドキュメントなどのデータを Chroma に追加する方法と、Chroma DB がそれらからベクトル埋め込みを作成する方法について説明しました。最後に、Vector Store に存在する特定のコレクションに関連する情報を取得する方法について説明しました。

このガイドの主なポイントは次のとおりです:

  • ベクトル埋め込みは、テキスト、画像、音声などの非数値データの数値表現(数値ベクトル)です。
  • ベクトルストアは、コレクション形式でベクトル埋め込みを格納するために使用されるデータベースです。
  • ベクトルデータから情報を効率的に格納および取得する機能を提供します。
  • Chroma DB は、インメモリデータベースとしてもバックエンドとしても機能します。
  • Chroma DB は、終了時にデータを保存し、接続を開始する際にメモリにデータをロードする機能があり、データを永続化します。
  • ベクトルストアを使用すると、ドキュメントから情報を抽出したり、推薦を生成したり、チャットボットアプリケーションを構築することが簡単になります。

よくある質問

この記事で表示されているメディアは Analytics Vidhya の所有物ではなく、著者の裁量で使用されています。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more