8.7.9. dasLLAMA-09 — Embeddings
Any chat model dasLLAMA loads doubles as an embedder. embed(model, text)
runs one forward pass, mean-pools the decoder’s last-layer hidden state
(post-final-norm) over every position, and L2-normalizes the result to unit
length. No separate embedding model is needed — the vector width is
model.config.dim, the decoder’s own embedding dimension.
Run:
daslang.exe -jit tutorials/dasLLAMA/09_embeddings.das -- model.gguf
8.7.9.1. One vector per sentence
embed is the whole API: text in, a fixed-width unit vector out. Because
every vector is unit length, cosine similarity is just the dot product — a
vector’s dot product with itself is 1.0, the cheapest check that the
result really is normalized.
var m <- load_model("SmolLM2-135M-Instruct-Q8_0.gguf", QuantMode.q8)
with_job_que() { // the forward pass needs the job queue
setup_dasllama_jobque()
let qv <- embed(m, "How do I sort a list in Python?")
print("{length(qv)} floats, self-similarity {cosine(qv, qv)}\n")
}
embed runs a forward pass, so — like generate — it must run inside
with_job_que(); model code outside one panics.
8.7.9.2. Semantic ranking
Retrieval in miniature: embed a handful of candidate sentences, score each against the query by cosine similarity, and sort. The on-topic answers float to the top and the unrelated ones sink; the model scores by meaning, so the concept sentence (“Quicksort and merge sort …”) ranks high without sharing the query’s words.
var scored : array<tuple<float; string>>
for (c in candidates) {
let cv <- embed(m, c)
scored |> push((cosine(qv, cv), c))
}
sort(scored) $(a, b) => a._0 > b._0 // most similar first
Running it against SmolLM2-135M ranks the two sorting answers above the oven and cat sentences — the vectors group by meaning, not by shared tokens.
8.7.9.3. RAG-grade, and what that means
A decoder used as an embedder gives RAG-grade vectors: good enough to
retrieve the relevant passage from a corpus or rank candidates by meaning,
which is what retrieval-augmented generation needs. It is not a substitute
for a dedicated embedding model (BGE, E5, …) — those train with a contrastive
objective and score higher on similarity benchmarks. Reach for embed when
the model is already loaded and “close enough” retrieval is the job; reach for
a real embedder when embedding quality is the product.
The same embed verb backs the server’s POST /v1/embeddings route, so an
OpenAI embeddings client talks to a loaded chat model unchanged.
See also
Full source: tutorials/dasLLAMA/09_embeddings.das
Previous tutorial: dasLLAMA-08 — Audio Chat
The embeddings server route: dasllama-server — an OpenAI-compatible server over dasLLAMA (POST /v1/embeddings)