Web 開発者向けの Vector データベース
シリーズの最初の 2 つの記事では、理論に基づいて完全な RAG システムを構築しました。 TypeScript と LangChain.js を使用したアーキテクチャから実際の実装まで。しかし、 専用の詳細な分析に値するコンポーネント: ベクトルデータベース。 適切なベクター ストアを選択すると、高速かつ正確な RAG システムに違いが生まれます。 そして遅いものは信頼できません。
この記事では、ベクトル データベースの世界、つまりその仕組みについて詳しく説明します。 内部的には、検索にどのようなアルゴリズムが使用されているか、ソリューションを比較する方法について詳しく説明します。 人気のあるものと、プロジェクトに適したものを選択する方法。実際の例を見てみましょう Pinecone、Chroma、Weaviate、Qdrant、pgvector のセットアップ。
シリーズ概要
| # | アイテム | 集中 |
|---|---|---|
| 1 | RAGとは何ですか | 基礎と建築 |
| 2 | TypeScript と LangChain.js を使用した RAG | 実用化 |
| 3 | あなたはここにいます - ベクターデータベース | ストレージと類似性検索 |
| 4 | OpenAI と Anthropic API | LLM の統合 |
| 5 | オラマとLLMローカル | オンプレミスモデル |
| 6 | 微調整と RAG の比較 | いつ何を使うか |
| 7 | AI エージェント: アーキテクチャ | 自律システム |
| 8 | CI/CD パイプラインにおける AI | DevOpsの自動化 |
何を学ぶか
- ベクトル データベースとは何か、また従来の DB では不十分な理由
- 埋め込みと類似性検索の仕組み
- 距離メトリック: コサイン、ドット積、ユークリッド
- インデックスアルゴリズム: HNSW、IVF、Flat
- 実用的な比較: Pinecone vs Chroma vs Weaviate vs Qdrant vs pgvector
- メタデータのフィルタリングとハイブリッド検索
- プロジェクトに適したベクトル データベースを選択する方法
1. ベクトルデータベースが必要な理由
従来のデータベース (PostgreSQL、MongoDB、MySQL) はデータを検索するように設計されています。 完全一致による: 「名前 = 'Marco' を持つすべてのユーザーを検索」または 「価格が 50 未満の製品を検索」。ただし、埋め込みを操作する場合、クエリは はまったく異なります。「この 1536 次元のベクトルに最も類似した 5 つのベクトルを見つけます」。
従来のデータベースとベクトル データベース
| 待ってます | 従来のDB | ベクターデータベース |
|---|---|---|
| クエリの種類 | 完全一致、範囲、結合 | 類似検索(最近傍検索) |
| データ型 | スカラー: 文字列、数値、日付 | 高次元ベクトル (128-3072) |
| 索引 | Bツリー、ハッシュ、GiST | HNSW、IVF、PQ、フラット |
| 結果 | 完全一致または結果なし | 類似度でソートされた上位 K 件の結果 |
| Esempio | SELECT * WHERE 名前 = 'RAG' | 「RAG とは?」に最も類似した 5 つのドキュメントを見つけます。 |
根本的な問題は、 計算の複雑さ。アプローチで 「ブルート フォース」(クエリ ベクトルとデータベース内のすべてのベクトルを比較)、検索 100 万の 1536 次元ベクトルでは、単一クエリごとに 15 億 3,600 万回の操作が必要です。 ベクトル データベースは、特殊なデータ構造を使用して、この複雑さを O(n) から O(log n) または O(1)、精度の最小限の割合が犠牲になります。
2. 類似性メトリクス: ベクトルを比較する方法
データベースを調査する前に、データベース間の「近さ」をどのように測定するかを理解する必要があります。 2つのベクトル。主要な指標は 3 つあり、それぞれに異なる特性があります。
2.1 コサイン類似度
2 つのベクトル間の角度を、その長さを無視して測定します。最もよく使われる指標です テキストの場合は、埋め込みモデルがすでに正規化されたベクトルを生成するためです。
// cosine_similarity(A, B) = (A . B) / (||A|| * ||B||)
// Range: [-1, 1] dove 1 = identici, 0 = ortogonali, -1 = opposti
function cosineSimilarity(a: number[], b: number[]): number {
let dot = 0, normA = 0, normB = 0;
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i];
normA += a[i] ** 2;
normB += b[i] ** 2;
}
return dot / (Math.sqrt(normA) * Math.sqrt(normB));
}
// Esempio:
// "gatto dorme" vs "felino riposa" -> 0.95 (molto simili)
// "gatto dorme" vs "prezzo oro" -> 0.12 (non correlati)
2.2 内積(ドット積)
内積は正規化を必要としないため、計算が速くなります。 ただし、ベクトルの長さの影響を受けます。ベクトルが長いほど、 意味的な類似性に関係なく、より高いスコアが得られます。
// dot_product(A, B) = sum(A[i] * B[i])
// Range: (-inf, +inf) più alto = più simile
function dotProduct(a: number[], b: number[]): number {
let result = 0;
for (let i = 0; i < a.length; i++) {
result += a[i] * b[i];
}
return result;
}
// Ideale quando i vettori sono già normalizzati (norma = 1)
// In quel caso, dot product = cosine similarity
2.3 ユークリッド距離(L2)
多次元空間内の 2 点間の「直線」距離を測定します。 最初の 2 つとは異なり、より多くの価値があります ベース より大きいことを示します 類似性。
// euclidean(A, B) = sqrt(sum((A[i] - B[i])^2))
// Range: [0, +inf) più basso = più simile
function euclideanDistance(a: number[], b: number[]): number {
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum += (a[i] - b[i]) ** 2;
}
return Math.sqrt(sum);
}
どの指標を選択するか
| メトリック | いつ使用するか | パフォーマンス | 注意事項 |
|---|---|---|---|
| ささいなこと | テキスト、正規化された埋め込み | 平均 | RAG のデフォルトの選択 |
| 内積 | ベクトルはすでに正規化されています | 速い | 正規化するとコサインと等価になります |
| ユークリッド | 画像、空間データ | 平均 | スケールに敏感 |
実践的なアドバイス
テキストを含む RAG アプリケーションの場合は、常に使用します。 少し似ている。 OpenAI、Voyage、HuggingFace 埋め込みモデルは GIA ベクトルを生成します 正規化されているため、コサイン類似度とドット積は同じ結果になります。 ドット積は、最大のパフォーマンスが必要であり、次のことが確実である場合にのみ使用してください。 ベクトルは正規化されています。
3. インデックス付けアルゴリズム: ベクター DB がどのように検索を高速化するか
ベクトル データベースの魅力は、データベースで使用できるインデックス付けアルゴリズムにあります。 サブリニア時間での近似検索(近似最近傍、ANN)。 3つの主なアプローチを見てみましょう。
3.1 HNSW (階層型ナビゲート可能なスモールワールド)
HNSW は最もよく使用されるアルゴリズムです。各ノードが含まれるマルチレベル グラフを構築します。 はベクトルを表し、円弧は隣接するベクトルを接続します。研究は以下から始まります より高いレベル (少数のノード、長い接続) とダウン (多数のノード、 短い接続)、世界地図から近隣地図に移動する方法。
Livello 2 (pochi nodi): A ----------- B
| |
Livello 1 (più nodi): A --- C --- D - B --- E
| | | | |
Livello 0 (tutti nodi): A-F-C-G-D-H-B-I-E-J
Ricerca per il vettore Q:
1. Livello 2: Parti da A, vai a B (più vicino a Q)
2. Livello 1: Da B, esplora E (più vicino a Q)
3. Livello 0: Da E, esplora I, J -> trova J come nearest neighbor
HNSWパラメータ
| パラメータ | 説明 | デフォルト | 効果 |
|---|---|---|---|
M |
ノードあたりの接続数 | 16 | 高い = 精度が高くなりますが、メモリが多くなります |
ef_construction |
候補リストのサイズは作成中です | 200 | 高い = 優れていますが、インデックスが遅くなります |
ef_search |
検索候補リストのサイズ | 50 | 高い = 精度は高くなりますが、速度が遅くなります |
3.2 IVF (逆ファイルインデックス)
IVF は、k 平均法を使用してベクトル空間をクラスターに分割します。捜索中、 クエリに最も近いクラスターが特定され、ベクトルのみが検索されます。 それらのクラスター内で。大規模なデータセットの場合は非常に効率的です。
Dataset con 1M di vettori, diviso in 1000 cluster:
Costruzione:
1. K-means con K=1000 -> 1000 centroidi
2. Ogni vettore assegnato al cluster più vicino
3. ~1000 vettori per cluster in media
Ricerca con nprobe=10:
1. Trova i 10 centroidi più vicini alla query
2. Cerca solo nei 10 cluster (10.000 vettori)
3. Invece di confrontare 1M vettori, ne confronta 10.000
4. Speedup: ~100x con minima perdita di precisione
3.3 フラット (総当たり)
インデックスなし: クエリをデータベース内のすべてのベクトルと比較します。 完璧な精度 (100%) ですが、時間は O(n) です。小規模なデータセットにのみ使用してください (ベクトル 10,000 個未満) または比較のベースラインとして。
インデックス作成アルゴリズムの比較
| アルゴリズム | 検索速度 | 精度 | メモリ | 使用事例 |
|---|---|---|---|---|
| ニューサウスウェールズ州 | 非常に速い | ~95-99% | 高い | 汎用、低遅延 |
| 体外受精 | 速い | ~90-98% | 平均 | 非常に大規模なデータセット |
| フラット | 遅い (O(n)) | 100% | 低い | 小規模なデータセット、ベースライン |
4. 比較: Pinecone vs Chroma vs Weaviate vs Qdrant vs pgvector
ここでは、Web 開発者向けに最も人気のある 5 つのソリューションを詳細に比較します。
一般的な比較
| 特徴 | 松ぼっくり | 彩度 | ウィアビエイト | クドラント | ベクター |
|---|---|---|---|---|---|
| タイプ | クラウド管理 | オープンソース | オープンソース | オープンソース | PG拡張子 |
| ホスティング | クラウドのみ | ローカル/クラウド | ローカル/クラウド | ローカル/クラウド | どこでも PostgreSQL |
| 言語 | 該当なし (SaaS) | パイソン | Go | さび | C |
| 索引 | 所有者 | ニューサウスウェールズ州 | ニューサウスウェールズ州 | ニューサウスウェールズ州 | IVFフラット、ニューサウスウェールズ州 |
| 無料プラン | はい (100,000 キャリア) | 無制限(ローカル) | 無制限(ローカル) | 無制限(ローカル) | 無制限 |
| メタデータフィルター | はい (上級) | はい(基本) | はい (GraphQL) | はい (上級) | はい (完全な SQL) |
| ハイブリッド検索 | Si | No | はい (BM25) | Si | はい (tsvector を使用) |
| レイテンシ | ~50ms (p99) | ~10 ~ 50 ミリ秒 (ローカル) | ~20~80ミリ秒 | ~10~30ミリ秒 | ~20~100ミリ秒 |
5. 松ぼっくり: Vector DB クラウドネイティブ
松ぼっくりは、メンテナンスを一切必要としない場合に最適です。完全にサービスですね シンプルな API、自動スケーリング、豊富な無料枠で管理されます。
import { Pinecone } from "@pinecone-database/pinecone";
// 1. Inizializza il client
const pinecone = new Pinecone({
apiKey: process.env.PINECONE_API_KEY!,
});
// 2. Crea un indice (una sola volta)
await pinecone.createIndex({
name: "rag-demo",
dimension: 1536, // Deve corrispondere al modello di embedding
metric: "cosine", // cosine | dotproduct | euclidean
spec: {
serverless: {
cloud: "aws",
region: "us-east-1",
},
},
});
// 3. Connetti all'indice
const index = pinecone.Index("rag-demo");
// 4. Inserisci vettori (upsert)
await index.upsert([
{
id: "doc-1",
values: [0.23, -0.45, 0.67, ...], // vettore a 1536 dimensioni
metadata: {
source: "manuale.pdf",
page: 1,
category: "tutorial",
},
},
]);
// 5. Ricerca per similarità
const results = await index.query({
vector: [0.22, -0.44, 0.68, ...], // vettore query
topK: 5,
includeMetadata: true,
filter: {
category: { $eq: "tutorial" },
},
});
松ぼっくりを選ぶ時期
- インフラストラクチャのメンテナンスをゼロにしたい
- 自動スケーリングが必要です
- プロジェクトは厳格な SLA に従って運用中です
- 予算が許せば(無料プランでも十分余裕があります)
6. Chroma: シンプルなローカル開発
Chroma はローカル開発とプロトタイピングに最適です。数秒でインストールでき、 メモリ内またはディスク永続性で動作し、クリーンな API を備えています。
import { ChromaClient } from "chromadb";
// 1. Connetti al server Chroma
const client = new ChromaClient({
path: "http://localhost:8000",
});
// 2. Crea o connetti a una collezione
const collection = await client.getOrCreateCollection({
name: "rag-demo",
metadata: {
"hnsw:space": "cosine", // Metrica di similarità
"hnsw:M": 16, // Connessioni HNSW
"hnsw:efConstruction": 200, // qualità costruzione indice
},
});
// 3. Aggiungi documenti con embeddings
await collection.add({
ids: ["doc-1", "doc-2", "doc-3"],
embeddings: [
[0.23, -0.45, 0.67, ...],
[0.11, -0.33, 0.82, ...],
[-0.56, 0.78, -0.12, ...],
],
metadatas: [
{ source: "manuale.pdf", page: 1 },
{ source: "manuale.pdf", page: 2 },
{ source: "faq.txt", page: 1 },
],
documents: [
"RAG combina retrieval e generation...",
"Gli embeddings catturano il significato...",
"I vector database accelerano la ricerca...",
],
});
// 4. Ricerca per similarità
const results = await collection.query({
queryEmbeddings: [[0.22, -0.44, 0.68, ...]],
nResults: 5,
where: { source: "manuale.pdf" }, // Filtro metadata
});
7. Weaviate: ハイブリッド検索と統合フォーム
Weaviate は、次のネイティブ サポートで際立っています。ハイブリッド検索 (セマンティック検索とキーワード検索の組み合わせ) および統合モジュールの場合 埋め込みの生成を自動的に管理します。
# docker-compose.yml
version: '3.4'
services:
weaviate:
image: cr.weaviate.io/semitechnologies/weaviate:1.24.5
ports:
- "8080:8080"
- "50051:50051"
environment:
QUERY_DEFAULTS_LIMIT: 25
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true'
PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
DEFAULT_VECTORIZER_MODULE: 'text2vec-openai'
ENABLE_MODULES: 'text2vec-openai,generative-openai'
OPENAI_APIKEY: ${OPENAI_API_KEY}
CLUSTER_HOSTNAME: 'node1'
volumes:
- weaviate_data:/var/lib/weaviate
volumes:
weaviate_data:
import weaviate from "weaviate-client";
// 1. Connetti al server
const client = await weaviate.connectToLocal();
// 2. Crea la classe (schema)
await client.collections.create({
name: "Document",
vectorizers: [
weaviate.configure.vectorizer.text2VecOpenAI({
model: "text-embedding-3-small",
})
],
properties: [
{ name: "content", dataType: "text" },
{ name: "source", dataType: "text" },
{ name: "page", dataType: "int" },
],
});
// 3. Aggiungi documenti (embeddings generati automaticamente)
const collection = client.collections.get("Document");
await collection.data.insertMany([
{ content: "RAG combina retrieval e generation", source: "manuale.pdf", page: 1 },
{ content: "Gli embeddings catturano il significato", source: "manuale.pdf", page: 2 },
]);
// 4. Hybrid search (semantica + keyword)
const results = await collection.query.hybrid("cos'è RAG?", {
limit: 5,
alpha: 0.75, // 0 = solo keyword, 1 = solo semantica
});
Weaviate を選択する場合
- 必要がある ハイブリッド検索 (セマンティクス + キーワード BM25)
- ベクトル DB に埋め込みを自動的に生成させたい
- クエリには GraphQL インターフェイスを優先する
- テキスト、画像、マルチモーダル用の統合モジュールが必要です
8. Qdrant: パフォーマンスと柔軟性
Rust で書かれた Qdrant は、ベクトル データベースの中で最高の純粋なパフォーマンスを提供します。 オープンソース。高度なメタデータ フィルタリングとフィルタ検索に優れています。 コンプレックス。
import { QdrantClient } from "@qdrant/js-client-rest";
// 1. Connetti al server (docker run -p 6333:6333 qdrant/qdrant)
const client = new QdrantClient({ url: "http://localhost:6333" });
// 2. Crea la collezione
await client.createCollection("rag-demo", {
vectors: {
size: 1536,
distance: "Cosine", // Cosine | Euclid | Dot
},
optimizers_config: {
default_segment_number: 2,
},
hnsw_config: {
m: 16,
ef_construct: 100,
},
});
// 3. Inserisci vettori
await client.upsert("rag-demo", {
wait: true,
points: [
{
id: 1,
vector: [0.23, -0.45, 0.67, ...],
payload: {
content: "RAG combina retrieval e generation",
source: "manuale.pdf",
page: 1,
tags: ["rag", "ai", "tutorial"],
},
},
],
});
// 4. Ricerca con filtri avanzati
const results = await client.search("rag-demo", {
vector: [0.22, -0.44, 0.68, ...],
limit: 5,
filter: {
must: [
{ key: "source", match: { value: "manuale.pdf" } },
{ key: "page", range: { gte: 1, lte: 10 } },
],
should: [
{ key: "tags", match: { value: "rag" } },
],
},
with_payload: true,
});
9. pgvector: PostgreSQL のベクトル
すでに PostgreSQL を使用している場合は、 ベクター ベクトルサポートを追加 新しいデータベースをスタックに導入する必要はありません。メンテナンスしたい方にぴったり オールインワンシステム。
-- 1. Installa l'estensione
CREATE EXTENSION IF NOT EXISTS vector;
-- 2. Crea la tabella con colonna vettoriale
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT NOT NULL,
source VARCHAR(255),
page INTEGER,
embedding vector(1536), -- Dimensione del vettore
created_at TIMESTAMP DEFAULT NOW()
);
-- 3. Crea l'indice HNSW (consigliato per < 1M righe)
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- 4. Oppure IVFFlat (consigliato per > 1M righe)
-- CREATE INDEX ON documents
-- USING ivfflat (embedding vector_cosine_ops)
-- WITH (lists = 100);
-- 5. Ricerca per similarità
SELECT id, content, source, page,
1 - (embedding <=> '[0.22, -0.44, 0.68, ...]') AS similarity
FROM documents
WHERE source = 'manuale.pdf'
ORDER BY embedding <=> '[0.22, -0.44, 0.68, ...]'
LIMIT 5;
import { PrismaClient } from "@prisma/client";
import pgvector from "pgvector";
const prisma = new PrismaClient();
// Inserisci un documento con embedding
async function insertDocument(
content: string,
embedding: number[],
source: string
): Promise<void> {
await prisma.$executeRaw`
INSERT INTO documents (content, source, embedding)
VALUES (${content}, ${source}, ${pgvector.toSql(embedding)}::vector)
`;
}
// Ricerca per similarità
async function searchSimilar(
queryEmbedding: number[],
limit: number = 5
): Promise<any[]> {
const results = await prisma.$queryRaw`
SELECT id, content, source,
1 - (embedding <=> ${pgvector.toSql(queryEmbedding)}::vector) as similarity
FROM documents
ORDER BY embedding <=> ${pgvector.toSql(queryEmbedding)}::vector
LIMIT ${limit}
`;
return results as any[];
}
pgvector を選択する場合
- スタック内で既に PostgreSQL を使用している
- メタデータに対する JOIN と集計を使用した複雑な SQL クエリが必要な場合
- 別個のデータベースを管理する複雑さを避けたい
- データセットのベクトル数は 500 万未満です
- ベクター データに対する ACID トランザクションが必要です
10. メタデータのフィルタリングとハイブリッド検索
純粋な類似性検索だけでは必ずしも十分とは限りません。本番環境では、多くの場合、 セマンティック検索とメタデータ フィルターまたは キーワード検索。
10.1 メタデータのフィルタリング
メタデータを使用すると、検索をドキュメントのサブセットに絞り込むことができます 類似検索を適用する前に。これにより両方の精度が向上します 公演よりも。
Scenario: Knowledge base con documentazione di 3 prodotti
Senza filtro:
Query: "Come resettare il dispositivo?"
Risultati: Mix di istruzioni per Prodotto A, B e C
Problema: L'utente sta usando il Prodotto B
Con filtro:
Query: "Come resettare il dispositivo?"
Filtro: product = "Prodotto B"
Risultati: Solo istruzioni per il Prodotto B
Vantaggio: Risposta precisa e pertinente
10.2 ハイブリッド検索
ハイブリッド検索は、セマンティック検索 (埋め込み) とキーワード検索を組み合わせたものです。 (BM25/TF-IDF)。これは、技術用語を含むクエリに特に役立ちます。 セマンティック検索では取得できない固有名またはコード。
ハイブリッド検索を使用する場合
| クエリの種類 | セマンティクスのみ | キーワードのみ | ハイブリッド |
|---|---|---|---|
| 「ログインはどのように機能しますか?」 | 素晴らしい | 良い | 素晴らしい |
| 「ERR_CONNECTION_REFUSED エラー」 | 貧しい | 素晴らしい | 素晴らしい |
| 「API エンドポイント /api/v2/users」 | 平均 | 素晴らしい | 素晴らしい |
| 「なぜアプリが遅いのですか?」 | 素晴らしい | 貧しい | 素晴らしい |
11. ベクターデータベースの選択ガイド
選択は特定のコンテキストによって異なります。これが実際的な意思決定ツリーです。
Hai già PostgreSQL nel tuo stack?
Si -> Dataset < 5M vettori?
Si -> pgvector (nessun nuovo DB da gestire)
No -> Considera un vector DB dedicato
Vuoi zero manutenzione?
Si -> Budget disponibile?
Si -> Pinecone (cloud managed)
No -> Chroma Cloud / Qdrant Cloud (piani gratuiti)
Hai bisogno di hybrid search?
Si -> Weaviate (BM25 integrato)
oppure Qdrant (sparse vectors)
Vuoi massime performance?
Si -> Qdrant (Rust, ottimizzato)
Stai prototipando / sviluppando localmente?
Si -> Chroma (setup in 1 minuto)
最終アドバイス
最初の選択にあまり時間を費やさないでください。 クロマを始めましょう ローカル開発の場合は、本番環境に移行するときに Pinecone または Qdrant に移行します。 LangChain.js はベクター ストア インターフェイスを抽象化するため、変更には次のことが必要です 数行のコードを変更します。
次のステップ
この記事では、ベクトル データベースについて深く理解しました。 内部で動作し、インデックス付けアルゴリズム、類似性メトリクス、 最も一般的なソリューション間の違い。松ぼっくりのセットアップ例を見たことがありますか? Chroma、Weaviate、Qdrant、pgvector と、適切なものを選択するための実践的なガイド。
Nel 次の記事 を探索してみます OpenAI と Anthropic API 詳細: Web アプリケーションへの統合方法、ストリーミングの管理方法、関数呼び出しの方法 モデル呼び出しのコストとパフォーマンスを最適化します。
追加リソース
- 松ぼっくり: pinecone.io - ドキュメントと無料プラン
- 彩度: trychroma.com - 1 分でローカルセットアップ
- 回避: weaviate.io - ハイブリッド検索および AI モジュール
- クドラント: qdrant.tech - パフォーマンスと高度なフィルター
- pgvector: github.com/pgvector/pgvector - PostgreSQL 拡張機能
- ANN ベンチマーク: ann-benchmarks.com - アルゴリズムのパフォーマンス比較







