Elixir
Fault-tolerant concurrency on the BEAM.
Elixir is a functional language that runs on the Erlang virtual machine (BEAM), the system that powers telecom switches and WhatsApp. It makes it easy to build apps that handle millions of connections and recover from crashes, and its Nx and Bumblebee libraries bring machine learning to the BEAM.
Why learn Elixir?
When an AI product needs thousands of live users, streaming responses and no downtime, Elixir is a strong choice.
- Concurrency: lightweight processes let you run millions of tasks at once.
- Fault tolerance: supervisors restart crashed parts automatically.
- ML on the BEAM: Nx, Axon and Bumblebee run models and serve them in production.
Set up and run your first program
Install Elixir (it brings Erlang). Use iex for an interactive shell and mix for projects.
elixir --version
elixir hello.exs
mix new my_appname = "Ada"
IO.puts("Hello, AI! Welcome to Elixir, #{name}.").exs files are scripts; .ex files are compiled as part of a project.Values and pattern matching
Data is immutable. = is a match, not just assignment: it can pull values out of tuples, lists and maps.
layers = 32
model = "llama3.1"
{:ok, gb} = {:ok, 80} # pattern match on a tuple
[first | rest] = ["H100", "H200", "B200"]
IO.puts("#{model}: #{layers} layers")
IO.inspect({gb, first, rest})
IO.puts(8.03e9 * 2 / 1.0e9)Modules and functions
Functions live in modules. Multiple clauses with guards replace if-chains. The pipe |> passes a value into the next function.
defmodule Precision do
def name(32), do: "FP32"
def name(16), do: "FP16"
def name(bits) when bits < 16, do: "low precision"
def params(layers, width \\ 4096), do: 12 * layers * width * width
end
IO.puts(Precision.name(8))
" Hello Elixir " |> String.trim() |> String.upcase() |> IO.puts()Lists, maps and Enum
The Enum module covers mapping, filtering and reducing. Maps hold key-value data.
vram = %{"H100" => 80, "H200" => 141, "RTX 5090" => 32}
big = for {name, gb} <- vram, gb >= 80, do: name
total = vram |> Map.values() |> Enum.sum()
squares = Enum.map(1..5, fn x -> x * x end)
IO.inspect(big)
IO.inspect({total, squares})Processes and messages
spawn starts a lightweight process. Processes share nothing and talk by sending messages. Task makes parallel work easy.
parent = self()
spawn(fn -> send(parent, {:done, "H100 benchmark"}) end)
receive do
{:done, job} -> IO.puts("finished " <> job)
end
results =
["llama", "qwen", "mistral"]
|> Task.async_stream(fn m -> {m, String.length(m)} end)
|> Enum.map(fn {:ok, r} -> r end)
IO.inspect(results)GenServer and supervision
OTP behaviours like GenServer hold state in a process, and supervisors restart them if they crash.
defmodule Counter do
use GenServer
def start_link(n), do: GenServer.start_link(__MODULE__, n, name: __MODULE__)
def add(x), do: GenServer.cast(__MODULE__, {:add, x})
def value, do: GenServer.call(__MODULE__, :value)
def init(n), do: {:ok, n}
def handle_cast({:add, x}, n), do: {:noreply, n + x}
def handle_call(:value, _from, n), do: {:reply, n, n}
end
Supervisor.start_link([{Counter, 0}], strategy: :one_for_one)
Counter.add(5)
IO.puts(Counter.value())AI with Elixir
The Nx ecosystem brings numerical computing to Elixir: Nx tensors compile to CPU or GPU through EXLA (XLA), Axon builds neural networks, and Bumblebee runs Hugging Face models with a few lines of code. Phoenix LiveView is popular for streaming chat interfaces.
The essential libraries
Run a Hugging Face model
Bumblebee downloads a sentiment model and serves it with Nx.Serving.
Mix.install([{:bumblebee, "~> 0.6"}, {:exla, ">= 0.0.0"}])
Nx.global_default_backend(EXLA.Backend)
repo = {:hf, "distilbert/distilbert-base-uncased-finetuned-sst-2-english"}
{:ok, model} = Bumblebee.load_model(repo)
{:ok, tokenizer} = Bumblebee.load_tokenizer(repo)
serving = Bumblebee.Text.text_classification(model, tokenizer)
Nx.Serving.run(serving, "Tensor cores make training so much faster!")
|> IO.inspect()Build an AI agent in Elixir
With the Req HTTP client, an agent is a recursive function that keeps calling the model until it stops asking for tools.
Mix.install([{:req, "~> 0.5"}])
defmodule ChatAgent do
@url "http://localhost:11434/v1/chat/completions"
@tools [%{type: "function", function: %{name: "get_weather", description: "Weather for a city",
parameters: %{type: "object", properties: %{city: %{type: "string"}}, required: ["city"]}}}]
def get_weather(%{"city" => city}), do: "It is 24°C and sunny in #{city}."
def run(messages, rounds \\ 5)
def run(_messages, 0), do: "gave up"
def run(messages, rounds) do
body = %{model: "llama3.1", messages: messages, tools: @tools}
msg = Req.post!(@url, json: body).body["choices"] |> hd() |> Map.get("message")
case msg["tool_calls"] do
calls when is_list(calls) and calls != [] ->
replies = for c <- calls do
args = Jason.decode!(c["function"]["arguments"])
%{role: "tool", tool_call_id: c["id"], content: get_weather(args)}
end
run(messages ++ [msg | replies], rounds - 1)
_ -> msg["content"]
end
end
end
IO.puts(ChatAgent.run([%{role: "user", content: "Should I take an umbrella in Lahore today?"}]))In a Phoenix app, run each conversation in its own process so one slow request never blocks the rest.
ollama pull llama3.1, and keep it running. The code talks to its OpenAI-compatible API at http://localhost:11434/v1, so the same program also works with vLLM, llama.cpp server or a cloud API by changing the URL, model name and adding an API key.Elixir learning roadmap
Tick items off as you go. Your progress is saved in this browser.
Beginner
Intermediate
Advanced
Projects to build
Elixir cheat sheet
| Task | Syntax |
|---|---|
| Interpolation | "Hi #{name}" |
| Anonymous fn | fn x -> x * 2 end |
| Pipe | x |> f() |> g() |
| Map | %{"a" => 1} |
| Comprehension | for x <- 1..5, do: x * x |
| Spawn | spawn(fn -> ... end) |
Common mistakes
- Data is immutable: functions return new values, they never change the old one.
- Calling an anonymous function needs a dot:
f.(x). - Use
<>to join strings, not+.
Where to go next
- Elixir guides — official
- Elixir School — free lessons
- Nx docs — numerical Elixir
On TensorCore.si: Erlang volume, Python volume.
Keyboard: [ previous language · ] next language · / search the library