> For the complete documentation index, see [llms.txt](https://deeplearning4j.konduit.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://deeplearning4j.konduit.ai/en-1.0.0-rewrite/omnihub/usage.md).

# Usage

OmniHub exposes two entry points for loading pretrained models: the `Pretrained` facade (the recommended path for named models) and the lower-level `OmniHubUtils` class (useful when you have a filename and framework string and want direct control).

***

## The Pretrained Facade

`org.eclipse.deeplearning4j.omnihub.models.Pretrained` is the simplest way to load a known model. It provides static accessor methods for the two framework namespaces:

```java
import org.eclipse.deeplearning4j.omnihub.models.Pretrained;

// Load the VGG19 (no-top) DL4J ComputationGraph
ComputationGraph vgg19 = Pretrained.dl4j().vgg19noTop(false);

// Load the AgeGoogLeNet SameDiff model
SameDiff ageGooglenet = Pretrained.samediff().ageGooglenet(false);

// Load ResNet18 SameDiff model
SameDiff resnet18 = Pretrained.samediff().resnet18(false);
```

The boolean argument is `forceDownload`. Pass `true` to delete the cached copy and re-download even if it already exists locally.

`Pretrained.dl4j()` returns a `Dl4jModels` instance. `Pretrained.samediff()` returns a `SameDiffModels` instance. Both classes are code-generated from the zoo manifest; their methods map directly to named model files.

***

## OmniHubUtils — Loading DL4J Models

### Loading a MultiLayerNetwork

```java
import org.eclipse.deeplearning4j.omnihub.OmniHubUtils;
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;

// Load from cache (download if not cached)
MultiLayerNetwork net = OmniHubUtils.loadNetwork("mymodel.zip");

// Force re-download even if cached
MultiLayerNetwork net = OmniHubUtils.loadNetwork("mymodel.zip", true);
```

`loadNetwork` downloads the file from the `dl4j/` directory of the zoo, stores it in `~/.omnihub/dl4j/`, and loads it using `MultiLayerNetwork.load(file, true)` (with the parameter updater restored).

### Loading a ComputationGraph

```java
import org.deeplearning4j.nn.graph.ComputationGraph;

ComputationGraph graph = OmniHubUtils.loadCompGraph("vgg19_weights_tf_dim_ordering_tf_kernels_notop.zip");

// With force download
ComputationGraph graph = OmniHubUtils.loadCompGraph(
    "vgg19_weights_tf_dim_ordering_tf_kernels_notop.zip",
    true
);
```

`loadCompGraph` is identical to `loadNetwork` except it calls `ComputationGraph.load(file, true)`.

***

## OmniHubUtils — Loading SameDiff Models

```java
import org.nd4j.autodiff.samediff.SameDiff;

SameDiff model = OmniHubUtils.loadSameDiffModel("age_googlenet.fb");

// With force download
SameDiff model = OmniHubUtils.loadSameDiffModel("age_googlenet.fb", true);
```

SameDiff models are stored as FlatBuffers files (`.fb`). They are downloaded from the `samediff/` directory of the zoo and cached under `~/.omnihub/samediff/`. Loading uses `SameDiff.load(file, true)`.

***

## Direct Download with downloadAndLoadFromZoo

For cases where you want the local `File` handle rather than an already-loaded model object, call `downloadAndLoadFromZoo` directly:

```java
import java.io.File;

File modelFile = OmniHubUtils.downloadAndLoadFromZoo(
    "samediff",           // framework subdirectory
    "resnet18.fb",        // filename
    false                 // forceDownload
);

// Now load it yourself
SameDiff sd = SameDiff.load(modelFile, true);
```

The framework string must match the subdirectory name in the zoo repository (`"dl4j"` or `"samediff"`).

***

## Caching Behavior

Models are cached in the directory returned by `OmnihubConfig.getOmnihubHome()`:

* Default: `~/.omnihub`
* Custom: set the `OMNIHUB_HOME` environment variable before the JVM starts.

The cache structure is flat per-framework:

```
~/.omnihub/
  dl4j/
    vgg19_weights_tf_dim_ordering_tf_kernels_notop.zip
  samediff/
    age_googlenet.fb
    resnet18.fb
```

A download is skipped if the destination file already exists (unless `forceDownload` is `true`). There is no checksum verification in the current implementation — if you suspect a file is corrupt, pass `forceDownload = true` to replace it.

***

## Overriding the Zoo URL

By default, models are fetched from:

```
https://raw.githubusercontent.com/KonduitAI/omnihub-zoo/main
```

To point at a private mirror or a local HTTP server (for air-gapped environments), set the `OMNIHUB_URL` environment variable:

```bash
export OMNIHUB_URL=http://internal-mirror.example.com/omnihub
```

The URL is read by `OmnihubConfig.getOmnihubUrl()` each time a download is needed. The file is resolved at:

```
${OMNIHUB_URL}/${framework}/${name}
```

For example, `OmniHubUtils.loadSameDiffModel("resnet18.fb")` would fetch:

```
http://internal-mirror.example.com/omnihub/samediff/resnet18.fb
```

***

## Download Progress

`OmniHubUtils` wraps the download stream in a `ProgressInputStream` that prints a progress indicator to the console. The indicator is sized using an HTTP `HEAD` request to obtain the `Content-Length` before streaming begins. No configuration is needed; it activates automatically for every download.

***

## Full Example

```java
import org.eclipse.deeplearning4j.omnihub.models.Pretrained;
import org.deeplearning4j.nn.graph.ComputationGraph;
import org.nd4j.linalg.factory.Nd4j;
import org.nd4j.linalg.api.ndarray.INDArray;

public class OmniHubExample {
    public static void main(String[] args) throws Exception {
        // Load VGG19 (no top layers) — downloads on first run, cached thereafter
        ComputationGraph vgg19 = Pretrained.dl4j().vgg19noTop(false);

        // VGG19 no-top expects input shape [batch, 3, 224, 224] (channels-first)
        INDArray input = Nd4j.rand(new int[]{1, 3, 224, 224});
        INDArray[] output = vgg19.output(input);

        System.out.println("VGG19 feature map shape: " + output[0].shapeInfoToString());
    }
}
```

***

***

## Custom Model Repositories (ADR 0076)

Out of the box, OmniHub resolves models from two backends: HuggingFace Hub (tried first, priority 10) and the GitHub-hosted `omnihub-zoo` (fallback, priority 20). The `ModelRepository` interface and `ModelRepositoryRegistry` let you register additional backends — private registries, S3 buckets, on-premise mirrors — without modifying any OmniHub code.

### How the fallback chain works

`OmniHubUtils.downloadAndLoadFromZoo()` internally delegates to `ModelRepositoryRegistry.getDefault().resolve(modelName, framework, forceDownload)`. The registry iterates its list of repositories in ascending priority order, calling `canResolve()` on each. The first repository that returns `true` and whose `resolve()` call succeeds provides the local file. If a repository is tried and throws `IOException`, the registry logs the failure and continues to the next.

### The ModelRepository interface

```java
package org.eclipse.deeplearning4j.omnihub.repository;

public interface ModelRepository {

    /** Human-readable identifier, e.g. "github", "huggingface", "internal-s3". */
    String name();

    /** Priority: lower values are tried first. Built-ins use 10 (HF) and 20 (GitHub). */
    int priority();

    /**
     * Quick check: can this repository potentially serve modelName / framework?
     * Returning true does not guarantee success — resolve() may still throw.
     */
    boolean canResolve(String modelName, String framework);

    /**
     * Download or retrieve from cache the model with the given name and framework.
     * Returns the local File on success; throws IOException if not available.
     */
    File resolve(String modelName, String framework, boolean forceDownload) throws IOException;

    /** Whether this repository supports HuggingFace-style repo ID resolution. */
    boolean supportsHuggingFace();

    /**
     * Resolve a HuggingFace repo by ID (e.g. "TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF")
     * and optional file glob pattern. Returns the local directory.
     */
    File resolveHuggingFace(String huggingFaceId, String filePattern, boolean forceDownload)
            throws IOException;
}
```

### Implementing a custom repository

The following example adds an internal HTTP mirror as a higher-priority source (priority 5 — tried before HuggingFace):

```java
import org.eclipse.deeplearning4j.omnihub.repository.ModelRepository;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

public class InternalMirrorRepository implements ModelRepository {

    private final String baseUrl;
    private final File cacheDir;

    public InternalMirrorRepository(String baseUrl, File cacheDir) {
        this.baseUrl = baseUrl;                        // e.g. "http://ml-mirror.corp.example.com/models"
        this.cacheDir = cacheDir;
    }

    @Override
    public String name() { return "internal-mirror"; }

    @Override
    public int priority() { return 5; }               // tried before HuggingFace (10) and GitHub (20)

    @Override
    public boolean canResolve(String modelName, String framework) {
        // Optimistic: assume this mirror has everything. Replace with a HEAD request if desired.
        return true;
    }

    @Override
    public File resolve(String modelName, String framework, boolean forceDownload) throws IOException {
        File dest = new File(new File(cacheDir, framework), modelName);

        if (dest.exists() && !forceDownload) {
            return dest;
        }

        String url = baseUrl + "/" + framework + "/" + modelName;
        dest.getParentFile().mkdirs();

        try (InputStream in = URI.create(url).toURL().openStream()) {
            Files.copy(in, dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
        }
        return dest;
    }

    @Override
    public boolean supportsHuggingFace() { return false; }

    @Override
    public File resolveHuggingFace(String huggingFaceId, String filePattern, boolean forceDownload) {
        throw new UnsupportedOperationException("Internal mirror does not support HuggingFace IDs");
    }
}
```

### Registering the custom repository

```java
import org.eclipse.deeplearning4j.omnihub.repository.ModelRepositoryRegistry;

ModelRepositoryRegistry registry = ModelRepositoryRegistry.getDefault();

registry.addRepository(new InternalMirrorRepository(
        "http://ml-mirror.corp.example.com/models",
        new File(System.getProperty("user.home"), ".omnihub")
));

// The registry is now: internal-mirror (5) → huggingface (10) → github (20)
// All subsequent OmniHubUtils calls go through the updated registry.
```

You can also **replace** the entire default registry (useful in tests or fully air-gapped environments):

```java
ModelRepositoryRegistry offline = new ModelRepositoryRegistry();
offline.addRepository(new InternalMirrorRepository("http://airgap-server/models",
        new File("/data/model-cache")));

ModelRepositoryRegistry.setDefault(offline);
```

### Targeting a specific repository by name

```java
import org.eclipse.deeplearning4j.omnihub.OmniHubUtils;

// Bypass the fallback chain and go directly to the named repository.
// Throws IOException if the named repository is not registered or cannot resolve the model.
File modelFile = OmniHubUtils.loadFromRepository("internal-mirror", "resnet18.fb", "samediff", false);
```

### Removing a built-in repository

```java
// Remove the GitHub fallback to prevent any outbound traffic to github.com
ModelRepositoryRegistry.getDefault().removeRepository("github");
```

### Default repository priorities at a glance

| Repository name | Priority    | Resolves                                            |
| --------------- | ----------- | --------------------------------------------------- |
| `huggingface`   | 10          | Any GGUF or SafeTensors file on HuggingFace Hub     |
| `github`        | 20          | Named models in the `omnihub-zoo` GitHub repository |
| *(custom)*      | your choice | Whatever your `resolve()` implementation fetches    |

### DSL integration

When using the OmniHub Kotlin DSL to declare model namespaces, you can pin a model to a specific repository by setting the `repository` field. `GGUFModel` and `SafeTensorsModel` builders default to `repository = "huggingface"`; `DL4JModel` and `SameDiffModel` use the full fallback chain by default.

```kotlin
// Kotlin DSL example
GGUFModel(
    name = "llama-3-8b-q4",
    huggingFaceId = "meta-llama/Meta-Llama-3-8B-GGUF",
    filePattern = "*Q4_K_M*.gguf",
    repository = "huggingface"   // explicit; same as default for GGUFModel
)

SameDiffModel(
    name = "resnet18",
    filename = "resnet18.fb",
    repository = null            // null → use the full fallback chain
)
```

***

## Next Steps

* [Available Models](/en-1.0.0-rewrite/omnihub/available-models.md) — full catalog of models in the zoo, with input/output details.
* [OmniHub Overview](/en-1.0.0-rewrite/omnihub/overview.md) — architecture, configuration, and comparison with deeplearning4j-zoo.
