Airweave supports 4 dense embedding models out of the box:
OpenAI Small (Recommended)
OpenAI Large
Mistral
Local (Self-Hosted)
Model: openai_text_embedding_3_smallProvider: OpenAIDimensions: Up to 1536 (Matryoshka support)Max Tokens: 8,192 per chunkAPI Model: text-embedding-3-smallConfiguration:
Best for: Production deployments, general-purpose search
Model: openai_text_embedding_3_largeProvider: OpenAIDimensions: Up to 3072 (Matryoshka support)Max Tokens: 8,192 per chunkAPI Model: text-embedding-3-largeConfiguration:
OpenAI’s text-embedding-3-small and text-embedding-3-large support Matryoshka Representation Learning, allowing you to use fewer dimensions:
What are Matryoshka embeddings?
Matryoshka embeddings encode information hierarchically:
Most important information in early dimensions
Less critical information in later dimensions
Can truncate to fewer dimensions with minimal quality loss
Example: Use 512 dimensions instead of 1536 for 3x faster search and 67% less storage.
How to configure
Set EMBEDDING_DIMENSIONS to any value up to the model’s maximum:text-embedding-3-small (max 1536):
EMBEDDING_DIMENSIONS=512 # Fast, lower qualityEMBEDDING_DIMENSIONS=1024 # BalancedEMBEDDING_DIMENSIONS=1536 # Maximum quality
text-embedding-3-large (max 3072):
EMBEDDING_DIMENSIONS=768 # Fast, lower qualityEMBEDDING_DIMENSIONS=1536 # BalancedEMBEDDING_DIMENSIONS=3072 # Maximum quality
Performance vs Quality Tradeoffs
Dimensions
Search Speed
Storage
Quality
256
6x faster
83% less
Good
512
3x faster
67% less
Better
1024
1.5x faster
33% less
Very Good
1536
Baseline
Baseline
Excellent
Recommendation: Start with 1536, reduce to 1024 if you need better performance.
Important: Cannot change after deployment
Changing EMBEDDING_DIMENSIONS after indexing data requires complete re-indexing. All documents must be re-synced.
Airweave validates dimensions at startup against the database:
EmbeddingConfigError: Embedding config mismatch: embedding_dimensions: code=1024, db=1536. Changing embedding model or dimensions makes all synced data unsearchable — you would have to delete all data and resync.
DENSE_EMBEDDER: str = settings.DENSE_EMBEDDER or ""EMBEDDING_DIMENSIONS: int = settings.EMBEDDING_DIMENSIONS or 0SPARSE_EMBEDDER: str = settings.SPARSE_EMBEDDER or ""
Error if missing:
EmbeddingConfigError: Required environment variable 'DENSE_EMBEDDER' is not set. Add it to your .env file.Available options: openai_text_embedding_3_small, openai_text_embedding_3_large, mistral_embed, local_minilm
if EMBEDDING_DIMENSIONS != dense_spec.max_dimensions: raise EmbeddingConfigError( f"Dense embedder '{DENSE_EMBEDDER}' does not support " f"Matryoshka dimensions — EMBEDDING_DIMENSIONS must be " f"exactly {dense_spec.max_dimensions}" )
4
Credential Check
Verifies required API keys are present:
if dense_spec.required_setting: # e.g., "OPENAI_API_KEY" value = getattr(settings, dense_spec.required_setting, None) if not value: raise EmbeddingConfigError( f"Dense embedder '{DENSE_EMBEDDER}' requires setting " f"'{dense_spec.required_setting}' but it is not set." )
5
Database Reconciliation
Checks configuration against existing deployment metadata:
# First deployment: Create metadata rowif row is None: row = VectorDbDeploymentMetadata( dense_embedder=DENSE_EMBEDDER, embedding_dimensions=EMBEDDING_DIMENSIONS, sparse_embedder=SPARSE_EMBEDDER, )# Existing deployment: Validate matchif row.dense_embedder != DENSE_EMBEDDER: raise EmbeddingConfigError( "Changing embedding model makes all synced data unsearchable" )
class OpenAIDenseEmbedder: _MAX_TOKENS_PER_TEXT: int = 8192 _MAX_TEXTS_PER_SUB_BATCH: int = 100 _MAX_TOKENS_PER_REQUEST: int = 300_000 _MAX_CONCURRENT_REQUESTS: int = 10 async def embed_many(self, texts: list[str]) -> list[DenseEmbedding]: # Validate inputs token_counts = self._validate_inputs(texts) # Split into sub-batches (max 100 texts) sub_batches = [ (texts[i:i+100], token_counts[i:i+100]) for i in range(0, len(texts), 100) ] # Process batches concurrently tasks = [self._embed_sub_batch(batch, counts) for batch, counts in sub_batches] nested_results = await asyncio.gather(*tasks) return [emb for batch in nested_results for emb in batch]
EmbeddingConfigError: EMBEDDING_DIMENSIONS=1024 exceeds max_dimensions=384 for dense embedder 'local_minilm'.
Solution: Use correct dimensions for your model:
OpenAI small: up to 1536
OpenAI large: up to 3072
Mistral: exactly 1024
Local: exactly 384
Error: Cannot change dimensions
Symptom:
EmbeddingConfigError: Embedding config mismatch: embedding_dimensions: code=1024, db=1536. Changing embedding model or dimensions makes all synced data unsearchable.
Solution: You have two options:
Revert: Change .env back to original dimensions (1536)
Re-index: Delete all data and re-sync:
docker compose down --volumes./start.sh# Re-create collections and sync
Error: Local embeddings not responding
Symptom:
EmbedderConnectionError: Local embedding connection failed: [Errno 111] Connection refused
Solution:
Ensure local embeddings container is running:
docker ps | grep text2vec
Check health:
curl http://localhost:9878/health
Restart if needed:
docker compose restart text2vec-transformers
Rate limit errors
Symptom:
EmbedderRateLimitError: OpenAI rate limit exceeded, retry after 30.0s
Solutions:
Reduce concurrency: Lower _MAX_CONCURRENT_REQUESTS in embedder