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
encodeFittedModelturns a model into plain JSON-friendly data.decodeFittedModelchecks 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.