Elixir SDK for OpenAI APIs
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
- Generated API modules for the bundled OpenAI specification
- Generated typespecs and API documentation
- Elixir-style API with required arguments as function parameters and optional arguments as keyword lists
- Support for streaming responses with SSE
- Editor features: autocompletion, typechecking, and inline documentation
- Support with OpenAI-compatible APIs (like OpenRouter)
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:
- Assistants - Create and manage assistants
- Audio - Speech, transcription, and translation
- Chat - Chat completions API
- Completions - Text completion API
- Embeddings - Vector embeddings
- Files - File management
- Images - Image generation and editing
- Models - Model management
- Responses - Stateful conversation API
- Threads - Thread-based conversations
- Vector Stores - Vector database operations
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.