SystemOneClient.Wire.OpenAIDecisions (SystemOneClient v0.3.0)

Copy Markdown View Source

Translation between the System One wire format and OpenAI's Decisions API (POST /v1/decisions).

Callers keep writing System One questions (a map of id to noul / choice / score) and get System One answers back; this module maps both directions:

System OneOpenAI Decisions
state (any JSON)input (text; non-string state is JSON-encoded)
images: optiona user message with input_image parts, then the state as input_text
%{id => question}[%{name: id, ...}]
noul with optional true / false criteriapredicate, with the criteria folded into instructions
choice criteria: %{value => description}choices: [%{value, description}]
score criteria: [description]levels: [%{label: "Level N", description}]
answers keyed by id, probabilities as mapsanswers array keyed by name, probabilities as arrays
nonerefusal, decoded to %{"type" => "refusal"}

Non-string instructions and descriptions (System One allows objects and arrays) are JSON-encoded, since OpenAI expects text.

Summary

Functions

Converts a /v1/decisions response into the System One shape: %{"answers" => %{id => raw_answer}, "model" => _, "usage" => _}, ready for SystemOneClient.Answer.parse_all/1.

Builds the /v1/decisions request body.

Functions

decode_response(body, questions \\ %{})

@spec decode_response(map(), map()) :: {:ok, map()} | {:error, term()}

Converts a /v1/decisions response into the System One shape: %{"answers" => %{id => raw_answer}, "model" => _, "usage" => _}, ready for SystemOneClient.Answer.parse_all/1.

Pass the original questions so score legends carry the caller's level text instead of the "Level N" labels sent to OpenAI.

encode_request(state, questions, model, images \\ [])

@spec encode_request(term(), map(), String.t() | nil, [String.t()]) ::
  {:ok, map()} | {:error, term()}

Builds the /v1/decisions request body.

iex> {:ok, body} =
...>   SystemOneClient.Wire.OpenAIDecisions.encode_request(
...>     "I was charged twice.",
...>     %{"urgent" => %{"type" => "noul", "instructions" => "Is this urgent?"}},
...>     "gpt-6-luna"
...>   )
iex> body.questions
[%{type: "predicate", name: "urgent", instructions: "Is this urgent?"}]