Python Chromadb 詳細開発ガイド

インストール

pip install chromadb

Chromadb データの永続化

import chromadb

Chroma データベースファイルの保存パスを指定できます。データが存在する場合、プログラム起動時にデータベースファイルが自動的に読み込まれます。

client = chromadb.PersistentClient(path="/data/tizi365.db")

path パラメータは Chroma データベースファイルへのパスです。

注意: Chroma データベースでは、クライアントオブジェクトを一度作成すれば十分です。同じパスで複数のクライアントを読み込んだり保存したりすると、データの削除を含む予期しない動作が発生する可能性があります。通常、アプリケーション内では1つの Chroma クライアントのみを作成するべきです。

クライアントオブジェクトの一般的に使用される関数:

client.reset()  # データベースをクリアして完全にリセットします

コレクション操作

Chromadb は collection プリミティブを使用して、ベクトルデータのコレクションを管理します。これは MySQL のテーブルに似ています。

コレクションの作成、表示、および削除

Chroma は URL でコレクション名を使用するため、名前にいくつかの命名規則があります:

  • 名前の長さは3〜63文字の間でなければなりません。
  • 名前は小文字または数字で始まり終わり、途中にピリオド、ハイフン、アンダースコアを含めることができます。
  • 名前に二重のピリオドを含めることはできません。
  • 名前は有効な IP アドレスではない必要があります。

コレクションを作成するには、コレクション名とオプションのベクトル計算関数(埋め込み関数とも呼ばれる)を指定する必要があります。埋め込み関数が提供された場合、コレクションにアクセスするたびに提供する必要があります。

注意: ベクトル計算関数(埋め込み関数)の目的は、テキストベクトルを計算することです。

collection = client.create_collection(name="my_collection", embedding_function=emb_fn)
collection = client.get_collection(name="my_collection", embedding_function=emb_fn)

埋め込み関数はテキストを入力として受け取り、計算されたベクトルを返します。

注意: 初心者は テキスト埋め込みモデルチュートリアル を学ぶことができます。

.get_collection 関数で既存のコレクションを参照し、.delete_collection を使用してコレクションを削除することができます。また、.get_or_create_collection を使用してコレクションを参照したり、存在しない場合は作成したりすることもできます。

collection = client.get_collection(name="tizi365")
collection = client.get_or_create_collection(name="tizi365")
client.delete_collection(name="tizi365")

その他よく使用されるコレクション操作:

collection.peek() # コレクション内の最初の10データのリストを返します
collection.count() # コレクション内のデータの総数を返します
collection.modify(name="新しい名前") # コレクションの名前を変更します

ベクトル距離計算方法の指定

create_collection 関数には、オプションの metadata パラメータも含まれています。hnsw:space の値を設定することで、ベクトル空間の距離計算方法をカスタマイズできます。

注意: ベクトルデータはベクトル間の空間距離を計算することで、ベクトル間の類似性を表現します。距離が近いほど類似性が高く、逆もまた然りです。

collection = client.create_collection(
        name="collection_name",
        metadata={"hnsw:space": "cosine"} # l2 がデフォルトの計算方法です
    )

hnsw:space の有効なオプションは "l2", "ip", "cosine" です。デフォルトは "l2" です。

コレクションへのデータの追加

.add メソッドを使用して、Chroma にデータを追加します。

ドキュメントベクトルを明示的に指定せずにデータを追加します:

collection.add(
    documents=["lorem ipsum...", "doc2", "doc3", ...],
    metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
    ids=["id1", "id2", "id3", ...]
)

Chroma にドキュメントのリストが渡されると、自動的にコレクションの埋め込み関数を使用してドキュメントのベクトルを計算します(コレクション作成時に埋め込み関数が指定されていない場合は、デフォルト値が使用されます)。Chroma はまた、ドキュメント自体を格納します。選択した埋め込み関数を使用してドキュメントを計算すると、大きすぎるドキュメントでは例外が発生します。

各ドキュメントにはユニークな ID(ids)が必要です。同じ ID を2回追加すると、初期値のみが保存されます。オプションで、各ドキュメントのためのメタデータ辞書のリスト(metadatas)を提供し、クエリ中にデータをフィルタリングするために使用できる追加情報を格納できます。

または、直接ドキュメントの関連ベクトルデータのリストを提供し、Chroma は自動的にベクトルを計算せずに提供されたベクトルデータを使用します。

collection.add(
    documents=["doc1", "doc2", "doc3", ...],
    embeddings=[[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
    metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
    ids=["id1", "id2", "id3", ...]
)

提供されたベクトルデータの次元(長さ)がコレクションの次元と一致しない場合は、例外が発生します。

また、ドキュメントを別の場所に保存し、Chroma にベクトルデータとメタデータリストを提供することもできます。これにより、ids を使用して別の場所に保存されたドキュメントとベクトルを関連付けることができます。

collection.add(
    embeddings=[[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
    metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
    ids=["id1", "id2", "id3", ...]
)

注:ベクトルデータベースの主な機能は、ベクトルデータに基づいたセマンティック類似性検索です。ベクトルデータベースのサイズを小さくし、効率を向上させるために、ベクトルデータといくつかの必要なフィルタリング属性をベクトルデータベースに保存することができます。記事の内容などの他のデータは、ID を介して関連付ける限り、MYSQL などのデータベースに保存することができます。

コレクションデータのクエリ

.queryメソッドは、さまざまな方法でChromaデータセットをクエリするために使用できます。

クエリは、クエリ埋め込み(ベクトルデータ)を使用して行うことができます。

ヒント:実際の開発シナリオでは、クエリ埋め込みは通常、まずテキスト埋め込みモデルを使用してユーザーのクエリのベクトルを計算し、その後このベクトルを使用して類似コンテンツをクエリします。

collection.query(
    query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
    n_results=10,
    where={"metadata_field": "is_equal_to_this"},
    where_document={"$contains":"search_string"}
)

クエリは、各クエリベクトル(query_embedding)に最もよく一致するn_results結果を順に返します。オプションでwhereフィルター辞書を提供して、各ドキュメントに関連するメタデータに基づいて結果をフィルタリングすることもできます。さらに、オプションでwhere_documentフィルター辞書を提供して、ドキュメント内容に基づいて結果をフィルタリングすることもできます。

提供されたクエリ埋め込みがコレクションの次元と一致しない場合は、例外が発生します。一貫したベクトル次元を確保するには、同じテキスト埋め込みモデルを使用してベクトルを計算してください。

また、クエリテキストセットを使用してもクエリできます。Chromaはまず、コレクションの埋め込み関数を使用して、各クエリテキストのベクトルを計算し、生成されたテキストベクトルを使用してクエリを実行します。

collection.query(
    query_texts=["doc10", "thus spake zarathustra", ...],
    n_results=10,
    where={"metadata_field": "is_equal_to_this"},
    where_document={"$contains":"search_string"}
)

また、.getを使用してコレクションからIDでデータをクエリすることもできます。

collection.get(
    ids=["id1", "id2", "id3", ...],
    where={"style": "style1"}
)

.getはwhereとwhere_documentフィルターもサポートしています。IDが提供されていない場合、whereとwhere_documentフィルターに一致するコレクション内のすべてのアイテムを返します。

戻り値フィールドの指定

getまたはqueryを使用する際に、includeパラメータを使用して返されるデータを指定できます。embeddingsdocuments、または**metadatas**を指定できます。クエリの場合は距離データも返される必要があります。デフォルトでは、Chromaはクエリに対してドキュメントとメタデータを返し、クエリに対して距離データを返します。"ids"は常に返されます。queryまたはgetメソッドのincludesパラメータにフィールド名の配列を渡すことで、返されるフィールドを指定できます。

collection.get(
    include=["documents"]
)

collection.query(
    query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
    include=["documents"]
)

Whereフィルターの使用

Chromaは、メタデータとドキュメントコンテンツに基づいてクエリをフィルタリングすることをサポートしています。whereフィルターはメタデータをフィルタリングするために使用され、where_documentフィルターはドキュメントコンテンツをフィルタリングするために使用されます。以下では、フィルタ条件式の記述方法について説明します。

メタデータでのフィルタリング

メタデータをフィルタリングするには、クエリ用に「where」フィルター辞書を提供する必要があります。辞書は次の構造を持つ必要があります:

{
    "metadata_field": {
        <Operator>: <Value>
    }
}

メタデータのフィルタリングでは、以下の演算子をサポートしています:

  • $eq - 等しい(文字列、整数、浮動小数点数)
  • $ne - 等しくない(文字列、整数、浮動小数点数)
  • $gt - より大きい(整数、浮動小数点数)
  • $gte - 以上(整数、浮動小数点数)
  • $lt - より小さい(整数、浮動小数点数)
  • $lte - 以下(整数、浮動小数点数)

$eq演算子を使用することは、whereフィルターを使用することと同等です。

{
    "metadata_field": "search_string"
}

{
    "metadata_field": {
        "$eq": "search_string"
    }
}

ドキュメントコンテンツでのフィルタリング

ドキュメントコンテンツをフィルタリングするには、クエリ用に「where_document」フィルター辞書を提供する必要があります。辞書は次の構造を持つ必要があります:

{
    "$contains": "search_string"
}

論理演算子の使用

複数のフィルタを組み合わせるために、$andおよび$orの論理演算子を使用することもできます。

$and演算子は、リスト内のすべてのフィルタと一致する結果を返します。

{
    "$and": [
        {
            "metadata_field": {
                <Operator>: <Value>
            }
        },
        {
            "metadata_field": {
                <Operator>: <Value>
            }
        }
    ]
}

$or演算子は、リスト内のいずれかのフィルタ条件と一致する結果を返します。

{
    "$or": [
        {
            "metadata_field": {
                <Operator>: <Value>
            }
        },
        {
            "metadata_field": {
                <Operator>: <Value>
            }
        }
    ]
}

コレクション内のデータの更新

.updateを使用すると、コレクション内のデータのプロパティを更新できます。

collection.update(
    ids=["id1", "id2", "id3", ...],
    embeddings=[[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
    metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
    documents=["doc1", "doc2", "doc3", ...],
)

コレクション内でidが見つからない場合、エラーが記録され、更新は無視されます。提供されたドキュメントに対応するベクトルが存在しない場合、コレクションの埋め込み関数が使用されてベクトルが計算されます。

提供されたベクトルデータがコレクションと異なる次元である場合、例外が発生します。

Chromaは、既存のデータを更新し、存在しない場合は新しいデータを挿入するアップサート操作をサポートしています。

collection.upsert(
    ids=["id1", "id2", "id3", ...],
    embeddings=[[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
    metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
    documents=["doc1", "doc2", "doc3", ...],
)

コレクションデータの削除

Chromaは、.deleteを使用して、idによってコレクションからデータを削除する機能をサポートしています。各データに関連するベクトル、ドキュメント、およびメタデータも削除されます。

collection.delete(
    ids=["id1", "id2", "id3",...],
    where={"chapter": "20"}
)

.deletewhereフィルタもサポートしています。idが提供されていない場合、whereフィルタに一致するコレクション内のすべてのアイテムが削除されます。