Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Some models require specific Python versions (e.g. FlowState 3.11-3.13, TabPFN &
- **Moirai:** `Salesforce/moirai-{1.0,1.1,2.0}-R-{small,base,large}`, `Salesforce/moirai-moe-1.0-R-*`
- **PatchTST-FM:** `ibm-research/patchtst-fm-r1`
- **Sundial:** `thuml/sundial-base-128m`
- **T0:** `theforecastingcompany/t0-alpha`
- **T0:** `theforecastingcompany/t0-alpha`, `theforecastingcompany/t0-beta` (requires `tfc-t0>=0.5.0`)
- **TabPFN:** default `tabpfn-v2-regressor-2noar4o2.ckpt`; TabPFN-3 via `model_path="tabpfn-v3-regressor-v3_20260506_timeseries.ckpt"` (LOCAL, `TABPFN_TOKEN`); or CLIENT mode with a Prior Labs API token
- **Tafsut:** `Tafsut-FM/tafsut-univariate-base`
- **TiRex:** `NX-AI/TiRex`, `NX-AI/TiRex-2`
Expand Down
1 change: 1 addition & 0 deletions docs/changelogs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

Welcome to the FoundationForecast Changelog. Here you will find a list of changes, updates, and improvements for each release. Explore the details of each version below.

- [v0.1.8](v0.1.8.md)
- [v0.1.7](v0.1.7.md)
- [v0.1.6](v0.1.6.md)
- [v0.1.5](v0.1.5.md)
Expand Down
31 changes: 31 additions & 0 deletions docs/changelogs/v0.1.8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
### Features

* **T0 beta support**: The shared [`T0`](../api/models/foundation/models.md#foundationforecast.models.t0.T0) wrapper now works with [`theforecastingcompany/t0-beta`](https://huggingface.co/theforecastingcompany/t0-beta) (~256M). Register it in gift-eval `models.yaml`; GIFT-Eval CI still replicates `t0-alpha` until leaderboard results exist for beta.

```python
import pandas as pd
from foundationforecast.models.t0 import T0

df = pd.read_csv(
"https://timecopilot.s3.amazonaws.com/public/data/air_passengers.csv",
parse_dates=["ds"],
)
model = T0(
repo_id="theforecastingcompany/t0-beta",
alias="t0-beta",
)
fcst = model.forecast(df, h=12, freq="D", quantiles=[0.1, 0.5, 0.9])
assert "t0-beta" in fcst.columns
```

### Fixes

* **T0 / gift-eval CI**: Bump `tfc-t0` to `>=0.5.0` and call `T0Forecaster.predict(quantile_levels=...)` instead of the removed `quantiles=` kwarg. Fixes gift-eval Modal runs after PyPI resolved `tfc-t0` 0.5.0 alongside the t0-beta release.

### Dependencies

* Bumped `tfc-t0` from `>=0.2.3` to `>=0.5.0` (required for t0-beta; still supports t0-alpha).
Comment on lines +25 to +27

---

**Full Changelog**: https://github.com/TimeCopilot/foundationforecast/compare/v0.1.7...v0.1.8
2 changes: 1 addition & 1 deletion docs/model-hub.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Below is the list of available foundation models. Click a model name for API det
- [Moirai](api/models/foundation/models.md#foundationforecast.models.moirai.Moirai) ([arXiv:2402.02592](https://arxiv.org/abs/2402.02592))
- [PatchTST-FM](api/models/foundation/models.md#foundationforecast.models.patchtst_fm.PatchTSTFM) ([arXiv:2602.06909](https://arxiv.org/abs/2602.06909)) — Python 3.11–3.13
- [Sundial](api/models/foundation/models.md#foundationforecast.models.sundial.Sundial) ([arXiv:2502.00816](https://arxiv.org/pdf/2502.00816))
- [T0](api/models/foundation/models.md#foundationforecast.models.t0.T0) ([model card](https://huggingface.co/theforecastingcompany/t0-alpha)) — Python 3.11–3.13
- [T0](api/models/foundation/models.md#foundationforecast.models.t0.T0) ([t0-alpha](https://huggingface.co/theforecastingcompany/t0-alpha), [t0-beta](https://huggingface.co/theforecastingcompany/t0-beta); requires `tfc-t0>=0.5.0` for beta) — Python 3.11–3.13
- [TabPFN](api/models/foundation/models.md#foundationforecast.models.tabpfn.TabPFN) ([arXiv:2501.02945](https://arxiv.org/abs/2501.02945)) — Python 3.10–3.12; TabPFN-2 (default) and TabPFN-3 via `model_path`; TabPFN-3 is LOCAL-only; weights use the [TabPFN NC license](https://ux.priorlabs.ai) (`TABPFN_TOKEN`)
- [Tafsut](api/models/foundation/models.md#foundationforecast.models.tafsut.Tafsut) ([GitHub](https://github.com/Tafsut-FM/tafsut))
- [TiRex / TiRex-2](api/models/foundation/models.md#foundationforecast.models.tirex.TiRex) ([arXiv:2505.23719](https://arxiv.org/abs/2505.23719), [arXiv:2607.01204](https://arxiv.org/abs/2607.01204)) — Python 3.11+
Expand Down
8 changes: 8 additions & 0 deletions experiments/gift-eval/configs/models.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ models:
repo_id: theforecastingcompany/t0-alpha
batch_size: 32

theforecastingcompany--t0-beta:
class: foundationforecast.models.t0.T0
reference_slug: null
kwargs:
repo_id: theforecastingcompany/t0-beta
alias: t0-beta
batch_size: 16

thuml--sundial-base-128m:
class: foundationforecast.models.sundial.Sundial
reference_slug: sundial_base_128m
Expand Down
10 changes: 10 additions & 0 deletions experiments/gift-eval/tests/test_models_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from src.eval.jobs import load_models_config


def test_t0_beta_registered_in_models_yaml():
models = load_models_config()
entry = models["theforecastingcompany--t0-beta"]
assert entry["class"] == "foundationforecast.models.t0.T0"
assert entry["reference_slug"] is None
assert entry["kwargs"]["repo_id"] == "theforecastingcompany/t0-beta"
assert entry["kwargs"]["alias"] == "t0-beta"
10 changes: 5 additions & 5 deletions experiments/gift-eval/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 7 additions & 6 deletions foundationforecast/models/t0.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,15 @@ def __init__(
Notes:
**Requirements:**

- T0 requires Python 3.11 to 3.13 (via the
[`tfc-t0`](https://pypi.org/project/tfc-t0/) package).
- T0 requires Python 3.11 to 3.13 and ``tfc-t0>=0.5.0`` (required
for ``t0-beta``; also supports ``t0-alpha``).

**Available models:**

| Model ID | Parameters |
| ------------------------------------------------------------------------------------------------- | ---------- |
| [`theforecastingcompany/t0-alpha`](https://huggingface.co/theforecastingcompany/t0-alpha) | ~102M |
| [`theforecastingcompany/t0-beta`](https://huggingface.co/theforecastingcompany/t0-beta) | ~256M |

**Resources:**

Expand All @@ -79,9 +80,9 @@ def __init__(

- The model is loaded onto the best available device (GPU if
available, otherwise CPU).
- T0 predicts 5 quantile knots (0.1, 0.25, 0.5, 0.75, 0.9); the
median (0.5) is used as the point forecast and other requested
quantiles are obtained by linear interpolation across the knots.
- ``t0-alpha`` predicts 5 quantile knots (0.1, 0.25, 0.5, 0.75, 0.9);
``t0-beta`` predicts 21 native levels (0.01–0.99). Requested
quantiles are interpolated; the median (0.5) is the point forecast.
- NaN values in the context are treated as missing observations.
- T0 natively supports past and known-future covariates through its
`predict` API; this integration currently exposes the univariate
Expand Down Expand Up @@ -194,7 +195,7 @@ def forecast(
out = model.predict(
self._to_context(batch),
horizon=h,
quantiles=pred_quantiles,
quantile_levels=pred_quantiles,
)
# shape: (batch, h, n_quantiles)
fcsts.append(out.quantiles.cpu().numpy())
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ nav:
- Contributing: contributing.md
- Changelogs:
- changelogs/index.md
- changelogs/v0.1.8.md
- changelogs/v0.1.7.md
- changelogs/v0.1.6.md
- changelogs/v0.1.5.md
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ dependencies = [
"scipy",
"tabpfn-time-series>=1.2.0 ; python_full_version < '3.13'",
"tafsut>=0.1.0",
"tfc-t0>=0.2.3 ; python_full_version >= '3.11' and python_full_version < '3.14'",
"tfc-t0>=0.5.0 ; python_full_version >= '3.11' and python_full_version < '3.14'",
"timecopilot-chronos-forecasting>=0.2.2",
"timecopilot-granite-tsfm>=0.2.1 ; python_full_version >= '3.11' and python_full_version < '3.14'",
"timecopilot-timesfm>=0.4.0",
Expand Down
8 changes: 8 additions & 0 deletions tests/models/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@
from foundationforecast.models.t0 import T0

models.append(T0(context_length=256, batch_size=2))
models.append(
T0(
repo_id="theforecastingcompany/t0-beta",
alias="t0-beta",
context_length=256,
batch_size=2,
)
)

if (3, 11) <= sys.version_info < (3, 14):
from foundationforecast.models.flowstate import FlowState
Expand Down
68 changes: 68 additions & 0 deletions tests/models/test_t0.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import sys
from unittest.mock import MagicMock

import numpy as np
import pytest

if sys.version_info < (3, 11) or sys.version_info >= (3, 14):
pytest.skip(
"T0 requires Python >= 3.11 and < 3.14",
allow_module_level=True,
)

import pandas as pd # noqa: E402

from tests.helpers import generate_series # noqa: E402
from foundationforecast.models.t0 import T0 # noqa: E402

pytestmark = pytest.mark.models


def test_t0_forecast_passes_quantile_levels(mocker):
model = T0(context_length=64, batch_size=2)
df = generate_series(2, freq="D", min_length=32, max_length=32)

mock_forecaster = MagicMock()
mock_out = MagicMock()
mock_out.quantiles.cpu.return_value.numpy.return_value = np.ones((2, 3, 3))
mock_forecaster.predict.return_value = mock_out

mock_cm = MagicMock()
mock_cm.__enter__.return_value = mock_forecaster
mock_cm.__exit__.return_value = None
mocker.patch.object(model, "_get_model", return_value=mock_cm)

model.forecast(df, h=3, freq="D", quantiles=[0.1, 0.9])

kwargs = mock_forecaster.predict.call_args.kwargs
assert kwargs["quantile_levels"] == [0.1, 0.5, 0.9]
assert "quantiles" not in kwargs


def test_t0_beta_forecast():
df = generate_series(2, freq="D", min_length=50, max_length=50)
model = T0(
repo_id="theforecastingcompany/t0-beta",
alias="t0-beta",
context_length=256,
batch_size=2,
)
fcst = model.forecast(df, h=3, freq="D")
assert fcst.shape == (6, 3)
assert "t0-beta" in fcst.columns


def test_t0_beta_quantile_forecast():
df = generate_series(2, freq="D", min_length=50, max_length=50)
model = T0(
repo_id="theforecastingcompany/t0-beta",
alias="t0-beta",
context_length=256,
batch_size=2,
)
fcst = model.forecast(df, h=3, freq="D", quantiles=[0.1, 0.9])
assert fcst.shape == (6, 5)
assert "t0-beta" in fcst.columns
assert "t0-beta-q-10" in fcst.columns
assert "t0-beta-q-90" in fcst.columns
assert pd.api.types.is_numeric_dtype(fcst["t0-beta-q-10"])
8 changes: 4 additions & 4 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading