How to Configure Embedding Models and Dimension Settings in OpenViking
You configure embedding models and their dimension settings in OpenViking through a declarative configuration file (ov.conf) or programmatically via the EmbeddingConfig Pydantic models, which validate provider-specific parameters and resolve dimensions through explicit overrides or automatic provider detection.
OpenViking (volcengine/OpenViking) implements a hierarchical configuration system that separates embedding model definitions from runtime instantiation. The architecture supports dense, sparse, and hybrid embedding types across multiple providers including OpenAI, Jina, and VolcEngine, with flexible dimension handling that accommodates both static truncation and dynamic auto-detection.
Configuration Architecture
OpenViking organizes embedding configuration into three nested layers defined in openviking_cli/utils/config/embedding_config.py.
EmbeddingModelConfig defines a single model instance. This Pydantic model validates fields including provider, model, api_key, api_base, dimension, batch_size, and backend. Each instance represents either a dense, sparse, or hybrid embedder.
EmbeddingConfig acts as a container holding optional dense, sparse, and hybrid fields (each containing an EmbeddingModelConfig), plus global settings like max_concurrent. According to the source in embedding_config.py (lines 91-112), at least one embedder type must be specified during validation.
OpenVikingConfig serves as the root configuration object accessed by the runtime. It initializes the embedding subsystem through the embedding attribute, which uses a default factory to create an empty EmbeddingConfig if the section is omitted (see open_viking_config.py, lines 49-52).
Dimension Resolution Logic
OpenViking resolves the effective embedding dimension through a three-tier precedence system implemented in EmbeddingConfig.get_dimension() (lines 71-77 of embedding_config.py):
- Explicit user specification via the
dimensionfield inEmbeddingModelConfig - Provider-specific auto-detection based on the API backend
- Global fallback of 2048 dimensions when no other value exists
OpenAI Auto-Detection
When configuring OpenAI models without an explicit dimension, the OpenAIDenseEmbedder._detect_dimension() method in openviking/models/embedder/openai_embedders.py (lines 73-80) executes a minimal API request to determine the vector length. If detection fails, the system defaults to 1536 dimensions (standard for text-embedding-3-small).
Jina Matryoshka Reduction
Jina embedders utilize a static dimension map defined as JINA_MODEL_DIMENSIONS in openviking/models/embedder/jina_embedders.py (lines 14-18). This maps model names to their maximum dimensions (e.g., 1024 for text-small, 768 for text-nano). When you specify a dimension smaller than the model's maximum, OpenViking applies Matryoshka truncation to reduce the output vector size while preserving semantic relevance.
VolcEngine Defaults
For VolcEngine providers, the VolcengineDenseEmbedder.get_dimension method returns a hard-coded default of 2048 when no explicit dimension is configured in the YAML or constructor.
Runtime Configuration Flow
You can instantiate configurations programmatically using OpenVikingConfig.from_dict(), which validates the structure through Pydantic and returns a ready-to-use embedder via EmbeddingConfig.get_embedder().
from openviking_cli.utils.config.open_viking_config import OpenVikingConfig
cfg_dict = {
"embedding": {
"dense": {
"provider": "jina",
"model": "jina-embeddings-v5-text-small",
"api_key": "jina_xxx",
"dimension": 512, # Matryoshka reduction from 1024
"task": "retrieval.query"
}
}
}
config = OpenVikingConfig.from_dict(cfg_dict)
embedder = config.embedding.get_embedder()
print("Effective dimension:", embedder.get_dimension()) # Output: 512
The get_embedder() method calls _create_embedder() (lines 22-44 of embedding_config.py), which routes to the appropriate concrete class—such as JinaDenseEmbedder, OpenAIDenseEmbedder, or VolcengineDenseEmbedder—based on the provider field.
YAML Configuration Examples
OpenViking typically reads configuration from an ov.conf YAML file. The parser resolves environment variables and validates the structure against the Pydantic schemas.
OpenAI Dense Embeddings
embedding:
dense:
provider: openai
model: text-embedding-3-large
api_key: ${OPENVIKING_OPENAI_API_KEY}
# dimension omitted - auto-detected (defaults to 1536 if detection fails)
batch_size: 64
VolcEngine Dense and Sparse
embedding:
dense:
provider: volcengine
model: volc_nlp_bert_base
api_key: ${VOLCENGINE_API_KEY}
dimension: 768 # Explicit override; otherwise 2048
sparse:
provider: volcengine
model: volc_sparse_encoder
api_key: ${VOLCENGINE_API_KEY}
Jina with Matryoshka Dimension Reduction
embedding:
dense:
provider: jina
model: jina-embeddings-v5-text-nano
api_key: ${JINA_API_KEY}
dimension: 256 # Reduced from maximum 768
task: retrieval.query
Hybrid Embeddings
For models that return both dense and sparse vectors simultaneously:
embedding:
hybrid:
provider: volcengine
model: volc_hybrid_encoder
api_key: ${VOLCENGINE_API_KEY}
dimension: 1024
# No separate sparse section required
Configuration File Discovery
The OpenViking CLI locates your configuration file through the resolve_config_path function in openviking_cli/utils/config/config_loader.py. The loader searches for ov.conf in a standard hierarchy: first checking environment variables, then the user home directory (~/.openviking/ov.conf), and finally system-level directories.
Summary
- Declarative Configuration: Define embedding models in
ov.confor Python dictionaries usingEmbeddingModelConfigandEmbeddingConfig. - Dimension Precedence: Explicit values override provider defaults; OpenAI auto-detects (fallback 1536), Jina uses static maps with Matryoshka support, and VolcEngine defaults to 2048.
- Provider Support: Configure dense, sparse, or hybrid embedders for OpenAI, Jina, and VolcEngine backends.
- Runtime Factory:
OpenVikingConfig.from_dict()validates input andget_embedder()instantiates the appropriate embedder class fromopenviking/models/embedder/. - File Location: Store configuration in
ov.conf, resolved viaconfig_loader.pyusing standard paths.
Frequently Asked Questions
What happens if I don't specify a dimension in my embedding configuration?
If you omit the dimension field, OpenViking falls back to provider-specific logic. OpenAI embedders execute _detect_dimension() to query the API directly (defaulting to 1536 if detection fails), Jina embedders use the static JINA_MODEL_DIMENSIONS map based on model name, and VolcEngine embedders default to 2048 dimensions.
How does OpenViking support Matryoshka embedding models?
For Jina embeddings, you can specify any dimension smaller than the model's native output (e.g., 256 for a 768-dimension model). The JinaDenseEmbedder truncates the full embedding vector to your specified size, enabling storage-efficient retrieval without reloading the model. This is implemented in openviking/models/embedder/jina_embedders.py.
Can I use dense and sparse embeddings simultaneously?
Yes. Configure both dense and sparse sections under embedding in your YAML file, or use a single hybrid configuration if your provider offers a unified model that outputs both vector types. The CompositeHybridEmbedder class handles the dual vector generation when using hybrid mode.
Where should I place my ov.conf configuration file?
The CLI loader in openviking_cli/utils/config/config_loader.py searches for ov.conf in the following order: paths specified via environment variables, ~/.openviking/ov.conf in the user home directory, and system-wide configuration directories. You can also pass a custom path directly to OpenVikingConfig.from_dict() by loading the YAML content manually.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →