ReqLLM.Provider.DSL (ReqLLM v1.0.0-rc.8)
View SourceDomain-Specific Language for defining ReqLLM providers.
This macro simplifies provider creation by automatically handling:
- Plugin behaviour implementation
- Metadata loading from JSON files
- Provider registry registration
- Default configuration setup
Usage
defmodule MyProvider do
use ReqLLM.Provider.DSL,
id: :my_provider,
base_url: "https://api.example.com/v1",
metadata: "priv/models_dev/my_provider.json"
  def attach(request, model) do
    # Provider-specific request configuration
  end
  def parse(response, model) do
    # Provider-specific response parsing
  end
endOptions
- :id- Unique provider identifier (required atom)
- :base_url- Default API base URL (required string)
- :metadata- Path to JSON metadata file (optional string)
- :context_wrapper- Module name for context wrapper struct (optional atom)
- :response_wrapper- Module name for response wrapper struct (optional atom)
- :provider_schema- NimbleOptions schema defining supported options and defaults (optional keyword list)
Generated Code
The DSL automatically generates:
- Plugin Behaviour: use Req.Plugin
- Default Base URL: def default_base_url(), do: "https://api.example.com/v1"
- Registry Registration: Calls ReqLLM.Provider.Registry.register/3
- Metadata Loading: Loads and parses JSON metadata at compile time
Metadata Files
Metadata files should contain JSON with model information:
{
  "models": [
    {
      "id": "my-model-1",
      "context_length": 8192,
      "capabilities": ["text_generation"],
      "pricing": {
        "input": 0.001,
        "output": 0.002
      }
    }
  ],
  "capabilities": ["text_generation", "embeddings"],
  "documentation": "https://api.example.com/docs"
}Example Implementation
defmodule ReqLLM.Providers.Example do
use ReqLLM.Provider.DSL,
id: :example,
base_url: "https://api.example.com/v1",
metadata: "priv/models_dev/example.json",
context_wrapper: ReqLLM.Providers.Example.Context,
response_wrapper: ReqLLM.Providers.Example.Response,
provider_schema: [
  temperature: [type: :float, default: 0.7],
  max_tokens: [type: :pos_integer, default: 1024],
  stream: [type: :boolean, default: false],
  api_version: [type: :string, default: "2023-06-01"]
]
  def attach(request, %ReqLLM.Model{} = model) do
    api_key = ReqLLM.get_key(:example_api_key)
    request
    |> Req.Request.put_header("authorization", "Bearer #{api_key}")
    |> Req.Request.put_header("content-type", "application/json")
    |> Req.Request.put_base_url(default_base_url())
    |> Req.Request.put_body(%{
      model: model.model,
      messages: format_messages(model.context),
      temperature: model.temperature
    })
  end
  def parse(response, %ReqLLM.Model{} = model) do
    case response.body do
      %{"content" => content} ->
        {:ok, content}
      %{"error" => error} ->
        {:error, ReqLLM.Error.api_error(error)}
      _ ->
        {:error, ReqLLM.Error.parse_error("Invalid response format")}
    end
  end
  # Private helper functions...
endSummary
Functions
Sigil for defining lists of atoms from space-separated words.