ExOutlines — Deterministic structured output from LLMs.
Main entry point for generating constrained outputs using retry-repair loops.
Summary
Functions
Generate structured output conforming to a spec.
Generate structured outputs for multiple specs concurrently.
Types
@type batch_opts() :: [ max_concurrency: pos_integer(), timeout: pos_integer(), on_timeout: :kill_task | :continue, ordered: boolean(), telemetry_metadata: map() ]
@type batch_result() :: [generate_result()]
@type generate_opts() :: [ backend: module(), backend_opts: keyword(), max_retries: pos_integer(), telemetry_metadata: map() ]
Functions
@spec generate(ExOutlines.Spec.t(), generate_opts()) :: generate_result()
Generate structured output conforming to a spec.
Options
:backend- Backend module implementingExOutlines.Backend:backend_opts- Options passed to backend (model, temperature, etc.):max_retries- Maximum retry attempts (default: 3):telemetry_metadata- Additional telemetry context
Returns
{:ok, result}- Successfully generated and validated output{:error, :max_retries_exceeded}- Exhausted all retry attempts{:error, {:backend_error, reason}}- Backend communication failure{:error, {:backend_exception, error}}- Backend raised an exception{:error, :no_backend}- No backend specified{:error, {:invalid_backend, value}}- Backend is not an atom
@spec generate_batch([{ExOutlines.Spec.t(), generate_opts()}], batch_opts()) :: batch_result()
Generate structured outputs for multiple specs concurrently.
Leverages BEAM's concurrency model to process multiple generation requests in parallel. Each task is independent and runs in its own process.
Options
:max_concurrency- Maximum concurrent tasks (default: System.schedulers_online()):timeout- Timeout per task in milliseconds (default: 60_000):on_timeout- How to handle timeouts::kill_taskor:continue(default: :kill_task):ordered- Return results in input order (default: true):telemetry_metadata- Additional telemetry context
Returns
List of results in the same order as input (if ordered: true). Each result is:
{:ok, result}- Successfully generated and validated output{:error, reason}- Task failed (timeout, validation, backend error, etc.)
Examples
# Process multiple schemas concurrently
tasks = [
{user_schema, [backend: HTTP, backend_opts: [...]]},
{product_schema, [backend: HTTP, backend_opts: [...]]},
{order_schema, [backend: HTTP, backend_opts: [...]]}
]
results = ExOutlines.generate_batch(tasks, max_concurrency: 3)
# Results match input order
[user_result, product_result, order_result] = results
# Handle mixed results
Enum.each(results, fn
{:ok, data} -> IO.inspect(data, label: "Success")
{:error, reason} -> IO.inspect(reason, label: "Error")
end)