Documentation/Embeddings
v2.0.0-beta.1Snapshot bebdcd1Markdown ↗

Embeddings

Embeddings

The library provides multi-vendor text embeddings and Google Gemini Embedding 2 multimodal embeddings through one API. Text, image, audio, video, and document inputs can share one vector space for semantic search, RAG, clustering, classification, and similarity matching.

Basic Usage

typescript
// Documentation check: complete example
import { Connector, Embeddings, Vendor } from 'oneringai';

// Setup connector
Connector.create({
  name: 'openai',
  vendor: Vendor.OpenAI,
  auth: { type: 'api_key', apiKey: process.env.OPENAI_API_KEY! },
});

// Create embeddings instance
const embeddings = Embeddings.create({ connector: 'openai' });

// Embed a single text
const result = await embeddings.embed('Hello world');
console.log(result.embeddings[0].length);  // 1536
console.log(result.usage.promptTokens);    // 2

// Embed multiple texts (batch)
const batch = await embeddings.embed([
  'The quick brown fox',
  'A lazy dog sleeps',
  'Machine learning is powerful',
]);
console.log(batch.embeddings.length);  // 3

Matryoshka Representation Learning (MRL)

Models that support MRL (marked with matryoshka: true in the registry) allow you to request fewer output dimensions. This produces smaller vectors; measure retrieval quality and latency on your own corpus.

typescript
// Full dimensions (default)
const full = await embeddings.embed('Hello world');
console.log(full.embeddings[0].length);  // 1536

// Reduced dimensions — 3x smaller vectors; evaluate retrieval quality
const compact = await embeddings.embed('Hello world', { dimensions: 512 });
console.log(compact.embeddings[0].length);  // 512

// Even smaller — great for large-scale approximate search
const tiny = await embeddings.embed('Hello world', { dimensions: 128 });
console.log(tiny.embeddings[0].length);  // 128

Models with MRL support include text-embedding-3-small, text-embedding-3-large, gemini-embedding-2, gemini-embedding-001, codestral-embed, embeddinggemma, all qwen3-embedding variants, and nomic-embed-text.

Default Dimensions

You can set default dimensions at creation time:

typescript
// All embeddings from this instance use 512 dimensions
const embeddings = Embeddings.create({
  connector: 'openai',
  model: 'text-embedding-3-small',
  dimensions: 512,
});

const result = await embeddings.embed('Hello');
console.log(result.embeddings[0].length);  // 512

// Override per-call
const full = await embeddings.embed('Hello', { dimensions: 1536 });
console.log(full.embeddings[0].length);  // 1536

OpenAI Embeddings

typescript
// text-embedding-3-small (recommended — cost-efficient, MRL)
const result = await embeddings.embed('search query', {
  model: 'text-embedding-3-small',
  dimensions: 1536,  // default, can reduce to 512 or 256
});

// text-embedding-3-large (higher quality, more dimensions)
const large = await embeddings.embed('search query', {
  model: 'text-embedding-3-large',
  dimensions: 3072,  // default, can reduce
});

Google Embeddings

typescript
Connector.create({
  name: 'google',
  vendor: Vendor.Google,
  auth: { type: 'api_key', apiKey: process.env.GOOGLE_API_KEY! },
});

const googleEmb = Embeddings.create({ connector: 'google' });

// gemini-embedding-2 is the current Google default (3072 dimensions).
const result = await googleEmb.embed('search query');
console.log(result.embeddings[0].length);  // 3072

// Task-aware text embedding with dimension reduction.
const compact = await googleEmb.embed('search query', {
  dimensions: 512,
  vendorOptions: {
    taskType: 'RETRIEVAL_QUERY',
    title: 'Product documentation query',
  },
});

// Multimodal content is exposed directly by the high-level API.
const mixed = await googleEmb.embedMultimodal([
  { type: 'text', text: 'Find assets similar to this launch brief' },
  { type: 'image', data: './campaign.png', mimeType: 'image/png' },
  { type: 'document', data: './brief.pdf', mimeType: 'application/pdf' },
], {
  dimensions: 1024,
  vendorOptions: { taskType: 'RETRIEVAL_DOCUMENT' },
});

embedMultimodal() currently requires gemini-embedding-2; the provider rejects multimodal content for text-only models. Buffer, local-path, data-URI, and arbitrary HTTP(S) inputs are sent inline; HTTP(S) content is fetched first with a 30-second default timeout and a streaming size guard. One request has a 100 MB aggregate inline-media budget; an individual PDF is limited to 50 MB. Content-Length is rejected before reading when present, and chunked responses are stopped as soon as they cross the budget. Configure a different positive timeout with vendorOptions.mediaDownloadTimeoutMs; the provider size ceilings remain fixed to Google's API contract. Only gs:// and Gemini Files API URIs are emitted as provider-hosted fileData references. Data URIs are strictly validated as base64, checked against the remaining byte budget before decoding, and re-encoded canonically before transmission.

mimeType is optional. Explicit values take precedence; otherwise the provider inspects common JPEG/PNG/BMP/WebP, WAV/AIFF/MP3/AAC/FLAC/Ogg/WebM/MP4, MOV/MP4/ AVI/WebM/MPEG/3GP, and PDF signatures before falling back to the path extension. This keeps JPEG buffers out of image/png, MP3 buffers out of audio/wav, and MOV files out of video/mp4.

Ollama Embeddings (Local)

Run embedding models locally with Ollama — free, private, no API key required.

typescript
Connector.create({
  name: 'ollama-local',
  vendor: Vendor.Ollama,
  auth: { type: 'none' },
  baseURL: 'http://localhost:11434/v1',
});

const local = Embeddings.create({ connector: 'ollama-local' });

// embeddinggemma (default) — compact multilingual model, 768 dims
const result = await local.embed('semantic search query');
console.log(result.embeddings[0].length);  // 768

// Use smaller model for constrained environments
const light = await local.embed('query', {
  model: 'qwen3-embedding:0.6b',  // ~400MB, 1024 dims
});

// Use nomic-embed-text for 768-dim vectors
const nomic = await local.embed('query', {
  model: 'nomic-embed-text',
});

Illustrative local-model sizing (verify memory use on your workload):

RAM Model Size Dimensions Quality
< 12 GB qwen3-embedding:0.6b ~400 MB 1024 Good
12-24 GB qwen3-embedding:4b ~2.5 GB 4096 Very good
24+ GB qwen3-embedding ~5 GB 4096 Largest of these variants; evaluate on your corpus

Available Models

The table summarizes checked-in embedding registry records. Availability and prices are registry metadata, not a live account probe. Use the active selectors; retired records remain available for lookup and migration.

Vendor Model Default Dims Max Dims MRL Max Tokens Price/1M Tokens
OpenAI text-embedding-3-small 1536 1536 Yes 8,191 $0.02
OpenAI text-embedding-3-large 3072 3072 Yes 8,191 $0.13
OpenAI text-embedding-ada-002 1536 1536 No 8,191 $0.10 (legacy)
Google gemini-embedding-2 3072 3072 Yes 8,192 $0.20 text; modality-specific media rates
Google gemini-embedding-001 3072 3072 Yes 2,048 $0.15 text
Mistral mistral-embed 1024 1024 No 8,192 $0.10
Mistral codestral-embed 3072 3072 Yes 8,192 $0.15
Ollama embeddinggemma 768 768 Yes 2,048 Free (local)
Ollama all-minilm 384 384 No 512 Free (local)
Ollama qwen3-embedding 4096 4096 Yes 8,192 Free (local)
Ollama qwen3-embedding:4b 4096 4096 Yes 8,192 Free (local)
Ollama qwen3-embedding:0.6b 1024 1024 Yes 8,192 Free (local)
Ollama nomic-embed-text 768 768 Yes 8,192 Free (local)
Ollama mxbai-embed-large 1024 1024 No 512 Free (local)

Model Introspection

typescript
import {
  getEmbeddingModelInfo,
  getEmbeddingModelsByVendor,
  getActiveEmbeddingModels,
  getEmbeddingModelsWithFeature,
  EMBEDDING_MODELS,
  Vendor,
} from 'oneringai';

// Get model information
const info = getEmbeddingModelInfo('text-embedding-3-small');
if (!info) throw new Error('Embedding model is not registered');
console.log(info.capabilities.maxDimensions);        // 1536
console.log(info.capabilities.maxTokens);            // 8191
console.log(info.capabilities.features.matryoshka);   // true
console.log(info.capabilities.features.multilingual);  // true
console.log(info.capabilities.limits.maxBatchSize);    // 2048

// List models by vendor
const ollamaModels = getEmbeddingModelsByVendor(Vendor.Ollama);
console.log(ollamaModels.map(m => m.name));
// ['embeddinggemma', 'all-minilm', 'qwen3-embedding', 'qwen3-embedding:4b', ...]

// Find MRL-capable models
const mrlModels = getEmbeddingModelsWithFeature('matryoshka');
console.log(mrlModels.map(m => `${m.name} (${m.capabilities.maxDimensions}d)`));

// Find multilingual models
const multilingualModels = getEmbeddingModelsWithFeature('multilingual');

// Use model constants for type safety
const modelName = EMBEDDING_MODELS[Vendor.OpenAI].TEXT_EMBEDDING_3_SMALL;
// 'text-embedding-3-small'

Cost Estimation

typescript
import { calculateEmbeddingCost } from 'oneringai';

// OpenAI text-embedding-3-small
const cost = calculateEmbeddingCost('text-embedding-3-small', 1_000_000);
console.log(`$${cost} per 1M tokens`);  // $0.02

// OpenAI text-embedding-3-large
const largeCost = calculateEmbeddingCost('text-embedding-3-large', 1_000_000);
console.log(`$${largeCost} per 1M tokens`);  // $0.13

// Ollama (free, returns null for no pricing)
const localCost = calculateEmbeddingCost('qwen3-embedding', 1_000_000);
console.log(localCost);  // null (free, local)

// Gemini Embedding 2 mixed-modality accounting plus the 50% batch discount.
const googleCost = calculateEmbeddingCost('gemini-embedding-2', 1_000_000, {
  images: 10,
  audioSeconds: 60,
  videoFrames: 30,
  batch: true,
});
console.log(googleCost); // 0.11725

Common Use Cases

Semantic Search (RAG):

typescript
// Embed documents at ingestion time
const docs = ['Document 1 text...', 'Document 2 text...', 'Document 3 text...'];
const docEmbeddings = await embeddings.embed(docs, { dimensions: 512 });
// Store docEmbeddings.embeddings in your vector database

// At query time, embed the query with the same model and dimensions
const queryResult = await embeddings.embed('user search query', { dimensions: 512 });
const queryVector = queryResult.embeddings[0];
// Use queryVector for vector similarity search

Text Classification:

typescript
// Embed labeled examples and new text
const categories = await embeddings.embed([
  'sports news about football',
  'financial market analysis',
  'cooking recipe instructions',
]);

const newText = await embeddings.embed('The team scored in the final minute');
// Compare newText vector to category vectors using cosine similarity

Documentation snapshot · 2026-11-02Suggest a correction ↗

Search documentation

Type to search the v2 documentation.