Packages

Protocol-based AI adapter foundation for Elixir. Provides unified abstractions for gemini_ex, claude_agent_sdk, and codex_sdk with automatic fallback support, runtime capability detection, and built-in telemetry.

Current section

Files

Jump to
altar_ai lib altar ai adapters fallback.ex
Raw

lib/altar/ai/adapters/fallback.ex

defmodule Altar.AI.Adapters.Fallback do
@moduledoc """
Heuristic fallback adapter when no AI providers are available.
Provides simple rule-based responses without requiring any external APIs.
Useful as a last resort in fallback chains.
"""
defstruct opts: []
@type t :: %__MODULE__{opts: keyword()}
def new(opts \\ []), do: %__MODULE__{opts: opts}
@doc "Always available."
def available?, do: true
end
defimpl Altar.AI.Generator, for: Altar.AI.Adapters.Fallback do
alias Altar.AI.{Response, Error}
def generate(_adapter, prompt, _opts) do
{:ok,
%Response{
content:
"[Fallback] Unable to generate AI response for: #{String.slice(prompt, 0, 50)}...",
provider: :fallback,
model: "fallback",
finish_reason: :fallback
}}
end
def stream(_adapter, _prompt, _opts) do
{:error, Error.new(:unsupported, "Fallback does not support streaming", provider: :fallback)}
end
end
defimpl Altar.AI.Classifier, for: Altar.AI.Adapters.Fallback do
alias Altar.AI.Classification
def classify(_adapter, text, labels, _opts) do
# Simple keyword-based classification
text_lower = String.downcase(text)
scores =
Enum.map(labels, fn label ->
label_lower = String.downcase(label)
score = if String.contains?(text_lower, label_lower), do: 0.8, else: 0.2
{label, score}
end)
{best_label, best_score} = Enum.max_by(scores, fn {_, s} -> s end)
{:ok,
%Classification{
label: best_label,
confidence: best_score,
all_scores: Map.new(scores)
}}
end
end