Documentation Index
Fetch the complete documentation index at: https://mintlify.com/firebase/genkit/llms.txt
Use this file to discover all available pages before exploring further.
Pinecone Plugin
The genkitx-pinecone plugin provides integration with Pinecone, a managed vector database optimized for production AI applications. Use it for high-performance retrieval-augmented generation (RAG) and semantic search at scale.
Installation
npm install genkitx-pinecone @pinecone-database/pinecone
Prerequisites
- Create Pinecone account: Sign up at pinecone.io
- Get API key: From the Pinecone console
- Create an index: Using the Pinecone console or API
Basic Setup
import { genkit } from 'genkit';
import { pinecone } from 'genkitx-pinecone';
import { googleAI } from '@genkit-ai/google-genai';
const ai = genkit({
plugins: [
googleAI(),
pinecone([
{
indexId: 'my-index',
embedder: googleAI.embedder('gemini-embedding-001'),
},
]),
],
});
The API key is automatically read from the PINECONE_API_KEY environment variable.
Configuration
Plugin Configuration
import { pinecone } from 'genkitx-pinecone';
import { googleAI } from '@genkit-ai/google-genai';
import type { PineconeConfiguration } from '@pinecone-database/pinecone';
// Basic configuration
pinecone([
{
indexId: 'documents',
embedder: googleAI.embedder('gemini-embedding-001'),
},
])
// With explicit API key
const clientParams: PineconeConfiguration = {
apiKey: process.env.PINECONE_API_KEY,
};
pinecone([
{
indexId: 'documents',
embedder: googleAI.embedder('gemini-embedding-001'),
clientParams: clientParams,
embedderOptions: { // Optional embedder config
taskType: 'RETRIEVAL_DOCUMENT',
},
},
])
// Multiple indexes
pinecone([
{
indexId: 'documents',
embedder: googleAI.embedder('gemini-embedding-001'),
},
{
indexId: 'code-snippets',
embedder: googleAI.embedder('text-embedding-005'),
},
])
Custom Content Key
By default, document content is stored in the _content metadata field:
pinecone([
{
indexId: 'my-index',
embedder: googleAI.embedder('gemini-embedding-001'),
contentKey: 'text', // Custom key instead of '_content'
},
])
Usage
Indexing Documents
import { pineconeIndexerRef } from 'genkitx-pinecone';
import { Document } from 'genkit';
// Define indexer
const indexer = pineconeIndexerRef({
indexId: 'my-index',
});
// Create documents with metadata
const documents = [
Document.fromText('Genkit is a framework for AI apps.', {
category: 'framework',
source: 'docs',
}),
Document.fromText('Pinecone is a vector database.', {
category: 'database',
source: 'docs',
}),
];
// Index documents
await ai.index({
indexer: indexer,
documents: documents,
});
Using Namespaces
Pinecone supports namespaces for logical data separation:
// Index to a namespace
await ai.index({
indexer: indexer,
documents: documents,
options: {
namespace: 'production', // Separate from 'staging', 'test', etc.
},
});
Retrieving Documents
import { pineconeRetrieverRef } from 'genkitx-pinecone';
// Define retriever
const retriever = pineconeRetrieverRef({
indexId: 'my-index',
});
// Retrieve relevant documents
const results = await ai.retrieve({
retriever: retriever,
query: 'What is Genkit?',
options: {
k: 5, // Return top 5 results (max: 1000)
},
});
console.log(results.documents);
Retrieve from Namespace
const results = await ai.retrieve({
retriever: retriever,
query: 'vector database',
options: {
k: 10,
namespace: 'production', // Query specific namespace
},
});
const results = await ai.retrieve({
retriever: retriever,
query: 'database tutorial',
options: {
k: 10,
filter: {
category: 'database', // Metadata filter
source: { $in: ['docs', 'blog'] },
},
},
});
RAG Examples
Simple RAG Flow
import { z } from 'genkit';
import { pineconeRetrieverRef } from 'genkitx-pinecone';
import { googleAI } from '@genkit-ai/google-genai';
const retriever = pineconeRetrieverRef({ indexId: 'knowledge-base' });
const ragFlow = ai.defineFlow(
{
name: 'ragFlow',
inputSchema: z.string(),
outputSchema: z.string(),
},
async (query) => {
// Retrieve context
const docs = await ai.retrieve({
retriever: retriever,
query: query,
options: { k: 3 },
});
// Build context
const context = docs.documents
.map(d => d.text)
.join('\n\n');
// Generate with context
const response = await ai.generate({
model: googleAI.model('gemini-2.5-flash'),
prompt: `Use this context to answer the question.\n\nContext:\n${context}\n\nQuestion: ${query}`,
});
return response.text();
}
);
Multi-namespace RAG
const multiNamespaceFlow = ai.defineFlow(
{
name: 'multiNamespaceRAG',
inputSchema: z.object({
query: z.string(),
sources: z.array(z.string()), // Namespace names
}),
},
async ({ query, sources }) => {
// Retrieve from multiple namespaces
const allDocs = await Promise.all(
sources.map(namespace =>
ai.retrieve({
retriever: retriever,
query: query,
options: { k: 3, namespace },
})
)
);
// Combine results
const context = allDocs
.flatMap(result => result.documents)
.map(d => d.text)
.join('\n\n');
// Generate
const response = await ai.generate({
model: googleAI.model('gemini-2.5-flash'),
prompt: `Context:\n${context}\n\nQuestion: ${query}`,
});
return response.text();
}
);
Index Management
Create Index
import { createPineconeIndex } from 'genkitx-pinecone';
await createPineconeIndex({
options: {
name: 'my-index',
dimension: 768, // Must match embedder dimensions
metric: 'cosine', // 'cosine', 'euclidean', or 'dotproduct'
spec: {
serverless: {
cloud: 'aws',
region: 'us-east-1',
},
},
},
});
Describe Index
import { describePineconeIndex } from 'genkitx-pinecone';
const indexInfo = await describePineconeIndex({
name: 'my-index',
});
console.log('Index status:', indexInfo.status);
console.log('Dimension:', indexInfo.dimension);
console.log('Vector count:', indexInfo.totalRecordCount);
Delete Index
import { deletePineconeIndex } from 'genkitx-pinecone';
await deletePineconeIndex({
name: 'old-index',
});
Advanced Features
Sparse Vectors (Hybrid Search)
Combine dense and sparse vectors for hybrid search:
const results = await ai.retrieve({
retriever: retriever,
query: 'machine learning',
options: {
k: 10,
sparseVector: { // BM25 or other sparse embeddings
indices: [1, 2, 5],
values: [0.5, 0.8, 0.3],
},
},
});
Custom Display Names
import { pineconeRetrieverRef, pineconeIndexerRef } from 'genkitx-pinecone';
const retriever = pineconeRetrieverRef({
indexId: 'docs-v2',
displayName: 'Production Documentation',
});
const indexer = pineconeIndexerRef({
indexId: 'docs-v2',
displayName: 'Production Documentation',
});
Complete Example
import { genkit, z } from 'genkit';
import {
pinecone,
pineconeRetrieverRef,
pineconeIndexerRef,
createPineconeIndex,
describePineconeIndex,
} from 'genkitx-pinecone';
import { googleAI } from '@genkit-ai/google-genai';
import { Document } from 'genkit';
// Initialize
const ai = genkit({
plugins: [
googleAI(),
pinecone([{
indexId: 'documentation',
embedder: googleAI.embedder('gemini-embedding-001'),
}]),
],
});
const indexer = pineconeIndexerRef({ indexId: 'documentation' });
const retriever = pineconeRetrieverRef({ indexId: 'documentation' });
// Ensure index exists
try {
const info = await describePineconeIndex({ name: 'documentation' });
console.log('Index exists:', info.name);
} catch (error) {
console.log('Creating index...');
await createPineconeIndex({
options: {
name: 'documentation',
dimension: 768,
metric: 'cosine',
spec: {
serverless: {
cloud: 'aws',
region: 'us-east-1',
},
},
},
});
}
// Index documents
const docs = [
Document.fromText('Genkit simplifies AI development.', {
topic: 'genkit',
type: 'overview',
}),
Document.fromText('Pinecone provides vector search.', {
topic: 'pinecone',
type: 'overview',
}),
];
await ai.index({
indexer: indexer,
documents: docs,
options: { namespace: 'prod' },
});
// RAG flow
const docSearch = ai.defineFlow(
{
name: 'documentSearch',
inputSchema: z.object({
query: z.string(),
topic: z.string().optional(),
}),
},
async ({ query, topic }) => {
const docs = await ai.retrieve({
retriever: retriever,
query: query,
options: {
k: 5,
namespace: 'prod',
filter: topic ? { topic } : undefined,
},
});
const context = docs.documents.map(d => d.text).join('\n');
const { text } = await ai.generate({
model: googleAI.model('gemini-2.5-flash'),
prompt: `Context:\n${context}\n\nQuestion: ${query}`,
});
return text;
}
);
Best Practices
Match Embedder Dimensions
Ensure index dimension matches embedder output:
// Gemini embeddings: 768 dimensions
createPineconeIndex({
options: {
name: 'gemini-index',
dimension: 768, // Match embedder
},
})
Use Namespaces for Isolation
// Separate environments
await ai.index({ indexer, documents, options: { namespace: 'production' } });
await ai.index({ indexer, documents, options: { namespace: 'staging' } });
await ai.index({ indexer, documents, options: { namespace: 'testing' } });
// Separate tenants
await ai.index({ indexer, documents, options: { namespace: 'tenant-abc' } });
await ai.index({ indexer, documents, options: { namespace: 'tenant-xyz' } });
Keep metadata small and indexed fields to a minimum:
// Good: Small, relevant metadata
Document.fromText('content', {
category: 'docs',
timestamp: Date.now(),
})
// Avoid: Large metadata
Document.fromText('content', {
fullDocument: largeObject, // Don't store full docs in metadata
allTags: longArrayOfTags, // Keep arrays small
})
Handle Errors
try {
await ai.retrieve({ retriever, query: 'test' });
} catch (error) {
if (error.message.includes('Index not found')) {
console.error('Index does not exist');
} else if (error.message.includes('PINECONE_API_KEY')) {
console.error('API key not configured');
} else {
console.error('Retrieval error:', error);
}
}
Configuration Options
Retriever Options
await ai.retrieve({
retriever: retriever,
query: 'search query',
options: {
k: 10, // Max results (1-1000)
namespace: 'production', // Query namespace
filter: { // Metadata filter
category: 'docs',
year: { $gte: 2023 },
},
sparseVector: { // Hybrid search
indices: [1, 2],
values: [0.5, 0.8],
},
},
});
Filter Operators
// Equality
filter: { category: 'docs' }
// Comparison
filter: {
year: { $gte: 2020, $lte: 2024 },
score: { $gt: 0.5 },
}
// Set membership
filter: {
category: { $in: ['docs', 'blog'] },
status: { $nin: ['draft', 'archived'] },
}
// Logical operators
filter: {
$and: [
{ category: 'docs' },
{ year: { $gte: 2023 } },
],
}
Troubleshooting
API Key Issues
Error: Please pass in the API key or set PINECONE_API_KEY
Solution: Set environment variable:
export PINECONE_API_KEY=your-api-key
Dimension Mismatch
Error: Dimension mismatch
Solution: Ensure index dimension matches embedder output (e.g., 768 for Gemini).
Index Not Ready
Solution: Wait for index to be ready after creation:
let status = 'Initializing';
while (status !== 'Ready') {
const info = await describePineconeIndex({ name: 'my-index' });
status = info.status.state;
await new Promise(resolve => setTimeout(resolve, 1000));
}
Links