ReqLLM.Provider.Registry (ReqLLM v1.0.0)

View Source

Registry for AI providers and their supported models.

The registry uses :persistent_term for efficient, read-heavy access patterns typical in AI applications. Providers are registered at compile time through the DSL, ensuring all available providers and models are known at startup.

Storage Format

The registry stores providers as:

%{
  provider_id => %{
    module: Module,
    metadata: %{models: [...], capabilities: [...], ...}
  }
}

Usage Examples

# Get a provider module
{:ok, module} = ReqLLM.Provider.Registry.get_provider(:anthropic)
module #=> ReqLLM.Providers.Anthropic

# Get model information
{:ok, model} = ReqLLM.Provider.Registry.get_model(:anthropic, "claude-3-sonnet")
model.metadata.context_length #=> 200000

# Check if a model exists
ReqLLM.Provider.Registry.model_exists?("anthropic:claude-3-sonnet") #=> true

# List all providers
ReqLLM.Provider.Registry.list_providers() #=> [:anthropic, :openai, :github_models]

# List models for a provider
ReqLLM.Provider.Registry.list_models(:anthropic) #=> ["claude-3-sonnet", "claude-3-haiku", ...]

Integration

The registry is automatically populated by providers using ReqLLM.Provider.DSL:

defmodule MyProvider do
  use ReqLLM.Provider.DSL,
    id: :my_provider,
    base_url: "https://api.example.com/v1",
    metadata: "priv/models_dev/my_provider.json"

  # Provider implementation...
end

The DSL calls register/3 during compilation to add the provider to the registry.

Summary

Functions

Clears the provider registry.

Alias for get_provider/1 to match legacy API expectations.

Gets the environment variable key for a provider's API authentication.

Retrieves model information for a specific provider and model.

Retrieves model information with bang syntax (raises on error).

Retrieves a provider module by ID.

Retrieves complete provider metadata by ID.

Checks if a provider is fully implemented.

Initializes the provider registry by discovering and registering all provider modules.

Initializes the provider registry from an effective catalog map.

Lists only fully implemented providers (have modules).

Lists providers that exist only as metadata (no implementation).

Lists all model names supported by a provider.

Lists all registered provider IDs.

Checks if a model specification exists in the registry.

Registers a provider in the global registry.

Functions

clear()

@spec clear() :: :ok

Clears the provider registry.

Mainly useful for testing.

fetch(provider_id)

Alias for get_provider/1 to match legacy API expectations.

get_env_key(provider_id)

@spec get_env_key(atom()) :: String.t() | nil

Gets the environment variable key for a provider's API authentication.

Tries to get the key from provider metadata first, then falls back to the provider's default_env_key/0 callback if implemented.

Parameters

  • provider_id - Provider atom identifier (e.g., :anthropic)

Returns

The environment variable name string, or nil if not found.

Examples

iex> ReqLLM.Provider.Registry.get_env_key(:anthropic)
"ANTHROPIC_API_KEY"

iex> ReqLLM.Provider.Registry.get_env_key(:unknown)
nil

get_model(provider_id, model_name)

@spec get_model(atom(), String.t()) ::
  {:ok, ReqLLM.Model.t()} | {:error, :provider_not_found | :model_not_found}

Retrieves model information for a specific provider and model.

Parameters

  • provider_id - The provider identifier (atom)
  • model_name - The model name (string)

Returns

  • {:ok, model} - ReqLLM.Model struct with metadata
  • {:error, :provider_not_found} - Provider not registered
  • {:error, :model_not_found} - Model not supported by provider

Examples

{:ok, model} = ReqLLM.Provider.Registry.get_model(:anthropic, "claude-3-sonnet")
model.metadata.context_length #=> 200000
model.metadata.pricing.input  #=> 0.003

ReqLLM.Provider.Registry.get_model(:anthropic, "unknown-model")
#=> {:error, :model_not_found}

get_model!(model_spec)

@spec get_model!(String.t()) :: ReqLLM.Model.t() | no_return()

Retrieves model information with bang syntax (raises on error).

Same as get_model/2 but raises ArgumentError instead of returning error tuples.

Parameters

  • model_spec - Model specification string (e.g., "anthropic:claude-3-sonnet")

Examples

model = ReqLLM.Provider.Registry.get_model!("anthropic:claude-3-sonnet")
model.metadata.context_length #=> 200000

ReqLLM.Provider.Registry.get_model!("unknown:model")
#=> ** (ArgumentError) Provider not found: unknown

get_provider(provider_id)

Retrieves a provider module by ID.

Parameters

  • provider_id - The provider identifier (atom)

Returns

  • {:ok, module} - Provider module found
  • {:error, %ReqLLM.Error.Invalid.Provider{}} - Provider not registered
  • {:error, %ReqLLM.Error.Invalid.Provider.NotImplemented{}} - Provider exists but has no implementation (metadata-only)

Examples

{:ok, module} = ReqLLM.Provider.Registry.get_provider(:anthropic)
module #=> ReqLLM.Providers.Anthropic

ReqLLM.Provider.Registry.get_provider(:unknown)
#=> {:error, %ReqLLM.Error.Invalid.Provider{provider: :unknown}}

get_provider_metadata(provider_id)

@spec get_provider_metadata(atom()) :: {:ok, map()} | {:error, :provider_not_found}

Retrieves complete provider metadata by ID.

Parameters

  • provider_id - The provider identifier (atom)

Returns

  • {:ok, metadata} - Provider metadata map
  • {:error, :not_found} - Provider not registered

Examples

{:ok, metadata} = ReqLLM.Provider.Registry.get_provider_metadata(:anthropic)
env_vars = get_in(metadata, ["provider", "env"])
env_vars #=> ["ANTHROPIC_API_KEY"]

implemented?(provider_id)

@spec implemented?(atom()) :: boolean()

Checks if a provider is fully implemented.

Parameters

  • provider_id - The provider identifier (atom)

Returns

  • true - Provider has both module and metadata
  • false - Provider is metadata-only or doesn't exist

Examples

ReqLLM.Provider.Registry.implemented?(:anthropic)
#=> true

ReqLLM.Provider.Registry.implemented?(:mistral)
#=> false (metadata-only)

initialize()

@spec initialize() :: :ok

Initializes the provider registry by discovering and registering all provider modules.

This function scans for modules that implement the ReqLLM.Provider behaviour and registers them automatically.

initialize(effective_catalog)

@spec initialize(map()) :: :ok

Initializes the provider registry from an effective catalog map.

This function accepts a catalog in the format produced by ReqLLM.Catalog.load/1:

%{
  provider_id_string => %{
    "id" => provider_id,
    "models" => %{model_id => model_map, ...},
    ...other provider metadata...
  }
}

For each provider in the catalog:

  1. Checks if a DSL module already registered it (via discover_providers/0)
  2. Converts provider ID string to atom
  3. Builds registry entry with module (if found) and metadata from catalog
  4. Stores the complete registry in :persistent_term

This enables the registry to work with both:

  • Implemented providers (have modules)
  • Metadata-only providers (from catalog only)

Parameters

  • effective_catalog - Map of provider_id (string) => provider metadata

Returns

  • :ok - Registry successfully initialized

Examples

catalog = %{
  "anthropic" => %{
    "id" => "anthropic",
    "models" => %{"claude-3-sonnet" => %{"id" => "claude-3-sonnet", ...}}
  }
}

ReqLLM.Provider.Registry.initialize(catalog)
#=> :ok

list_implemented_providers()

@spec list_implemented_providers() :: [atom()]

Lists only fully implemented providers (have modules).

Returns

List of provider atoms that can actually make API calls.

Examples

ReqLLM.Provider.Registry.list_implemented_providers()
#=> [:anthropic, :openai]

list_metadata_only_providers()

@spec list_metadata_only_providers() :: [atom()]

Lists providers that exist only as metadata (no implementation).

Returns

List of provider atoms that have metadata but no implementation.

Examples

ReqLLM.Provider.Registry.list_metadata_only_providers()
#=> [:mistral, :openrouter, :groq]

list_models(provider_id)

@spec list_models(atom()) :: {:ok, [String.t()]} | {:error, :provider_not_found}

Lists all model names supported by a provider.

Parameters

  • provider_id - The provider identifier (atom)

Returns

  • {:ok, models} - List of model name strings
  • {:error, :not_found} - Provider not registered

Examples

{:ok, models} = ReqLLM.Provider.Registry.list_models(:anthropic)
models #=> ["claude-3-sonnet", "claude-3-haiku", "claude-3-opus"]

ReqLLM.Provider.Registry.list_models(:unknown)
#=> {:error, :not_found}

list_providers()

@spec list_providers() :: [atom()]

Lists all registered provider IDs.

Returns

List of provider atoms in registration order.

Examples

ReqLLM.Provider.Registry.list_providers()
#=> [:anthropic, :openai, :github_models]

model_exists?(model_spec)

@spec model_exists?(String.t()) :: boolean()

Checks if a model specification exists in the registry.

Parameters

  • model_spec - Model specification string (e.g., "anthropic:claude-3-sonnet")

Returns

Boolean indicating if the model exists.

Examples

ReqLLM.Provider.Registry.model_exists?("anthropic:claude-3-sonnet") #=> true
ReqLLM.Provider.Registry.model_exists?("unknown:model") #=> false

register(provider_id, module, metadata)

@spec register(atom(), module(), map()) ::
  :ok | {:error, {:already_registered, module()} | {:validation_error, term()}}

Registers a provider in the global registry.

Called automatically by the DSL during compilation. Should not be called manually.

Parameters

  • provider_id - Unique identifier for the provider (atom)
  • module - The provider module implementing Req plugin pattern
  • metadata - Provider metadata including supported models

Examples

ReqLLM.Provider.Registry.register(:my_provider, MyProvider, %{
  models: ["model-1", "model-2"],
  capabilities: [:text_generation, :embeddings]
})

reload()

@spec reload() :: :ok