Skip to content

Embeddings

rhizodat.embed

Embeddings: vectors for nodes' text, kept beside them, and the nearest nodes by meaning.

An Embedder turns texts into vectors (model, dimensions, embed(texts)); rhizodat ships none that understands meaning, only HashEmbedder for tests and offline demos. A real model plugs in as module:Class (load_embedder), for example a thin class around an API client or a local model.

embed_nodes embeds the text of every node with a label and writes the vectors in one unit, each with the model that made it and a hash of its text, so a second run embeds only edited texts, or everything after a model change. similar finds the nodes nearest to a text or a vector. The store needs the Vectors capability (drevo has it).

Embedder

Bases: Protocol

model property

model: str

The model's name and version: a vector made by another model is made again.

embed

embed(texts: list[str]) -> list[list[float]]

One vector of dimensions floats per text, in order.

HashEmbedder

Words hashed into a fixed number of buckets, the vector normalised.

Equal texts give equal vectors and texts sharing words are closer than texts sharing none, with no model and no network. It knows no meaning (synonyms are strangers): for tests and offline demos only.

load_embedder

load_embedder(spec: str) -> Embedder

hash / hash:<dimensions>, or module:Name (a class or factory called with no arguments).

embed_nodes

embed_nodes(
    dat: Rhizodat,
    *,
    store: str,
    label: str,
    text: str,
    embedder: Embedder,
    property: str = "embedding",
    batch: int = 64,
) -> EmbedReport

Embed the text property of every label node whose text or model changed since its vector was made; all new vectors are written as one unit.

similar

similar(
    dat: Rhizodat,
    *,
    store: str,
    label: str,
    query: str | Sequence[float],
    embedder: Embedder | None = None,
    property: str = "embedding",
    k: int = 10,
) -> list[Neighbour]

The k label nodes nearest to query (a text, embedded with embedder — the model that made the stored vectors — or a vector), closest first.

rhizodat.core.vectors

Vectors: entity fields that hold embeddings, and what a graph holding them returns.

Vector(n) marks an entity field as an embedding of n dimensions::

@entity(stores={"pg": ["title", "embedding", "model"]})
class Issue:
    title: str
    embedding: Annotated[list[float], Vector(384)] | None
    model: str | None

The field is stored like any list of floats and versioned with the entity; EntityRepository.similar searches it (a Match per entity found). VectorCandidate and Neighbour are what a graph store with the rhizodat.core.adapter.Vectors capability reads and returns for rhizodat.embed.

Vector dataclass

Marks a list[float] field as a vector of dimensions floats.

Match dataclass

An entity found by similar and how close its vector is to the query.

score instance-attribute

score: float

Cosine similarity, 1.0 the closest.

VectorCandidate dataclass

A node with text to embed, and what its current vector was made from.

hash instance-attribute

hash: str | None

The hash of the text the stored vector was made from; None if there is none.

model instance-attribute

model: str | None

The model that made the stored vector.

Neighbour dataclass

score instance-attribute

score: float

Cosine similarity, 1.0 the closest.

properties class-attribute instance-attribute

properties: dict[str, Any] = field(default_factory=dict)

The node's properties, without the vector and its bookkeeping.

vector_dimensions

vector_dimensions(annotation: object) -> int | None

The dimensions of a Vector field (optional or not); None for other fields.

Raises TypeError when Vector marks something other than list[float].

as_vector

as_vector(
    value: object, dimensions: int, what: str
) -> list[float]

value as a list of dimensions finite floats, or ValueError naming what.

cosine

cosine(a: Sequence[float], b: Sequence[float]) -> float

Cosine similarity, 1.0 the closest; 0.0 when either vector is all zeros.