Elixir SDK for OpenAI APIs

Hex.pm VersionHex DocsHex.pm Download Total

ExOpenAI is an (unofficial) Elixir SDK for interacting with the OpenAI APIs. Its API modules and types are generated from the bundled OpenAPI specification.

Features

Installation

Add :ex_openai as a dependency in your mix.exs file:

def deps do
[
{:ex_openai, "~> 2.0.0-beta4"}
]
end

Quick Start

Configuration

import Config
config :ex_openai,
api_key: System.get_env("OPENAI_API_KEY"),
organization_key: System.get_env("OPENAI_ORGANIZATION_KEY"),
# Optional settings
base_url: System.get_env("OPENAI_API_URL"),
http_options: [recv_timeout: 50_000],
http_headers: [{"OpenAI-Beta", "assistants=v2"}]

Basic Usage

# List available models
{:ok, models} = ExOpenAI.Models.list_models()
# Create a chat completion
messages = [
%ExOpenAI.Components.ChatCompletionRequestSystemMessage{
role: :system,
content: "You are a concise assistant."
},
%ExOpenAI.Components.ChatCompletionRequestUserMessage{
role: :user,
content: "What is the capital of France?"
}
]
{:ok, chat_response} = ExOpenAI.Chat.create_chat_completion(messages, "gpt-4o-mini")
# Responses
{:ok, response} = ExOpenAI.Responses.create_response(
input: "Tell me a joke about programming",
model: "gpt-4o-mini"
)
# Continue the conversation
{:ok, follow_up} = ExOpenAI.Responses.create_response(
input: "Explain why that joke is funny",
model: "gpt-4o-mini",
previous_response_id: response.id
)

More examples in Examples

API Overview

The API is organized into resource modules, including:

For detailed documentation on each module, see the API Documentation.

Advanced Usage

Streaming Responses

# Using a callback function
callback = fn
:finish ->
IO.puts("\nDone")
{:data, %ExOpenAI.Components.CreateChatCompletionStreamResponse{} = chunk} ->
(chunk.choices || [])
|> Enum.map_join("", fn choice -> Map.get(choice.delta || %{}, :content) || "" end)
|> IO.write()
{:error, err} ->
IO.puts("Error: #{inspect(err)}")
end
messages = [
%ExOpenAI.Components.ChatCompletionRequestUserMessage{
role: :user,
content: "Tell me a short story"
}
]
ExOpenAI.Chat.create_chat_completion(
messages,
"gpt-4o-mini",
stream: true,
stream_to: callback
)

For more advanced streaming options, see the Streaming Guide.

File Uploads

# Simple file upload
image_data = File.read!("path/to/image.png")
{:ok, result} = ExOpenAI.Images.create_image_variation(image_data)
# With filename information
audio_data = File.read!("path/to/audio.wav")
{:ok, transcript} = ExOpenAI.Audio.create_transcription({"audio.wav", audio_data}, "whisper-1")

Documentation

Types and response data

Request components accept structs or atom-keyed maps through their input() types. Response components use t() and return structs with atom keys. Dynamic objects, such as metadata and JSON Schema properties, retain their string keys.

Dialyzer catches incompatible positional arguments and explicitly typed schemas, but does not validate every keyword option or nested union. The SDK does not perform runtime JSON Schema validation.

Streaming calls return {:ok, reference()}. Chat chunks and Responses events use their generated structs; applications accumulate deltas themselves. See the Streaming Guide for callback and process examples.

Contributing

Contributions are welcome! If you find a bug or want to add a feature, please open an issue or submit a PR.

To update the SDK when OpenAI changes their API:

mise exec -- mix update_openai_docs
mise run generate_openai
mise run check
mise run test
mise run lint

Projects Using ExOpenAI

Add yours with a PR!

License

Available as open source under the terms of the MIT License.