# `ALLM.ImagePart`
[🔗](https://github.com/cykod/ALLM/blob/v0.3.0/lib/allm/image_part.ex#L1)

An image content part used in multimodal `ALLM.Message{:content}` lists.
See spec §35.6.

Layer A — pure serializable data. `:image` (an `%ALLM.Image{}`) is the only
required field. `:detail` is a closed-set atom in `[:auto, :low, :high]`
matching OpenAI's vision-detail wire field; `:auto` is the default and
matches OpenAI's documented default. `:metadata` defaults to an empty map.

## Validation

`ALLM.Validate.message/1` accepts any `%ImagePart{}` in a content list per
Decision #11 (Phase 14.4). Layer A does not enforce `:detail` membership —
callers passing an unknown atom (e.g. `:medium`) round-trip cleanly through
ETF but JSON decoding will surface
`{:_unknown, :atom_decode_failed}` per the Serializer rescue contract
(Phase 13).

## Serializability

ETF round-trip via `:erlang.term_to_binary/1` is total. JSON round-trip via
`ALLM.Serializer` follows the standard `__type__`-tagged wire shape; the
embedded `%ALLM.Image{}` round-trips through its own encoder.

# `detail`

```elixir
@type detail() :: :auto | :low | :high
```

# `t`

```elixir
@type t() :: %ALLM.ImagePart{detail: detail(), image: ALLM.Image.t(), metadata: map()}
```

# `new`

```elixir
@spec new(
  ALLM.Image.t(),
  keyword()
) :: t()
```

Build an `%ImagePart{}` from an `%ALLM.Image{}` and optional keyword opts.

Accepts `:detail` (one of `:auto | :low | :high`; default `:auto`) and
`:metadata` (a map).

## Examples

    iex> img = ALLM.Image.from_url("https://example.com/cat.png")
    iex> ALLM.ImagePart.new(img).detail
    :auto

    iex> img = ALLM.Image.from_url("https://example.com/cat.png")
    iex> ALLM.ImagePart.new(img, detail: :high).detail
    :high

---

*Consult [api-reference.md](api-reference.md) for complete listing*
