docsv0.5.1

[[models]]

Reference for [[models]] in a urna build spec: model roles, dims, space_dtype, per-model knobs, and which vector spaces each model writes into the file.

Each [[models]] entry picks an embedding model from the model registry and says what it embeds and where the vectors go. A spec needs at least one entry, and exactly one of them has text = "default".

[[models]]
preset = "potion"
text = "default"              # the file's main vectors (space 0)

[[models]]
preset = "wemm-2b"
text = "space"                # named space wemm-2b-text@256
image = "space"               # named space wemm-2b@256
dims = [256]
space_dtype = "int8"

[output]
allow_remote_code = ["wemm-2b"]

Keys

KeyTypeDefaultApplies toMeaning
presetstring""allA preset name from the model registry. Each preset appears at most once per spec
textstring"none"alldefault, space or none. See roles
imagestring"none"presets with an image towerspace or none. See roles
dimslist of integers[]presets with a validated dimension ladderOne named space per listed dimension. [] means one space at the native dimension
space_dtypestring"int8"named spacesStored precision of this model's named spaces: float32, float16, int8 or int4
model_pathpath""sentence-transformers presetsModel directory, the first place looked for weights. potion and open_clip presets do not load from it, but it keys the cached model hash
devicestring""sentence-transformers and open_clip presetscpu, mps, cuda and so on. "" picks automatically. potion runs on the CPU
batch_sizeinteger32sentence-transformers and open_clip presetsEncoder batch size
dtypestring""sentence-transformers presetsTorch dtype of the weights: float32, float16, bfloat16. "" uses the device default
text_corpus_modestringpreset defaultsentence-transformers presetsHow row text is encoded: document (encode as a document), query, or plain (plain encode). Any other value behaves like plain
text_query_modestringpreset defaultrecorded onlyRecorded in the embedding recipe. The build embeds documents only, and urna ask does not read it
image_modestringpreset default (image_document)recorded onlyRecorded in the embedding recipe; nothing reads it
image_promptstringpreset default (Represent this image.)wemm-* presetsText paired with each image document
normalizebooleantruesentence-transformers presetsL2-normalize the output. potion and open_clip always normalize
preprocess_versionstringpreset default (processor-native-v1)allA tag in the embedding recipe. Change it to force new vectors
image_max_sideinteger0 (preset default)sentence-transformers presetsImages larger than this are shrunk before encoding. wemm-* default to 768
encode_kwargstable{}sentence-transformers presetsExtra arguments for the encode call, merged over the preset's (the jina-* presets set task = "retrieval")

The sentence-transformers presets are jina-v5-omni-nano, jina-v5-omni-small, wemm-2b, wemm-4b and wemm-9b. The open_clip presets are clip-vit-b32 and siglip2.

text_corpus_mode, text_query_mode, image_mode, image_prompt, normalize, preprocess_version, image_max_side, encode_kwargs, dtype and device enter the model's embedding recipe, which keys the embed cache: changing one computes that model's vectors again. dims, space_dtype and batch_size do not; a change to dims or space_dtype reuses the cached vectors and only changes what is stored.

Roles

text and image decide what a model embeds and where the vectors land:

SettingEffect
text = "default"Embeds every row's stored text into the file's main vectors, space 0. This model's name and model_hash go into the file's manifest, and urna ask, urna retrieve and search-text query with it. Exactly one model per spec
text = "space"Embeds every row's stored text into named spaces <preset>-text or <preset>-text@<dim>
image = "space"Embeds each unique image into named spaces <preset> or <preset>@<dim>
text = "none" with image = "none"Not allowed: the model would write nothing

A model can hold text = "default" and image = "space" at once: its text vectors are space 0 and its image vectors are a named space.

image = "space" needs a source with images: kind = "image_dir", or a [source.image] path_template. What gets embedded (the source files or the decoded media) is set by [embedding.image_input].

Dimensions

dims works only on presets trained for prefix truncation (Matryoshka). Each listed dimension must be on the preset's validated ladder; the vectors are cut to the first dim components and L2-normalized again.

PresetAllowed dims
jina-v5-omni-nano32, 64, 128, 256, 512, 768
jina-v5-omni-small32, 64, 128, 256, 512, 768, 1024
wemm-2b128, 256, 512, 1024, 2048
wemm-4b128, 256, 512, 1024, 2560
wemm-9b128, 256, 512, 1024, 4096
potion, clip-vit-b32, siglip2none

dims shapes only named spaces. On a text = "default" model without image = "space" it produces nothing; to shorten space 0, use [build] mrl_dim (see [build]).

space_dtype = "int4" needs every listed dimension, or the preset's default dimension when dims is empty, to be a multiple of 64.

What a file contains

For each output file:

  • Space 0 holds the text = "default" model's text vectors over all rows, at the precision of the [build] preset. Its dimension is the model's native one, or [build] mrl_dim when set.
  • Named spaces follow the order of [[models]] in the spec. Within one model, image spaces come first, then text spaces, one per entry in dims. Each is stored at the model's space_dtype and carries the preset's model_hash, which both towers of a model share.
  • A spec can emit at most 15 named spaces. More fail validation with models: N named spaces > max 15.

With [output] mode = "per-model" or "both", each model also gets its own file with space 0 plus that model's named spaces (see [output]). The manifest lists every space with its name, preset, modality, dimension (null for native) and space_dtype. List a file's spaces with urna stats and query one with urna search-space.

Validation rules

Validation errors (exit 2 unless noted):

MessageCause
models: at least one [[models]] requiredNo [[models]] entry
models: exactly one text="default" required (RFC-0 N14), found NZero or several models with text = "default", also after a --models filter
models: duplicate preset '<p>'The same preset twice
registry error: unknown model preset '<p>'. valid presets: ...Unknown name (exit 4)
models.<p>: preset has no text towertext set on an image-only preset
models.<p>: preset has no image towerimage = "space" on a text-only preset such as potion
models.<p>.image=space: source declares no imagesimage = "space" without images in the source
models.<p>.dims: preset is not MRL-trained; dims not alloweddims on a preset without a ladder
models.<p>.dims: <d> not in the validated ladder [...] (method prefix_slice_l2)A dimension off the ladder
models.<p>: int4 requires dim%64==0, got <d>int4 with a dimension that is not a multiple of 64
models.<p>: flagged too heavy for this machine; pass --allow-heavywemm-4b or wemm-9b without --allow-heavy
models.<p>: executes model-repo code; opt in with output.allow_remote_code = ["<p>"] (RFC-0 N11)A jina-* or wemm-* preset not listed in [output] allow_remote_code

Invalid values of text, image and space_dtype also fail with a message naming the allowed values. The other keys are not checked: a bad dtype fails inside the model worker as a registry error (exit 4).

Where weights come from

The build never downloads a model. It resolves a model directory in this order: model_path, then URNA_MODEL_DIR_<NAME> (the preset name in upper case with - as _, for example URNA_MODEL_DIR_WEMM_2B), then the preset's built-in local directory if it exists, then, for sentence-transformers presets, the Hugging Face cache snapshot that refs/main points to. urna build --dry-run prints nothing about the directory; python python/tools/urna_forge.py --spec corpus.toml --dry-run --json shows it as model_dir.

A sentence-transformers preset with no directory on disk fails with a Python TypeError (exit 1). potion ships its weights in the repository.

Device and dtype for sentence-transformers presets: device in the spec, else URNA_ST_DEVICE, else cuda, mps, cpu in that order of availability. dtype in the spec, else URNA_ST_DTYPE, else bfloat16 on cuda, float16 on mps and float32 on cpu. The dtype enters the model_hash, so the same weights built on different devices get different hashes unless you pin dtype.

Querying what you built

Only potion corpora answer from an installed binary

urna ask and urna retrieve embed the query with the file's text = "default" model. The query embedder that the release channels install covers potion only. For any other default model, run the query from a checkout with that preset's packages and weights. See Known limits.

The query side uses the preset's defaults. Spec overrides of text_query_mode, encode_kwargs, image_prompt, normalize, dtype and device are not carried to ask or retrieve. Because normalize and the resolved dtype enter the model_hash, a corpus built with a non-default dtype, or on a device whose default dtype differs from the query machine's, is refused by the model gate unless URNA_ST_DTYPE matches at query time. See the model gate.

On this page