ReqLLM.Provider.Utils (ReqLLM v1.14.0)

View Source

Shared utilities for provider implementations.

Contains common functions used across multiple providers to eliminate duplication and ensure consistency.

Examples

iex> ReqLLM.Provider.Utils.normalize_messages("Hello world")
[%{role: "user", content: "Hello world"}]

iex> messages = [%{role: "user", content: "Hi"}]
iex> ReqLLM.Provider.Utils.normalize_messages(messages)
[%{role: "user", content: "Hi"}]

Summary

Functions

Ensures the response body is parsed from JSON if it's binary.

Extracts custom headers from req_http_options for use in streaming requests.

Conditionally puts a value into a keyword list or map if the value is not nil.

Conditionally adds a key-value pair to opts, skipping if value is nil or in skip_values list.

Sanitizes a URL by redacting sensitive query parameters.

Converts atom keys in a map to string keys.

Recursively converts map keys to strings.

Functions

ensure_parsed_body(body)

@spec ensure_parsed_body(term()) :: term()

Ensures the response body is parsed from JSON if it's binary.

Common utility for providers to ensure they have parsed JSON data instead of raw binary response bodies.

Parameters

  • body - Response body that may be binary JSON or already parsed

Returns

Parsed body (map/list) or original body if parsing fails.

Examples

iex> ReqLLM.Provider.Utils.ensure_parsed_body(~s({"message": "hello"}))
%{"message" => "hello"}

iex> ReqLLM.Provider.Utils.ensure_parsed_body(%{"already" => "parsed"})
%{"already" => "parsed"}

iex> ReqLLM.Provider.Utils.ensure_parsed_body("invalid json")
"invalid json"

extract_custom_headers(req_http_options)

@spec extract_custom_headers(keyword() | map() | nil) :: [{binary(), binary()}]

Extracts custom headers from req_http_options for use in streaming requests.

The req_http_options keyword list may contain a :headers key with a list of header tuples. This function extracts those headers for use when building Finch requests for streaming.

Parameters

  • req_http_options - Keyword list of HTTP options (may contain :headers)

Returns

List of header tuples {name, value} to be added to the request.

Examples

iex> ReqLLM.Provider.Utils.extract_custom_headers([])
[]

iex> ReqLLM.Provider.Utils.extract_custom_headers(headers: [{"X-Custom", "value"}])
[{"X-Custom", "value"}]

iex> ReqLLM.Provider.Utils.extract_custom_headers(headers: [{"X-Custom", "value"}], timeout: 5000)
[{"X-Custom", "value"}]

maybe_put(opts, key, value)

@spec maybe_put(keyword() | map(), atom(), term()) :: keyword() | map()

Conditionally puts a value into a keyword list or map if the value is not nil.

Parameters

  • opts - Keyword list or map to potentially modify
  • key - Key to add
  • value - Value to add (if not nil)

Returns

The keyword list or map, with key-value pair added if value is not nil.

Examples

iex> ReqLLM.Provider.Utils.maybe_put([], :name, "John")
[name: "John"]

iex> ReqLLM.Provider.Utils.maybe_put(%{}, :name, "John")
%{name: "John"}

iex> ReqLLM.Provider.Utils.maybe_put([], :name, nil)
[]

iex> ReqLLM.Provider.Utils.maybe_put(%{}, :name, nil)
%{}

maybe_put_skip(opts, key, value, skip_values)

@spec maybe_put_skip(keyword() | map(), atom(), term(), list()) :: keyword() | map()

Conditionally adds a key-value pair to opts, skipping if value is nil or in skip_values list.

This is useful for providers that need to omit certain default values from API requests.

Parameters

  • opts - Options map or keyword list to update
  • key - Key to add
  • value - Value to add (will be skipped if nil or in skip_values)
  • skip_values - List of values to skip (defaults to [])

Examples

iex> ReqLLM.Provider.Utils.maybe_put_skip(%{}, :service_tier, "auto", ["auto"])
%{}

iex> ReqLLM.Provider.Utils.maybe_put_skip(%{}, :service_tier, "performance", ["auto"])
%{service_tier: "performance"}

iex> ReqLLM.Provider.Utils.maybe_put_skip(%{}, :key, nil, [])
%{}

sanitize_url(url)

@spec sanitize_url(binary()) :: binary()

Sanitizes a URL by redacting sensitive query parameters.

This prevents API keys and tokens from being leaked in logs or error messages. Redacts common sensitive parameter names: key, api_key, apikey, access_token, token.

Parameters

  • url - URL string that may contain sensitive query parameters

Returns

URL string with sensitive parameters redacted as [REDACTED].

Examples

iex> ReqLLM.Provider.Utils.sanitize_url("https://api.example.com/v1?key=secret123&alt=sse")
"https://api.example.com/v1?key=[REDACTED]&alt=sse"

iex> ReqLLM.Provider.Utils.sanitize_url("https://api.example.com/v1")
"https://api.example.com/v1"

iex> ReqLLM.Provider.Utils.sanitize_url("https://api.example.com/v1?api_key=abc&format=json")
"https://api.example.com/v1?api_key=[REDACTED]&format=json"

stringify_keys(map)

@spec stringify_keys(map()) :: map()

Converts atom keys in a map to string keys.

Useful for normalizing maps that may have atom or string keys to ensure consistent access patterns. Only converts top-level keys.

Parameters

  • map - Map with atom and/or string keys

Returns

Map with all keys as strings.

Examples

iex> ReqLLM.Provider.Utils.stringify_keys(%{foo: "bar", "baz" => "qux"})
%{"foo" => "bar", "baz" => "qux"}

iex> ReqLLM.Provider.Utils.stringify_keys(%{"already" => "strings"})
%{"already" => "strings"}

stringify_keys_deep(struct)

@spec stringify_keys_deep(term()) :: term()

Recursively converts map keys to strings.