> For the complete documentation index, see [llms.txt](https://docs.telys.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.telys.ai/embeddings/dimensions-and-space-id.md).

# Dimensions & spaces

A Telys collection is bound to one vector space for its whole life. Two numbers fix that space: the **dimension** (how wide each vector is) and the **space ID** (a digest of the embedder's [`EmbeddingProfile`](/embeddings/embedding-profile.md)). After creation both are frozen — you cannot search with vectors of a different width, and you cannot re-attach an embedder from a different space.

## The dimension contract

The `dim` you declare at creation must agree with the embedder in three places:

* the `dim` you pass to `create_collection`,
* the embedder's `profile.dimension`,
* the width of the array the embedder returns (`shape[1]`).

```python
from telys import Telys
from telys.embedding import CallableEmbedder, EmbeddingProfile

profile = EmbeddingProfile("openai", "text-embedding-3-small", "1", dimension=1536)
embedder = CallableEmbedder(embed_fn, profile)

ame = Telys("./store")
col = ame.create_collection("docs", dim=1536, partition_by="scope", embedder=embedder)
#                                     ^^^^ must equal profile.dimension (1536)
```

If those numbers disagree, the collection and embedder describe different spaces and the operation is rejected. After creation, every query vector is checked too: `search(vector, ...)` validates `len(vector) == dim`, and `add(vectors, ...)` requires an `(n, dim)` array.

## What a space ID is

The space ID is `EmbeddingProfile.space_id()` — `"sha256:"` plus 16 hex characters, computed from the space-defining fields (provider, model, version, dimension, dtype, normalization, distance, pooling, and the tokenizer/projection tags). It answers one question: *are these two sets of vectors comparable?*

```python
profile.space_id()          # e.g. "sha256:9c1f4a2b7e0d5163"
```

`save()` writes the profile to disk. `open_collection(...)` re-attaches an embedder from the provider registry by matching `model_id` and `space_id()`. A provider from a different space will not attach.

## Changing the embedder means a new space

Anything that changes the profile's identity changes the space ID, and a new space ID is **incompatible** with an existing collection:

| Change                                                          | New `space_id()`? | Effect on an existing collection                      |
| --------------------------------------------------------------- | ----------------- | ----------------------------------------------------- |
| Different model (`text-embedding-3-small` → `bge-base-en-v1.5`) | Yes               | Incompatible — vectors are not comparable.            |
| Different dimension (1536 → 512)                                | Yes               | Incompatible — and the width no longer matches `dim`. |
| Different `normalization` or `distance`                         | Yes               | Incompatible — scores would be meaningless.           |
| New `model_version`                                             | Yes               | Incompatible — treat as a fresh space.                |
| Only `created` (provenance timestamp)                           | No                | Still compatible — reopen keeps working.              |

There is no in-place "re-embed" and no way to swap a collection onto a new space. A different embedding model is a different space, and a different space is a new collection.

## Migrating to a new model

Create a **new** collection under the new space and re-embed your source text into it. Vectors cannot be reused across spaces, so re-run `add_texts` from the original documents — keep your source text.

{% stepper %}
{% step %}

#### Create a new collection for the new space

```python
new_profile = EmbeddingProfile("bge", "BAAI/bge-base-en-v1.5", "1.5", dimension=768)
new_embedder = CallableEmbedder(bge_embed, new_profile)

ame = Telys("./store")
new_col = ame.create_collection("docs_v2", dim=768, partition_by="scope", embedder=new_embedder)
```

{% endstep %}

{% step %}

#### Re-embed the source text into it

```python
new_col.add_texts(texts=source_texts, ids=source_ids, metadata=source_metadata)
new_col.save()
```

{% endstep %}

{% step %}

#### Cut over reads to the new collection

Point searches at `docs_v2`. Keep the old collection until you have verified recall, then delete its directory.
{% endstep %}
{% endstepper %}

## Dimension-mismatch errors

<details>

<summary>Query vector length does not match the collection</summary>

`search(vector, ...)` validates `len(vector) == dim`. Passing a 768-d vector to a 1536-d collection (or vice versa) fails. Embed the query with the **same** embedder that built the collection, or use `search_text`, which embeds through the attached embedder.

</details>

<details>

<summary>Raw vectors are not shaped <code>(n, dim)</code></summary>

`add(vectors, ...)` and `upsert(vectors, ...)` require a 2-D `float32` array whose second axis equals `dim`. Reshape or cast before inserting: `np.asarray(vectors, dtype="float32").reshape(-1, dim)`.

</details>

<details>

<summary>Reopened embedder will not attach</summary>

The registered provider's `space_id()` differs from the one stored in the collection. Register a provider that describes the same space (same model, version, dimension, normalization, distance) before calling `open_collection`.

</details>

## Next steps

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Embedding dimension mismatches</strong></td><td>Diagnose and fix the exact errors above.</td><td><a href="/pages/cLf0cG2Rm2TZeyApGR9I">/pages/cLf0cG2Rm2TZeyApGR9I</a></td></tr><tr><td><strong>EmbeddingProfile &#x26; space compatibility</strong></td><td>Every profile field and how space_id() is computed.</td><td><a href="/pages/xwahgwdIzO1r8VFfN9l8">/pages/xwahgwdIzO1r8VFfN9l8</a></td></tr><tr><td><strong>Embeddings &#x26; vector spaces</strong></td><td>The concept behind spaces and comparability.</td><td><a href="/pages/RzDIZEyqpor8emxw5SUJ">/pages/RzDIZEyqpor8emxw5SUJ</a></td></tr></tbody></table>

Next: work through concrete failures in [Embedding dimension mismatches](/troubleshooting/dimension-mismatches.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.telys.ai/embeddings/dimensions-and-space-id.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
