Skip to Content
How it works@ignitionai/storage

@ignitionai/storage

Single responsibility: persist and fetch trained agent weights. The first implementation targets HuggingFace Hub; the ModelStorageProvider interface is the extension point for other backends (S3, IPFS, local filesystem, whatever you need).

Source: packages/storage/src/ on GitHub.

Public API surface

ExportKindPurpose
ModelStorageProviderinterfaceThe contract any storage backend must implement.
ModelInfotypeMetadata for a stored model (modelId, uri, createdAt, metadata).
HuggingFaceProviderclassCloud persistence via HuggingFace Hub.
IndexedDBProviderclassBrowser persistence for large models (recommended).
LocalStorageProviderclassBrowser persistence for small models & metadata.
DownloadProviderclassExport model as downloadable file (write-only).
HFStorageConfigtypeConfig for HuggingFaceProvider (token, repoId).
hfStorageConfigSchemaZod schemaValidation for HFStorageConfig.
parseHFConfigfunctionParses and validates the HF config from environment variables.

The ModelStorageProvider interface

This is the contract. Anything implementing it is a valid storage backend:

export interface ModelStorageProvider { save(modelId: string, model: tf.LayersModel, metadata?: Record<string, unknown>): Promise<void> load(modelId: string): Promise<tf.LayersModel> list(): Promise<ModelInfo[]> delete(modelId: string): Promise<void> exists(modelId: string): Promise<boolean> }

Five methods. That’s the whole surface area. If you wanted to add, say, an S3 backend, you’d implement those five methods and publish it as @ignitionai/storage-s3. The rest of the framework doesn’t need to change.

Browser-local providers

For development and small models, you don’t need a cloud account. Three browser-native providers ship out of the box:

ProviderBest forSize limitLoad support
IndexedDBProviderLarge TF.js models~50-100 MB (browser quota)✅ Yes
LocalStorageProviderSmall models, configs, metadata~5 MB✅ Yes
DownloadProviderExporting for external useNo limit (user’s disk)❌ No
browser-save.ts
import { IgnitionEnvTFJS } from '@ignitionai/backend-tfjs' import { CartPoleEnv } from '@ignitionai/environments' import { IndexedDBProvider } from '@ignitionai/storage' const env = new IgnitionEnvTFJS(new CartPoleEnv()) env.train('dqn', { storageProvider: new IndexedDBProvider() }) // Later — save the current checkpoint await env.save('cartpole-dqn-v1', { reward: 195.4 }) // Even later — load it back await env.load('cartpole-dqn-v1')

env.save() serializes the model weights and the agent’s internal state (epsilon, trainStepCounter, bestReward). env.load() restores both. No manual bookkeeping.

LocalStorage — for configs and Q-Tables

localstorage-save.ts
import { LocalStorageProvider } from '@ignitionai/storage' const env = new IgnitionEnvTFJS(new CartPoleEnv()) env.train('qtable', { storageProvider: new LocalStorageProvider() }) await env.save('cartpole-qtable-v1')

Q-Table agents serialize their entire table as JSON, so LocalStorageProvider is a perfect fit. For neural-network agents, prefer IndexedDBProvider — TF.js weights can easily exceed the 5 MB localStorage limit.

Download — export for external use

download.ts
import { DownloadProvider } from '@ignitionai/storage' const env = new IgnitionEnvTFJS(new CartPoleEnv()) env.train('dqn') // Triggers a browser download of model.json + weights.bin await env.save('my-model', { download: true })

DownloadProvider is write-only. Use it when you want to hand off a trained model to someone else or archive it outside the browser.

HuggingFace Hub — cloud persistence

HuggingFaceProvider wraps the huggingface.js client and saves / loads TF.js models directly from a HF repo. HF Hub is a natural fit for RL weights because it already handles versioning, public/private visibility, and a web UI for browsing.

Setup

  1. Create a HuggingFace account and a new model repository (e.g., your-user/my-rl-agent).
  2. Generate an access token at huggingface.co/settings/tokens  with Write access to the repo.
  3. Set the token and repo as environment variables (or pass them inline):
export HF_TOKEN=hf_... export HF_REPO_ID=your-user/my-rl-agent

A complete save / load round-trip

save-and-load.ts
import { IgnitionEnvTFJS } from '@ignitionai/backend-tfjs' import { CartPoleEnv } from '@ignitionai/environments' import { HuggingFaceProvider, parseHFConfig } from '@ignitionai/storage' // 1. Train an agent const cartpole = new CartPoleEnv() const env = new IgnitionEnvTFJS(cartpole) env.train('dqn', { storageProvider: new HuggingFaceProvider(parseHFConfig(process.env)) }) // ... wait for convergence ... env.stop() // 2. Save the trained model (weights + agent state + metadata) await env.save('cartpole-dqn-v1', { episodesTrained: 500, meanReward: 195.4, }) // 3. Later — load the same model into a fresh agent await env.load('cartpole-dqn-v1') console.log('Model loaded, epsilon:', (env.agent as any).epsilon)

Four lines to save. Two lines to load. The metadata object is stored alongside the weights and is returned by list().

Listing and deleting

manage.ts
import { HuggingFaceProvider, parseHFConfig } from '@ignitionai/storage' const storage = new HuggingFaceProvider(parseHFConfig(process.env)) // See what's in the repo const models = await storage.list() for (const model of models) { console.log(`${model.modelId} — created ${model.createdAt}`) console.log(` metadata: ${JSON.stringify(model.metadata)}`) } // Check if a specific model exists if (await storage.exists('cartpole-dqn-v1')) { // Delete it await storage.delete('cartpole-dqn-v1') }

Security note — tokens

The HF token has Write access to the repo, so treat it like a password:

  • Never hard-code it into source files.
  • In Node, read from process.env.HF_TOKEN.
  • In the browser, do not use a write-enabled token at all — use a read-only token (or no token at all for public repos) for the load path, and do your writes from a backend.
  • parseHFConfig will throw if the token is missing or malformed, so you’ll notice the misconfiguration immediately.

Using it alongside the ONNX path

The HF Hub flow is for TF.js-native weights (training + checkpointing). If you want to deploy a trained model, you can either:

  • Save the TF.js weights via @ignitionai/storage — fastest for iterating between train and test runs in JS.
  • Export to ONNX via @ignitionai/backend-onnx — necessary for deploying to Unity, Unreal, Python, or mobile.

These aren’t mutually exclusive. A common workflow is: save TF.js checkpoints to HF during training (fast iteration), and export the final version to ONNX once you’re happy with it (deploy).

Adding your own storage backend

To add an S3 backend:

s3-provider.ts
import type { ModelStorageProvider, ModelInfo } from '@ignitionai/storage' import * as tf from '@tensorflow/tfjs' export class S3Provider implements ModelStorageProvider { constructor(private bucket: string, private region: string) {} async save(modelId: string, model: tf.LayersModel, metadata?: Record<string, unknown>): Promise<void> { // ... serialize model, upload to S3 ... } async load(modelId: string): Promise<tf.LayersModel> { // ... download from S3, deserialize ... } async list(): Promise<ModelInfo[]> { /* ... */ return [] } async delete(modelId: string): Promise<void> { /* ... */ } async exists(modelId: string): Promise<boolean> { /* ... */ return false } }

Five methods, zero changes to any other package. That’s the shape of every good extension point in IgnitionAI.


Previous: ← @ignitionai/backend-onnx · Next: React Three Fiber →

Last updated on