ReqLLM.Provider.DSL (ReqLLM v1.0.0-rc.8)

View Source

Domain-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
end

Options

  • :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:

  1. Plugin Behaviour: use Req.Plugin
  2. Default Base URL: def default_base_url(), do: "https://api.example.com/v1"
  3. Registry Registration: Calls ReqLLM.Provider.Registry.register/3
  4. 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...
end

Summary

Functions

Sigil for defining lists of atoms from space-separated words.

Functions

__using__(opts)

(macro)

Sigil for defining lists of atoms from space-separated words.

Examples

~a[temperature max_tokens top_p]  # => [:temperature, :max_tokens, :top_p]