PipeconeでVector DBの作成と、Cloudflare WorkersからのDB操作を試してみた
この記事では、2023年のクラウドサービスのトレンドとして、Amazon BedrockやCloudflare Workers AIの登場により、AIやレコメンドなどの機能が注目されました。その中で、「Vector DB」について触れられており、Pineconeを利用してVector DBを作成する方法が説明されています。PineconeはAI向けの長期記憶のサービスであり、無料プランもあるため、個人開発などにも利用しやすいです。また、Cloudflare Workersでは、PineconeClientを使用する必要があります。
目次
この記事は、「Cloudflare Advent Calendar 2023」9日目の記事です。
2023年はAmazon BedrockにCloudflare Workers AIなどの登場により、様々なクラウドサービスでLLMを用いたアプリ・RAG・レコメンドなどが可能になりました。その中であまり触ることのなかった、「Vector DB」をいろいろ触ってみたいと思ったので、まずはPineconeから触り始めてみました。
Pineconeとは
PineconeはAIサービス向けの長期記憶(Long-term memory for AI)のサービスとTOPページで歌っているサービスです。自分の中では、「AI / LLM向けのサービスのための、Vector DB as a Service」という風に認識しています。
Pineconeを使うメリットの1つは、「無料プランがある」ことです。また、DBaaSのため、どのサービスからも大体同じ連携方法で利用できるというのも特徴です。
Pineconeアカウントは、メールまたはGoogle / GitHub / Microsoftアカウントで作る
まずはアカウントを作ってみます。シングルサインオンが使えるのがありがたいですし、プロバイダーにGitHubが入っているのが開発者向けサービス感を強めていますね。
アカウントを作成すると、簡単なアンケートが待っています。「何を目的にアカウントを作って、どんなものを、どんな言語で作るつもりですか?」というものなので、近しいものを選びましょう。
ホーム画面はこんな感じです。
PineconeでVector DBのインデックスを作成する
早速Vector DBを作りましょう。ダッシュボードのTOP画面に、[Create index]ボタンがあるので、これをクリックします。
ちなみに、[Load Sample Data]を使って、サンプルデータがある状態のインデックスを作る方法もあります。
新しく作る場合は、インデックス名とインデックスの設定、そしてプランを選びます。
DimensionsはEmbeddingに利用するモデルによって値が変わる
Dimensions項目はなかなか見慣れない項目です。が、右側にある[Setup by model]を選ぶことで、どんな数字を入れるべきかがわかるように作られています。
OpenAIなら1536
ですし、Cohereの場合は768
を利用します。なお、Amazon BedrokのTitan Embeddings G1(amazon.titan-embed-text-v1
)は最大出力ベクトル長が1536と書かれていました。
amazon.titan-embed-text-v1
このモデルは、テキスト検索、セマンティック類似性、クラスタリングをサポートします。入力テキストの最大数は 8K トークン、出力ベクトルの最大長は 1536 です。https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/embeddings.html
数字を見ると、OpenAIと同じ値ですので、OpenAIのモデルを使うつもりで設定すればよさそうです。
決済情報を登録していなくても、Starterプランは利用できる
クレジットカードなどを登録していない場合Starterプランのみ選択できます。これが無料プランですので、個人開発などで本番利用も検討している方は念の為スペックや上位プランの価格も見ておきましょう。
出来上がったインデックス
作成に成功するとこんな画面に移動します。GCPのUSリージョンにあるサーバーで動いている様子ですね。
インデックスに接続するための情報を取得する
インデックス詳細画面右上にある[Connect]ボタンをクリックすると、接続方法のガイドがでます。
API keyはダッシュボード左側のメニューから取得しましょう。
TypeScriptで実装する際の注意点 (2023/12/1時点)
記事にアップロードしているモーダルに表示されているコードは、すこし古いバージョンの実装の様子でした。TypeScriptを使ってコードをコピーアンドペーストすると、型定義エラーが発生します。
APIドキュメントを見る限り、2023/12時点の実装はこんな感じになる様子です。
import { Pinecone } from "@pinecone-database/pinecone";
const pinecone = new Pinecone({
environment: "gcp-starter",
apiKey: "********-****-****-****-************",
});
const index = pinecone.Index("first-vdb");
Cloudflare Workersでは、2023/11時点では非推奨のPineconeClient
を使う必要がある様子
上のサンプルコードを、Cloudflare Workers (powered by Hono)で実装したところ、次のようなコンパイルエラーが出ました。
Error compiling schema, function code: const schema2 = scope.schema[2];const schema1 = scope.schema[1];return function validate1(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){let vErrors = null;let errors = 0;if(!(((typeof data == "number") && (!(data % 1) && !isNaN(data))) && (isFinite(data)))){const err0 = {instancePath,schemaPath:"#/definitions/nonNegativeInteger/type",keyword:"type",params:{type: "integer"},message:"must be integer"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if((typeof data == "number") && (isFinite(data))){if(data < 0 || isNaN(data)){const err1 = {instancePath,schemaPath:"#/definitions/nonNegativeInteger/minimum",keyword:"minimum",params:{comparison: ">=", limit: 0},message:"must be >= 0"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}}validate1.errors = vErrors;return errors === 0;}
Trace: EvalError: Code generation from strings disallowed for this context
PineconeのSDKをGitHubに見に行ったところ、どうやらCloudflare Workers / Pages functionsで利用しているランタイムでは動かない状況になっているみたいです。そのため、非推奨ではあるものの、PineconeClient
を利用する必要があるとのことです。
AFAIU, the current workaround is to use the old deprecated
PineconeClient
in the meantime.
https://github.com/pinecone-io/pinecone-ts-client/issues/164
ということで、Cloudflare WorkersでPineconeのインデックスに接続するコードサンプルはこちらです。
import { Hono } from "hono"
import { PineconeClient } from "@pinecone-database/pinecone";
const app = new Hono()
app.get('/index', async c => {
const pinecone = new PineconeClient();
await pinecone.init({
environment: "gcp-starter",
apiKey: "xxxxxxxxxx",
});
const index = pinecone.Index("first-vdb");
const result = await index.upsert({
upsertRequest: {
vectors: [{
id: 'record-1',
values: [0.176, 0.345, 0.263],
},{
id: 'record-2',
values: [0.176, 0.345, 0.263],
}]
}
})
return c.json(result)
})
このAPIも実行するとエラーがでます。
PineconeClient: Error calling upsert: PineconeErro… 3 does not match the dimension of the index 1536
ただしこちらは「設定したDimensionと違うベクトルデータが来ていますよ」というもので、upsert
しているデータがダミーであることが原因です。
もし実際に動かして試す場合は、OpenAIまたはAmazon BedrockのAPIやLangChain.jsなどを利用してEmbeddingを生成すると良いかと思います。
触ってみて
DBaaSを触ることが実はほとんどなかったのですが、Pineconはかなり気軽に触って試せて驚きました。
Cloudflare WorkersへのSDK対応状況は少し気になりますが、Amazon Bedrock Knowledge baseで利用するVector Storeに利用できるなどの強みもあります。
MomentやSupabaseも触ってみて、使い所・使い分けについては年末ゆっくり考えてみようと思います。