ExAthena.Config (ExAthena v0.15.1)

Copy Markdown View Source

Resolves the provider and per-call options for an ExAthena request.

Resolution order (per key, highest to lowest priority):

  1. opts[:key] — per-call override always wins.
  2. For atom-named providers: Application.get_env(:ex_athena, provider)[:key] — provider-specific config.exs entry. For string-named providers: the matching JSON file loaded from ~/.config/ex_athena/providers/ by ExAthena.ProviderRegistry.
  3. Application.get_env(:ex_athena, :key) — top-level library config.
  4. Provider default (if the provider declares one).

Matches the stripity_stripe / ex_aws pattern: per-call overrides win, application config is the default, no global mutable state.

String provider names (e.g. provider: "my-groq") are resolved through ExAthena.ProviderRegistry, which loads *.json files from ~/.config/ex_athena/providers/ at application startup. See the Providers guide for the full JSON schema, security notes, and ready-to-copy examples.

Known providers

AtomModule
:ollamaExAthena.Providers.ReqLLM
:openai_compatibleExAthena.Providers.ReqLLM
:openaiExAthena.Providers.ReqLLM
:llamacppExAthena.Providers.ReqLLM
:claudeExAthena.Providers.ReqLLM
:anthropicExAthena.Providers.ReqLLM
:geminiExAthena.Providers.ReqLLM
:openrouterExAthena.Providers.ReqLLM
:req_llmExAthena.Providers.ReqLLM
:mockExAthena.Providers.Mock

You may also pass any module that implements ExAthena.Provider directly, or define custom providers by placing JSON files in ~/.config/ex_athena/providers/ (loaded at startup by ExAthena.ProviderRegistry).

Request queue

ExAthena.RequestQueue is an opt-in semaphore that caps concurrent in-flight requests per provider. Enable it with:

config :ex_athena, :request_queue, enabled: true

Per-provider depth limits can be set inside provider config blocks:

config :ex_athena, :ollama, request_queue: [max_depth: 3]

A global max_depth applies to all providers that don't have a per-provider override:

config :ex_athena, :request_queue, enabled: true, max_depth: 5

Built-in defaults (used when no application config is set):

ProviderDefault max_depth
:ollama2
:llamacpp1
:exo3
:openai, :anthropic, :claude, :gemini, :openrouter, :req_llm10
unknown10

Summary

Functions

Look up a single configuration value for provider_module with the tiered resolution order. opts wins, then provider-specific config, then top-level config, then the supplied default.

Return all known providers: built-in atoms plus any specs loaded by ExAthena.ProviderRegistry.

Pop :provider from opts and return {provider_module, remaining_opts}.

Resolve a provider atom (or module) to its implementing module.

Build the keyword list passed to a provider's query/2 / stream/3 callback.

Translate an ExAthena provider atom into the req_llm provider tag used in "tag:model-id" specs. Returns nil when the atom doesn't map to req_llm (e.g. :mock, or a user-supplied module).

Return true when the request queue feature is enabled via application config.

Return the maximum concurrent request depth for provider_atom.

Functions

get(provider_module, key, opts, default \\ nil)

@spec get(module(), atom(), keyword(), term()) :: term()

Look up a single configuration value for provider_module with the tiered resolution order. opts wins, then provider-specific config, then top-level config, then the supplied default.

The provider atom is derived from the module name: Providers.Ollama:ollama.

list_providers()

@spec list_providers() :: [
  %{
    name: String.t(),
    display_name: String.t(),
    module: module(),
    source: :builtin | :registry
  }
]

Return all known providers: built-in atoms plus any specs loaded by ExAthena.ProviderRegistry.

Each entry is a map with:

  • :name — string name of the provider
  • :module — the implementing module
  • :source:builtin or :registry

pop_provider!(opts)

@spec pop_provider!(keyword()) :: {module(), keyword()}

Pop :provider from opts and return {provider_module, remaining_opts}.

Raises ArgumentError if no provider is set in opts or in application env.

For registry-loaded providers the following spec fields are threaded into opts using Keyword.put_new/3 so per-call overrides always win:

  • :req_llm_provider_tag — from spec.req_llm_provider_tag
  • :base_url — from spec.base_url
  • :extra_headers — from spec.extra_headers (non-empty maps only)
  • :api_key — from spec.api_key, or resolved from spec.api_key_env

provider_module(mod)

@spec provider_module(atom() | module()) :: module()

Resolve a provider atom (or module) to its implementing module.

Resolution order:

  1. Built-in provider map (compile-time constant, fastest path).
  2. ExAthena.ProviderRegistry — for providers loaded from JSON config files.
  3. Module check — accepts any atom that is a loaded module implementing ExAthena.Provider.

provider_opts(provider_module, opts, provider_atom \\ nil)

@spec provider_opts(module(), keyword(), atom() | nil) :: keyword()

Build the keyword list passed to a provider's query/2 / stream/3 callback.

Flattens per-call overrides + application env for this provider into one keyword list. Providers use Keyword.get/3 on the result.

req_llm_provider_tag(atom)

@spec req_llm_provider_tag(atom() | module()) :: String.t() | nil

Translate an ExAthena provider atom into the req_llm provider tag used in "tag:model-id" specs. Returns nil when the atom doesn't map to req_llm (e.g. :mock, or a user-supplied module).

Resolution order: a registry-loaded JSON spec wins (its req_llm_provider_tag field), with the static built-in map as fallback when no spec is loaded for the atom or the spec's tag is unset. This matters when a JSON-defined provider's name collides with a built-in atom (e.g. :openrouter, which is also present in the built-in map for config.exs users) — the user's JSON file is authoritative.

request_queue_enabled?()

@spec request_queue_enabled?() :: boolean()

Return true when the request queue feature is enabled via application config.

Opt-in: defaults to false. Enable with:

config :ex_athena, :request_queue, enabled: true

request_queue_max_depth(provider_atom)

@spec request_queue_max_depth(atom()) :: pos_integer()

Return the maximum concurrent request depth for provider_atom.

Resolution order:

  1. config :ex_athena, provider_atom, request_queue: [max_depth: N]
  2. config :ex_athena, :request_queue, max_depth: N
  3. Built-in per-provider default (ollama: 2, llamacpp: 1, exo: 3, cloud: 10).
  4. 10 for unrecognised providers.