Loading...
Loading...
Cloudflare Vectorize vector database for semantic search and RAG. Use for vector indexes, embeddings, similarity search, or encountering dimension mismatches, filter errors.
npx skill4agent add secondsky/claude-skills cloudflare-vectorize# 1. Create the index with FIXED dimensions and metric
bunx wrangler vectorize create my-index \
--dimensions=768 \
--metric=cosine
# 2. Create metadata indexes IMMEDIATELY (before inserting vectors!)
bunx wrangler vectorize create-metadata-index my-index \
--property-name=category \
--type=string
bunx wrangler vectorize create-metadata-index my-index \
--property-name=timestamp \
--type=number# Dimensions MUST match your embedding model output:
# - Workers AI @cf/baai/bge-base-en-v1.5: 768 dimensions
# - OpenAI text-embedding-3-small: 1536 dimensions
# - OpenAI text-embedding-3-large: 3072 dimensions
# Metrics determine similarity calculation:
# - cosine: Best for normalized embeddings (most common)
# - euclidean: Absolute distance between vectors
# - dot-product: For non-normalized vectors{
"name": "my-vectorize-worker",
"main": "src/index.ts",
"compatibility_date": "2025-10-21",
"vectorize": [
{
"binding": "VECTORIZE_INDEX",
"index_name": "my-index"
}
],
"ai": {
"binding": "AI"
}
}export interface Env {
VECTORIZE_INDEX: VectorizeIndex;
AI: Ai;
}
interface VectorizeVector {
id: string;
values: number[] | Float32Array | Float64Array;
namespace?: string;
metadata?: Record<string, string | number | boolean | string[]>;
}
interface VectorizeMatches {
matches: Array<{
id: string;
score: number;
values?: number[];
metadata?: Record<string, any>;
namespace?: string;
}>;
count: number;
}| Operation | Method | Key Point |
|---|---|---|
| Insert | | Keeps first if ID exists |
| Upsert | | Overwrites if ID exists (use for updates) |
| Query | | Returns similar vectors |
| Delete | | Remove by ID array |
| Get | | Retrieve specific vectors |
| Operator | Example | Description |
|---|---|---|
| | Equality (implicit) |
| | Not equal |
| | In array |
| | Not in array |
| | Range queries |
references/vector-operations.md| Model | Provider | Dimensions | Best For |
|---|---|---|---|
| Workers AI | 768 | Free, general purpose |
| OpenAI | 1536 | Balance quality/cost |
| OpenAI | 3072 | Highest quality |
references/integration-workers-ai-bge-base.mdreferences/integration-openai-embeddings.md| Limit | Value |
|---|---|
| Max metadata indexes | 10 per index |
| Max metadata size | 10 KiB per vector |
| String index | First 64 bytes (UTF-8) |
| Filter size | Max 2048 bytes |
."$references/metadata-guide.mdexport default {
async fetch(request: Request, env: Env): Promise<Response> {
const { question } = await request.json();
// 1. Generate embedding for user question
const questionEmbedding = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: question
});
// 2. Search vector database for similar content
const results = await env.VECTORIZE_INDEX.query(
questionEmbedding.data[0],
{
topK: 3,
returnMetadata: 'all',
filter: { type: "documentation" }
}
);
// 3. Build context from retrieved documents
const context = results.matches
.map(m => m.metadata.content)
.join('\n\n---\n\n');
// 4. Generate answer with LLM using context
const answer = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
messages: [
{
role: "system",
content: `Answer based on this context:\n\n${context}`
},
{
role: "user",
content: question
}
]
});
return Response.json({
answer: answer.response,
sources: results.matches.map(m => m.metadata.title)
});
}
};doc_idchunk_indexcontenttemplates/document-ingestion.tsProblem: Filtering doesn't work on existing vectors
Solution: Delete and re-insert vectors OR create metadata indexes BEFORE insertingProblem: "Vector dimensions do not match index configuration"
Solution: Ensure embedding model output matches index dimensions:
- Workers AI bge-base: 768
- OpenAI small: 1536
- OpenAI large: 3072Problem: "Invalid metadata key"
Solution: Keys cannot:
- Be empty
- Contain . (dot)
- Contain " (quote)
- Start with $ (dollar sign)Problem: "Filter exceeds 2048 bytes"
Solution: Simplify filter or split into multiple queriesProblem: Slow queries or reduced accuracy
Solution: Use lower cardinality fields for range queries, or use seconds instead of milliseconds for timestampsProblem: Updates not reflecting in index
Solution: Use upsert() to overwrite existing vectors, not insert()Problem: "VECTORIZE_INDEX is not defined"
Solution: Add [[vectorize]] binding to wrangler.jsoncProblem: Unclear when to use namespace vs metadata filtering
Solution:
- Namespace: Partition key, applied BEFORE metadata filters
- Metadata: Flexible key-value filtering within namespace# Create index (dimensions/metric are PERMANENT)
bunx wrangler vectorize create <name> --dimensions=768 --metric=cosine
# Create metadata index (MUST be before inserting vectors!)
bunx wrangler vectorize create-metadata-index <name> --property-name=category --type=string
# Get index info
bunx wrangler vectorize info <name>references/wrangler-commands.mdreturnValues: true| Reference File | Load When... |
|---|---|
| Need full insert/upsert/query/delete code examples |
| Setting up metadata indexes, filtering best practices |
| Using Vectorize CLI commands |
| Integrating Workers AI embeddings |
| Integrating OpenAI embeddings |
| Comparing embedding model options |
| Index lifecycle management |
| Template | Purpose |
|---|---|
| Simple vector search |
| Complete RAG chatbot |
| Document chunking pipeline |
| Advanced filtering |