Normandy.LLM.OpenAICompatibleAdapter
(normandy v2.2.0)
View Source
Adapter implementing Normandy.Agents.Model against any OpenAI-compatible
Chat Completions endpoint (OpenAI, DigitalOcean Inference, etc.).
Text-completion only (v1): tool/function calling is not supported and a
non-empty request.tools raises. An answer is parsed once with
Normandy.LLM.JsonDeserializer.parse_and_validate/3 and the :on_parse_failure policy
applies; an answer that does not parse is not re-asked (Normandy.LLM.ClaudioAdapter
re-asks). An answer that parses but breaks a schema constraint is re-asked by BaseAgent
on any client, under enable_json_retry and json_retry_max_attempts.
client = %Normandy.LLM.OpenAICompatibleAdapter{
api_key: System.get_env("OPENAI_API_KEY"),
base_url: "https://api.openai.com/v1"
}Options
The adapter reads these keys from options (a map):
:timeout- how long to wait for the response, in milliseconds (default: 120_000):req_options- Req options merged into the request (see "Transport injection"):max_tokens_param- which body key carries the request'smax_tokens::max_tokens(the default),:max_completion_tokens(OpenAI reasoning models), or:omit(send neither; the server's own limit applies). Any other value raisesArgumentErrorwhen the agent is built (BaseAgent.init/1)
Transport injection (testing)
options[:req_options] is merged into the Req request, so tests can route
the HTTP layer to a Req.Test stub without network access (this needs
:plug in your test dependencies):
Req.Test.stub(MyStub, fn conn ->
Req.Test.json(conn, %{"choices" => [%{"message" => %{"content" => "hi"}}]})
end)
client = %Normandy.LLM.OpenAICompatibleAdapter{
api_key: "test",
options: %{req_options: [plug: {Req.Test, MyStub}]}
}Errors
converse/3 returns {:ok, %Normandy.LLM.Response{}}, or
{:error, %Normandy.LLMError{}} on non-2xx responses or transport failures,
classified as follows:
- 429 →
:rate_limit, retryable - 408, 5xx →
:server, retryable - 401 →
:authentication, not retryable - 403 →
:permission, not retryable - 404 →
:not_found, not retryable - Other 4xx →
:invalid_request, not retryable - Other status →
:unknown, not retryable Req.TransportError,Mint.TransportError,Mint.HTTPError→:transport, retryable- Anything else → wrapped via
LLMError.wrap/1
stream/3 returns {:error, %Normandy.LLMError{type: :unsupported}}: this adapter
does not stream.
Summary
Functions
Checks client.options once, up front; BaseAgent.init/1 calls it. Raises
ArgumentError for an unknown :max_tokens_param.
Types
Functions
Checks client.options once, up front; BaseAgent.init/1 calls it. Raises
ArgumentError for an unknown :max_tokens_param.