Skip to content
Open
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
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 TimeCopilot Changelog. Here, you will find a comprehensive list of all the changes, updates, and improvements made to the TimeCopilot project. This section is designed to keep you informed about the latest features, bug fixes, and enhancements as we continue to develop and refine the TimeCopilot experience. Stay tuned for regular updates and feel free to explore the details of each release below.

- [v0.0.32](v0.0.32.md)
- [v0.0.31](v0.0.31.md)
- [v0.0.30](v0.0.30.md)
- [v0.0.29](v0.0.29.md)
Expand Down
32 changes: 32 additions & 0 deletions docs/changelogs/v0.0.32.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
### Features

* **TimesFM 3.0 foundation model**: Added support for [`google/timesfm-3.0-pytorch`](https://huggingface.co/google/timesfm-3.0-pytorch) via `foundationforecast>=0.1.3`. Use the existing `TimesFM` class with the 3.0 repo id; no API changes are required in TimeCopilot.

```python
import pandas as pd
from timecopilot.models.foundation.timesfm import TimesFM

df = pd.read_csv(
"https://timecopilot.s3.amazonaws.com/public/data/air_passengers.csv",
parse_dates=["ds"],
)

model = TimesFM(
repo_id="google/timesfm-3.0-pytorch",
alias="TimesFM-3",
context_length=2048,
)
fcst_df = model.forecast(df, h=12, freq="MS")
```

**License note:** TimesFM 3.0 pretrained weights are [non-commercial](https://huggingface.co/google/timesfm-3.0-pytorch/blob/main/LICENSE); TimesFM 1.0–2.5 checkpoints remain Apache-2.0.

* **TimesFM family notebook**: Added [`timesfm-family` example notebook](../examples/timesfm-family.ipynb) comparing TimesFM 1.0, 2.0, 2.5, and 3.0 with supported prediction intervals.

### Dependencies

* Bumped `foundationforecast` from `>=0.1.2` to `>=0.1.3` (includes `timecopilot-timesfm>=0.4.0` and the `_TimesFMV3` backend).

---

**Full Changelog**: https://github.com/TimeCopilot/timecopilot/compare/v0.0.31...v0.0.32
1 change: 1 addition & 0 deletions docs/examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ For model API details, see the [Model Hub](../model-hub.md).
|----------|-------------------|---------------|
| [Compare Foundation Models](ts-foundation-models-comparison-quickstart.ipynb) | Benchmark multiple foundation models side by side | Python 3.10+; GPU optional |
| [Chronos Family](chronos-family.ipynb) | Forecast with Chronos 1.x and 2.x checkpoints | Python 3.10+ |
| [TimesFM Family](timesfm-family.ipynb) | Forecast with TimesFM 1.0, 2.0, 2.5, and 3.0 with prediction intervals | Python 3.10+ |
| [TiRex Family](tirex-family.ipynb) | Forecast with TiRex 1.0 and 2.0 | Python 3.11+ |
| [Toto Family](toto-family.ipynb) | Forecast with Toto 1.0 and 2.0 | Python 3.10+ |
| [Finetuning](finetuning.ipynb) | Adapt Chronos 2 and TimeGPT to your data | Python 3.10+; GPU recommended |
Expand Down
737 changes: 737 additions & 0 deletions docs/examples/timesfm-family.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/model-hub.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ TimeCopilot provides a unified interface to state-of-the-art foundation models f
- [TabPFN](api/models/foundation/models.md#timecopilot.models.foundation.tabpfn) ([arXiv:2501.02945](https://arxiv.org/abs/2501.02945))
- [TiRex / TiRex-2](api/models/foundation/models.md#timecopilot.models.foundation.tirex) ([arXiv:2505.23719](https://arxiv.org/abs/2505.23719), [arXiv:2607.01204](https://arxiv.org/abs/2607.01204))
- [TimeGPT](api/models/foundation/models.md#timecopilot.models.foundation.timegpt) ([arXiv:2310.03589](https://arxiv.org/abs/2310.03589))
- [TimesFM](api/models/foundation/models.md#timecopilot.models.foundation.timesfm) ([arXiv:2310.10688](https://arxiv.org/abs/2310.10688))
- [TimesFM](api/models/foundation/models.md#timecopilot.models.foundation.timesfm) ([arXiv:2310.10688](https://arxiv.org/abs/2310.10688); [3.0 license](https://huggingface.co/google/timesfm-3.0-pytorch/blob/main/LICENSE))
- [Toto](api/models/foundation/models.md#timecopilot.models.foundation.toto) ([arXiv:2505.14766](https://arxiv.org/abs/2505.14766))

---
Expand Down
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ nav:
- Compare Foundation Models: examples/ts-foundation-models-comparison-quickstart.ipynb
- Family Guides:
- Chronos: examples/chronos-family.ipynb
- TimesFM: examples/timesfm-family.ipynb
- TiRex: examples/tirex-family.ipynb
- Toto: examples/toto-family.ipynb
- Finetuning: examples/finetuning.ipynb
Expand All @@ -61,6 +62,7 @@ nav:
- experiments/fev.md
- Changelogs:
- changelogs/index.md
- changelogs/v0.0.32.md
- changelogs/v0.0.31.md
- changelogs/v0.0.30.md
- changelogs/v0.0.29.md
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ dependencies = [
"catboost>=1.2.10",
"datasets>=4.1.1",
"fire",
"foundationforecast>=0.1.2",
"foundationforecast>=0.1.3",
"fsspec>=2025.9.0",
"huggingface-hub>=0.36.2,<2.0",
"hydra-core>=1.3.2",
Expand Down Expand Up @@ -107,7 +107,7 @@ license = "MIT"
name = "timecopilot"
readme = "README.md"
requires-python = ">=3.10"
version = "0.0.31"
version = "0.0.32"

[project.optional-dependencies]
distributed = [
Expand Down
4 changes: 4 additions & 0 deletions tests/models/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ def disable_mps_session(monkeypatch):
repo_id="google/timesfm-2.5-200m-pytorch",
context_length=256,
),
TimesFM(
repo_id="google/timesfm-3.0-pytorch",
context_length=256,
),
Comment thread
AzulGarza marked this conversation as resolved.
MedianEnsemble(
models=[
Chronos(repo_id="amazon/chronos-t5-tiny", alias="Chronos-T5"),
Expand Down
32 changes: 30 additions & 2 deletions tests/models/foundation/test_timesfm.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os

import pytest
from foundationforecast.models.timesfm import _TimesFMV1, _TimesFMV2_p5
from foundationforecast.models.timesfm import _TimesFMV1, _TimesFMV2_p5, _TimesFMV3

MODEL_PARAMS = [
(
Expand All @@ -17,6 +17,13 @@
"foundationforecast.models.timesfm.TimesFM_2p5_200M_torch",
],
),
(
_TimesFMV3,
[
"foundationforecast.models.timesfm.ModelConfig",
"foundationforecast.models.timesfm.TimesFM3Evaluator",
],
),
]


Expand Down Expand Up @@ -46,9 +53,15 @@ def test_load_model_from_local_path(mocker, model_class, mock_paths):
expected_path = os.path.join(local_path, "torch_model.ckpt")
mock_loader[0].assert_called_once_with(path=expected_path)
elif model_class is _TimesFMV2_p5:
# `from_pretrained` handles both local directories and HF repos.
assert predictor is mock_loader[0].from_pretrained.return_value
mock_loader[0].from_pretrained.assert_called_once_with(local_path)
elif model_class is _TimesFMV3:
assert predictor is mock_loader[1].return_value
mock_loader[0].assert_called_once_with(
checkpoint_path=local_path,
per_core_batch_size=32,
)
mock_loader[1].assert_called_once_with(mock_loader[0].return_value)


@pytest.mark.parametrize("model_class, mock_paths", MODEL_PARAMS)
Expand Down Expand Up @@ -80,6 +93,13 @@ def test_load_model_from_hf_repo(mocker, model_class, mock_paths):
elif model_class is _TimesFMV2_p5:
assert predictor is mock_loader[0].from_pretrained.return_value
mock_loader[0].from_pretrained.assert_called_once_with(repo_id)
elif model_class is _TimesFMV3:
assert predictor is mock_loader[1].return_value
mock_loader[0].assert_called_once_with(
checkpoint_path=repo_id,
per_core_batch_size=32,
)
mock_loader[1].assert_called_once_with(mock_loader[0].return_value)


@pytest.mark.parametrize("model_class, _", MODEL_PARAMS)
Expand All @@ -106,3 +126,11 @@ def test_model_raises_OSError_on_failed_load(mocker, model_class, _):

mock_os_exists.assert_called_once_with(repo_id)
mock_repo_exists.assert_called_once_with(repo_id)


def test_timesfm_routes_3_0_repo():
from timecopilot.models.foundation.timesfm import TimesFM

model = TimesFM(repo_id="google/timesfm-3.0-pytorch")
assert isinstance(model, _TimesFMV3)
assert model.repo_id == "google/timesfm-3.0-pytorch"
16 changes: 8 additions & 8 deletions uv.lock

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

Loading