Embedding prefixes
EmbeddingFunctions.matryoshka derives a shorter, L2-normalized prefix from any EmbeddingFunction. The helper and EmbeddingDimensionMismatchException are @since 0.14.0 in TnsAI 0.14.0 (TnsAI@c2bb5306). They ship in Maven Central 0.14.1.
TnsAI 0.15.0 also makes the declarative hash-embedding fallback
visible. That warning ships in 0.15.0 and later. See Hash-embedding fallback.
Use this only when the delegate model is Matryoshka-trained (or otherwise prefix-compatible). Truncating a non-Matryoshka vector changes the geometry; the helper does not invent a second model.
What it does
EmbeddingFunction full = /* application provider, e.g. 1024-d */;
EmbeddingFunction reduced = EmbeddingFunctions.matryoshka(full, 256);
VectorMemoryStore store = new VectorMemoryStore(reduced);Each embed call:
- asks the delegate for the full vector
- copies the first
dimensionsvalues (the delegate array is never mutated or returned) - L2-normalizes that prefix; an all-zero prefix stays a zero vector
dimensions must be positive. A non-finite prefix value fails with
IllegalArgumentException. A delegate vector shorter than dimensions
throws EmbeddingDimensionMismatchException (expectedDimension /
actualDimension).
Store pin
VectorMemoryStore pins the first admitted vector's length for the store's
lifetime. Later add and non-empty search vectors must match that length or
the same mismatch exception is thrown. clear() removes entries but does
not reset the pin.
Build the store with the reduced function from the first add. Mixing a 1024-d query against a 256-d index is a typed failure, not a silent reshape.
Hash-embedding fallback (0.15.0)
Declarative Role bindings discover one process-wide EmbeddingFunction
through Java ServiceLoader. When none is installed, the runtime uses
the bundled 128-dimensional hash embedding — a normalised bag-of-words
that ranks by token overlap, not meaning. Cosine is near zero for two
documents that say the same thing in different words. @Retrieval(strategy = SEMANTIC) then behaves lexically.
On Maven Central 0.14.1 that fallback is silent: no warning, no
diagnostic. The annotation says SEMANTIC; the results are token overlap.
TnsAI 0.15.0 (TnsAI@89d41d1b,
PR #195 /
TAN-5885)
emits one WARN per Role class for the process lifetime when both of
these hold:
- the resolved function is the bundled hash embedding
- the requested strategy is vector-backed:
SEMANTIC,HYBRID,HIERARCHICAL, orTEMPORAL
KEYWORD, GRAPH, REASONING, and MULTI_QUERY do not warn on this
path. An installed provider logs nothing. The runtime does not throw
— the hash embedding stays a deliberate zero-setup default so offline
tests and examples keep running.
What you see
A single warning that names the Role, states that retrieval is ranking by token overlap rather than meaning, and names remedies. Repeat dispatches do not repeat the line.
What it means
SEMANTIC (and the other vector-backed modes above) is not semantic
until a real provider is installed. Hybrid fusion is only partly
degraded — BM25 still runs — but the vector half is lexical. Treat the
warning as "this annotation is advertising a capability you do not
have."
What to do
- Install one
EmbeddingFunctionprovider — see Strategies. - Or set
strategy = KEYWORDif lexical matching is what you want. - Or acknowledge the fallback deliberately with
-Dtnsai.rag.acknowledgeHashEmbedding=trueso the warning is not suppressed globally by a log-level workaround.
To ask what resolved, including whether the snapshot is the bundled
fallback, use
RagDiagnostics (@since 0.15.0).
Not this page
- Process-wide declarative
EmbeddingFunctiondiscovery — see Strategies - Inspecting the resolved RAG binding —
RAG diagnostics (
@since 0.15.0) - The Matryoshka helper ships in Maven Central
0.14.1. The hash-fallback warning does not.
RAG diagnostics
com.tnsai.intelligence.rag.binding.RagDiagnostics is @since 0.15.0 (TnsAI@32e17445, PR #199 / TAN-5888). It ships in 0.15.0 and later — see Installation for the coordinates.
File formats and ingestion
KnowledgeType.FILE says where documents come from (a path). DocumentFormat says how their bytes are interpreted. They are not the same field.