> 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/bigram.md).

# Bigram embedder

A compact, on-device **lexical** embedder. It hashes character bigrams of each input into a fixed-width `float32` vector, L2-normalized so inner-product search behaves like cosine similarity. It runs entirely inside the native kernel — no model download, no network — and is the smallest shipped space, which suits short strings such as keys, tags, and symbol names.

```python
from telys.embedding import AlgentaBigramEmbedder

emb = AlgentaBigramEmbedder(max_bytes=1 << 20)
```

## Signature

```python
AlgentaBigramEmbedder(*, max_bytes: int = 1 << 20)
```

Keyword-only. Takes no `dimension`, `model_id`, or `space_id` argument — space identity comes from the profile, and the dimension is read from the native kernel at construction time.

| Parameter   | Type  | Default           | Meaning                                                                                           |
| ----------- | ----- | ----------------- | ------------------------------------------------------------------------------------------------- |
| `max_bytes` | `int` | `1 << 20` (1 MiB) | Upper bound on the UTF-8 bytes read per input string. Longer inputs are truncated before hashing. |

## Requirements

{% hint style="warning" %}
`AlgentaBigramEmbedder` requires the **native kernel**. Constructing it without the kernel raises `ImportError`. Install and confirm the runtime with `telys runtime install` and `telys runtime verify`. Override the kernel library path with `$TELYS_KERNEL` (highest priority), then `$AME_KERNEL`.
{% endhint %}

## Interface

`AlgentaBigramEmbedder` satisfies the `EmbeddingProvider` protocol:

| Member                   | Returns                   | Notes                                          |
| ------------------------ | ------------------------- | ---------------------------------------------- |
| `profile`                | `EmbeddingProfile`        | The frozen space descriptor (see below).       |
| `embed_documents(texts)` | `ndarray[N, D]` `float32` | Embeds documents for ingestion.                |
| `embed_queries(texts)`   | `ndarray[N, D]` `float32` | Embeds queries; defaults to `embed_documents`. |

```python
emb = AlgentaBigramEmbedder()

emb.profile.dimension            # e.g. 64 — read from the native kernel
vecs = emb.embed_documents(["hello world", "telys memory"])
vecs.shape                       # (2, D)   float32, L2-normalized rows
```

## Profile

The embedder exposes a frozen [`EmbeddingProfile`](/embeddings/embedding-profile.md) with fixed identity fields:

| Field           | Value                                                   |
| --------------- | ------------------------------------------------------- |
| `provider`      | `"algenta"`                                             |
| `model_id`      | `"bigram"`                                              |
| `dimension`     | read from the native kernel (hint: `64`)                |
| `dtype`         | `"float32"`                                             |
| `normalization` | `"l2"`                                                  |
| `distance`      | `"ip"` (inner product; with L2 rows this equals cosine) |
| `pooling`       | `"bigram-hash"`                                         |

`model_version` (`"1.0.0"`) and `tokenizer_hash` (`"utf8-bytes"`) are fixed constants; `projection_version` and `created` default to empty strings. Only `dimension` is read from the kernel. Inspect the exact values for your install:

```python
emb.profile.as_dict()
emb.profile.space_id()           # "sha256:<16 hex>" identity of the space
```

Two embedders address the same collection only when their `space_id()` values match — see [`compatible_with`](/embeddings/embedding-profile.md).

## Using it with a collection

Create the collection with the embedder's own dimension, never a hard-coded kernel hint:

```python
from telys import Telys
from telys.embedding import AlgentaBigramEmbedder

engine = Telys("./memory")
emb = AlgentaBigramEmbedder()

col = engine.create_collection(
    "tags",
    dim=emb.profile.dimension,
    partition_by="scope",
    embedder=emb,
)
col.add_texts(
    ["invoice paid", "invoice overdue"],
    ids=["t1", "t2"],
    metadata=[{"scope": "billing"}, {"scope": "billing"}],
)
col.save()

hits = col.search_text("overdue invoice", top_k=5)
```

## See also

* [AlgentaMultigramEmbedder](/embeddings/multigram.md) — the richer lexical space and MCP default.
* [Choosing an embedder](/embeddings/choosing-an-embedder.md) — the decision matrix.
* [EmbeddingProfile & space compatibility](/embeddings/embedding-profile.md) — how space identity is computed.
* [Embedders API](/reference/embedders-api.md) — the full embedding surface.
* [Lexical vs dense embeddings](/understand-telys/lexical-vs-dense.md) — when lexical recall is the right tool.


---

# 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/bigram.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.
