# `ImageVision.ModelCache`
[🔗](https://github.com/elixir-image/image_vision/blob/v0.2.0/lib/image_vision/model_cache.ex#L1)

On-disk cache for ONNX model weights downloaded from
[HuggingFace](https://huggingface.co).

`Image.Segmentation` and `Image.Detection` use this cache to fetch
their default models on first call. Files are downloaded once and
reused for the lifetime of the cache directory.

## Cache directory

The cache root is resolved in this order:

* `Application.get_env(:image_vision, :cache_dir)` if set.

* Otherwise, `:filename.basedir(:user_cache, "image_vision")` —
  on macOS this is `~/Library/Caches/image_vision`, on Linux it's
  `$XDG_CACHE_HOME/image_vision` (typically `~/.cache/image_vision`).

Configure explicitly in `config/runtime.exs`:

    config :image_vision, :cache_dir, "/var/lib/image_vision/models"

## Layout

Cached files are stored under `{cache_root}/{repo}/{filename}`,
preserving the HuggingFace repository hierarchy. For example, the
SAM 2.1 Tiny encoder lives at:

    {cache_root}/facebook/sam2.1-hiera-tiny/sam2.1_hiera_tiny.encoder.onnx

## Offline use

Pre-populate the cache with the expected layout to operate fully
offline. `cached?/2` reports whether a given file is present without
triggering a download.

# `cache_root`

```elixir
@spec cache_root() :: Path.t()
```

Returns the absolute path to the cache root directory, creating it
if it does not yet exist.

### Returns

* The absolute path as a binary.

# `cached?`

```elixir
@spec cached?(String.t(), String.t()) :: boolean()
```

Returns true if the given HuggingFace file is already present in the
local cache.

### Arguments

* `repo` is the HuggingFace repository.

* `filename` is the path within the repository.

### Returns

* A boolean.

# `fetch!`

```elixir
@spec fetch!(String.t(), String.t()) :: Path.t()
```

Returns the local path for a HuggingFace model file, downloading it
on cache miss.

### Arguments

* `repo` is the HuggingFace repository, e.g. `"facebook/sam2.1-hiera-tiny"`.

* `filename` is the path within the repository, e.g.
  `"sam2.1_hiera_tiny.encoder.onnx"`. Sub-directories are supported
  (`"onnx/encoder.onnx"`).

### Returns

* The absolute local path to the file as a binary.

Raises if the download fails.

### Examples

    iex> path = ImageVision.ModelCache.fetch!("facebook/sam2.1-hiera-tiny", "config.json")
    iex> File.exists?(path)
    true

# `path`

```elixir
@spec path(String.t(), String.t()) :: Path.t()
```

Returns the local path that a given HuggingFace file would be cached
at, without checking whether it exists or downloading it.

### Arguments

* `repo` is the HuggingFace repository.

* `filename` is the path within the repository.

### Returns

* The absolute local path as a binary.

---

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