> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runanywhere.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Models

> Find, download, load, switch, and remove models

`RunAnywhere.models` is the model catalog and its residency.

## The short version

Generation loads what it needs and downloads when `options.model` names a model that is not on
disk:

```dart theme={null}
final result = await RunAnywhere.llm.generate(
  'Hello',
  options: LlmOptions(model: 'qwen3-0.6b'),
);
```

Reach for the `models` namespace to control **when** that cost is paid, show progress, or let a
person choose.

## What is available

```dart theme={null}
final models = await RunAnywhere.models.list();
final model = await RunAnywhere.models.get('qwen3-0.6b');
```

<Note>
  `list` takes a **positional optional** filter, so it is `list(filter)` and not `list(filter:
      filter)`. Same for `unloadAll(category)`.
</Note>

```dart theme={null}
final language = await RunAnywhere.models.list(
  ModelFilter(category: ModelCategory.MODEL_CATEGORY_LANGUAGE),
);
```

## Downloading, with progress

`download` returns a `Stream<DownloadEvent>`.

```dart theme={null}
await for (final event in RunAnywhere.models.download('qwen3-0.6b')) {
  if (event is DownloadEventProgress) {
    setState(() {
      _fraction = event.fraction ?? 0;
      _speed = event.bytesPerSecond;
    });
  }
}
```

With a subscription, so you can cancel:

```dart theme={null}
_subscription = RunAnywhere.models.download(id).listen(
  (event) {
    if (event is DownloadEventProgress) {
      setState(() => _fraction = event.fraction ?? 0);
    }
  },
  onError: (Object e) => setState(() => _error = e.toString()),
  onDone: () => setState(() => _done = true),
);
```

Cancel it in `dispose`, and check `mounted` before every `setState` that follows an `await`.

Progress carries `bytesDone`, `bytesTotal`, `fraction`, `percent`, `bytesPerSecond`,
`etaSeconds`, `retryAttempt`, `currentFileIndex`, `totalFiles`, and `overallProgress`.

## Loading

```dart theme={null}
final loaded = await RunAnywhere.models.load('qwen3-0.6b');

final tuned = await RunAnywhere.models.load(
  'qwen3-0.6b',
  options: LoadOptions(contextLength: 4096, threads: 4),
);
```

| Field                | Meaning                                  |
| -------------------- | ---------------------------------------- |
| `backendPreferences` | Ordered preference; each can be required |
| `accelerator`        | Accelerator policy                       |
| `contextLength`      | Context window to allocate               |
| `threads`            | CPU threads                              |
| `forceReload`        | Reload even if already resident          |
| `framework`          | Pin to one backend                       |
| `useGpu`             | Request GPU execution                    |

`contextLength` costs memory whether you use it or not.

## Switching models

```dart theme={null}
class ModelSwitcher {
  String? _current;

  Future<void> use(String id) async {
    final current = _current;
    if (current != null && current != id) {
      await RunAnywhere.models.unload(current);
    }
    await RunAnywhere.models.load(id);
    _current = id;
  }
}
```

On a phone, unload before loading. Or switch per call, without touching residency:

```dart theme={null}
await RunAnywhere.llm.generate(prompt, options: LlmOptions(model: 'qwen3-0.6b'));
await RunAnywhere.llm.generate(prompt, options: LlmOptions(model: 'llama-3.2-1b'));
```

## Unloading

```dart theme={null}
await RunAnywhere.models.unload('qwen3-0.6b');
await RunAnywhere.models.unloadAll(ModelCategory.MODEL_CATEGORY_LANGUAGE);
await RunAnywhere.models.unloadAll();
```

Frees memory and leaves the file on disk. Do this in `dispose`, and on
`AppLifecycleState` change if you hold several models.

## What is resident right now

```dart theme={null}
final state = await RunAnywhere.models.state();
```

## Deleting

```dart theme={null}
await RunAnywhere.models.delete('qwen3-0.6b');
await RunAnywhere.models.unregister('qwen3-0.6b');
```

## Registering your own model

```dart theme={null}
final info = await RunAnywhere.models.register(registration);
```

## Refreshing the registry

```dart theme={null}
await RunAnywhere.models.refresh();
```

Reconciles the catalog against the bytes actually on disk.

## A complete picker

```dart theme={null}
class ModelPicker extends ChangeNotifier {
  List<ModelInfo> models = const [];
  String? downloading;
  double fraction = 0;

  Future<void> refresh() async {
    models = await RunAnywhere.models.list(
      ModelFilter(category: ModelCategory.MODEL_CATEGORY_LANGUAGE),
    );
    notifyListeners();
  }

  Future<void> download(String id) async {
    downloading = id;
    fraction = 0;
    notifyListeners();

    try {
      await for (final event in RunAnywhere.models.download(id)) {
        if (event is DownloadEventProgress) {
          fraction = event.fraction ?? 0;
          notifyListeners();
        }
      }
      await refresh();
    } finally {
      downloading = null;
      notifyListeners();
    }
  }

  Future<void> use(String id) async {
    await RunAnywhere.models.unloadAll(ModelCategory.MODEL_CATEGORY_LANGUAGE);
    await RunAnywhere.models.load(id);
  }

  Future<void> delete(String id) async {
    await RunAnywhere.models.delete(id);
    await refresh();
  }
}
```

## Errors worth handling

| Code                  | Cause                            |
| --------------------- | -------------------------------- |
| `modelNotFound`       | The id is not in the registry    |
| `insufficientStorage` | Not enough disk for the download |
| `insufficientMemory`  | The model will not fit in RAM    |
| `networkUnavailable`  | A download needs a connection    |
