annoy-rbで初めてのベクトル検索をめちゃくちゃ手軽に試す
背景
ベクトル検索は興味あるけど、ベクトル化するところでいつもつまずく1ので、「いちばん簡単なの緯度経度ちゃうの?」と思って探してみたら実は意外と緯度経度情報をベクトル検索するという話題がない2のでやってみた。
今回の成果
データベースも使わず、embedding などの技法も何も要らない、めちゃくちゃ素朴なベクトル検索ができた。
ベクトル検索に関する各要素についてなんとなくの理解だったが、この素朴なものができたおかげで理解がよりクリアになった。(理解したとは言っていない)
おさらい
- 最近AIとかで有名なベクトル検索は、与えられたベクトルが候補となるベクトルとどの程度近いかを比較し、近いものから抽出とかしてくれる
- これに特化したデータベースがベクトルデータベース
- ベクトルの「近さ」にはいくつかある
- ベクトルの「近さ」を計算するライブラリがある。ミニマムなものはこの辺り。
準備
今回は例によって Ruby でやるので、Ruby 用の binding を探すと以下のような感じ。
- ankane/faiss-ruby: Efficient similarity search and clustering for Ruby
- yoshoku/annoy-rb: annoy-rb provides Ruby bindings for the Annoy (Approximate Nearest Neighbors Oh Yeah).
AI 関係調べるとよく出てくる安定の ankane さんと洋食さんなので安心でしょう。
ベクトルの類似度、近似度についてイチから学習する気は今回はないので、どっちも軽く触ってみて、なんとなく分かりやすそうな annoy の方を使ってみる。インデックス方式の違いがよく分からん。
作ったもの
- 日本の各都道府県の人口上位3都市とその緯度経度(たぶん普通は庁舎のある地点だとオム)を ChatGPT 3.5 さんで適当に生成
- その ID と緯度経度情報(ベクトル)だけを annoy-rb に与えてビルド
- 緯度経度を与えたらそれを検索するだけの CLI アプリ
wtnabe/example-simple-vector-search-with-annoy-rb
分かったこと
- annoy-rb は DBM っぽい何かのように使える
- ベクトルの次元と距離計算の方法を先に決める必要がある
- データを入れたらビルドが必要
- ベクトル検索はベクトルしか持っていないので ID で元データと突き合わせが必要
- 逆に言うと突き合わせさえできるなら別に専用の大掛かりなベクトル検索の仕組みがなくてもベクトル化、embedding さえなんとかなれば、意外と導入はローコストにできるのかも3
- 単純に緯度経度で検索する場合、コサイン類似度などではなく、ユークリッド距離で比較しないと直感に反した結果になります(そりゃそうだ)