ReqLLM.Provider.DSL (ReqLLM v1.0.0)
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...
end
Summary
Functions
Sigil for defining lists of atoms from space-separated words.