Model struct with Zoi schema validation.
Represents an LLM model with complete metadata including identity, provider, dates, limits, costs, pricing, modalities, capabilities, tags, lifecycle status, and aliases.
Lifecycle
Models have a lifecycle with three possible states: "active", "deprecated", and "retired".
The lifecycle is represented in two ways for flexibility and backward compatibility:
:deprecatedand:retired- Boolean flags for quick checks:lifecycle- Structured map with status, dates, and replacement info
These are automatically synchronized:
- If
lifecycle.statusis set, the boolean flags are derived from it - If only boolean flags are set,
lifecycle.statusis derived from them
Lifecycle Fields
lifecycle.status- One of"active","deprecated","retired"lifecycle.deprecated_at- ISO8601 date when deprecation occurred/will occurlifecycle.retires_at- ISO8601 date when retirement is plannedlifecycle.replacement- Suggested replacement model ID
Temporal Lifecycle
Use effective_status/2, deprecated?/2, and retired?/2 to get status
that respects deprecated_at and retires_at dates:
model = LLMDB.Model.new!(%{
id: "old-model",
provider: :openai,
lifecycle: %{status: "active", deprecated_at: "2025-01-01", retires_at: "2025-06-01"}
})
LLMDB.Model.effective_status(model, ~U[2025-03-01 00:00:00Z])
# => "deprecated"
LLMDB.Model.retired?(model, ~U[2025-07-01 00:00:00Z])
# => truePricing Fields
Models have two pricing-related fields:
:cost- Legacy simple pricing (per-million-token rates for input/output/cache/reasoning):pricing- Flexible component-based pricing with support for tokens, tools, images, storage
The :cost field is automatically converted to :pricing.components at load time
for backward compatibility. See LLMDB.Pricing and the Pricing and Billing guide.
Snapshot-loaded :extra metadata retains its JSON string keys. Treat that
field as provider-owned opaque data rather than a schema-keyed map.
Summary
Functions
Returns true if the model is deprecated or retired (effective status).
Returns the effective lifecycle status, considering dates, declared status, and boolean flags.
Formats a model as a spec string in the given format.
Returns the declared lifecycle status from the model's lifecycle field.
Creates a new Model struct from a map, validating with Zoi schema.
Creates a new Model struct from a map, raising on validation errors.
Returns true if the model is retired (effective status).
Returns the Zoi schema for Model
Formats a model as a spec string in the given format.
Types
@type t() :: %LLMDB.Model{ aliases: [binary()], base_url: nil | nil | binary(), capabilities: nil | nil | %{ :json => %{ optional(:native) => nil | boolean(), optional(:strict) => nil | boolean(), optional(:schema) => nil | boolean() }, :tools => %{ optional(:enabled) => nil | boolean(), optional(:strict) => nil | boolean(), optional(:parallel) => nil | boolean(), optional(:streaming) => nil | boolean(), optional(:forced_choice) => nil | boolean() }, :reasoning => %{ optional(:enabled) => nil | boolean(), optional(:effort) => nil | %{ optional(:default) => nil | binary(), values: [binary()], supported: boolean() }, optional(:thinking) => nil | %{ :types => [binary()], :supported => boolean(), optional(:default_type) => nil | binary(), optional(:disable_supported) => nil | boolean(), optional(:raw_output_supported) => nil | boolean(), optional(:summary_supported) => nil | boolean(), optional(:encrypted_supported) => nil | boolean() }, optional(:token_budget) => nil | integer() | %{ optional(:default) => nil | integer(), optional(:max) => nil | integer(), optional(:min) => nil | integer() } }, :streaming => %{ optional(:text) => nil | boolean(), optional(:tool_calls) => nil | boolean() }, :chat => boolean(), :embeddings => boolean() | %{ optional(:min_dimensions) => nil | integer(), optional(:max_dimensions) => nil | integer(), optional(:default_dimensions) => nil | integer() }, :rerank => boolean(), optional(:caching) => nil | %{optional(:type) => nil | binary()}, optional(:batch) => nil | %{features: [binary()], supported: boolean()}, optional(:citations) => nil | %{features: [binary()], supported: boolean()}, optional(:code_execution) => nil | %{features: [binary()], supported: boolean()}, optional(:context_management) => nil | %{features: [binary()], supported: boolean()} }, catalog_only: boolean(), cost: nil | nil | %{ optional(:input) => nil | number(), optional(:output) => nil | number(), optional(:request) => nil | number(), optional(:image) => nil | number(), optional(:cache_read) => nil | number(), optional(:cache_write) => nil | number(), optional(:training) => nil | number(), optional(:reasoning) => nil | number(), optional(:audio) => nil | number(), optional(:input_audio) => nil | number(), optional(:output_audio) => nil | number(), optional(:input_video) => nil | number(), optional(:output_video) => nil | number() }, deprecated: boolean(), doc_url: nil | nil | binary(), execution: nil | nil | %{ optional(:text) => nil | %{ optional(:path) => nil | binary(), optional(:family) => nil | binary(), :supported => boolean(), optional(:wire_protocol) => nil | binary(), optional(:transport) => nil | binary(), optional(:provider_model_id) => nil | binary(), optional(:base_url) => nil | binary() }, optional(:image) => nil | %{ optional(:path) => nil | binary(), optional(:family) => nil | binary(), :supported => boolean(), optional(:wire_protocol) => nil | binary(), optional(:transport) => nil | binary(), optional(:provider_model_id) => nil | binary(), optional(:base_url) => nil | binary() }, optional(:embed) => nil | %{ optional(:path) => nil | binary(), optional(:family) => nil | binary(), :supported => boolean(), optional(:wire_protocol) => nil | binary(), optional(:transport) => nil | binary(), optional(:provider_model_id) => nil | binary(), optional(:base_url) => nil | binary() }, optional(:object) => nil | %{ optional(:path) => nil | binary(), optional(:family) => nil | binary(), :supported => boolean(), optional(:wire_protocol) => nil | binary(), optional(:transport) => nil | binary(), optional(:provider_model_id) => nil | binary(), optional(:base_url) => nil | binary() }, optional(:transcription) => nil | %{ optional(:path) => nil | binary(), optional(:family) => nil | binary(), :supported => boolean(), optional(:wire_protocol) => nil | binary(), optional(:transport) => nil | binary(), optional(:provider_model_id) => nil | binary(), optional(:base_url) => nil | binary() }, optional(:speech) => nil | %{ optional(:path) => nil | binary(), optional(:family) => nil | binary(), :supported => boolean(), optional(:wire_protocol) => nil | binary(), optional(:transport) => nil | binary(), optional(:provider_model_id) => nil | binary(), optional(:base_url) => nil | binary() }, optional(:realtime) => nil | %{ optional(:path) => nil | binary(), optional(:family) => nil | binary(), :supported => boolean(), optional(:wire_protocol) => nil | binary(), optional(:transport) => nil | binary(), optional(:provider_model_id) => nil | binary(), optional(:base_url) => nil | binary() } }, extra: nil | nil | map(), family: nil | nil | binary(), id: binary(), knowledge: nil | nil | binary(), last_updated: nil | nil | binary(), lifecycle: nil | nil | %{ optional(:status) => nil | binary(), optional(:replacement) => nil | binary(), optional(:deprecated_at) => nil | binary(), optional(:retires_at) => nil | binary() }, limits: nil | nil | %{ optional(:input) => nil | integer(), optional(:output) => nil | integer(), optional(:context) => nil | integer() }, modalities: nil | nil | %{optional(:input) => nil | [atom()], optional(:output) => nil | [atom()]}, model: nil | nil | binary(), name: nil | nil | binary(), pricing: nil | nil | %{ :merge => binary(), optional(:currency) => nil | binary(), components: [ %{ :id => binary(), optional(:unit) => nil | binary(), optional(:mode) => nil | binary(), optional(:source) => nil | binary(), optional(:kind) => nil | binary(), optional(:tool) => nil | atom() | binary(), optional(:notes) => nil | binary(), optional(:per) => nil | integer(), optional(:rate) => nil | number(), optional(:meter) => nil | binary(), optional(:size_class) => nil | binary(), optional(:multiplier) => nil | number(), optional(:derives_from) => nil | binary(), optional(:applies_to) => nil | [binary()], optional(:applies_when) => nil | map(), optional(:excludes_when) => nil | map(), optional(:charge_scope) => nil | binary() } ] }, provider: atom(), provider_model_id: nil | nil | binary(), release_date: nil | nil | binary(), retired: boolean(), tags: nil | nil | [binary()] }
Functions
@spec deprecated?(t(), DateTime.t()) :: boolean()
Returns true if the model is deprecated or retired (effective status).
Considers declared status, date-based lifecycle transitions, and boolean flags.
Examples
iex> model = %LLMDB.Model{id: "gpt-4", provider: :openai, deprecated: true}
iex> LLMDB.Model.deprecated?(model)
true
@spec effective_status(t(), DateTime.t()) :: String.t()
Returns the effective lifecycle status, considering dates, declared status, and boolean flags.
This function determines status using this precedence:
- Declared
lifecycle.status(if it indicates an advanced stage) - Date-based auto-advancement (
deprecated_at,retires_at) - Boolean flags (
retired,deprecated) as fallback - Default:
"active"
Examples
iex> model = %LLMDB.Model{
...> id: "gpt-4",
...> provider: :openai,
...> lifecycle: %{status: "active", deprecated_at: "2025-01-01T00:00:00Z"}
...> }
iex> LLMDB.Model.effective_status(model, ~U[2025-06-01 00:00:00Z])
"deprecated"
Formats a model as a spec string in the given format.
Compatibility wrapper for spec/2.
Returns the declared lifecycle status from the model's lifecycle field.
Examples
iex> model = %LLMDB.Model{id: "gpt-4", provider: :openai, lifecycle: %{status: "deprecated"}}
iex> LLMDB.Model.lifecycle_status(model)
"deprecated"
iex> model = %LLMDB.Model{id: "gpt-4", provider: :openai}
iex> LLMDB.Model.lifecycle_status(model)
nil
Creates a new Model struct from a map, validating with Zoi schema.
Examples
iex> LLMDB.Model.new(%{id: "gpt-4", provider: :openai})
{:ok, %LLMDB.Model{id: "gpt-4", model: "gpt-4", provider: :openai}}
iex> LLMDB.Model.new(%{})
{:error, _validation_errors}
Creates a new Model struct from a map, raising on validation errors.
Examples
iex> LLMDB.Model.new!(%{id: "gpt-4", provider: :openai})
%LLMDB.Model{id: "gpt-4", model: "gpt-4", provider: :openai}
@spec retired?(t(), DateTime.t()) :: boolean()
Returns true if the model is retired (effective status).
Considers declared status, date-based lifecycle transitions, and boolean flags.
Examples
iex> model = %LLMDB.Model{id: "gpt-4", provider: :openai, retired: true}
iex> LLMDB.Model.retired?(model)
true
Returns the Zoi schema for Model
Formats a model as a spec string in the given format.
Delegates to LLMDB.Spec.format_spec/2 with the model's provider and ID.
If no format is specified, uses the application config :llm_db, :model_spec_format
(default: :provider_colon_model).
Parameters
model- The model structformat- Optional format override (:provider_colon_model,:model_at_provider,:filename_safe)
Examples
iex> model = %LLMDB.Model{provider: :openai, id: "gpt-4"}
iex> LLMDB.Model.spec(model)
"openai:gpt-4"
iex> LLMDB.Model.spec(model, :model_at_provider)
"gpt-4@openai"
iex> LLMDB.Model.spec(model, :filename_safe)
"gpt-4@openai"