From eb065c5cbc4ba14e5b81ab27ceb3547e12c4a1a5 Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:16:55 -0500 Subject: [PATCH 01/11] feat: adapter for sktime forecasters --- timecopilot/models/sktime.py | 88 ++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 timecopilot/models/sktime.py diff --git a/timecopilot/models/sktime.py b/timecopilot/models/sktime.py new file mode 100644 index 0000000..60c47c6 --- /dev/null +++ b/timecopilot/models/sktime.py @@ -0,0 +1,88 @@ +from typing import Any + +import numpy as np +import pandas as pd + +from .utils.forecaster import Forecaster + +# from sktime.forecasting.base import BaseForecaster, ForecastingHorizon + +# NOTE: SKTime notes +# https://www.sktime.net/en/stable/examples/01_forecasting.html# +# https://www.sktime.net/en/stable/api_reference/auto_generated/sktime.forecasting.base.BaseForecaster.html +# NOTE: forecaster setup args vary, that setup is currently being left to users +# TODO: some forecasters require horizon be provided in fit() call, account for that +# TODO: exogenous data support +# TODO: different alias for different sktime forecasters +# should this be required? + + +class SKTimeAdapter(Forecaster): + """ + Wrapper for SKTime Forecaster models for time series forecasting. + + + See the [official documentation](https://www.sktime.net/en/stable/api_reference/auto_generated/sktime.forecasting.base.BaseForecaster.html) + for more details. + """ + + def __init__( + self, + model, + # model: BaseForecaster, + alias: str = "SKTimeAdapter", + *args: Any, + **kwargs: Any, + ): + """ + Args: + alias (str, optional): Custom name for the model instance. + Default is "SKTimeAdapter". + *args: Additional positional arguments passed to SKTimeAdapter. + **kwargs: Additional keyword arguments passed to SKTimeAdapter. + """ + super().__init__(*args, **kwargs) + self.alias = alias + self.model = model + + def forecast( + self, + df: pd.DataFrame, + h: int, + freq: str | None = None, + level: list[int | float] | None = None, + quantiles: list[float] | None = None, + ) -> pd.DataFrame: + # TODO: support for exogenous data + # TODO: add support for level for sktime models that can support it + # TODO: add support for quantiles for sktime models that can support it + if level is not None: + raise ValueError( + "Level and quantiles are not supported for adapted sktime models yet." + ) + # NOTE: may not be needed + freq = self._maybe_infer_freq(df, freq) + forecast_horizon = np.arange(1, 1 + h) + id_col = "unique_id" + datetime_col = "ds" + y_col = "y" + df = df.copy() + df[datetime_col] = pd.to_datetime(df[datetime_col]) + df = df.set_index([id_col, datetime_col]) + + # some sktime models require fh be passed in fit() + model = self.model + model.fit(y=df, fh=forecast_horizon) + # fh doesn't need to be passed in predict because it is being passed in fit + # if quantiles is not None: + # print("sktime quantile pred") + # fcst_df = model.predict_quantiles( + # alpha=qc.quantiles + # ) + # fcst_df = fcst_df.reset_index() + # return fcst_df + fcst_df = model.predict() + fcst_df = fcst_df.reset_index() + # fcst_df = qc.maybe_convert_quantiles_to_level(fcst_df, models=[self.alias]) + fcst_df.rename(columns={y_col: self.alias}, inplace=True) + return fcst_df From a278e5e0018b8530510d6d9e7cd78c46267f6efd Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:18:06 -0500 Subject: [PATCH 02/11] docs: example notebook for sktime --- docs/examples/sktime.ipynb | 416 +++++++++++++++++++++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 docs/examples/sktime.ipynb diff --git a/docs/examples/sktime.ipynb b/docs/examples/sktime.ipynb new file mode 100644 index 0000000..02f4f61 --- /dev/null +++ b/docs/examples/sktime.ipynb @@ -0,0 +1,416 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e890f3b3", + "metadata": {}, + "source": [ + "# Using sktime models\n", + "\n", + "This is an example for using sktime based models with the `timecopilot` library." + ] + }, + { + "cell_type": "markdown", + "id": "6140af37", + "metadata": {}, + "source": [ + "## imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f5c85b29", + "metadata": {}, + "outputs": [], + "source": [ + "import nest_asyncio\n", + "nest_asyncio.apply()\n", + "\n", + "import timecopilot\n", + "import sktime as skt\n", + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "id": "694b7854", + "metadata": {}, + "source": [ + "## Setup the sktime model and adapt it to TimeCopilot\n", + "\n", + "sktime models need to be adapted to work properly with TimeCopilot. This is done by creating your model with sktime and passing it through SKTimeAdapter. Some sktime models may require more configuration to function properly with the data you intend to use it on. For example, when using sktime's NaiveForecaster with yearly data you might want to initialize it with an `sp` argument of `12` like this `NaiveForecaster(sp=12)`.\n", + "\n", + "The `Alias` argument should also be provided, especially if you plan on adding multiple sktime forecasters. If you add multiple sktime models without specifying aliases, TimeCopilot will not be able to properly call all of them." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "e1870fe0", + "metadata": {}, + "outputs": [], + "source": [ + "from sktime.forecasting.trend import TrendForecaster\n", + "from timecopilot.models.sktime import SKTimeAdapter\n", + "\n", + "trend_forecaster = TrendForecaster()\n", + "\n", + "adapted_model = SKTimeAdapter(\n", + " model=trend_forecaster,\n", + " alias=\"TrendForecaster\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "37419dd4", + "metadata": {}, + "source": [ + "## Create a TimeCopilot instance with your sktime model\n", + "\n", + "You will need to specify the forecasters you're using when using sktime models. " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "f793b038", + "metadata": {}, + "outputs": [], + "source": [ + "tc = timecopilot.TimeCopilot(\n", + " llm=\"openai:gpt-4o\",\n", + " forecasters=[\n", + " adapted_model,\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "401d5b6f", + "metadata": {}, + "source": [ + "### Extending default model list with an sktime adapted model\n", + "\n", + "if you want to use the default list with the addition of your sktime model you could make a copy of the default list and append your model to it:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "76505216", + "metadata": {}, + "outputs": [], + "source": [ + "model_list = timecopilot.agent.DEFAULT_MODELS.copy()\n", + "model_list.append(adapted_model)\n", + "\n", + "tc = timecopilot.TimeCopilot(\n", + " llm=\"openai:gpt-4o\",\n", + " forecasters=model_list\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "2d6f09e4", + "metadata": {}, + "source": [ + "## Forecasting \n", + "Once that setup is complete, you can use TimeCopilot with your adapted sktime model the same way you'd normally use TimeCopilot" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "e9122229", + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv(\"https://timecopilot.s3.amazonaws.com/public/data/air_passengers.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "f95e1578", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1it [00:00, 4.70it/s]\n", + "1it [00:00, 223.32it/s]\n", + "11it [00:00, 77.11it/s]\n" + ] + } + ], + "source": [ + "result = tc.forecast(\n", + " df=df,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "7355c143", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The 'AirPassengers' time series has a series length of 144 with a clear seasonal pattern identified using key features. The high 'seasonal_strength' of 0.981 suggests strong seasonality, evident from the 12-month seasonal period. The time series also exhibits trends, shown by a 'trend' score of 0.997, and moderate curvature at 1.069. The high autocorrelation 'x_acf1' at 0.948 indicates the persistence of patterns over time. The Holt-Winters parameters suggest a stable level (alpha ~1) with no trend component (beta ~0) and significant seasonal smoothing (gamma ~0.75). These features suggest that both trend and seasonality are prominent and need to be captured by the model.\n" + ] + } + ], + "source": [ + "print(result.output.tsfeatures_analysis)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "86acfa60", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
unique_iddsTrendForecaster
0AirPassengers1961-01-01473.023018
1AirPassengers1961-02-01475.729097
2AirPassengers1961-03-01478.173296
3AirPassengers1961-04-01480.879374
4AirPassengers1961-05-01483.498159
5AirPassengers1961-06-01486.204237
6AirPassengers1961-07-01488.823023
7AirPassengers1961-08-01491.529101
8AirPassengers1961-09-01494.235179
9AirPassengers1961-10-01496.853964
10AirPassengers1961-11-01499.560042
11AirPassengers1961-12-01502.178827
12AirPassengers1962-01-01504.884906
13AirPassengers1962-02-01507.590984
14AirPassengers1962-03-01510.035183
15AirPassengers1962-04-01512.741261
16AirPassengers1962-05-01515.360046
17AirPassengers1962-06-01518.066125
18AirPassengers1962-07-01520.684910
19AirPassengers1962-08-01523.390988
20AirPassengers1962-09-01526.097066
21AirPassengers1962-10-01528.715851
22AirPassengers1962-11-01531.421929
23AirPassengers1962-12-01534.040714
\n", + "
" + ], + "text/plain": [ + " unique_id ds TrendForecaster\n", + "0 AirPassengers 1961-01-01 473.023018\n", + "1 AirPassengers 1961-02-01 475.729097\n", + "2 AirPassengers 1961-03-01 478.173296\n", + "3 AirPassengers 1961-04-01 480.879374\n", + "4 AirPassengers 1961-05-01 483.498159\n", + "5 AirPassengers 1961-06-01 486.204237\n", + "6 AirPassengers 1961-07-01 488.823023\n", + "7 AirPassengers 1961-08-01 491.529101\n", + "8 AirPassengers 1961-09-01 494.235179\n", + "9 AirPassengers 1961-10-01 496.853964\n", + "10 AirPassengers 1961-11-01 499.560042\n", + "11 AirPassengers 1961-12-01 502.178827\n", + "12 AirPassengers 1962-01-01 504.884906\n", + "13 AirPassengers 1962-02-01 507.590984\n", + "14 AirPassengers 1962-03-01 510.035183\n", + "15 AirPassengers 1962-04-01 512.741261\n", + "16 AirPassengers 1962-05-01 515.360046\n", + "17 AirPassengers 1962-06-01 518.066125\n", + "18 AirPassengers 1962-07-01 520.684910\n", + "19 AirPassengers 1962-08-01 523.390988\n", + "20 AirPassengers 1962-09-01 526.097066\n", + "21 AirPassengers 1962-10-01 528.715851\n", + "22 AirPassengers 1962-11-01 531.421929\n", + "23 AirPassengers 1962-12-01 534.040714" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result.fcst_df" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "timecopilot", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From d3dcfe964db2c57c6954ae5269a2e676c734b3f7 Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Mon, 15 Dec 2025 16:38:28 -0500 Subject: [PATCH 03/11] docs: sktime adapter docstrings --- timecopilot/models/sktime.py | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/timecopilot/models/sktime.py b/timecopilot/models/sktime.py index 60c47c6..9ad8f35 100644 --- a/timecopilot/models/sktime.py +++ b/timecopilot/models/sktime.py @@ -36,6 +36,7 @@ def __init__( ): """ Args: + model (sktime.forecasting.base.BaseForecaster): sktime forecasting model alias (str, optional): Custom name for the model instance. Default is "SKTimeAdapter". *args: Additional positional arguments passed to SKTimeAdapter. @@ -53,6 +54,56 @@ def forecast( level: list[int | float] | None = None, quantiles: list[float] | None = None, ) -> pd.DataFrame: + """ + Generate forecasts for time series data using an sktime model. + + This method produces point forecasts and, optionally, prediction + intervals or quantile forecasts. The input DataFrame can contain one + or multiple time series in stacked (long) format. + + Prediction intervals and quantile forecasts are not currently supported + with sktime based models + + Args: + df (pd.DataFrame): + DataFrame containing the time series to forecast. It must + include as columns: + + - "unique_id": an ID column to distinguish multiple series. + - "ds": a time column indicating timestamps or periods. + - "y": a target column with the observed values. + + h (int): + Forecast horizon specifying how many future steps to predict. + freq (str, optional): + Frequency of the time series (e.g. "D" for daily, "M" for + monthly). See [Pandas frequency aliases](https://pandas.pydata.org/ + pandas-docs/stable/user_guide/timeseries.html#offset-aliases) for + valid values. If not provided, the frequency will be inferred + from the data. + level (list[int | float], optional): + Confidence levels for prediction intervals, expressed as + percentages (e.g. [80, 95]). If provided, the returned + DataFrame will include lower and upper interval columns for + each specified level. + quantiles (list[float], optional): + List of quantiles to forecast, expressed as floats between 0 + and 1. Should not be used simultaneously with `level`. When + provided, the output DataFrame will contain additional columns + named in the format "model-q-{percentile}", where {percentile} + = 100 × quantile value. + + Returns: + pd.DataFrame: + DataFrame containing forecast results. Includes: + + - point forecasts for each timestamp and series. + - prediction intervals if `level` is specified. + - quantile forecasts if `quantiles` is specified. + + For multi-series data, the output retains the same unique + identifiers as the input DataFrame. + """ # TODO: support for exogenous data # TODO: add support for level for sktime models that can support it # TODO: add support for quantiles for sktime models that can support it From 303b113926646580f27d08001b6cb54515ebeb4f Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Tue, 16 Dec 2025 09:49:52 -0500 Subject: [PATCH 04/11] feat: sktime adapter alias auto default by default retrieve alias in sktime adapter from model type name --- timecopilot/models/sktime.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/timecopilot/models/sktime.py b/timecopilot/models/sktime.py index 9ad8f35..4e8a2f7 100644 --- a/timecopilot/models/sktime.py +++ b/timecopilot/models/sktime.py @@ -30,7 +30,7 @@ def __init__( self, model, # model: BaseForecaster, - alias: str = "SKTimeAdapter", + alias: str | None = None, *args: Any, **kwargs: Any, ): @@ -38,12 +38,12 @@ def __init__( Args: model (sktime.forecasting.base.BaseForecaster): sktime forecasting model alias (str, optional): Custom name for the model instance. - Default is "SKTimeAdapter". + By default alias is retrieved from the type name of model. *args: Additional positional arguments passed to SKTimeAdapter. **kwargs: Additional keyword arguments passed to SKTimeAdapter. """ super().__init__(*args, **kwargs) - self.alias = alias + self.alias = alias if alias is not None else type(model).__name__ self.model = model def forecast( From 7fc2de7034472aa61f327539753d2f83a22d1b3a Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Tue, 16 Dec 2025 09:54:55 -0500 Subject: [PATCH 05/11] docs: sktime nb added in mkdocs --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index 7e8f424..973c275 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -28,6 +28,7 @@ nav: - examples/gift-eval.ipynb - examples/chronos-family.ipynb - examples/crytpocurrency-quickstart.ipynb + - examples/sktime.ipynb - Experiments: - experiments/gift-eval.md - experiments/fev.md From c414be0c5db1117e1e32ed644b3637ed751195b9 Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:08:25 -0500 Subject: [PATCH 06/11] refactor: move sktime adapter to adapters directory --- timecopilot/models/{ => adapters}/sktime.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename timecopilot/models/{ => adapters}/sktime.py (100%) diff --git a/timecopilot/models/sktime.py b/timecopilot/models/adapters/sktime.py similarity index 100% rename from timecopilot/models/sktime.py rename to timecopilot/models/adapters/sktime.py From 328aa2e62c78db676c489ffe9b892f197537a999 Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:09:51 -0500 Subject: [PATCH 07/11] docs: update sktime example modify sktime adapter import in notebook example to reflect move to adapters directory --- docs/examples/sktime.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/sktime.ipynb b/docs/examples/sktime.ipynb index 02f4f61..276e40b 100644 --- a/docs/examples/sktime.ipynb +++ b/docs/examples/sktime.ipynb @@ -47,13 +47,13 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "e1870fe0", "metadata": {}, "outputs": [], "source": [ "from sktime.forecasting.trend import TrendForecaster\n", - "from timecopilot.models.sktime import SKTimeAdapter\n", + "from timecopilot.models.adapters.sktime import SKTimeAdapter\n", "\n", "trend_forecaster = TrendForecaster()\n", "\n", From acd23d0d7618f9a14409d195fea87bd9281f7b7f Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Tue, 16 Dec 2025 12:51:35 -0500 Subject: [PATCH 08/11] docs: add adapters to api reference --- docs/api/models/adapters/adapters.md | 8 ++++++++ mkdocs.yml | 1 + timecopilot/models/adapters/__init__.py | 0 3 files changed, 9 insertions(+) create mode 100644 docs/api/models/adapters/adapters.md create mode 100644 timecopilot/models/adapters/__init__.py diff --git a/docs/api/models/adapters/adapters.md b/docs/api/models/adapters/adapters.md new file mode 100644 index 0000000..c56efa2 --- /dev/null +++ b/docs/api/models/adapters/adapters.md @@ -0,0 +1,8 @@ +# `timecopilot.models.adapters` + + +::: timecopilot.models.adapters.sktime + options: + members: + - SKTimeAdapter + diff --git a/mkdocs.yml b/mkdocs.yml index 973c275..f7f0484 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -44,6 +44,7 @@ nav: - api/models/ml.md - api/models/neural.md - api/models/ensembles.md + - api/models/adapters/adapters.md - api/models/utils/forecaster.md - api/gift-eval/gift-eval.md - Changelogs: diff --git a/timecopilot/models/adapters/__init__.py b/timecopilot/models/adapters/__init__.py new file mode 100644 index 0000000..e69de29 From 45eb1458a6f1d07295584d93fae4e250874965e7 Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Tue, 16 Dec 2025 14:59:27 -0500 Subject: [PATCH 09/11] docs: add example to sktime forecast docstring --- timecopilot/models/adapters/sktime.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/timecopilot/models/adapters/sktime.py b/timecopilot/models/adapters/sktime.py index 4e8a2f7..4155eac 100644 --- a/timecopilot/models/adapters/sktime.py +++ b/timecopilot/models/adapters/sktime.py @@ -54,6 +54,7 @@ def forecast( level: list[int | float] | None = None, quantiles: list[float] | None = None, ) -> pd.DataFrame: + # fmt: off """ Generate forecasts for time series data using an sktime model. @@ -103,7 +104,22 @@ def forecast( For multi-series data, the output retains the same unique identifiers as the input DataFrame. + + Example: + ```python + import pandas as pd + from timecopilot import TimeCopilot + from timecopilot.models.adapters.sktime import SKTimeAdapter + from sktime.forecasting.trends import TrendForecaster + + df = pd.read_csv("https://timecopilot.s3.amazonaws.com/public/data/air_passengers.csv") + adapted_skt_model = SKTimeAdapter(TrendForecaster()) + tc = TimeCopilot(llm="openai:gpt-4o", models=[adapted_skt_model]) + result = tc.forecast(df, h=12, freq="MS") + print(result.output) + ``` """ + # fmt: on # TODO: support for exogenous data # TODO: add support for level for sktime models that can support it # TODO: add support for quantiles for sktime models that can support it From 32592603a4c70068d3301519ddf9ed73c328fc3d Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Wed, 17 Dec 2025 11:42:16 -0500 Subject: [PATCH 10/11] fix: fix import error in sktime adapter error was caused by moving sktime adapter into adapters directory without updating relative import --- timecopilot/models/adapters/sktime.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/timecopilot/models/adapters/sktime.py b/timecopilot/models/adapters/sktime.py index 4155eac..b5e4b62 100644 --- a/timecopilot/models/adapters/sktime.py +++ b/timecopilot/models/adapters/sktime.py @@ -3,7 +3,7 @@ import numpy as np import pandas as pd -from .utils.forecaster import Forecaster +from ..utils.forecaster import Forecaster # from sktime.forecasting.base import BaseForecaster, ForecastingHorizon From f404d37ba6010e2b4dd326792da77b342074138c Mon Sep 17 00:00:00 2001 From: spolisar <22416070+spolisar@users.noreply.github.com> Date: Wed, 17 Dec 2025 15:03:07 -0500 Subject: [PATCH 11/11] ci: add sktime as dev dependency --- pyproject.toml | 1 + uv.lock | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 71a4d60..0e5769f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ dev = [ "pytest-rerunfailures>=15.1", "pytest-xdist>=3.8.0", "s3fs>=2025.3.0", + "sktime>=0.40.1", ] docs = [ "mkdocs-include-markdown-plugin>=7.1.6", diff --git a/uv.lock b/uv.lock index f4b177c..39bbcae 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'linux'", @@ -6585,6 +6585,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/69/e2/b011c38e5394c4c18fb5500778a55ec43ad6106126e74723ffaee246f56e/safetensors-0.5.3-cp38-abi3-win_amd64.whl", hash = "sha256:836cbbc320b47e80acd40e44c8682db0e8ad7123209f69b093def21ec7cafd11", size = 308878, upload-time = "2025-02-26T09:15:14.99Z" }, ] +[[package]] +name = "scikit-base" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/4d/53b477e05ba7897026133543114c48c9e67646180b85a9e3bd6edb6e5223/scikit_base-0.13.0.tar.gz", hash = "sha256:436c26067173a7235c465c64ac105008f6f889f09308c5e4e4a16e21c38c3ddc", size = 127431, upload-time = "2025-10-08T20:39:35.509Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/1c/7c00d3823bef4ef2e5a95507475bc5cf3bdabf00c8577f8bb5ff406e9f2e/scikit_base-0.13.0-py3-none-any.whl", hash = "sha256:efe7df0f09854b9f28e9532f6be87ef433dd8f1358cabd24ebf168aa4ccca1fc", size = 151529, upload-time = "2025-10-08T20:39:33.951Z" }, +] + [[package]] name = "scikit-learn" version = "1.6.1" @@ -6815,6 +6824,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] +[[package]] +name = "sktime" +version = "0.40.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "joblib" }, + { name = "numpy", version = "1.26.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" }, + { name = "numpy", version = "2.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13'" }, + { name = "packaging" }, + { name = "pandas", version = "2.1.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" }, + { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13'" }, + { name = "scikit-base" }, + { name = "scikit-learn", version = "1.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" }, + { name = "scikit-learn", version = "1.7.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13'" }, + { name = "scipy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/84/7a/22b99a00a7cabaa34c350f78f33ae89711cfc08deef06043daee3835dbb3/sktime-0.40.1.tar.gz", hash = "sha256:bbf3c2971c7ad388fbebc1d1fb573e20f730e6486c00935b336d8edf13bca04d", size = 35197759, upload-time = "2025-11-25T00:03:38.744Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/0d/3b2e5b51593009f72fb7fb6956e6c652da1450c8c5484c40a276113c2114/sktime-0.40.1-py3-none-any.whl", hash = "sha256:130bb0c39ca4377e491c4dfa64c8ac67c3de2660dd406dd7690db6a8ac349c4e", size = 36265753, upload-time = "2025-11-25T00:03:34.522Z" }, +] + [[package]] name = "smmap" version = "5.0.2" @@ -7304,6 +7334,7 @@ dev = [ { name = "pytest-rerunfailures" }, { name = "pytest-xdist" }, { name = "s3fs" }, + { name = "sktime" }, ] docs = [ { name = "mkdocs" }, @@ -7356,6 +7387,7 @@ dev = [ { name = "pytest-rerunfailures", specifier = ">=15.1" }, { name = "pytest-xdist", specifier = ">=3.8.0" }, { name = "s3fs", specifier = ">=2025.3.0" }, + { name = "sktime", specifier = ">=0.40.1" }, ] docs = [ { name = "mkdocs", specifier = ">=1.6.1" },