Pineconeとは
Pineconeとはフルマネージドなクラウド型のベクトルデータベースです。
ローカル管理は不要でDB作成、拡張、削除など全て提供されるAPIで実施することができます。
クラウド型のベクトルDBには他にもたくさん存在しますが、Pineconeは商用実績が豊富、導入が楽、無料枠があるため検証にはもってこいだと思います。
他のクラウド型ベクトルDB代表例
・Qdrant
・Upstash
・Zilliz Cloud
・Cloudflare Vectorize
ちなみに読み方は ピンコーン パインコーン です。
Pineconeはどういう仕組みなのか
Pineconeの仕組みについて簡単に図にまとめました。

それぞれの概念について以下で説明していきます。
アカウント管理
Organization
Pineconeアカウントの最上位単位。
Organization単位で課金が発生する。
通常利用において意識することはない。
Project
Organization内に作成できるグループ。
APIキーの発行やIndex管理はProject単位で行う。
検証環境、性能環境、本番環境といった使い分けでの利用が想定される。
Index管理
Index
ベクトルデータを格納、検索する基本単位。
セマンティック検索やキーワード検索、データ永続化を行う。
セマンティック検索 : ニュアンスや文脈を理解した上で最適な情報を検索すること
無料枠で作成できるIndex数は1つのみ。
Index作成において以下のような設定が可能。
spec
設定例: Serverless, Pod-based
- Serverless
従量課金型。
自動スケーリング可能で、Read/Write単位で課金が発生する。 - Pod-based
専用のコンピューティングリソース。
自動スケーリングはせずキャパシティ固定。
Index作成時にはType,Size,Replicasを設定する。- Replicas : Podの複製数。複製数を増やすことでスループットや可用性が向上する。
読み込みスループットが向上するだけで書き込むSpecが増えるわけではない。
- Replicas : Podの複製数。複製数を増やすことでスループットや可用性が向上する。
| Type | 詳細 |
|---|---|
| s1 | Storage優先。大量データや低頻度のクエリ実行の場合に適する。 |
| p1 | パフォーマンス優先。高頻度のクエリ実行、低レイテンシが求められる場合に的する。 |
| p2 |
s1,p1を超える性能。 |
| Size | 詳細 |
|---|---|
| x1 | 基本の容量サイズ |
| x2 | 基本の2倍の容量サイズ |
| x4 | 基本の4倍の容量サイズ |
| x8 | 基本の8倍の容量サイズ |
demension
設定例: 1536
Indexに保存するベクトルの次元数。
利用する埋め込み(Embedding)モデルの次元数に合わせる必要がある。
metric
設定例: cosine, euclidean, dotproduct
| 項目 | 詳細 |
|---|---|
| cosine (コサイン類似度) | ベクトルの向きによる類似性を測定する必要がある場合に使用。文書や単語などの類似性測定に有用。 |
| euclidean (ユークリッド距離) | ベクトル間の物理的距離を測定する必要がある場合に使用。画像や音声などの類似性測定に有効。 |
| dotproduct (ドット積) | ベクトルの向きと大きさによる類似性を測定する必要がある場合に使用。 |
# Serverless Index作成例
c.create_index(
name="my-index",
dimension=1536,
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1")
)
# Pod-based Index作成例
pc.create_index(
name="my-index",
dimension=1536,
metric="cosine",
spec=PodSpec(
environment="us-east-1-aws",
pod_type="p1.x1",
pods=1,
replicas=2
)
)
データ管理
namespace
Index内の論理的なパーティション。
任意項目(デフォルトは""が設定される)。
Index内でデータ分離を行うことで、迅速な検索やデータ更新を可能にする。
# Namespace別にデータを格納
index.upsert(vectors=[...], namespace="user_123")
index.upsert(vectors=[...], namespace="user_456")
vector
Pineconeに格納される最小単位のデータ。
チャンクに分割した際には、1チャンク = 1vectorになるイメージ。
vectorの構成要素:id, values, metadata, sparse_values
metadata
ベクトルデータに付随するデータ。
フィルタリング検索や補足情報の追加などで活用される。
# メタデータでフィルタリング
index.query(
vector=[...],
filter={
"category": {"$eq": "programming"},
"year": {"$gte": 2020}
},
top_k=10
)
sparse_values
ハイブリッド検索(意味検索 + キーワード検索)を実現するために、キーワード情報を格納するための引数。
- 概要
ベクトル検索は通常、プロンプトの「意味」を数値化した密ベクトル(Dense Vector)検索なのに対して、Sparse Vectorはキーワードの頻出度や重要度を数値化した疎ベクトルを指す。
| ベクトル | 強み・弱み |
|---|---|
| 密ベクトル | セマンティック検索 強み:同じニュアンスや意味を読み取ること 弱み:「iOS 18.1」のような固有名詞の完全一致検索 |
| 疎ベクトル | キーワード検索 強み:キーワードが含まれているか、一致するか厳密に判定すること 弱み:セマンティック検索ができない |
sparse_valuesを設定することでセマンティック検索、キーワード検索どちらも考慮した上で最適な検索が可能になる。
その他
Collection
Indexの静的スナップショット。
Indexのバックアップを取りたい時(設定変更時やDR対策)に利用する。
バックアップに特化しているため、Collectionに対して検索やデータ登録はできない。
Collectionは有料枠でしか利用できない。
導入手順
インストール
pip install pinecone-client
アカウント作成
以下の公式アカウントからアカウント作成する。
APIキーの設定
アカウント作成した後に「Generate API Key」を押下してAPIキーを発行する。

実際に実装してみる
Indexを作成する
Indexは実装だけでなく、PineconeのGUIから作成することも可能です。
GUIから作成する場合は「Create index」を押下。

実装例
from dotenv import load_dotenv
from pinecone import Pinecone, ServerlessSpec
# APIキーの設定
load_dotenv()
# インスタンス生成
pc = Pinecone()
index_name = "sample_index"
# Index作成
pc.create_index(
index_name,
dimension=1536, # text-embedding-3-smallの次元数
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1")
)
# APIキーは別ファイルに設定
OPENAI_API_KEY="hogehogehoge"
PINECONE_API_KEY="fugafugafuga"
作成したIndexにデータを投入する
作成したIndexに実際にデータを投入するには upsert を使います。
upsertを指定した場合、データが存在しない場合には登録、既にデータが存在する場合には更新を行います。
upsertのデータ更新は新しいデータで古いデータを上書きします。
もし、データの一部だけ更新したい場合には update を利用しましょう。
実装例
from langchain_openai import OpenAIEmbeddings
# データ埋め込みモデル生成
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
texts = [
{
"header_level": 1,
"header_title": "第1章",
"body": "サンプルテキスト1"
},
{
"header_level": 1,
"header_title": "第2章",
"body": "サンプルテキスト2"
}
]
# テキストのベクトル化
vectors = embeddings.embed_documents(texts)
# Pinecone用のデータを作成
upsert_data = []
for j, (text, vector) in enumerate(zip(texts, vectors)):
# ユニークなIDを生成
doc_id = f"unique_{j}"
upsert_data.append({
"id": doc_id,
"values": vector,
"metadata": {
"header_level": doc["header_level"],
"header_title": doc["header_title"],
"body": doc["body"],
}
})
# Pineconeにアップサート
index.upsert(vectors=upsert_data)
解説
Pineconeにデータをupsertするには2点必須で実施しないといけません。
- ユニークidの生成
- upsertするデータのベクトル化
1. ユニークidの生成
上記でも述べていますが、データ登録の最小単位はvectorです。
vectorはidを主キーとするため一意な値を生成する必要があります。
2. upsertするデータのベクトル化
データはvectorのvaluesに設定しますが設定値はベクトル数値である必要があります。
そのために、OpenAIのデータ埋め込みモデル:text-embedding-3-smallの生成、テキストのベクトル化を行います。
ベクトル数値は以下のような値で人間には解読できない値です。
[0.0275665745139122, 0.04805426672101021]
【補足】metadataについて
metadataには付随データを設定しています。
ここで設定した項目は検索時のフィルタリングや補足情報の付与等を行う際に活用されます。
metadataのkeyとvalueの値は完全任意なのでユーザごとに自由に設定可能です。
適切な設定を行うことで検索速度、回答精度の向上につながります。
Indexからデータを取得する
作成したデータを取得するには query を使います。
実装例
# データ検索用にベクトル化
input_query = "第2章について教えて"
query_vector = embeddings.embed_query(input_query)
# filter付き検索
results = index.query(
vector=query_vector,
top_k=100,
include_metadata=False,
filter={"chapter": {"$eq": chapter_num}}
)
解説
検索も比較的簡単にできます。
index.queryの引数として設定する項目は以下の通り。
| 引数名 | 必須 | 説明 |
|---|---|---|
| vector | ※1 | 検索の基準となるベクトルデータ。通常はOpenAIなどのEmbeddingモデルで作った数値配列を渡す。 |
| id | ※1 | ベクトルの代わりに、既にDB内にあるデータのIDを指定して、それに似たものを探すことができます。 |
| top_k | ◯ | 類似度の高い順に何件取得するかを指定します。 |
| filter | メタデータフィルタリング。特定の条件に合致するものだけに絞り込んでから検索します。 | |
| include_metadata | True : header_level,header_title,body等の登録したメタデータも返却する。False : デフォルト値 |
|
| include_values | True : 取得したデータのベクトル数値も返却する。 False : デフォルト値 |
|
| namespace | Index内でデータをパーティション分けしている場合に、検索対象のグループを指定します。 |
※1 vector または id のどちらか一方が必須です。
metadataでfilterする際の検索条件
| 演算子 | 説明 | 例 |
|---|---|---|
$eq |
等しい | {"status": {"$eq": "active"}} |
$ne |
等しくない | {"status": {"$ne": "deleted"}} |
$gt |
より大きい | {"price": {"$gt": 100}} |
$gte |
以上 | {"price": {"$gte": 100}} |
$lt |
より小さい | {"price": {"$lt": 100}} |
$lte |
以下 | {"price": {"$lte": 100}} |
$in |
含む | {"tag": {"$in": ["a", "b"]}} |
$nin |
含まない | {"tag": {"$nin": ["x"]}} |
Indexを削除する
不要なIndexを削除する際に利用します。
こちらもIndex作成と同様にGUI上から可能です。

実装例
res = index.delete(
ids=['100'],
namespace='blog_example'
)
少し使ってみた感想
Chroma同様、セットアップは楽にできるし導入コストは低い。
Pineconeはmetadataやsparse_valuesの設定が結構難しくクセがあると感じた。
もちろん使いこなすことができれば低コストで高性能、低レイテンシなRAGを作ることができるが、使いこなせるようになるまでには一定の訓練が必要そう。
ただ、冒頭でも書いたが実績No1のクラウド型ベクトルDBでナレッジが豊富に転がっているので、少し訓練すれば大丈夫そう。
まだ触り始めて1週間程度なので、しばらく色々触ってみます。
その他おすすめ記事