defmodule ExOpenAi.Api do @moduledoc """ The main module for the ExOpenAi API client. Provides a wrapper around Httpoison for making requests to the OpenAI API. """ use HTTPoison.Base alias ExOpenAi.Config alias ExOpenAi.Parser alias ExOpenAi.URLGenerator, as: URL alias __MODULE__ # Image generation can take some time, so we need to increase the timeout @default_timeout 25_000 @type data :: map | list @doc """ Create a new resource in the OpenAI API with a POST request. ## Examples ExOpenAi.Api.create(ExOpenAi.Completion, [prompt: "tell me a joke", max_tokens: 500]) {:ok, %Completion{ ... }} ExOpenAi.Api.create(ExOpenAi.Completion, []) {:error, %{"model" => "model is required"}, 400} """ @spec create(atom, data :: list | map, list) :: Parser.success() | Parser.error() def create(module, data, options \\ []) do data = format_data(data) module |> URL.infer_url() |> Api.post!(data, options, recv_timeout: Config.timeout()) |> Parser.parse(module, options[:simple]) end @doc """ Builds the authorization header for the request. """ @spec auth_header(options :: list) :: list def auth_header(options \\ []) do auth_header([], {options[:api_key], options[:organization]}) end @doc """ Builds the actual authorization header for the request. ## Examples iex> ExOpenAi.Api.auth_header([], {"api123", "org345"}) [{"Authorization", "Bearer api123"}, {"OpenAI-Organization", "org345"}] iex> ExOpenAi.Api.auth_header([], {"api123", nil}) [{"Authorization", "Bearer api123"}] """ @spec auth_header(header :: list, tuple()) :: list def auth_header(headers, {api_key, organzation}) do headers |> put_header("Authorization", "Bearer #{api_key}") |> put_header("OpenAI-Organization", organzation) end defp put_header(headers, _key, value) when is_nil(value), do: headers defp put_header(headers, key, value), do: headers ++ [{key, value}] @spec format_data(list | map) :: binary def format_data(data) def format_data(data) when is_list(data) do data |> Map.new() |> Jason.encode!() end def format_data(data) when is_map(data), do: Jason.encode!(data) ### # HTTPoison API ### def process_request_headers(headers \\ []) do headers |> Keyword.put(:"Content-Type", "application/json") |> auth_header({Config.api_key(), Config.organization()}) end end