# `PhoenixKitAgent.Models`
[🔗](https://github.com/BeamLabEU/phoenix_kit_agent/blob/v0.1.0/lib/phoenix_kit_agent/models.ex#L1)

The choice of a model for a user (spec §7.2). The module has no models of its
own: the choice is among the endpoints of `phoenix_kit_ai` (an endpoint is a
connection plus a model), and only endpoints that can chat.

`list_endpoints/1` is the choice; `tools_support/1` says, per endpoint,
whether its model takes tools — the assistant is useless on one that does
not, so the screens mark those. `image_input_support/1` is the same question
about images in; the attachments (spec §9) use it to decide whether a
picture goes to the model as pixels or as a description. Both read
`PhoenixKitAI.Capabilities.for_endpoint/1` — the provider's catalogue as
`phoenix_kit_ai` keeps it, with what an admin declared on the endpoint where
the catalogue says nothing — from its cache only, never the network:

  * `:supported` / `:unsupported` — the model is known to take it, or not;
  * `:unknown` — nobody knows: a provider without a catalogue whose
    endpoint declares nothing, a model the catalogue does not list, a
    catalogue not read yet.

Only `:supported` lets pixels go to a model (`image_input/1`).

`reports_cost?/2` says whether a call on an endpoint gets what it cost in
the AI journal — the money limits count only such calls (spec §7.3).

# `call_kind`

```elixir
@type call_kind() :: :chat | :vision
```

What a call on an endpoint is: a model call of a turn, or a picture
described by the vision model.

# `summary`

```elixir
@type summary() :: %{
  uuid: String.t(),
  name: String.t(),
  model: String.t(),
  provider: String.t(),
  reports_cost?: boolean()
}
```

What a page shows of an endpoint: never the endpoint itself, which carries
its API key. `reports_cost?` is `reports_cost?/2` of a chat call on it.

# `support`

```elixir
@type support() :: :supported | :unsupported | :unknown
```

Whether a model takes tools.

# `image_input`

```elixir
@spec image_input(String.t() | nil) :: support()
```

`image_input_support/1` for the one endpoint with this uuid, read again from
the database. `:unknown` for no endpoint (`nil`) and for one that does not
exist.

# `image_input_support`

```elixir
@spec image_input_support([PhoenixKitAI.Endpoint.t()]) :: %{
  required(String.t()) =&gt; support()
}
```

Whether each endpoint's model takes images as input (see the moduledoc):
`%{endpoint_uuid => support}`. A model that can only produce images does not.

# `image_input_support_of`

```elixir
@spec image_input_support_of([String.t()]) :: %{required(String.t()) =&gt; support()}
```

`image_input_support/1` for the endpoints with these uuids, read again from
the database (one that is gone is left out).

# `list_endpoints`

```elixir
@spec list_endpoints(keyword()) :: [PhoenixKitAI.Endpoint.t()]
```

The endpoints a user can be given: enabled ones that chat (not speech,
embedding or image models), by name. `include: uuid` (or a list of uuids)
adds that endpoint even if it can no longer be picked — the one a user has
now, so that saving the form does not drop it unnoticed.

# `reports_cost?`

```elixir
@spec reports_cost?(PhoenixKitAI.Endpoint.t() | summary() | nil, call_kind()) ::
  boolean()
```

Whether a call on the endpoint gets what it cost in the AI journal, as
`phoenix_kit_ai` prices it. On an endpoint where it does not, money is not
counted and only the turn limit applies.

  * `:chat` (a model call of a turn) — `PhoenixKitAI.reports_cost?/1`: the
    provider reports the cost (OpenRouter), or the operator's catalogue, a
    manual price on the endpoint or Anthropic's list price prices its model.
  * `:vision` (a picture described, `PhoenixKitAI.describe_image/3`) —
    `PhoenixKitAI.TaskLimits.money_counted?/2` with `:vision`, which is the
    chat rule: `phoenix_kit_ai` prices a description like a chat call (the
    provider's cost, a catalogue, a manual or a list price).

A `t:summary/0` carries the answer for `:chat`.

# `summaries`

```elixir
@spec summaries([String.t()]) :: %{required(String.t()) =&gt; summary()}
```

The endpoints with these uuids as `t:summary/0`: `%{uuid => summary}`.

# `summary`

```elixir
@spec summary(PhoenixKitAI.Endpoint.t()) :: summary()
```

An endpoint as a page keeps it (`t:summary/0`).

# `tools_support`

```elixir
@spec tools_support([PhoenixKitAI.Endpoint.t()]) :: %{
  required(String.t()) =&gt; support()
}
```

Whether each endpoint's model takes tools (see the moduledoc): `%{endpoint_uuid => support}`.

# `tools_support_of`

```elixir
@spec tools_support_of([String.t()]) :: %{required(String.t()) =&gt; support()}
```

`tools_support/1` for the endpoints with these uuids, read again from the
database (one that is gone is left out).

---

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