UniLM.jl
A unified Julia interface for large language models.
What is UniLM.jl?
UniLM.jl provides a Julian, type-safe interface to LLM providers via the OpenAI-compatible API standard — covering the Chat Completions API, the Responses API, Image Generation, Embeddings, and MCP. Works with OpenAI, Azure, Gemini, Mistral, DeepSeek, Ollama, vLLM, LM Studio, and any OpenAI-compatible provider.
Key Features
- 🗣️ Chat Completions — stateful conversations with automatic history management
- 🔮 Responses API — OpenAI's newer API with built-in tools, multi-turn chaining, and reasoning
- 🖼️ Image Generation — create images from text prompts with
gpt-image-1.5 - 🔧 Tool/Function Calling — first-class support for function tools in both APIs, with automated
tool_loop - 🔌 MCP (Model Context Protocol) — connect to MCP servers or build your own, with seamless tool loop integration
- 📊 Embeddings — text embedding generation
- 🌊 Streaming — real-time token streaming with
do-block syntax - 📐 Structured Output — JSON Schema–constrained generation
- ☁️ Multi-Backend — OpenAI, Azure, Gemini, DeepSeek, Ollama, Mistral, vLLM, LM Studio
- ✅ Type Safety — invalid states are unrepresentable; tested with JET.jl and Aqua.jl
Two APIs, One Package
| Feature | Chat Completions | Responses API |
|---|---|---|
| Stateful conversations | Chat + push! | previous_response_id |
| System prompt | Message(Val(:system), ...) | instructions kwarg |
| Tool calling | GPTTool / GPTToolCall | FunctionTool / function_tool |
| Web search | — | WebSearchTool |
| File search | — | FileSearchTool |
| Streaming | stream=true + callback | do-block syntax |
| Structured output | ResponseFormat | TextConfig / json_schema_format |
| Reasoning (O-series) | — | Reasoning |
| Automated tool loop | tool_loop! | tool_loop |
| MCP integration | mcp_tools bridge | MCPTool / mcp_tool |
Installation
using Pkg
Pkg.add(url="https://github.com/algunion/UniLM.jl")Or in the Pkg REPL:
pkg> add https://github.com/algunion/UniLM.jlQuick Example
Building requests — these construct objects locally without calling the API:
using UniLM
using JSON
# Chat Completions request
chat = Chat(model="gpt-5.2")
push!(chat, Message(Val(:system), "You are a Julia expert."))
push!(chat, Message(Val(:user), "Explain multiple dispatch in one sentence."))
println("Chat has ", length(chat), " messages, model: ", chat.model)
println("Request body preview:")
println(JSON.json(chat))Chat has 2 messages, model: gpt-5.2
Request body preview:
{"messages":[{"role":"system","content":"You are a Julia expert."},{"role":"user","content":"Explain multiple dispatch in one sentence."}],"model":"gpt-5.2"}# Responses API request
r = Respond(input="What makes Julia special?")
println("Respond model: ", r.model)
println(JSON.json(r))Respond model: gpt-5.2
{"model":"gpt-5.2","input":"What makes Julia special?"}# Image Generation request
ig = ImageGeneration(prompt="A watercolor Julia logo", quality="high")
println("Image model: ", ig.model)
println(JSON.json(ig))Image model:
{"quality":"high","prompt":"A watercolor Julia logo","model":"gpt-image-1.5"}With a valid API key, actual API calls return structured results:
Responses API (recommended for new code):
result = respond("Explain Julia's multiple dispatch in 2-3 sentences.")
if result isa ResponseSuccess
println(output_text(result))
else
println("Request failed — ", output_text(result))
endJulia’s multiple dispatch means a function can have many method definitions, and Julia chooses which one to run based on the types of *all* arguments, not just the first. This lets you write generic code while still getting specialized, efficient behavior for different combinations of input types.Chat Completions:
chat = Chat(model="gpt-4o-mini")
push!(chat, Message(Val(:system), "You are a concise Julia programming tutor."))
push!(chat, Message(Val(:user), "What is multiple dispatch? Answer in 2-3 sentences."))
result = chatrequest!(chat)
if result isa LLMSuccess
println(result.message.content)
else
println("Request failed — see result for details")
endMultiple dispatch is a programming paradigm where the method that gets executed is determined by the types of all arguments passed to a function, rather than just the first one, as in single dispatch. This allows for more flexible and expressive code, enabling developers to define different function behaviors based on combinations of argument types. Julia is known for its built-in support for multiple dispatch, making it a key feature of the language.Image Generation:
result = generate_image(
"A watercolor painting of a friendly robot reading a Julia programming book",
size="1024x1024", quality="medium"
)
println("Success: ", result isa ImageSuccess)
if result isa ImageSuccess
save_image(image_data(result)[1], joinpath(@__DIR__, "assets", "generated_robot.png"))
println("Saved to assets/generated_robot.png")
else
println("Image generation failed — see result for details")
endSuccess: true
Saved to assets/generated_robot.png
Next Steps
- Getting Started — setup and first requests
- Chat Completions Guide — deep dive into
Chatandchatrequest! - Responses API Guide — the newer Responses API
- Image Generation Guide — create images from text prompts
- MCP Guide — connect to MCP servers or build your own
- API Reference — full type and function reference