LoginSignup
0
0

Qdrantの構造を理解する

Last updated at Posted at 2024-06-06

概要

Vector databaseの1つであるQdrantを利用するにあたって、その内部構造を理解する必要があると感じたので、調査した内容を記載します。

Qdrantの全体像

image.png
出典

こちらの絵が非常にわかりやすいです。
詳細な説明は公式ドキュメントに譲りますが、重要だと感じた要素を簡単に整理します。

用語 意味
Collection RDBにおけるテーブルに相当する概念。Pointの集合
Point RDBにおけるレコードに相当する概念。Id,Vector,Payloadで構成される
Id 一意の識別子
Vector 画像、音声、ドキュメント、ビデオなどのデータの高次元表現
Payload Vectorに追加されたJSON形式のデータ

Payload を用いて類似性検索時にフィルタリングできるというのが、Qdrantの特徴のようです。

また、ストレージの仕組みについては2つの方式があるようです。

用語 意味
In-memory Vectorをメモリに格納する方式。高速
Memmap Vectorをディスクに格納する方式。ディスク上のファイルを、仮想メモリのアドレス空間にマッピングする。十分なメモリがあれば、In-memoryと同じくらい高速。Qdrantマシンが高速なディスクで稼働し、大規模なCollectionを扱う場合に推奨される方式

次に、CollectionやPointの中身を実際に触ってみようと思います。
私はpythonに明るくないため、curlで操作します。

環境

下記のバージョンで確認をしました。
Qdrant 1.9.4
Docker 24.0.5
WSL2 Ubuntu 22.04 on Windows

Qdrantインストール

インストール方法はこちらを参照してください。
私は今回、Dockerでインストールしました。

$ docker run -d -p 6333:6333 \
    -v $(pwd)/path/to/data:/qdrant/storage \
    qdrant/qdrant

Collection作成、確認

QdrantのAPIドキュメントにサンプルが載っていたので利用させていただきます。
test_collectionという名前のCollectionを作成します。
今回は指定していませんが、"on_disk": trueと設定することで、前述のMemmap利用モードになるようです。
詳細はこちらをご確認下さい。

$ curl -X PUT 'http://localhost:6333/collections/test_collection' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "vectors": {
      "size": 4,
      "distance": "Dot"
    }
  }'

QdrantはWebUI機能も備えており、ブラウザから下記のURLでダッシュボード画面にアクセスできます。ダッシュボード画面から、Qdrantに登録したデータが閲覧可能なため、実運用の際には6333 Portを外部公開しないなど、慎重に取り扱う必要がありそうです。
http://localhost:6333/dashboard

ダッシュボードを開くと、test_collectionが作成されていることが確認できます。
image.png

curlで確認することも可能です。次のコマンドではCollectionの一覧を取得しています。

$ curl -X GET "http://localhost:6333/collections" -H "Content-Type: application/json"
{"result":{"collections":[{"name":"test_collection"}]},"status":"ok","time":4.5e-6}

次のコマンドでは、作成したtest_collectionの詳細情報を取得しています。

$ curl -X GET "http://localhost:6333/collections/test_collection" -H "Content-Type: application/json"
{"result":{"status":"green","optimizer_status":"ok","indexed_vectors_count":0,"points_count":0,"segments_count":8,"config":{"params":{"vectors":{"size":4,"distance":"Dot"},"shard_number":1,"replication_factor":1,"write_consistency_factor":1,"on_disk_payload":true},"hnsw_config":{"m":16,"ef_construct":100,"full_scan_threshold":10000,"max_indexing_threads":0,"on_disk":false},"optimizer_config":{"deleted_threshold":0.2,"vacuum_min_vector_number":1000,"default_segment_number":0,"max_segment_size":null,"memmap_threshold":null,"indexing_threshold":20000,"flush_interval_sec":5,"max_optimization_threads":null},"wal_config":{"wal_capacity_mb":32,"wal_segments_ahead":0},"quantization_config":null},"payload_schema":{}},"status":"ok","time":0.0000653}

Point作成、確認

こちらもサンプルがあったので利用させていただきます。Pointを6つPUTしてみます。
コマンドを見ると、Pointは以下の3つの要素から構成されていることが確かに分かります。
・id
・vector
・payLoad

$ curl -L -X PUT 'http://localhost:6333/collections/test_collection/points?wait=true' \
 -H 'Content-Type: application/json'\
 --data-raw '{
  "points": [
    {"id": 1, "vector": [0.05, 0.61, 0.76, 0.74], "payload": {"city": "Berlin"}},
    {"id": 2, "vector": [0.19, 0.81, 0.75, 0.11], "payload": {"city": ["Berlin", "London"] }},
    {"id": 3, "vector": [0.36, 0.55, 0.47, 0.94], "payload": {"city": ["Berlin", "Moscow"] }},
    {"id": 4, "vector": [0.18, 0.01, 0.85, 0.80], "payload": {"city": ["London", "Moscow"] }},
    {"id": 5, "vector": [0.24, 0.18, 0.22, 0.44], "payload": {"count": [0]}},
    {"id": 6, "vector": [0.35, 0.08, 0.11, 0.44]}
  ]
}'
{"result":{"operation_id":0,"status":"completed"},"status":"ok","time":0.011843266}

WebUIから、Pointが作成されていることが確認できます。

image.png

curlでの確認結果は次の通りです。id 1 のPoint情報を取得しています。

$ curl -X GET "http://localhost:6333/collections/test_collection/points/1" -H "Content-Type: application/json"
{"result":{"id":1,"payload":{"city":"Berlin"},"vector":[0.05,0.61,0.76,0.74]},"status":"ok","time":0.0001196}

【おまけ】類似性検索

Pointを登録できたので、最後に類似性検索をしてみます。
Vectorとして[0.2,0.1,0.9,0.7]を与え、Top3を検索します。

$ curl -L -X POST 'http://localhost:6333/collections/test_collection/points/search' \
 -H 'Content-Type: application/json' \
  --data-raw '{
    "vector": [0.2,0.1,0.9,0.7],
    "with_vectors": true,
    "with_payload": true,
    "top": 3
}'
{"result":[{"id":4,"version":0,"score":1.362,"payload":{"city":["London","Moscow"]},"vector":[0.18,0.01,0.85,0.8],"order_value":null},{"id":1,"version":0,"score":1.273,"payload":{"city":"Berlin"},"vector":[0.05,0.61,0.76,0.74],"order_value":null},{"id":3,"version":0,"score":1.208,"payload":{"city":["Berlin","Moscow"]},"vector":[0.36,0.55,0.47,0.94],"order_value":null}],"status":"ok","time":0.0021894}

scoreが高い順に
id 4
id 1
id 3
の3件がヒットすることを確認できました。

所感

手を動かすことで、ぼんやりとしていたQdrantに対する理解は、ある程度深まったと思います。

参考

https://qdrant.tech/documentation/overview/
https://qdrant.tech/documentation/concepts/storage/
https://qdrant.tech/documentation/concepts/payload/
https://qdrant.github.io/qdrant/redoc/index.html
https://qdrant.tech/documentation/concepts/search/#payload-and-vector-in-the-result

0
0
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
0