Getting Started with Mojentic

Copy Markdown View Source

This guide will help you get up and running with Mojentic in your Elixir project.

Installation

Add Mojentic to your mix.exs dependencies:

def deps do
  [
    {:mojentic, "~> 0.1.0"}
  ]
end

Then run:

mix deps.get

Prerequisites

Mojentic requires:

  • Elixir 1.15 or later
  • A local or remote LLM service (Ollama, OpenAI, etc.)

Setting up Ollama (Local LLMs)

  1. Install Ollama from ollama.ai
  2. Pull a model:
ollama pull phi4:14b
  1. Start the Ollama service (runs on http://localhost:11434 by default)

Setting up OpenAI (Planned)

# Set your API key
System.put_env("OPENAI_API_KEY", "your-api-key")

Your First LLM Call

Create a simple script to test your setup:

# In a script or IEx session
alias Mojentic.LLM.{Broker, Message}
alias Mojentic.LLM.Gateways.Ollama

# Create a broker with your model
broker = Broker.new("phi4:14b", Ollama)

# Create a message
messages = [Message.user("What is the capital of France?")]

# Generate a response
case Broker.generate(broker, messages) do
  {:ok, response} ->
    IO.puts("AI: #{response}")

  {:error, reason} ->
    IO.puts("Error: #{inspect(reason)}")
end

Understanding the Broker

The Broker is your main interface to LLMs. It handles:

  • Model selection
  • Gateway routing
  • Message formatting
  • Tool execution
  • Error handling

Basic Broker Usage

# Simple text generation
broker = Broker.new("qwen3:14b", Ollama)
messages = [Message.user("Hello!")]
{:ok, response} = Broker.generate(broker, messages)

# With configuration
config = CompletionConfig.new(temperature: 0.7, max_tokens: 1000)
{:ok, response} = Broker.generate(broker, messages, [], config)

# With correlation ID for tracking
broker = Broker.new("qwen3:14b", Ollama, "request-123")

Working with Messages

Messages form the conversation context:

alias Mojentic.LLM.Message

# Different message types
messages = [
  Message.system("You are a helpful assistant"),
  Message.user("What's the weather?"),
  Message.assistant("I don't have access to weather data"),
  Message.user("Can you tell me a joke instead?")
]

{:ok, response} = Broker.generate(broker, messages)

Structured Output

Parse responses into structured data:

# Define a schema
schema = %{
  type: "object",
  properties: %{
    name: %{type: "string"},
    age: %{type: "integer"},
    hobbies: %{
      type: "array",
      items: %{type: "string"}
    }
  },
  required: ["name", "age"]
}

messages = [Message.user("Generate a person profile")]

case Broker.generate_object(broker, messages, schema) do
  {:ok, person} ->
    IO.inspect(person)
    # %{"name" => "Alice", "age" => 30, "hobbies" => ["reading", "coding"]}

  {:error, reason} ->
    IO.puts("Failed: #{inspect(reason)}")
end

Using Tools

Tools let LLMs perform actions:

alias Mojentic.LLM.Tools.DateResolver

messages = [
  Message.user("What date is next Friday?")
]

# Pass tools to the broker
tools = [DateResolver]
{:ok, response} = Broker.generate(broker, messages, tools)

Configuration Options

Customize LLM behavior with CompletionConfig:

alias Mojentic.LLM.CompletionConfig

config = CompletionConfig.new(
  temperature: 0.7,      # Randomness (0.0-2.0)
  max_tokens: 2000,      # Maximum response length
  num_ctx: 8192,         # Context window size
  num_predict: 1024      # Prediction length
)

{:ok, response} = Broker.generate(broker, messages, [], config)

Error Handling

All Mojentic functions return {:ok, result} or {:error, reason}:

case Broker.generate(broker, messages) do
  {:ok, response} ->
    # Handle success
    process_response(response)

  {:error, :timeout} ->
    # Handle timeout
    Logger.warn("Request timed out")

  {:error, {:http_error, status}} ->
    # Handle HTTP errors
    Logger.error("HTTP #{status}")

  {:error, {:gateway_error, msg}} ->
    # Handle gateway errors
    Logger.error("Gateway error: #{msg}")

  {:error, reason} ->
    # Handle other errors
    Logger.error("Error: #{inspect(reason)}")
end

Next Steps