Skip to content

Commit c7fdea8

Browse files
authored
Time Series Forecast API Documentation (#507)
* add time series API doc Signed-off-by: jinan.zhou <jinan.zhou@nutanix.com> * add sample usage Signed-off-by: jinan.zhou <jinan.zhou@nutanix.com> * add k8x deployment example Signed-off-by: jinan.zhou <jinan.zhou@nutanix.com> --------- Signed-off-by: jinan.zhou <jinan.zhou@nutanix.com>
1 parent c507750 commit c7fdea8

1 file changed

Lines changed: 349 additions & 0 deletions

File tree

  • docs/reference/time_series

docs/reference/time_series/api.md

Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
# TimeSeries LLM Forecast API Documentation
2+
3+
## Overview
4+
5+
A [time series](https://en.wikipedia.org/wiki/Time_series) records how a measurement changes over time, while [forecasting](https://en.wikipedia.org/wiki/Forecasting) estimates future values based on past behavior. Time series forecasting is commonly used for future-looking decisions in finance, supply chains, energy, and other operations that depend on reliable projections.
6+
7+
To ease and standardize the deployment of time series models in the LLM era, we designed the TimeSeries LLM Forecast API in Kserve so you can run forecasts with transformer-based models. This API supports both univariate and multivariate time series, provides quantile forecasting, and is designed to be extensible for future enhancements. The API is compatible with standard RESTful practices and allows for flexible options and metadata handling, making it suitable for a wide range of time series applications across industries.
8+
9+
## Table of Contents
10+
11+
* [Overview](#overview)
12+
* [Quick Start](#quick-start)
13+
* [Request Schema](#request-schema)
14+
* [ForecastRequest Fields](#forecastrequest-fields)
15+
* [TimeSeriesInput](#timeseriesinput)
16+
* [ForecastOptions](#forecastoptions)
17+
* [Metadata](#metadata)
18+
* [Response Schema](#response-schema)
19+
* [ForecastResponse Fields](#forecastresponse-fields)
20+
* [ForecastOutput](#forecastoutput)
21+
* [TimeSeriesForecast](#timeseriesforecast)
22+
* [Usage](#usage)
23+
* [Error Handling](#error-handling)
24+
* [Enumerations](#enumerations)
25+
* [Frequency](#frequency)
26+
* [Status](#status)
27+
* [TimeSeriesType](#timeseriestype)
28+
* [Examples](#examples)
29+
* [Request Example](#request-example)
30+
* [Response Example](#response-example)
31+
* [Best Practices](#best-practices)
32+
* [FAQ](#faq)
33+
* [Changelog](#changelog)
34+
35+
36+
## Quick Start
37+
38+
### Endpoint
39+
40+
```
41+
POST /v1/timeseries/forecast
42+
```
43+
44+
### Typical Workflow
45+
46+
1. Prepare your input time series data and specify forecasting options (e.g., horizon, quantiles).
47+
2. Compose a JSON request payload according to the [Request Schema](#request-schema).
48+
3. Send a POST request to `/v1/timeseries/forecast`.
49+
4. Parse the response for forecast results, quantiles, and usage metrics.
50+
51+
52+
## Request Schema
53+
54+
### ForecastRequest Fields
55+
56+
| Field | Type | Required | Description |
57+
| ------------------- | ---------------------- | -------- | ---------------------------------------------- |
58+
| model | string | Yes | Name/ID of the model to use |
59+
| inputs | List\[TimeSeriesInput] | Yes | List of input time series to forecast |
60+
| options | ForecastOptions | Yes | Forecasting options (e.g., horizon, quantiles) |
61+
| metadata | Metadata | No | Arbitrary user metadata |
62+
| other\_properties | any | No | Additional extensible fields |
63+
64+
#### JSON Structure
65+
66+
```json
67+
{
68+
"model": "timesfm",
69+
"inputs": [...],
70+
"options": {...},
71+
"metadata": {...}, // optional
72+
"other_properties": ... // optional
73+
}
74+
```
75+
76+
77+
### TimeSeriesInput
78+
79+
| Field | Type | Required | Description |
80+
| ------------------ | ---------------- | -------- | ---------------------------------------------------------- |
81+
| type | TimeSeriesType | Yes | 'univariate\_time\_series' or 'multivariate\_time\_series' |
82+
| name | string | Yes | Name of the time series (unique in request) |
83+
| series | TimeSeries | Yes | Observed data: List\[float] or List\[List\[float]] |
84+
| frequency | Frequency | Yes | Frequency (see [Frequency](#frequency)) |
85+
| start\_timestamp | string (ISO8601) | No | Start timestamp of series (for aligning output) |
86+
| ...extra fields | any | No | Additional extensible fields |
87+
88+
89+
### ForecastOptions
90+
91+
| Field | Type | Required | Description |
92+
| ----------- | ------------ | -------- | ---------------------------------- |
93+
| horizon | int | Yes | Number of steps to forecast |
94+
| quantiles | List\[float] | No | Quantiles (e.g., \[0.1, 0.5, 0.9]) |
95+
| ...extra | any | No | Additional extensible fields |
96+
97+
98+
### Metadata
99+
100+
* Arbitrary user-provided metadata. No required or fixed fields.
101+
102+
103+
## Response Schema
104+
105+
### ForecastResponse Fields
106+
107+
| Field | Type | Required | Description |
108+
| ----------- | --------------------- | -------- | --------------------------------- |
109+
| id | string | Yes | Unique response identifier |
110+
| created\_at | int (unix ts) | Yes | Time of response creation |
111+
| status | Status | Yes | Overall status of the request |
112+
| error | Error | No | Top-level error (if any) |
113+
| model | string | Yes | The model used for forecasting |
114+
| outputs | List\[ForecastOutput] | Yes | Forecast results, one per input |
115+
| usage | Usage | No | Token usage metrics (if relevant) |
116+
| ...extra | any | No | Additional extensible fields |
117+
118+
119+
### ForecastOutput
120+
121+
| Field | Type | Required | Description |
122+
| -------- | ------------------------- | -------- | --------------------------------------------- |
123+
| type | string | Yes | 'time\_series\_forecast' |
124+
| id | string | Yes | Unique forecast output identifier |
125+
| status | Status | Yes | Status of this forecast result |
126+
| content | List\[TimeSeriesForecast] | Yes | One or more time series forecasts (per input) |
127+
| error | Error | No | Error if this forecast failed |
128+
| ...extra | any | No | Additional extensible fields |
129+
130+
131+
### TimeSeriesForecast
132+
133+
| Field | Type | Required | Description |
134+
| ---------------- | ---------------------- | -------- | ---------------------------------------------------------- |
135+
| type | TimeSeriesType | Yes | 'univariate\_time\_series' or 'multivariate\_time\_series' |
136+
| name | string | Yes | The name of the time series |
137+
| mean\_forecast | TimeSeries | Yes | Mean (expected) forecast values |
138+
| frequency | Frequency | Yes | Frequency of the forecasted time series |
139+
| start\_timestamp | string (ISO8601) | Yes | Start timestamp for the forecast horizon |
140+
| quantiles | Dict\[str, TimeSeries] | No | Map from quantile string (e.g., "0.1") to values |
141+
| ...extra | any | No | Additional extensible fields |
142+
143+
144+
### Usage
145+
146+
| Field | Type | Required | Description |
147+
| ------------------ | ---- | -------- | ------------------------------------------- |
148+
| prompt\_tokens | int | Yes | Number of tokens in prompt (if LLM-related) |
149+
| completion\_tokens | int | Yes | Number of tokens in result |
150+
| total\_tokens | int | Yes | Total tokens used |
151+
| ...extra | any | No | Additional extensible fields |
152+
153+
154+
### Error Handling
155+
156+
If an error occurs, the response may contain a top-level `error` field, or errors may be reported per-forecast (in the corresponding output object). The structure is:
157+
158+
```json
159+
{
160+
"error": {
161+
"code": "<string>",
162+
"message": "<description>",
163+
"param": "<string>",
164+
"type": "<string>"
165+
}
166+
}
167+
```
168+
169+
170+
## Enumerations
171+
172+
### Frequency
173+
174+
* `SECOND`, `S`: second
175+
* `MINUTE`, `T`: minute
176+
* `HOUR`, `H`: hour
177+
* `DAY`, `D`: day
178+
* `WEEK`, `W`: week
179+
* `MONTH`, `M`: month
180+
* `QUARTER`, `Q`: quarter
181+
* `YEAR`, `Y`: year
182+
183+
### Status
184+
185+
* `COMPLETED`: The forecast completed successfully
186+
* `ERROR`: There was an error in processing
187+
* `PENDING`: The forecast is still running
188+
* `PARTIAL`: Partially completed
189+
190+
### TimeSeriesType
191+
192+
* `univariate_time_series`
193+
* `multivariate_time_series`
194+
195+
196+
## Examples
197+
198+
### Deploy on KServe
199+
200+
The steps below assume you already have a Kubernetes cluster with KServe installed and that you can pull the model weights from Hugging Face (set the `HUGGING_FACE_HUB_TOKEN` secret if the model is gated).
201+
202+
```yaml
203+
apiVersion: serving.kserve.io/v1beta1
204+
kind: InferenceService
205+
metadata:
206+
name: timeseries-forecast
207+
namespace: kserve-demo
208+
spec:
209+
predictor:
210+
containers:
211+
- name: timesfm
212+
image: kserve/huggingfaceserver:latest
213+
args:
214+
- "--model_id=google/timesfm-2.0-500m-pytorch"
215+
- "--model_name=timesfm2"
216+
- "--http_port=8080"
217+
resources:
218+
requests:
219+
cpu: "4"
220+
memory: "8Gi"
221+
limits:
222+
cpu: "8"
223+
memory: "16Gi"
224+
nvidia.com/gpu: "1"
225+
```
226+
227+
### Request Example
228+
229+
```bash
230+
curl -X POST "${SERVICE_URL}/v1/timeseries/forecast" \
231+
-H "Content-Type: application/json" \
232+
-d '{
233+
"model": "timesfm2",
234+
"inputs": [
235+
{
236+
"type": "univariate_time_series",
237+
"name": "stock_price",
238+
"series": [120, 122, 125, 127, 130, 133, 135],
239+
"frequency": "D",
240+
"start_timestamp": "2025-06-05T13:10:00Z"
241+
},
242+
{
243+
"type": "univariate_time_series",
244+
"name": "humidity",
245+
"series": [33, 34, 35, 36, 37],
246+
"frequency": "H",
247+
"start_timestamp": "2025-06-05T13:10:00Z"
248+
}
249+
],
250+
"options": {
251+
"horizon": 4,
252+
"quantiles": [0.1, 0.5, 0.9],
253+
"other_options": "value"
254+
},
255+
"metadata": {
256+
"request_id": "user_defined_request_id",
257+
"other_data": "value"
258+
},
259+
"other_properties": "value"
260+
}'
261+
```
262+
263+
264+
### Response Example
265+
266+
```json
267+
{
268+
"id": "resp_67ccd2bed1ec8190b14f964abc0542670bb6a6b452d3795b",
269+
"created_at": 1741476542,
270+
"status": "completed",
271+
"error": null,
272+
"model": "timesfm2",
273+
"outputs": [
274+
{
275+
"type": "time_series_forecast",
276+
"id": "ts_67ccd2bf17f0819081ff3bb2cf6508e60bb6a6b452d3795b",
277+
"status": "completed",
278+
"content": [
279+
{
280+
"type": "univariate_time_series",
281+
"name": "stock_price",
282+
"mean_forecast": [138, 141, 144, 147],
283+
"frequency": "D",
284+
"start_timestamp": "2025-06-12T13:10:00Z",
285+
"quantiles": {
286+
"0.1": [135, 138, 140, 143],
287+
"0.5": [138, 141, 144, 147],
288+
"0.9": [142, 145, 148, 151]
289+
}
290+
}
291+
]
292+
},
293+
{
294+
"type": "time_series_forecast",
295+
"id": "ts_67ccd2bsdf9q3wadfk439jngjmaphng0oswa34nm8we0ejrf",
296+
"status": "completed",
297+
"content": [
298+
{
299+
"type": "univariate_time_series",
300+
"name": "humidity",
301+
"mean_forecast": [39, 40, 41, 42],
302+
"frequency": "H",
303+
"start_timestamp": "2025-06-05T18:10:00Z",
304+
"quantiles": {
305+
"0.1": [37, 38, 39, 40],
306+
"0.5": [39, 40, 41, 42],
307+
"0.9": [41, 42, 43, 44]
308+
}
309+
}
310+
]
311+
}
312+
],
313+
"usage": {
314+
"prompt_tokens": 4,
315+
"completion_tokens": 2,
316+
"total_tokens": 6
317+
},
318+
"other_properties": "value"
319+
}
320+
```
321+
322+
323+
## Best Practices
324+
325+
* Always include `start_timestamp` for correct alignment of output forecast horizon with input data.
326+
* Quantiles are returned as string keys (e.g., "0.1").
327+
* Make use of `metadata` to pass request-tracking info (e.g., request\_id).
328+
* Check both top-level and per-output `status` and `error` fields to handle errors robustly.
329+
330+
331+
## FAQ
332+
333+
**Q:** What happens if quantiles are not specified?
334+
**A:** Only mean forecast will be returned.
335+
336+
**Q:** How is the forecast `start_timestamp` determined?
337+
**A:** It is typically `input.start_timestamp + options.horizon` intervals, but the exact logic depends on the model and frequency.
338+
339+
**Q:** How are multivariate series represented?
340+
**A:** As `List[List[float]]`, with the first dimension for time and the second for variables.
341+
342+
**Q:** Are additional fields allowed?
343+
**A:** Yes, both request and response models allow arbitrary extra fields for forward compatibility.
344+
345+
346+
## Changelog
347+
348+
* **2025-07-24**: Initial version of API documentation created.
349+
* **2025-10-20**: Added Kubernetes deployment example.

0 commit comments

Comments
 (0)