k-NN

  • 近傍探索する
  • ドキュメントの量に比例して検索時間が伸びる
  • 実運用には耐えられない

近似 k-NN

これらを組み合わせることで、データ量が億いくぐらいまで増大しても対応

  • ベクトル検索を高速化
  • ベクトルを圧縮

HNDW (Hierarchical Navigable Small World ) algorithm

ある初期検索値から近い一のベクトルを探していく 貪欲な探索アルゴリズムっぽい

IVF algorithm

  • ベクトルを事前に複数バケットにクラスタリングする
    • k-means クラスタリングとかが使われる
  • 各クラスターのセントロイド(中央の値?)をみて、クラスタを決定する

ベクトルの量子化 (圧縮)

  • マスターデータ的なIDを用意する
  • ベクトルを小さな部分に分割し、各部分がマスターデータのどこに所属するか ID で指定
  • マスターデータのサイズだけになるので、容量めっちゃ減る

HNDW より IVF の方が精度低めらしい

フィルタリング

実際はk-NN対象をメタデータ属性とかで、事前にフィルタすることが多い

VectorDB s

  • ElasticSearch
  • OpenSearch
  • Aurora / RDS ( postgres )

OSS

  • Elastic Cloud

  • redis

  • Pinecone etc…

  • opensearch :

    • HNSW / IVF :
    • 圧縮PQ
    • postフィルタ
    • 最大次元 16000
  • pgvector : 最近は対応している pgvector v0.5.0 から

    • HNSW / IVF
    • 圧縮なし
    • postフィルタ
    • 最大次元 16000 (格納)
      • 近似k-NNの場合使用できるのは 2000

この辺が根拠 https://aws.amazon.com/jp/blogs/news/introducing-the-vector-engine-for-amazon-opensearch-serverless-now-in-preview/

ベクトルエンジンは、ユークリッド距離、コサイン類似度、ドット積などの一般的な距離メトリックをサポートし、16,000 次元に対応できるため、幅広い基盤モデルやその他の AI/ML モデルのサポートに適しています。

https://aws.amazon.com/jp/blogs/news/choose-the-k-nn-algorithm-for-your-billion-scale-use-case-with-opensearch/

直積量子化 (PQ) は最近傍検索の領域では非常に良く使われる量子化手法です。ANN アルゴリズムと併用して最近傍検索に使うことができます。 OpenSearch 1.2 では、k-NN プラグインに IVF と共に Faiss の PQ 実装をサポートするようになりました。

用語調査

リランキング

  • 機械学習を活用した検索後処理、すなわちリランキング(Re-ranking)です。

  • 検索後処理?

  • Solr の re-ranking はクエリのトップ N 件のスコアを変更するタイプ

    • 上N件だけ丁寧になるから計算速度の割に精度がでる

セマンティックサーチ

結局コンテキストをいろいろなところから集めて検索することなので、技術的用語ではないっぽい

資料調査

https://zenn.dev/kun432/articles/20230921-vector-databases-jp-part-1 キーワード検索+ベクトル検索のハイブリッドが最良の結果をもたらす ![[Pasted image 20231125223150.png]]

https://docs.google.com/spreadsheets/d/1tUxif_MQYByprhFArZ2XqssvlMVfn5mKjsPjYTOO08o/edit#gid=0

適当な VectorDB 使ってみる

chromadb https://pypi.org/project/chromadb/ The fastest way to build Python or JavaScript LLM apps with memory!

https://www.trychroma.com/ Chroma has all the tools you need to use embeddings the AI-native open-source embedding database 自然言語を計算が可能な形に変換することを Embedding と呼ぶらしい

特徴

  • Redis 上に乗っかってて速い
  • Word2Vec / GloVe / FastTextなど、さまざまな埋め込みフォーマットをサポート
  • 最近傍探索 (Nearest neighbor search) のサポート: ChromaDBは、指定された埋め込みの最近傍を見つけるために使用
    • k-NNのこと -> yes : Nearest neighbor search が最近傍探索

OpenSearch資料 https://zenn.dev/tasai/scraps/9fd55a1babc043

使ってみた

pip3 install chromadb
import chromadb
client = chromadb.Client()

collection = client.create_collection("sample_collection")  
# Add docs to the collection. Can also update and delete. Row-based API coming soon!

collection.add(
documents=["This is document1", "This is document2"], # we embed for you, or 
metadatas=[{"source": "notion"}, {"source": "google-docs"}], # filter on arbitrary metadata!
ids=["doc1", "doc2"], # must be unique for each doc
)

  

results = collection.query(
query_texts=["This is a query document"],
n_results=2,
)

Collection を作って、そこに doc を add して最後にそこに対してクエリで検索できるっぽい

https://docs.trychroma.com/getting-started

  • AI App 向けのDB
  • Collection : Embedding(自然言語を計算可能な形にしたデータ)、document、metadata を保存するDB
  • テキストを保存すると、tokenization と embedding と indexing を自動で行う
    • 自前ですでに embedding を行った結果のベクトルを格納することもできる
collection.add(  
embeddings=[[1.2, 2.3, 4.5], [6.7, 8.2, 9.2]],  
documents=["This is a document", "This is another document"],  
metadatas=[{"source": "my_source"}, {"source": "my_source"}],  
ids=["id1", "id2"]  
)

n近傍の検索が可能

永続データの利用

client = chromadb.PersistentClient(path="/Users/hge/_tmp/chroma")
ls -l
total 288
drwxr-xr-x  6 shuaki  staff     192 Nov 25 22:21 c1e7b412-5f05-43a7-b1c6-3f32ab46e641
-rw-r--r--  1 shuaki  staff  147456 Nov 25 22:21 chroma.sqlite3

collection に対する embedding function の指定

  • collection への document の追加時の tokenization / embedding 処理を指定
  • Chroma will use sentence transfomer as a default.
  • 他には?
    • カスタムで自作できるっぽい

距離関数の変更

  • hnsw:space
    • Squared L2 がデフォルト

Qdrant

finch vm start
finch pull qdrant/qdrant
finch run -p 6333:6333 qdrant/qdrant

WEB UI が立ち上がるっぽい

elapsed: 172.0s                                                                   total:  51.7 M (308.1 KiB/s)
           _                 _
  __ _  __| |_ __ __ _ _ __ | |_
 / _` |/ _` | '__/ _` | '_ \| __|
| (_| | (_| | | | (_| | | | | |_
 \__, |\__,_|_|  \__,_|_| |_|\__|
    |_|

Access web UI at http://localhost:6333/dashboard

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

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]}
  ]
}'
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],
    "top": 3
}'

簡単な CRUD はできた

サンプル 

SNSサンプル

コレクション作成

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

オプション

  • vectors : 必須
    • size : ベクターの次元数
    • distance : cos or dot
  • hnsw_config
  • wal_config
  • optimizers_config
  • shard_number
  • on_disk_payload
  • quantization_config

あ〜このDBもしかして、ベクトル情報は保存できるけど Embedding後しかだめっぽい?

https://zenn.dev/kun432/scraps/8eab42294bde75 OpenAI で Embedding して, 保存している。この場合 1536 次元

GiNZA の場合 300 次元

https://zenn.dev/tfutada/articles/acf8adbb2ba5be

search(query_vector=クエリーベクトル)で検索します。検索に使用するドキュメントのベクトルを引数に渡します。Qdrant自体にはベクトル化の機能は無いため、ドキュメント(原型)を渡すことはできません。

Qdrant 使う場合は Embedding エンジンを別途用意しとかないとダメっぽい

https://zenn.dev/kun432/articles/20230921-vector-databases-jp-part-2

Embedding ツール調査

  • Titan Embedding とか?
  • Chroma provides lightweight wrappers around popular embedding providers
    • OpenAI
    • Cohere
    • GooglePaLM
    • HugginFace
    • Instructor
  • 基本 LLM でベクトル生成するぽい
    • TnesorFlow
    • Gensim
    • FastText
    • BERT
    • ELMo
    • GinZAもそう

GiNZAの単語分散表現にchiVeを使って精度向上のお試し - Taste of Tech Topics https://acro-engineer.hatenablog.com/entry/2020/07/21/120000 単語にベクトル埋め込むのは Word2Vec などが有名 未知語対応や文脈把握は文章単位でベクトル変換が必要