LLMDB.Spec (LLM DB v2025.12.4)
View SourceCanonical "provider:model" spec parsing and resolution.
This module provides functions to parse and resolve model specifications in various formats, including "provider:model" strings, "model@provider" strings (filename-safe), tuples, and bare model IDs with provider scope.
String Formats
Two string formats are supported:
"provider:model"- Traditional colon separator (default)"model@provider"- Email-like format, filesystem-safe for filenames
Both formats parse to the same internal representation and can be used interchangeably. The @ format is recommended when model specs are used in filenames, CI artifact names, or other filesystem contexts.
Amazon Bedrock Inference Profiles
For Amazon Bedrock models, inference profile IDs with region prefixes (us., eu., ap., ca., global.) are supported. The region prefix is stripped for catalog lookup but preserved in the returned model ID. For example:
iex> LLMDB.Spec.resolve("bedrock:us.anthropic.claude-opus-4-1-20250805-v1:0")
{:ok, {:bedrock, "us.anthropic.claude-opus-4-1-20250805-v1:0", %LLMDB.Model{}}}The lookup uses "anthropic.claude-opus-4-1-20250805-v1:0" to find metadata, but the returned model ID retains the "us." prefix for API routing purposes.
Summary
Functions
Builds a model specification string from various inputs.
Formats a model specification as a string.
Normalizes a model specification to tuple format.
Parses and validates a provider identifier.
Parses a model specification string in either "provider:model" or "model@provider" format.
Parses a model specification string, raising on error.
Resolves a model specification to a canonical model record.
Functions
Builds a model specification string from various inputs.
Accepts strings (in any supported format) or tuples and outputs a string in the desired format.
Parameters
input- Model spec as string or tupleopts- Keyword list with optional:formatfor output format
Examples
iex> LLMDB.Spec.build_spec("openai:gpt-4", format: :filename_safe)
"gpt-4@openai"
iex> LLMDB.Spec.build_spec({:openai, "gpt-4"}, format: :model_at_provider)
"gpt-4@openai"
Formats a model specification as a string.
Converts a {provider, model_id} tuple to string format. The output format can be
controlled via the format parameter or falls back to the application config
:llm_db, :model_spec_format (default: :provider_colon_model).
Parameters
spec- {provider_atom, model_id} tupleformat- Optional format override (atom)
Supported Formats
:provider_colon_model- "provider:model" (default):model_at_provider- "model@provider" (filename-safe):filename_safe- alias for:model_at_provider
Examples
iex> LLMDB.Spec.format_spec({:openai, "gpt-4"})
"openai:gpt-4"
iex> LLMDB.Spec.format_spec({:openai, "gpt-4"}, :model_at_provider)
"gpt-4@openai"
iex> LLMDB.Spec.format_spec({:openai, "gpt-4o-mini"}, :filename_safe)
"gpt-4o-mini@openai"
Normalizes a model specification to tuple format.
Accepts either a string (in any supported format) or a tuple and returns a normalized {provider, model_id} tuple.
Examples
iex> LLMDB.Spec.normalize_spec("openai:gpt-4")
{:openai, "gpt-4"}
iex> LLMDB.Spec.normalize_spec("gpt-4@openai")
{:openai, "gpt-4"}
iex> LLMDB.Spec.normalize_spec({:openai, "gpt-4"})
{:openai, "gpt-4"}
@spec parse_provider(atom() | binary()) :: {:ok, atom()} | {:error, :unknown_provider | :bad_provider}
Parses and validates a provider identifier.
Accepts atom or binary input, normalizes to atom, and verifies the provider exists in the current catalog.
Parameters
input- Provider identifier as atom or binary
Returns
{:ok, atom}- Normalized provider atom if valid and exists in catalog{:error, :unknown_provider}- Provider not found in catalog{:error, :bad_provider}- Invalid provider format
Examples
iex> LLMDB.Spec.parse_provider(:openai)
{:ok, :openai}
iex> LLMDB.Spec.parse_provider("google-vertex")
{:ok, :google_vertex}
iex> LLMDB.Spec.parse_provider("nonexistent")
{:error, :unknown_provider}
@spec parse_spec( String.t() | {atom(), String.t()}, keyword() ) :: {:ok, {atom(), String.t()}} | {:error, :invalid_format | :ambiguous_format | :unknown_provider | :bad_provider | :invalid_chars | :empty_segment}
Parses a model specification string in either "provider:model" or "model@provider" format.
Automatically detects the format based on separators present. Validates the provider exists in the catalog and checks for reserved characters in segments.
Parameters
spec- String in "provider:model" or "model@provider" format, or {provider, model_id} tupleopts- Keyword list with optional:formatto explicitly specify format
Options
:format- Explicitly specify the format as:colonor:at. Required when both separators present.
Returns
{:ok, {provider_atom, model_id}}- Parsed and normalized spec{:error, :invalid_format}- No valid separator found{:error, :ambiguous_format}- Both separators present without explicit format{:error, :unknown_provider}- Provider not found in catalog{:error, :bad_provider}- Invalid provider format{:error, :invalid_chars}- Reserved characters in provider or model segments{:error, :empty_segment}- Provider or model segment is empty
Examples
iex> LLMDB.Spec.parse_spec("openai:gpt-4")
{:ok, {:openai, "gpt-4"}}
iex> LLMDB.Spec.parse_spec("gpt-4@openai")
{:ok, {:openai, "gpt-4"}}
iex> LLMDB.Spec.parse_spec("google-vertex:gemini-pro")
{:ok, {:google_vertex, "gemini-pro"}}
iex> LLMDB.Spec.parse_spec("provider:model@ambiguous", format: :colon)
{:ok, {:provider, "model@ambiguous"}}
iex> LLMDB.Spec.parse_spec("gpt-4")
{:error, :invalid_format}
Parses a model specification string, raising on error.
Same as parse_spec/2 but raises ArgumentError instead of returning error tuple.
Examples
iex> LLMDB.Spec.parse_spec!("openai:gpt-4")
{:openai, "gpt-4"}
iex> LLMDB.Spec.parse_spec!("gpt-4@openai")
{:openai, "gpt-4"}
@spec resolve( String.t() | {atom(), String.t()}, keyword() ) :: {:ok, {atom(), String.t(), LLMDB.Model.t()}} | {:error, term()}
Resolves a model specification to a canonical model record.
Accepts multiple input formats:
- "provider:model" string
- {provider, model_id} tuple
- Bare "model" string with opts[:scope] = provider_atom
Handles alias resolution and validates the model exists in the catalog.
Parameters
input- Model specification in one of the supported formatsopts- Keyword list with optional:scopefor bare model resolution
Returns
{:ok, {provider, canonical_id, Model.t()}}- Resolved model{:error, :not_found}- Model doesn't exist{:error, :ambiguous}- Bare model ID exists under multiple providers without scope{:error, :invalid_format}- Malformed input{:error, term}- Other parsing errors
Examples
iex> LLMDB.Spec.resolve("openai:gpt-4")
{:ok, {:openai, "gpt-4", %LLMDB.Model{}}}
iex> LLMDB.Spec.resolve({:openai, "gpt-4"})
{:ok, {:openai, "gpt-4", %LLMDB.Model{}}}
iex> LLMDB.Spec.resolve("gpt-4", scope: :openai)
{:ok, {:openai, "gpt-4", %LLMDB.Model{}}}
iex> LLMDB.Spec.resolve("gpt-4")
{:error, :ambiguous}