defmodule Replicate.Models do @moduledoc """ Documentation for `Models`. """ @behaviour Replicate.Models.Behaviour @replicate_client Application.compile_env(:replicate, :replicate_client, Replicate.Client) alias Replicate.Models.Model @doc """ Gets a model from a owner/name string. Raises an error if the model doesn't exist. ## Examples ``` iex> %Model{owner: owner, name: name} = Replicate.Models.get!("replicate/hello-world") iex> owner "replicate" iex> name "hello-world" ``` """ def get!(name) do [username, name] = String.split(name, "/") {:ok, result} = @replicate_client.request(:get, "/v1/models/#{username}/#{name}") model = Jason.decode!(result) |> string_to_atom() struct(Model, model) end @doc """ Gets a model from a owner/name string. Returns {:error, "Not found"} if the model doesn't exist. ## Examples ``` iex> {:ok, %Model{owner: owner, name: name}} = Replicate.Models.get("replicate/hello-world") iex> owner "replicate" iex> name "hello-world" ``` """ def get(name) do [username, name] = String.split(name, "/") case @replicate_client.request(:get, "/v1/models/#{username}/#{name}") do {:ok, result} -> model = Jason.decode!(result) |> string_to_atom() {:ok, struct(Model, model)} {:error, message} -> {:error, message} end end @doc """ Gets a version of a model. Raises an error if the version doesn't exist. ## Examples ``` iex> model = Replicate.Models.get!("replicate/hello-world") iex> version = Replicate.Models.get_version!(model, "v2") iex> version.id "v2" ``` """ def get_version!(%Model{owner: owner, name: name}, version) do {:ok, result} = @replicate_client.request(:get, "/v1/models/#{owner}/#{name}/versions/#{version}") version = Jason.decode!(result) |> string_to_atom() struct(Replicate.Models.Version, version) end @doc """ Gets the latest version of a model. Raises an error if the version doesn't exist. ## Examples ``` iex> model = Replicate.Models.get!("replicate/hello-world") iex> version = Replicate.Models.get_latest_version!(model) iex> version.id "v2" ``` """ def get_latest_version!(%Model{latest_version: %{"id" => id}} = model) do model |> get_version!(id) end @doc """ Returns a list of all versions for a model. ## Examples ``` iex> model = Replicate.Models.get!("replicate/hello-world") iex> versions = Replicate.Models.list_versions(model) iex> %Replicate.Models.Version{id: id, cog_version: cog_version} = List.first(versions) iex> id "v1" iex> cog_version "0.3.0" ``` """ def list_versions(%Model{owner: owner, name: name}) do case @replicate_client.request(:get, "/v1/models/#{owner}/#{name}/versions") do {:ok, results} -> %{"results" => versions} = Jason.decode!(results) versions |> Enum.map(fn v -> atom_map = string_to_atom(v) struct(Replicate.Models.Version, atom_map) end) {:error, message} -> raise message end end @doc """ Get a paginated list of all public models. ## Examples iex> %{next: next, previous: previous, results: results} = Replicate.Models.list() iex> next "https://api.replicate.com/v1/trainings?cursor=cD0yMDIyLTAxLTIxKzIzJTNBMTglM0EyNC41MzAzNTclMkIwMCUzQTAw" iex> previous nil iex> results |> length() 25 iex> results |> Enum.at(0) %Replicate.Models.Model{ url: "https://replicate.com/replicate/hello-world", owner: "replicate", name: "hello-world", description: "A tiny model that says hello", visibility: "public", github_url: "https://github.com/replicate/cog-examples", paper_url: nil, license_url: nil, run_count: 12345, cover_image_url: nil, default_example: nil, latest_version: %{ "cog_version" => "0.3.0", "created_at" => "2022-03-21T13:01:04.418669Z", "id" => "v2", "openapi_schema" => %{} } } """ def list() do case @replicate_client.request(:get, "/v1/models") do {:ok, response} -> %{"results" => results, "next" => next, "previous" => previous} = Jason.decode!(response) models = results |> Enum.map(fn m -> atom_map = string_to_atom(m) struct!(Model, atom_map) end) %{next: next, previous: previous, results: models} {:error, message} -> raise message end end defp string_to_atom(body) do for {k, v} <- body, into: %{}, do: {String.to_atom(k), v} end end