Skip to content

Saving and loading models ​

Fitting takes a moment; predicting from a fitted model is fast. Save a fitted model as JSON and load it later, for example to fit once in a nightly job and forecast on demand in an API.

ts
import { readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";

import { Effect } from "effect";
import {
  decodeFittedModel,
  encodeFittedModel,
  fit,
  predict,
  prophetFittingBackendLayer,
} from "effect-prophet";

const date = (day: number) => new Date(Date.UTC(2025, 0, 1 + day)).toISOString();

const history = Array.from({ length: 90 }, (_, day) => ({
  timestamp: date(day),
  value: 100 + day * 0.5 + 10 * Math.sin((2 * Math.PI * day) / 7),
}));

const file = join(tmpdir(), "effect-prophet-model.json");

// Train once and save the model as plain JSON.
const model = await Effect.runPromise(
  fit(history).pipe(Effect.provide(prophetFittingBackendLayer)),
);

const encoded = await Effect.runPromise(encodeFittedModel(model));

await writeFile(file, JSON.stringify(encoded));

// Later, maybe in another process: load it and forecast without retraining.
const saved: unknown = JSON.parse(await readFile(file, "utf8"));

const forecast = await Effect.runPromise(
  Effect.gen(function* () {
    const restored = yield* decodeFittedModel(saved);

    return yield* predict(restored, [date(90)]);
  }),
);

console.log(forecast[0]?.value.toFixed(2));

await rm(file);

Things to know ​

  • encodeFittedModel turns a model into plain JSON-friendly data. decodeFittedModel checks the data and turns it back into a model.
  • Loading and predicting don't need the forecasting engine, so no layer is required.
  • No refitting happens on load. The restored model gives exactly the same forecasts as the original.
  • Saved models are meant to be loaded by the same version of Effect Prophet. Refit after upgrading.
  • This format is not compatible with Python Prophet's model_to_json.

Inspired by Prophet from Meta. Not affiliated with Meta.