A text-embedding response — Layer A serializable data.
iex> resp = ALLM.EmbeddingResponse.new(embeddings: [ALLM.Embedding.new(vector: [0.1, 0.2])])
iex> ALLM.EmbeddingResponse.vectors(resp)
[[0.1, 0.2]]Invariants
- Order correspondence —
Enum.at(vectors(response), i)is the embedding ofEnum.at(request.input, i)for everyi. Preserved across chunk merges by index rebasing and byvectors/1's sort. - Uniform dimensionality — every vector in
:embeddingshas the same length. Asserted by the adapter conformance suite, not enforced by the constructor. - Cardinality —
length(response.embeddings) == length(request.input)on success.
Usage
:usage is an ALLM.Usage.t/0 and is never nil; a response that
carries no counters holds %ALLM.Usage{} with every field nil.
Embeddings bill in tokens, so adapters populate :input_tokens and
:total_tokens; :output_tokens is always nil. Providers that report
only one of the two counters leave the other nil rather than
synthesizing a value.
:raw carries the same caller-responsibility contract as
ALLM.Response.raw: a non-JSON-encodable :raw raises at encode time.
Summary
Functions
Length of the first vector, or nil when :embeddings is empty. Use to
size a vector(N) column.
Build an %EmbeddingResponse{} from keyword opts.
Vectors sorted by :index, flattened for direct insertion into a
vector(N) column.
Types
@type t() :: %ALLM.EmbeddingResponse{ embeddings: [ALLM.Embedding.t()], id: String.t() | nil, metadata: map(), model: String.t() | nil, raw: term(), request_id: String.t() | nil, usage: ALLM.Usage.t() }
Functions
@spec dimensions(t()) :: non_neg_integer() | nil
Length of the first vector, or nil when :embeddings is empty. Use to
size a vector(N) column.
"First" means first in list order, not lowest :index — unlike
vectors/1, this function does not sort. The two agree only under the
uniform-dimensionality invariant above, which is asserted by the adapter
conformance suite rather than by this struct.
The return is non_neg_integer/0, not pos_integer/0: a caller can
hand-build %ALLM.Embedding{vector: []}, and this function then returns
0. Adapters cannot — one that would build an empty vector from a
provider response returns
%ALLM.Error.EmbeddingAdapterError{reason: :malformed_response} instead —
so 0 is reachable only through direct struct construction, never from a
provider round-trip.
Examples
iex> resp = ALLM.EmbeddingResponse.new(embeddings: [ALLM.Embedding.new(vector: [1.0, 2.0])])
iex> ALLM.EmbeddingResponse.dimensions(resp)
2
iex> ALLM.EmbeddingResponse.dimensions(ALLM.EmbeddingResponse.new())
nil
Build an %EmbeddingResponse{} from keyword opts.
Unknown keys raise KeyError via struct!/2.
Examples
iex> resp = ALLM.EmbeddingResponse.new(model: "text-embedding-3-small")
iex> resp.embeddings
[]
iex> resp.usage
%ALLM.Usage{}
Vectors sorted by :index, flattened for direct insertion into a
vector(N) column.
Sorting is what guarantees the order-correspondence invariant even when a provider returns items out of order or a chunk merge interleaves them.
Examples
iex> resp = ALLM.EmbeddingResponse.new(embeddings: [
...> ALLM.Embedding.new(vector: [1.0], index: 1),
...> ALLM.Embedding.new(vector: [0.0], index: 0)
...> ])
iex> ALLM.EmbeddingResponse.vectors(resp)
[[0.0], [1.0]]
iex> ALLM.EmbeddingResponse.vectors(ALLM.EmbeddingResponse.new())
[]