{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "27371399-17ac-4fcf-8e2d-19091b32cdf7",
   "metadata": {},
   "outputs": [],
   "source": [
    "#| hide\n",
    "!pip install -Uqq nixtla"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e428575b-700a-49a6-a0a9-6fa884119d86",
   "metadata": {},
   "outputs": [],
   "source": [
    "#| hide\n",
    "from nixtla.utils import in_colab"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fba11152-1fbb-43b5-b6c7-ccb5ff688ce2",
   "metadata": {},
   "outputs": [],
   "source": [
    "#| hide \n",
    "IN_COLAB = in_colab()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e0438f77-6a7e-400d-8739-09c9e347dcac",
   "metadata": {},
   "outputs": [],
   "source": [
    "#| hide\n",
    "if not IN_COLAB:\n",
    "    from nixtla.utils import colab_badge\n",
    "    from dotenv import load_dotenv"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4bcec3f-9ffe-41e0-a38b-92e77e460154",
   "metadata": {},
   "source": [
    "# Re-using fine-tuned models\n",
    "\n",
    "Save and re-use fine-tuned models across all of our endpoints."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "56e9125c-53b3-41e4-bace-e920fb827c06",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "[![](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Nixtla/nixtla/blob/main/nbs/docs/tutorials/061_reusing_finetuned_models.ipynb.ipynb)"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#| echo: false\n",
    "if not IN_COLAB:\n",
    "    load_dotenv()    \n",
    "    colab_badge('docs/tutorials/061_reusing_finetuned_models')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7eb9fc0-4541-4c1e-8ffe-442d115fd638",
   "metadata": {},
   "source": [
    "## 1. Import packages\n",
    "First, we import the required packages and initialize the Nixtla client"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89c80a4a-645d-43f9-9454-415a98685105",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from nixtla import NixtlaClient\n",
    "from utilsforecast.losses import rmse\n",
    "from utilsforecast.evaluation import evaluate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "73d7516f-2a78-4be1-972e-41cb70800bcd",
   "metadata": {},
   "outputs": [],
   "source": [
    "nixtla_client = NixtlaClient(\n",
    "    # defaults to os.environ[\"NIXTLA_API_KEY\"]\n",
    "    api_key = 'my_api_key_provided_by_nixtla'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a60ca743-7d68-4d4b-af72-10f63dbf5b26",
   "metadata": {},
   "outputs": [],
   "source": [
    "#| hide\n",
    "if not IN_COLAB:\n",
    "    nixtla_client = NixtlaClient()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "83ca8dec-ca2a-4e9f-8983-886208423769",
   "metadata": {},
   "source": [
    "## 2. Load data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb5ef6b1-4756-4f79-8609-12f051503431",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>unique_id</th>\n",
       "      <th>ds</th>\n",
       "      <th>y</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>H1</td>\n",
       "      <td>1</td>\n",
       "      <td>605.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>H1</td>\n",
       "      <td>2</td>\n",
       "      <td>586.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>H1</td>\n",
       "      <td>3</td>\n",
       "      <td>586.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>H1</td>\n",
       "      <td>4</td>\n",
       "      <td>559.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>H1</td>\n",
       "      <td>5</td>\n",
       "      <td>511.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  unique_id  ds      y\n",
       "0        H1   1  605.0\n",
       "1        H1   2  586.0\n",
       "2        H1   3  586.0\n",
       "3        H1   4  559.0\n",
       "4        H1   5  511.0"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_parquet('https://datasets-nixtla.s3.amazonaws.com/m4-hourly.parquet')\n",
    "\n",
    "h = 48\n",
    "valid = df.groupby('unique_id', observed=True).tail(h)\n",
    "train = df.drop(valid.index)\n",
    "train.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7b61f18-64a3-4b7f-8f86-76a78d6a0c0c",
   "metadata": {},
   "source": [
    "## 3. Zero-shot forecast\n",
    "\n",
    "We can try forecasting without any finetuning to see how well TimeGPT does."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3e60cbbe-2710-4a7b-a453-27e52bf8b32b",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:nixtla.nixtla_client:Validating inputs...\n",
      "INFO:nixtla.nixtla_client:Preprocessing dataframes...\n",
      "INFO:nixtla.nixtla_client:Querying model metadata...\n",
      "WARNING:nixtla.nixtla_client:The specified horizon \"h\" exceeds the model horizon, this may lead to less accurate forecasts. Please consider using a smaller horizon.\n",
      "INFO:nixtla.nixtla_client:Restricting input...\n",
      "INFO:nixtla.nixtla_client:Calling Forecast Endpoint...\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>metric</th>\n",
       "      <th>TimeGPT</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>rmse</td>\n",
       "      <td>1504.474342</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  metric      TimeGPT\n",
       "0   rmse  1504.474342"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fcst_kwargs = {'df': train, 'freq': 1, 'model': 'timegpt-1-long-horizon'}\n",
    "fcst = nixtla_client.forecast(h=h, **fcst_kwargs)\n",
    "zero_shot_eval = evaluate(fcst.merge(valid), metrics=[rmse], agg_fn='mean')\n",
    "zero_shot_eval"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f966407c-9c7d-4bce-8d6c-31870e00e7b5",
   "metadata": {},
   "source": [
    "## 4. Fine-tune\n",
    "\n",
    "We can now fine-tune TimeGPT a little and save our model for later use. We can define the ID that we want that model to have by providing it through `output_model_id`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6ffd8395-c30c-4522-b597-349a9d3a4b2e",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:nixtla.nixtla_client:Validating inputs...\n",
      "INFO:nixtla.nixtla_client:Preprocessing dataframes...\n",
      "INFO:nixtla.nixtla_client:Calling Fine-tune Endpoint...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'my-first-finetuned-model'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first_model_id = 'my-first-finetuned-model'\n",
    "nixtla_client.finetune(output_model_id=first_model_id, **fcst_kwargs)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1198429a-5518-43a3-bd73-2fa5d1f48cc3",
   "metadata": {},
   "source": [
    "We can now forecast using this fine-tuned model by providing its ID through the `finetuned_model_id` argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb996e6a-37e1-44ea-af8d-3b71cf6276ae",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:nixtla.nixtla_client:Validating inputs...\n",
      "INFO:nixtla.nixtla_client:Preprocessing dataframes...\n",
      "WARNING:nixtla.nixtla_client:The specified horizon \"h\" exceeds the model horizon, this may lead to less accurate forecasts. Please consider using a smaller horizon.\n",
      "INFO:nixtla.nixtla_client:Restricting input...\n",
      "INFO:nixtla.nixtla_client:Calling Forecast Endpoint...\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>metric</th>\n",
       "      <th>TimeGPT_zero_shot</th>\n",
       "      <th>TimeGPT_first_finetune</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>rmse</td>\n",
       "      <td>1504.474342</td>\n",
       "      <td>1472.024619</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  metric  TimeGPT_zero_shot  TimeGPT_first_finetune\n",
       "0   rmse        1504.474342             1472.024619"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first_finetune_fcst = nixtla_client.forecast(h=h, finetuned_model_id=first_model_id, **fcst_kwargs)\n",
    "first_finetune_eval = evaluate(first_finetune_fcst.merge(valid), metrics=[rmse], agg_fn='mean')\n",
    "zero_shot_eval.merge(first_finetune_eval, on=['metric'], suffixes=('_zero_shot', '_first_finetune'))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb763ee8-07c0-4a6b-85dd-deb6c8216ddd",
   "metadata": {},
   "source": [
    "We can see the error was reduced."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b97ad55-a82c-4dd2-878c-40e2e9bf8945",
   "metadata": {},
   "source": [
    "## 5. Further fine-tune\n",
    "\n",
    "We can now take this model and fine-tune it a bit further by using the `NixtlaClient.finetune` method but providing our already fine-tuned model as `finetuned_model_id`, which will take that model and fine-tune it a bit more. We can also change the fine-tuning settings, like using `finetune_depth=3`, for example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "99ede33c-379b-4569-8e1a-996abbe8576e",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:nixtla.nixtla_client:Validating inputs...\n",
      "INFO:nixtla.nixtla_client:Preprocessing dataframes...\n",
      "INFO:nixtla.nixtla_client:Calling Fine-tune Endpoint...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'468b13fb-4b26-447a-bd87-87a64b50d913'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "second_model_id = nixtla_client.finetune(finetuned_model_id=first_model_id, finetune_depth=3, **fcst_kwargs)\n",
    "second_model_id"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70f0cab5-7b01-4d2d-8afe-0a2317644eed",
   "metadata": {},
   "source": [
    "Since we didn't provide `output_model_id` this time, it got assigned an UUID.\n",
    "\n",
    "We can now use this model to forecast."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4cfeed2e-0a39-4211-82d1-67d1f868b311",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:nixtla.nixtla_client:Validating inputs...\n",
      "INFO:nixtla.nixtla_client:Preprocessing dataframes...\n",
      "WARNING:nixtla.nixtla_client:The specified horizon \"h\" exceeds the model horizon, this may lead to less accurate forecasts. Please consider using a smaller horizon.\n",
      "INFO:nixtla.nixtla_client:Restricting input...\n",
      "INFO:nixtla.nixtla_client:Calling Forecast Endpoint...\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>metric</th>\n",
       "      <th>TimeGPT_first_finetune</th>\n",
       "      <th>TimeGPT_second_finetune</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>rmse</td>\n",
       "      <td>1472.024619</td>\n",
       "      <td>1435.365211</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  metric  TimeGPT_first_finetune  TimeGPT_second_finetune\n",
       "0   rmse             1472.024619              1435.365211"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "second_finetune_fcst = nixtla_client.forecast(h=h, finetuned_model_id=second_model_id, **fcst_kwargs)\n",
    "second_finetune_eval = evaluate(second_finetune_fcst.merge(valid), metrics=[rmse], agg_fn='mean')\n",
    "first_finetune_eval.merge(second_finetune_eval, on=['metric'], suffixes=('_first_finetune', '_second_finetune'))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2bc7c72-47be-4cc5-b774-f75980e8d70b",
   "metadata": {},
   "source": [
    "We can see the error was reduced a bit more."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "611406fe-2379-4b92-bdd4-5f9a86438d91",
   "metadata": {},
   "source": [
    "## 6. Listing fine-tuned models\n",
    "\n",
    "We can list our fine-tuned models with the `NixtlaClient.finetuned_models` method."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9648bb4-74ad-4a94-8c8a-74625e9795d7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[FinetunedModel(id='468b13fb-4b26-447a-bd87-87a64b50d913', created_at=datetime.datetime(2024, 12, 30, 17, 57, 31, 241455, tzinfo=TzInfo(UTC)), created_by='user', base_model_id='my-first-finetuned-model', steps=10, depth=3, loss='default', model='timegpt-1-long-horizon', freq='MS'),\n",
       " FinetunedModel(id='my-first-finetuned-model', created_at=datetime.datetime(2024, 12, 30, 17, 57, 16, 978907, tzinfo=TzInfo(UTC)), created_by='user', base_model_id='None', steps=10, depth=1, loss='default', model='timegpt-1-long-horizon', freq='MS')]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "finetuned_models = nixtla_client.finetuned_models()\n",
    "finetuned_models"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95e591c8-80b0-43f8-afed-dfa760597af8",
   "metadata": {},
   "source": [
    "While that representation may be useful for programmatic use, in this exploratory setting it's nicer to see them as a dataframe, which we can get by providing `as_df=True`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0cacc468-0aa3-42af-85d9-7c31bfd2a4f3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>created_at</th>\n",
       "      <th>created_by</th>\n",
       "      <th>base_model_id</th>\n",
       "      <th>steps</th>\n",
       "      <th>depth</th>\n",
       "      <th>loss</th>\n",
       "      <th>model</th>\n",
       "      <th>freq</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>468b13fb-4b26-447a-bd87-87a64b50d913</td>\n",
       "      <td>2024-12-30 17:57:31.241455+00:00</td>\n",
       "      <td>user</td>\n",
       "      <td>my-first-finetuned-model</td>\n",
       "      <td>10</td>\n",
       "      <td>3</td>\n",
       "      <td>default</td>\n",
       "      <td>timegpt-1-long-horizon</td>\n",
       "      <td>MS</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>my-first-finetuned-model</td>\n",
       "      <td>2024-12-30 17:57:16.978907+00:00</td>\n",
       "      <td>user</td>\n",
       "      <td>None</td>\n",
       "      <td>10</td>\n",
       "      <td>1</td>\n",
       "      <td>default</td>\n",
       "      <td>timegpt-1-long-horizon</td>\n",
       "      <td>MS</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     id                       created_at  \\\n",
       "0  468b13fb-4b26-447a-bd87-87a64b50d913 2024-12-30 17:57:31.241455+00:00   \n",
       "1              my-first-finetuned-model 2024-12-30 17:57:16.978907+00:00   \n",
       "\n",
       "  created_by             base_model_id  steps  depth     loss  \\\n",
       "0       user  my-first-finetuned-model     10      3  default   \n",
       "1       user                      None     10      1  default   \n",
       "\n",
       "                    model freq  \n",
       "0  timegpt-1-long-horizon   MS  \n",
       "1  timegpt-1-long-horizon   MS  "
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nixtla_client.finetuned_models(as_df=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9697c759-1b08-4192-a14f-5df1fdb03191",
   "metadata": {},
   "source": [
    "We can seee that the `base_model_id` of our second model is our first model, along with other metadata."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eae29db5-de09-4954-9352-4f22eb0c3675",
   "metadata": {},
   "source": [
    "## 7. Deleting fine-tuned models\n",
    "\n",
    "In order to keep things organized, and since there's a limit of 50 fine-tuned models, you can delete models that weren't so promising to make room for more experiments. For example, we can delete our first finetuned model. Note that even though it was used as the base for our second model, they're saved independently so removing it won't affect our second model, except for the dangling metadata."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7232bc3b-9096-4875-978a-430b7627688f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nixtla_client.delete_finetuned_model(first_model_id)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0973b161-368f-4681-8447-c87537a46583",
   "metadata": {},
   "source": [
    "We can verify that our first model model doesn't show up anymore in our available models."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1b80edea-8926-4a13-8fb8-ec9bbcf4d575",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>created_at</th>\n",
       "      <th>created_by</th>\n",
       "      <th>base_model_id</th>\n",
       "      <th>steps</th>\n",
       "      <th>depth</th>\n",
       "      <th>loss</th>\n",
       "      <th>model</th>\n",
       "      <th>freq</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>468b13fb-4b26-447a-bd87-87a64b50d913</td>\n",
       "      <td>2024-12-30 17:57:31.241455+00:00</td>\n",
       "      <td>user</td>\n",
       "      <td>my-first-finetuned-model</td>\n",
       "      <td>10</td>\n",
       "      <td>3</td>\n",
       "      <td>default</td>\n",
       "      <td>timegpt-1-long-horizon</td>\n",
       "      <td>MS</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     id                       created_at  \\\n",
       "0  468b13fb-4b26-447a-bd87-87a64b50d913 2024-12-30 17:57:31.241455+00:00   \n",
       "\n",
       "  created_by             base_model_id  steps  depth     loss  \\\n",
       "0       user  my-first-finetuned-model     10      3  default   \n",
       "\n",
       "                    model freq  \n",
       "0  timegpt-1-long-horizon   MS  "
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nixtla_client.finetuned_models(as_df=True)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
