はじめてのコサイン類似度
diaryをdiairyにするべく、ai検索機能を実装することにした。
ai検索の仕組みは調べたら面白かった。
実際には以下のような仕組みで動いている。
(1)事前に記事情報をembeddingしてDBに保存しておく。
embeddingとはテキスト情報をVectorにすることだ。
例えば"りんご"という言葉をVector(1,1,1)のようにする。
そして"バナナ"はVector(-1,-1,-1)、
青リンゴはVector(1,1,3)とする。
このVector情報をsupabaseというDBの保存しておく。
embeddingはOpenAIのembeddingAPIを使用した。
(2)ユーザーの質問をvectorに変換する。
ユーザーの質問もまた、vector情報に変換する。
(3)ユーザーの質問のvectorと記事情報のvectorの類似度を計算する
類似度を計算するときは、コサイン類似度という手法が使われる。
実際には他の方法があるかもしれないが、
ここではコサイン類似度について説明する。
コサイン類似度は、2つのベクトルの内積/2つのベクトルをかけたもので測ることができる。
例えば、「りんご」と「バナナ」と「青リンゴ」の類似度を計算する。
りんごはVector(1,1,1)
バナナはVector(-1,-1,-1)
青リンゴはVector(1,1,3)
とする。
まずはりんごとバナナのコサイン類似度を計算する。
内積は、-3、ベクトルの大きさは、ルート9、つまり-1になる。
りんごと青リンゴの場合、
内積は、5、ベクトルの大きさは、ルート33、つまり0.87になる。
類似度は1に近いほど類似していると言える。
つまり「りんご」と「青リンゴ」の類似度は高いと言える。
この例では、私がりんごと青リンゴとバナナのVectorを勝手に決めたが、
本来は自然言語処理という機能が担うことになる。
(4)類似度の高い文章をLLMにプロンプトともにリクエストする
ユーザーの質問と類似度が高い記事をDBから取得して、その記事をプロンプトをもとにLLMに問い合わせる。
そして期待する結果を得る。
以上。
これがdiairyの仕組みである。