0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Weaviateの初歩 Pythonでcollectionを作ってみる

Last updated at Posted at 2024-09-02

以前の記事でWeaviateをk3sクラスタ上に構築したので、コレクションを作ってみましょう。RDBで言うところのテーブルみたいなものでしょうか。

どのようなコレクションを作るか

ER図で示すのが正しいのか分かりませんが、以下のような関係性を持たせたいと思います。

・TestAのエンティティにはtitleとsummaryがあります。
・TestAは複数のTestBエンティティを持ちます。
・TestBのエンティティにはchapterとtextがあります。

事前準備

$ pip install weaviate-client

コレクションの作成

10C_define_class_TestA.py(注:うまくいかない)
import weaviate
import weaviate.classes.config as wc

weaviate_client = weaviate.connect_to_custom(
    http_host="xxx.xxx.xxx.xxx",  # URL only, no http prefix
    http_port=30020,
    http_secure=False,   # Set to True if https
    grpc_host="xxx.xxx.xxx.xxx",
    grpc_port=30021,      # Default is 50051, WCD uses 443
    grpc_secure=False,   # Edit as needed
)

weaviate_client.collections.create(
    name='TestA',
    properties=[wc.Property(name='title',data_type=wc.DataType.TEXT),
                wc.Property(name='summary',data_type=wc.DataType.TEXT)],
    references=[wc.ReferenceProperty(
            name='children',
            target_collection='TestB'
        )
    ],
    vectorizer_config=[wc.Configure.NamedVectors.text2vec_aws(
        name='textdocument_vector',
        service='bedrock',
        model='cohere.embed-multilingual-v3',
        region='us-west-2'
    )        
    ]
)

weaviate_client.close()

WeaviateClient.collections.create()でコレクションを作成します。
・引数propertiesはリストを取ります。ここにwc.Property型のインスタンスを並べます。インスタンス中のdata_typeの指定はwc.DataTypeを使います。
・引数referencesはリストを取ります。ここにwc.ReferenceProperty型のインスタンスを並べます。インスタンス中のtarget_collectionには、リファレンス先のコレクションの名前を指定します。
・ベクトル化の肝であるベクトライザーをコレクションに対して指定しています。その指定には引数vectorizer_configを使いますが、これにwc.Configure.NamedVectors以下のメソッドを指定してあげます。ここにtext2vec_openaiやらtext2vec_cohereやらありますが、私はBedrockでcohere embeddingを使うのでtext2vec_awsを使いました。これらベクトライザーモジュール関連についての詳細は以下が詳しいと思います。英語ですが。

ところが、これを実行すると以下のように叱られてしまいました。

$ python 10C_define_class_TestA.py
()
    raise UnexpectedStatusCodeError(error_msg, response=res)
weaviate.exceptions.UnexpectedStatusCodeError: Collection may not have been created properly.! Unexpected status code: 422, with response body: {'error': [{'message': "property 'children': invalid dataType: reference property to nonexistent class"}]}.
/home/yterashi/.pyenv/versions/3.12.4/lib/python3.12/site-packages/weaviate/warnings.py:303: ResourceWarning: Con004: The connection to Weaviate was not closed properly. This can lead to memory leaks.
            Please make sure to close the connection using `client.close()`.
/home/yterashi/.pyenv/versions/3.12.4/lib/python3.12/asyncio/selector_events.py:879: ResourceWarning: unclosed transport <_SelectorSocketTransport fd=10 read=idle write=<idle, bufsize=0>>

reference property to nonexistent classという一文からすると、リファレンス先のコレクションTestBがまだ存在しないのが問題のようです。存在しないコレクションへのリファレンスは作ることが出来ないみたいですね。
TestB側のコレクションを作るスクリプトは以下の通りです。

10D_define_class_TestB.py
import weaviate
import weaviate.classes.config as wc

weaviate_client = weaviate.connect_to_custom(
    http_host="xxx.xxx.xxx.xxx",  # URL only, no http prefix
    http_port=30020,
    http_secure=False,   # Set to True if https
    grpc_host="xxx.xxx.xxx.xxx",
    grpc_port=30021,      # Default is 50051, WCD uses 443
    grpc_secure=False,   # Edit as needed
)

weaviate_client.collections.create(
    name='TestB',
    properties=[wc.Property(name='chapter',data_type=wc.DataType.INT),
                wc.Property(name='text',data_type=wc.DataType.TEXT)],
    references=[wc.ReferenceProperty(
            name='parent',
            target_collection='TestA'
    )        
    ],
    vectorizer_config=[wc.Configure.NamedVectors.text2vec_aws(
        name='textdocument_vector',
        service='bedrock',
        model='cohere.embed-multilingual-v3',
        region='us-west-2'
    )        
    ]
)

weaviate_client.close()

やはりこちらも同じようなエラーが出てしまいました。そこで、TestA側を作るスクリプトを少し変え、一旦リファレンスを設定しない事にします。

10C_define_class_TestA.py(修正)
import weaviate
import weaviate.classes.config as wc

weaviate_client = weaviate.connect_to_custom(
    http_host="xxx.xxx.xxx.xxx",  # URL only, no http prefix
    http_port=30020,
    http_secure=False,   # Set to True if https
    grpc_host="xxx.xxx.xxx.xxx",
    grpc_port=30021,      # Default is 50051, WCD uses 443
    grpc_secure=False,   # Edit as needed
)

weaviate_client.collections.create(
    name='TestA',
    properties=[wc.Property(name='title',data_type=wc.DataType.TEXT),
                wc.Property(name='summary',data_type=wc.DataType.TEXT)],
    vectorizer_config=[wc.Configure.NamedVectors.text2vec_aws(
        name='textdocument_vector',
        service='bedrock',
        model='cohere.embed-multilingual-v3',
        region='us-west-2'
    )        
    ]
)

weaviate_client.close()

今度はうまくいきました。その次に、10D_define_class_TestB.pyも(こちらは変更せず)うまくいきました。TestB側のリファレンス作成がうまくいったのはコレクションTestAが既にできていたからですね。

リファレンスを追加する

TestA側にTestBへのリファレンス追加がやり残しになってるので、これを追加しましょう。config.add_referenceというメソッドがあります。

10E_define_reference_TestA.py
import weaviate
from weaviate.classes.config import ReferenceProperty

weaviate_client = weaviate.connect_to_custom(
    http_host="xxx.xxx.xxx.xxx",  # URL only, no http prefix
    http_port=30020,
    http_secure=False,   # Set to True if https
    grpc_host="xxx.xxx.xxx.xxx",
    grpc_port=30021,      # Default is 50051, WCD uses 443
    grpc_secure=False,   # Edit as needed
)

TestA = weaviate_client.collections.get('TestA')

try:
    TestA.config.add_reference(
        ReferenceProperty(
            name='children',
            target_collection='TestB'
        )
    )
except Exception as e:
    print(f"エラーが発生しました。{e}")

weaviate_client.close()

エラーも返らず、うまくいったようです。ここでcurlを使い、データベースのスキーマを得ることにしましょう。以下で、json形式でデータベース全体のスキーマを得ることが出来ます。なお、ポート番号は8080が標準ですが、私の場合k3sのnodeportの都合上30020となっています。

$ curl http://xxx.xxx.xxx.xxx:30020/v1/schema > schema.json

結果は以下の通りです。

schema.json
{
    "classes": [
        {
            "class": "TestA",
            "invertedIndexConfig": {
                "bm25": {
                    "b": 0.75,
                    "k1": 1.2
                },
                "cleanupIntervalSeconds": 60,
                "stopwords": {
                    "additions": null,
                    "preset": "en",
                    "removals": null
                }
            },
            "multiTenancyConfig": {
                "autoTenantActivation": false,
                "autoTenantCreation": false,
                "enabled": false
            },
            "properties": [
                {
                    "dataType": [
                        "text"
                    ],
                    "indexFilterable": true,
                    "indexSearchable": true,
                    "moduleConfig": {
                        "text2vec-aws": {
                            "skip": false,
                            "vectorizePropertyName": false
                        }
                    },
                    "name": "title",
                    "tokenization": "word"
                },
                {
                    "dataType": [
                        "text"
                    ],
                    "indexFilterable": true,
                    "indexSearchable": true,
                    "moduleConfig": {
                        "text2vec-aws": {
                            "skip": false,
                            "vectorizePropertyName": false
                        }
                    },
                    "name": "summary",
                    "tokenization": "word"
                },
                {
                    "dataType": [
                        "TestB"
                    ],
                    "indexFilterable": true,
                    "indexSearchable": false,
                    "moduleConfig": {
                        "text2vec-aws": {
                            "skip": false,
                            "vectorizePropertyName": false
                        }
                    },
                    "name": "children"
                }
            ],
            "replicationConfig": {
                "factor": 1
            },
            "shardingConfig": {
                "actualCount": 1,
                "actualVirtualCount": 128,
                "desiredCount": 1,
                "desiredVirtualCount": 128,
                "function": "murmur3",
                "key": "_id",
                "strategy": "hash",
                "virtualPerPhysical": 128
            },
            "vectorConfig": {
                "textdocument_vector": {
                    "vectorIndexConfig": {
                        "bq": {
                            "enabled": false
                        },
                        "cleanupIntervalSeconds": 300,
                        "distance": "cosine",
                        "dynamicEfFactor": 8,
                        "dynamicEfMax": 500,
                        "dynamicEfMin": 100,
                        "ef": -1,
                        "efConstruction": 128,
                        "flatSearchCutoff": 40000,
                        "maxConnections": 64,
                        "pq": {
                            "bitCompression": false,
                            "centroids": 256,
                            "enabled": false,
                            "encoder": {
                                "distribution": "log-normal",
                                "type": "kmeans"
                            },
                            "segments": 0,
                            "trainingLimit": 100000
                        },
                        "skip": false,
                        "vectorCacheMaxObjects": 1000000000000
                    },
                    "vectorIndexType": "hnsw",
                    "vectorizer": {
                        "text2vec-aws": {
                            "model": "cohere.embed-multilingual-v3",
                            "region": "us-west-2",
                            "service": "bedrock",
                            "vectorizeClassName": true
                        }
                    }
                }
            }
        },
        {
            "class": "TestB",
            "invertedIndexConfig": {
                "bm25": {
                    "b": 0.75,
                    "k1": 1.2
                },
                "cleanupIntervalSeconds": 60,
                "stopwords": {
                    "additions": null,
                    "preset": "en",
                    "removals": null
                }
            },
            "multiTenancyConfig": {
                "autoTenantActivation": false,
                "autoTenantCreation": false,
                "enabled": false
            },
            "properties": [
                {
                    "dataType": [
                        "int"
                    ],
                    "indexFilterable": true,
                    "indexSearchable": false,
                    "moduleConfig": {
                        "text2vec-aws": {
                            "skip": false,
                            "vectorizePropertyName": false
                        }
                    },
                    "name": "chapter"
                },
                {
                    "dataType": [
                        "text"
                    ],
                    "indexFilterable": true,
                    "indexSearchable": true,
                    "moduleConfig": {
                        "text2vec-aws": {
                            "skip": false,
                            "vectorizePropertyName": false
                        }
                    },
                    "name": "text",
                    "tokenization": "word"
                },
                {
                    "dataType": [
                        "TestA"
                    ],
                    "indexFilterable": true,
                    "indexSearchable": false,
                    "moduleConfig": {
                        "text2vec-aws": {
                            "skip": false,
                            "vectorizePropertyName": false
                        }
                    },
                    "name": "parent"
                }
            ],
            "replicationConfig": {
                "factor": 1
            },
            "shardingConfig": {
                "actualCount": 1,
                "actualVirtualCount": 128,
                "desiredCount": 1,
                "desiredVirtualCount": 128,
                "function": "murmur3",
                "key": "_id",
                "strategy": "hash",
                "virtualPerPhysical": 128
            },
            "vectorConfig": {
                "textdocument_vector": {
                    "vectorIndexConfig": {
                        "bq": {
                            "enabled": false
                        },
                        "cleanupIntervalSeconds": 300,
                        "distance": "cosine",
                        "dynamicEfFactor": 8,
                        "dynamicEfMax": 500,
                        "dynamicEfMin": 100,
                        "ef": -1,
                        "efConstruction": 128,
                        "flatSearchCutoff": 40000,
                        "maxConnections": 64,
                        "pq": {
                            "bitCompression": false,
                            "centroids": 256,
                            "enabled": false,
                            "encoder": {
                                "distribution": "log-normal",
                                "type": "kmeans"
                            },
                            "segments": 0,
                            "trainingLimit": 100000
                        },
                        "skip": false,
                        "vectorCacheMaxObjects": 1000000000000
                    },
                    "vectorIndexType": "hnsw",
                    "vectorizer": {
                        "text2vec-aws": {
                            "model": "cohere.embed-multilingual-v3",
                            "region": "us-west-2",
                            "service": "bedrock",
                            "vectorizeClassName": true
                        }
                    }
                }
            }
        }
    ]
}
schemaがどのように定義されているか解読したい場合は、以下の資料が役に立つと思います。

感想

・ベクトルDBのことはよく知らないのですが、WeaviateはベクトルDBとグラフDBのハイブリッドのようなものなんですね(グラフDBのこともよく知りませんけど)
・Weaviateを操作するGUIクライアントのようなものが無くて、Pythonスクリプトを走らせるとかしないと操作できないですね、今のところ。コマンドラインで動かすより、jupyter notebookのような環境で操作する方が楽かもしれないです(と気付いた)。
・ネット上にはPython ClientのV3とV4の資料が混在していて苦労します。

次の記事は

オブジェクトの挿入、取得、全削除をやってみます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?