# How to Configure Embedding Models and Dimension Settings in OpenViking

> Learn how to configure embedding models and dimension settings in OpenViking using configuration files or Pydantic models for seamless integration and efficient dimension management.

- Repository: [Volcengine/OpenViking](https://github.com/volcengine/OpenViking)
- Tags: how-to-guide
- Published: 2026-03-08

---

**You configure embedding models and their dimension settings in OpenViking through a declarative configuration file ([`ov.conf`](https://github.com/volcengine/OpenViking/blob/main/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`](https://github.com/volcengine/OpenViking/blob/main/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`](https://github.com/volcengine/OpenViking/blob/main/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`](https://github.com/volcengine/OpenViking/blob/main/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`](https://github.com/volcengine/OpenViking/blob/main/embedding_config.py)):

1. **Explicit user specification** via the `dimension` field in `EmbeddingModelConfig`
2. **Provider-specific auto-detection** based on the API backend
3. **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`](https://github.com/volcengine/OpenViking/blob/main/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`](https://github.com/volcengine/OpenViking/blob/main/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()`.

```python
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`](https://github.com/volcengine/OpenViking/blob/main/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`](https://github.com/volcengine/OpenViking/blob/main/ov.conf) YAML file. The parser resolves environment variables and validates the structure against the Pydantic schemas.

### OpenAI Dense Embeddings

```yaml
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

```yaml
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

```yaml
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:

```yaml
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`](https://github.com/volcengine/OpenViking/blob/main/openviking_cli/utils/config/config_loader.py). The loader searches for [`ov.conf`](https://github.com/volcengine/OpenViking/blob/main/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.conf`](https://github.com/volcengine/OpenViking/blob/main/ov.conf) or Python dictionaries using `EmbeddingModelConfig` and `EmbeddingConfig`.
- **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 and `get_embedder()` instantiates the appropriate embedder class from `openviking/models/embedder/`.
- **File Location**: Store configuration in [`ov.conf`](https://github.com/volcengine/OpenViking/blob/main/ov.conf), resolved via [`config_loader.py`](https://github.com/volcengine/OpenViking/blob/main/config_loader.py) using 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`](https://github.com/volcengine/OpenViking/blob/main/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`](https://github.com/volcengine/OpenViking/blob/main/ov.conf) configuration file?

The CLI loader in [`openviking_cli/utils/config/config_loader.py`](https://github.com/volcengine/OpenViking/blob/main/openviking_cli/utils/config/config_loader.py) searches for [`ov.conf`](https://github.com/volcengine/OpenViking/blob/main/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.