Packages
llama_cpp_ex
0.8.36
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.28
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.10
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.0
0.6.14
0.6.13
0.6.12
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.0
0.4.4
0.4.3
0.4.2
0.4.1
0.3.0
0.2.0
Elixir bindings for llama.cpp — run LLMs locally with Metal, CUDA, Vulkan, or CPU acceleration.
Current section
Files
Jump to
Current section
Files
lib/llama_cpp_ex/schema.ex
defmodule LlamaCppEx.Schema do
@moduledoc """
Converts Ecto schema modules to JSON Schema maps for structured output.
Requires `{:ecto, "~> 3.0"}` as an optional dependency. If Ecto is not
available, calling these functions will raise at runtime.
## Type Mapping
| Ecto type | JSON Schema |
|-----------|-------------|
| `:string`, `:binary` | `{"type": "string"}` |
| `:integer`, `:id` | `{"type": "integer"}` |
| `:float`, `:decimal` | `{"type": "number"}` |
| `:boolean` | `{"type": "boolean"}` |
| `:map` | `{"type": "object"}` |
| `{:array, inner}` | `{"type": "array", "items": ...}` |
| `:date` | `{"type": "string", "format": "date"}` |
| `:utc_datetime`, etc. | `{"type": "string", "format": "date-time"}` |
| `embeds_one` | nested object |
| `embeds_many` | array of nested objects |
## Excluded Fields
The following fields are automatically excluded: `:id`, `:inserted_at`,
`:updated_at`, and virtual fields.
## Examples
defmodule MyApp.Person do
use Ecto.Schema
schema "people" do
field :name, :string
field :age, :integer
field :email, :string
timestamps()
end
end
schema = LlamaCppEx.Schema.to_json_schema(MyApp.Person)
# => %{"type" => "object", "properties" => %{"name" => ..., "age" => ..., "email" => ...}, ...}
# Use directly with generate/chat
{:ok, json} = LlamaCppEx.chat(model, messages, json_schema: schema, temp: 0.0)
"""
@doc """
Converts an Ecto schema module to a JSON Schema map.
Extracts fields from the schema, maps Ecto types to JSON Schema types,
and marks all non-virtual fields as required. Excludes `:id`, timestamp
fields (`:inserted_at`, `:updated_at`), and virtual fields.
"""
@spec to_json_schema(module()) :: map()
def to_json_schema(module) do
unless Code.ensure_loaded?(Ecto.Schema) do
raise "Ecto is required for LlamaCppEx.Schema. Add {:ecto, \"~> 3.0\"} to your deps."
end
unless function_exported?(module, :__schema__, 1) do
raise ArgumentError, "#{inspect(module)} is not an Ecto schema module"
end
fields = module.__schema__(:fields)
types = for field <- fields, into: %{}, do: {field, module.__schema__(:type, field)}
# Exclude :id and timestamp fields
excluded = [:id, :inserted_at, :updated_at]
fields = Enum.reject(fields, &(&1 in excluded))
# Exclude virtual fields (they won't appear in __schema__(:fields) anyway,
# but filter by checking type is not nil)
fields = Enum.filter(fields, fn f -> types[f] != nil end)
# Build properties and handle embeds
embeds = module.__schema__(:embeds)
{properties, required} =
Enum.reduce(fields, {%{}, []}, fn field, {props, req} ->
property = field_property(module, field, types, embeds)
{Map.put(props, to_string(field), property), [to_string(field) | req]}
end)
%{
"type" => "object",
"properties" => properties,
"required" => Enum.reverse(required)
}
end
defp field_property(module, field, types, embeds) do
if field in embeds do
embed_property(module.__schema__(:embed, field))
else
ecto_type_to_json(types[field])
end
end
defp embed_property(%{cardinality: :one, related: embed_mod}), do: to_json_schema(embed_mod)
defp embed_property(%{cardinality: :many, related: embed_mod}),
do: %{"type" => "array", "items" => to_json_schema(embed_mod)}
defp ecto_type_to_json(:string), do: %{"type" => "string"}
defp ecto_type_to_json(:binary), do: %{"type" => "string"}
defp ecto_type_to_json(:integer), do: %{"type" => "integer"}
defp ecto_type_to_json(:float), do: %{"type" => "number"}
defp ecto_type_to_json(:decimal), do: %{"type" => "number"}
defp ecto_type_to_json(:boolean), do: %{"type" => "boolean"}
defp ecto_type_to_json(:map), do: %{"type" => "object"}
defp ecto_type_to_json({:map, _}), do: %{"type" => "object"}
defp ecto_type_to_json({:array, inner}),
do: %{"type" => "array", "items" => ecto_type_to_json(inner)}
defp ecto_type_to_json(:date), do: %{"type" => "string", "format" => "date"}
defp ecto_type_to_json(:time), do: %{"type" => "string", "format" => "time"}
defp ecto_type_to_json(:utc_datetime), do: %{"type" => "string", "format" => "date-time"}
defp ecto_type_to_json(:utc_datetime_usec), do: %{"type" => "string", "format" => "date-time"}
defp ecto_type_to_json(:naive_datetime), do: %{"type" => "string", "format" => "date-time"}
defp ecto_type_to_json(:naive_datetime_usec), do: %{"type" => "string", "format" => "date-time"}
defp ecto_type_to_json(:id), do: %{"type" => "integer"}
defp ecto_type_to_json(:binary_id), do: %{"type" => "string"}
defp ecto_type_to_json(_other), do: %{"type" => "string"}
end