Encoders
You're reading the docs for Semantic Router 0.x. Version 1.0 is out: read this page for v1, or the migration guide to upgrade.
An encoder turns text (or images, or other data) into a vector — a list of numbers that captures meaning. Those vectors are what let Semantic Router measure how similar two inputs are. Every routing decision starts here.
What an encoder does
An encoder does two jobs:
- At setup, it embeds the example utterances in your routes.
- At runtime, it embeds each incoming query.
The router compares the two and picks the closest route — even when the wording is completely different.
Dense vs. sparse
Semantic Router supports two kinds of encoder. They see text very differently, and each has its strengths.
Dense encoders
Dense encoders fill every dimension of the vector. They:
- Produce fixed-size vectors (1536 dimensions for OpenAI's
text-embedding-3-small, for example). - Capture rich semantic relationships.
- Do well when context and meaning matter more than exact words.
import os
from semantic_router.encoders import OpenAIEncoder
os.environ["OPENAI_API_KEY"] = "your-api-key"
encoder = OpenAIEncoder()
embeddings = encoder(["How's the weather today?", "Tell me about politics"])Sparse encoders
Sparse encoders leave most dimensions at zero, with only a few non-zero values. They:
- Key off specific words and tokens.
- Excel at exact keyword matching and term frequency.
- Are more interpretable — a non-zero dimension usually maps to a specific word.
import os
from semantic_router.encoders import AurelioSparseEncoder
os.environ["AURELIO_API_KEY"] = "your-api-key"
encoder = AurelioSparseEncoder()
embeddings = encoder(["How's the weather today?", "Tell me about politics"])Using both: hybrid routing
You don't have to choose. The HybridRouter takes a dense and a sparse encoder together, so you get semantic understanding and keyword precision. The alpha parameter sets the balance.
import os
from semantic_router import Route
from semantic_router.routers import HybridRouter
from semantic_router.encoders import OpenAIEncoder, AurelioSparseEncoder
os.environ["OPENAI_API_KEY"] = "your-openai-api-key"
os.environ["AURELIO_API_KEY"] = "your-aurelio-api-key"
routes = [
Route(name="weather", utterances=["How's the weather?", "Is it raining?"]),
Route(name="politics", utterances=["Tell me about politics", "Who's the president?"]),
]
router = HybridRouter(
encoder=OpenAIEncoder(),
sparse_encoder=AurelioSparseEncoder(),
routes=routes,
alpha=0.5, # 0 = all dense, 1 = all sparse
)Supported encoders
Most encoders ship with the base install. The ones that run models locally need the local extra:
pip install -qU "semantic-router[local]"Dense encoders
| Encoder | What it uses | Install |
|---|---|---|
| OpenAIEncoder | OpenAI embedding models | base |
| AzureOpenAIEncoder | Azure OpenAI embedding models | base |
| CohereEncoder | Cohere embedding models | base |
| MistralEncoder | Mistral embedding models | base |
| GoogleEncoder | Google embedding models | base |
| BedrockEncoder | AWS Bedrock embedding models | base |
| JinaEncoder | Jina embedding models | base |
| VoyageEncoder | Voyage embedding models | base |
| NimEncoder | NVIDIA NIM embedding models | base |
| LiteLLMEncoder | Any provider supported by LiteLLM | base |
| OllamaEncoder | Embedding models served by a local Ollama instance | base |
| HFEndpointEncoder | Hugging Face Inference API | base |
| HuggingFaceEncoder | Hugging Face models, run locally | local |
| LocalEncoder | Any sentence-transformers model, run locally | local |
| FastEmbedEncoder | FastEmbed models, run locally | local |
| VitEncoder | Vision Transformer, for image embeddings | local |
| CLIPEncoder | CLIP, for image and text embeddings | local |
Sparse encoders
| Encoder | What it uses | Install |
|---|---|---|
| BM25Encoder | BM25 | base |
| TfidfEncoder | TF-IDF | base |
| AurelioSparseEncoder | Aurelio's API for BM25 sparse embeddings | base |
| LocalSparseEncoder | Neural sparse models (SPLADE, CSR) via sentence-transformers, run locally | local |
LocalSparseEncoder is worth a closer look if you want sparse vectors without an API. It uses the sentence-transformers SparseEncoder API (v5+), runs on CPU, CUDA, or MPS, and works with any compatible model from the Hugging Face Hub:
from semantic_router.encoders import LocalSparseEncoder
encoder = LocalSparseEncoder(name="naver/splade-v3")
embeddings = encoder(["How's the weather today?", "Tell me about politics"])AutoEncoder
If you'd rather pick an encoder by name at runtime, AutoEncoder resolves the right class for you:
from semantic_router.encoders import AutoEncoder
from semantic_router.schema import EncoderType
encoder = AutoEncoder(type=EncoderType.OPENAI.value, name="text-embedding-3-small").model
embeddings = encoder(["How can I help you today?"])Choosing an encoder
A few questions to ask:
- Accuracy. Dense encoders understand meaning better but can miss exact keywords. Sparse encoders are the reverse.
- Speed. Local encoders avoid network round-trips, though cloud models are often more accurate.
- Cost. Cloud encoders (OpenAI, Cohere, Aurelio) bill per call. Local ones don't.
- Privacy. Local encoders keep your data on your machine.
- Both? When you're unsure, a hybrid setup often gives the best balance.
Each encoder's reference page covers its specific options.