chronos4pm 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chronos4pm-0.1.0/LICENSE +21 -0
- chronos4pm-0.1.0/MANIFEST.in +2 -0
- chronos4pm-0.1.0/PKG-INFO +348 -0
- chronos4pm-0.1.0/README.md +326 -0
- chronos4pm-0.1.0/chronos4pm/__init__.py +46 -0
- chronos4pm-0.1.0/chronos4pm/api.py +326 -0
- chronos4pm-0.1.0/chronos4pm/configuration.py +94 -0
- chronos4pm-0.1.0/chronos4pm/covariates.py +441 -0
- chronos4pm-0.1.0/chronos4pm/inference.py +134 -0
- chronos4pm-0.1.0/chronos4pm/logs.py +151 -0
- chronos4pm-0.1.0/chronos4pm/predictive.py +186 -0
- chronos4pm-0.1.0/chronos4pm/py.typed +0 -0
- chronos4pm-0.1.0/chronos4pm/tasks.py +266 -0
- chronos4pm-0.1.0/chronos4pm.egg-info/PKG-INFO +348 -0
- chronos4pm-0.1.0/chronos4pm.egg-info/SOURCES.txt +24 -0
- chronos4pm-0.1.0/chronos4pm.egg-info/dependency_links.txt +1 -0
- chronos4pm-0.1.0/chronos4pm.egg-info/requires.txt +13 -0
- chronos4pm-0.1.0/chronos4pm.egg-info/top_level.txt +1 -0
- chronos4pm-0.1.0/examples/__init__.py +1 -0
- chronos4pm-0.1.0/examples/quickstart.py +47 -0
- chronos4pm-0.1.0/main.py +15 -0
- chronos4pm-0.1.0/pyproject.toml +40 -0
- chronos4pm-0.1.0/setup.cfg +4 -0
- chronos4pm-0.1.0/tests/test_contract.py +418 -0
- chronos4pm-0.1.0/tests/test_inference.py +83 -0
- chronos4pm-0.1.0/tests/test_integration.py +78 -0
chronos4pm-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Christian Imenkamp
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chronos4pm
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Zero-shot process-mining forecasts with Chronos-2 and PM4Py data structures
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: pm4py==2.7.23.4
|
|
10
|
+
Requires-Dist: ebi-pm==0.3.12
|
|
11
|
+
Requires-Dist: chronos-forecasting==2.1.0
|
|
12
|
+
Requires-Dist: numpy<3,>=2
|
|
13
|
+
Requires-Dist: pandas<4,>=2.2
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
16
|
+
Requires-Dist: mypy>=1.15; extra == "dev"
|
|
17
|
+
Requires-Dist: pandas-stubs; extra == "dev"
|
|
18
|
+
Requires-Dist: ruff; extra == "dev"
|
|
19
|
+
Requires-Dist: build; extra == "dev"
|
|
20
|
+
Requires-Dist: twine; extra == "dev"
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# Chronos4PM
|
|
24
|
+
|
|
25
|
+
Forecast process behavior with a frozen Chronos-2 model, using familiar
|
|
26
|
+
[PM4Py](https://processintelligence.solutions/pm4py) event logs, pandas DataFrames,
|
|
27
|
+
activity names, and directly-follows graphs.
|
|
28
|
+
|
|
29
|
+
This standalone package extracts the 16 task mappings from
|
|
30
|
+
[Chronos-2 meets Process Mining](https://github.com/chimenkamp/chronos-2-meets-process-mining).
|
|
31
|
+
It does not import or modify the benchmark repository. It contains no training,
|
|
32
|
+
fine-tuning, benchmark runner, paper reporting, or FEEED integration.
|
|
33
|
+
|
|
34
|
+
**These functions forecast the next window or event.** PM4Py normally describes
|
|
35
|
+
an already observed log. Dictionary keys and tuple structures are familiar, but
|
|
36
|
+
distribution values here are probabilities, not observed integer counts. This
|
|
37
|
+
is a forecast API, not a drop-in replacement for every PM4Py function or option.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
Use Python 3.11 or newer in a separate environment. From this repository:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python -m venv .venv
|
|
45
|
+
source .venv/bin/activate
|
|
46
|
+
python -m pip install .
|
|
47
|
+
python main.py
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`main.py` runs a small illustrative event log through the real model. The first
|
|
51
|
+
forecast downloads the checkpoint from Hugging Face unless it is already cached.
|
|
52
|
+
Importing `chronos4pm` does not load a model. The default device is CPU.
|
|
53
|
+
|
|
54
|
+
The distribution name and import name are both `chronos4pm`. This repository does
|
|
55
|
+
not publish anything to PyPI. Until a release is uploaded, install from a checkout
|
|
56
|
+
or a supplied wheel:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python -m pip install /path/to/Chronos4PM
|
|
60
|
+
# Or, after building:
|
|
61
|
+
python -m pip install dist/chronos4pm-0.1.0-py3-none-any.whl
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The package metadata pins `pm4py==2.7.23.4`, `ebi-pm==0.3.12`, and
|
|
65
|
+
`chronos-forecasting==2.1.0`. EBI's Python import is `ebi`. Other transitive
|
|
66
|
+
dependencies are resolved by pip; the package is not a complete lock of the
|
|
67
|
+
paper's experimental environment.
|
|
68
|
+
|
|
69
|
+
## Load a log and forecast
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
import pm4py
|
|
73
|
+
import chronos4pm as cpm
|
|
74
|
+
|
|
75
|
+
log = pm4py.read_xes("completed_cases.xes") # DataFrame or legacy EventLog
|
|
76
|
+
dfg, start_activities, end_activities = cpm.discover_dfg(log, n_windows=8)
|
|
77
|
+
|
|
78
|
+
print(dfg) # {("Register", "Review"): probability, ...}
|
|
79
|
+
print(start_activities) # {"Register": probability, ...}
|
|
80
|
+
print(cpm.discover_temporal_profile(log, n_windows=8))
|
|
81
|
+
# {("Register", "Review"): (mean_seconds, stdev_seconds), ...}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
For tabular input, use columns `case:concept:name`, `concept:name`, and
|
|
85
|
+
`time:timestamp`. For example:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import pandas as pd
|
|
89
|
+
import chronos4pm as cpm
|
|
90
|
+
|
|
91
|
+
log = pd.read_csv("completed_cases.csv")
|
|
92
|
+
log["time:timestamp"] = pd.to_datetime(log["time:timestamp"], utc=True)
|
|
93
|
+
probabilities = cpm.get_start_activities(log, n_windows=8)
|
|
94
|
+
|
|
95
|
+
# Custom column names work too:
|
|
96
|
+
dfg, starts, ends = cpm.discover_dfg(
|
|
97
|
+
custom_log,
|
|
98
|
+
activity_key="activity",
|
|
99
|
+
timestamp_key="timestamp",
|
|
100
|
+
case_id_key="case_id",
|
|
101
|
+
n_windows=8,
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`custom_log` above is your DataFrame with the three named columns. Inputs are
|
|
106
|
+
copied; the package does not mutate them. Events are sorted by timestamp and
|
|
107
|
+
cases by first timestamp, then case identifier. Supplied timezones are preserved
|
|
108
|
+
because calendar covariates use the observed local hour. Keep timestamps and the
|
|
109
|
+
forecast origin consistently timezone-aware (or consistently naive); normalize
|
|
110
|
+
to UTC explicitly, as above, when working with mixed input offsets. Use the same
|
|
111
|
+
time basis as the benchmark when comparing calendar covariates.
|
|
112
|
+
|
|
113
|
+
## Windows and forecast boundaries
|
|
114
|
+
|
|
115
|
+
Aggregate methods divide completed cases into **eight equal-size chronological
|
|
116
|
+
windows** by default and predict one further window of that same case count.
|
|
117
|
+
`n_windows` changes the number of history points. Case count must be at least
|
|
118
|
+
`n_windows` and divisible by it; the package rejects an uneven split rather than
|
|
119
|
+
discarding cases. A window is measured in cases, not hours or days.
|
|
120
|
+
|
|
121
|
+
Supply only completed historical cases. When `forecast_origin` is supplied,
|
|
122
|
+
every context case must end strictly before it. Automatic selected/global
|
|
123
|
+
covariates require this known timestamp to construct the benchmark's future
|
|
124
|
+
calendar covariates:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
probabilities = cpm.get_start_activities(
|
|
128
|
+
log,
|
|
129
|
+
n_windows=8,
|
|
130
|
+
covariates="selected",
|
|
131
|
+
forecast_origin=pd.Timestamp("2026-01-01T00:00:00Z"),
|
|
132
|
+
)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Choose an origin after **all** events in your completed-case context. Without
|
|
136
|
+
`forecast_origin`, target-only calls cannot check that external boundary; the
|
|
137
|
+
caller is responsible for supplying genuinely historical data. The package does
|
|
138
|
+
not construct the benchmark's held-out blocks or rolling evaluation origins.
|
|
139
|
+
|
|
140
|
+
## API
|
|
141
|
+
|
|
142
|
+
Every function takes `covariates="target_only"`, `"selected"`, or `"global"`.
|
|
143
|
+
Aggregate functions accept the shared keyword parameters listed below.
|
|
144
|
+
|
|
145
|
+
| Function | Forecast result |
|
|
146
|
+
| --- | --- |
|
|
147
|
+
| `discover_dfg(log)` | `(edge_probabilities, start_probabilities, end_probabilities)` |
|
|
148
|
+
| `discover_dfg_edges(log)` | `set[tuple[str, str]]`, from binary-presence scores ≥ 0.5 |
|
|
149
|
+
| `get_start_activities(log)` | `dict[str, float]` of start probabilities |
|
|
150
|
+
| `get_end_activities(log)` | `dict[str, float]` of end probabilities |
|
|
151
|
+
| `get_event_attribute_values(log, attribute="concept:name")` | `dict[str, float]` of event-mass probabilities |
|
|
152
|
+
| `get_variants_as_tuples(log)` | `dict[tuple[str, ...], float]` of variant probabilities |
|
|
153
|
+
| `discover_footprints(log)` | Dictionary of `activities`, `sequence`, and `parallel` sets |
|
|
154
|
+
| `discover_performance_dfg(log)` | `(edge_mean_seconds, start_probabilities, end_probabilities)` |
|
|
155
|
+
| `get_performance_bottlenecks(log)` | List of `(edge, seconds)` pairs, longest duration first |
|
|
156
|
+
| `discover_temporal_profile(log)` | `dict[tuple[str, str], tuple[float, float]]` of mean/stdev seconds |
|
|
157
|
+
| `analyse_entropy(log)` | EBI trace-distribution entropy forecast, in bits |
|
|
158
|
+
| `analyse_variety(log)` | EBI trace-variety forecast |
|
|
159
|
+
| `analyse_completeness(log)` | EBI event-log completeness forecast |
|
|
160
|
+
| `predict_next_activity(log, prefix)` | Next activity label (`str`) |
|
|
161
|
+
| `predict_next_event_time(log, prefix)` | Duration until the next event, in seconds (`float`) |
|
|
162
|
+
| `predict_remaining_time(log, prefix)` | Remaining case duration, in seconds (`float`) |
|
|
163
|
+
|
|
164
|
+
The three `analyse_*` names follow EBI; the prefix prediction and bottleneck/edge
|
|
165
|
+
helpers have no equivalent PM4Py prediction API. `discover_footprints` exposes
|
|
166
|
+
only the three fields modeled by the benchmark. `discover_performance_dfg` uses
|
|
167
|
+
PM4Py's **mean** edge duration target, not its default collection of aggregations.
|
|
168
|
+
DFG tuple methods also run start/end distribution forecasts; these are three
|
|
169
|
+
separate task requests sharing the cached model.
|
|
170
|
+
|
|
171
|
+
| Shared keyword | Default | Meaning |
|
|
172
|
+
| --- | --- | --- |
|
|
173
|
+
| `n_windows` | `8` | Equal-size aggregate history windows; aggregate methods only |
|
|
174
|
+
| `forecast_origin` | omitted | Known next-window origin; aggregate methods only |
|
|
175
|
+
| `activity_key` | `"concept:name"` | Activity column/event key |
|
|
176
|
+
| `timestamp_key` | `"time:timestamp"` | Timestamp column/event key |
|
|
177
|
+
| `case_id_key` | `"case:concept:name"` | Case column for DataFrames |
|
|
178
|
+
| `attribute_allowlist` | omitted | Event-carried attributes eligible for automatic global covariates |
|
|
179
|
+
| `past_covariates` | `{}` | Additional named, aligned numeric or categorical histories |
|
|
180
|
+
| `future_covariates` | `{}` | Additional known length-one values; names must occur in past covariates |
|
|
181
|
+
|
|
182
|
+
For `get_event_attribute_values`, use `attribute` to choose the activity/target
|
|
183
|
+
column; it takes precedence over `activity_key`.
|
|
184
|
+
|
|
185
|
+
## Predict from a case prefix
|
|
186
|
+
|
|
187
|
+
`log` contains completed prior cases. `prefix` contains **only events observed
|
|
188
|
+
so far** in one current case. It may be a PM4Py `Trace`, a one-case `EventLog`,
|
|
189
|
+
or a one-case DataFrame. Every context case must end before the first prefix
|
|
190
|
+
event; overlapping context is rejected, not silently removed.
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
import pandas as pd
|
|
194
|
+
import chronos4pm as cpm
|
|
195
|
+
|
|
196
|
+
history = pd.read_csv("completed_cases.csv")
|
|
197
|
+
prefix = pd.DataFrame(
|
|
198
|
+
[
|
|
199
|
+
{
|
|
200
|
+
"case:concept:name": "open-case",
|
|
201
|
+
"concept:name": "Register",
|
|
202
|
+
"time:timestamp": pd.Timestamp("2026-01-01T09:00:00Z"),
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"case:concept:name": "open-case",
|
|
206
|
+
"concept:name": "Review",
|
|
207
|
+
"time:timestamp": pd.Timestamp("2026-01-01T10:00:00Z"),
|
|
208
|
+
},
|
|
209
|
+
]
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
activity = cpm.predict_next_activity(history, prefix, covariates="selected")
|
|
213
|
+
next_seconds = cpm.predict_next_event_time(history, prefix, covariates="selected")
|
|
214
|
+
remaining_seconds = cpm.predict_remaining_time(history, prefix, covariates="global")
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The history must be earlier than this example's case start. Next activity uses
|
|
218
|
+
one-hot observed activity histories on context-supported labels. It needs one
|
|
219
|
+
observed event and does not predict an end-of-case class. Next-event time needs
|
|
220
|
+
two events to observe at least one interval. Remaining time uses PM4Py's remaining
|
|
221
|
+
durations from completed prior cases **at the same prefix position**, including
|
|
222
|
+
terminal zero durations when present in history. It rejects positions with no
|
|
223
|
+
context support. Pass a prefix whose case is still running; the package cannot
|
|
224
|
+
infer whether the last supplied event is actually terminal.
|
|
225
|
+
|
|
226
|
+
## Covariates as parameters
|
|
227
|
+
|
|
228
|
+
`target_only` adds no automatic covariates. `selected` and `global` use the
|
|
229
|
+
benchmark's task-dependent selections:
|
|
230
|
+
|
|
231
|
+
- Aggregate selected sets use progress/calendar and task-specific event volume
|
|
232
|
+
or activity, variant and DFG support. Performance tasks select timing instead
|
|
233
|
+
of mean prefix length. Global sets add all applicable aggregate families.
|
|
234
|
+
- Prefix sets use observed position, activity (where applicable), elapsed time,
|
|
235
|
+
previous intervals, and cyclic calendar features. Global remaining-time inputs
|
|
236
|
+
include collision-safe JSON encodings of complete observed activity prefixes.
|
|
237
|
+
- Global attributes are discovered only from context events. Case attributes
|
|
238
|
+
are forward-filled after their first observation; event attributes are aligned
|
|
239
|
+
directly. Trace metadata is not promoted into event covariates. Use
|
|
240
|
+
`attribute_allowlist=["customer_type", "org:resource"]` to restrict fields to
|
|
241
|
+
those known at prediction time. Availability cannot be inferred from a name.
|
|
242
|
+
|
|
243
|
+
You can add your own series to any set. For an aggregate call with eight windows:
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
probabilities = cpm.get_start_activities(
|
|
247
|
+
log,
|
|
248
|
+
n_windows=8,
|
|
249
|
+
past_covariates={"staff_on_shift": [4, 4, 5, 5, 6, 5, 4, 5]},
|
|
250
|
+
future_covariates={"staff_on_shift": [6]},
|
|
251
|
+
)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Numerical lists/arrays and categorical string lists/arrays are supported. Each
|
|
255
|
+
past covariate is one-dimensional and has exactly the target history length;
|
|
256
|
+
each future covariate has length one and the same name as a past series. Names
|
|
257
|
+
must not collide with automatic covariates. Arrays are shared across target
|
|
258
|
+
channels, not extra jointly forecast targets.
|
|
259
|
+
|
|
260
|
+
| Task | Alignment of caller-provided past covariates |
|
|
261
|
+
| --- | --- |
|
|
262
|
+
| Aggregate | One value per chronological context window |
|
|
263
|
+
| Next activity | One value per observed prefix event; future covariates are rejected |
|
|
264
|
+
| Next-event time | One value per observed interval, aligned to its **starting** event; future values describe the current observed event |
|
|
265
|
+
| Remaining time | One value per chronologically ordered context case reaching the prefix position; future values describe the current observed prefix |
|
|
266
|
+
|
|
267
|
+
Only supply values available at the forecast origin. Shape validation cannot
|
|
268
|
+
detect a future-derived attribute. Full histories are passed to Chronos so its
|
|
269
|
+
categorical encoding occurs before its internal context truncation; this avoids
|
|
270
|
+
changing the long-history remaining-time mapping. Preparing very large histories
|
|
271
|
+
can therefore use substantial host memory.
|
|
272
|
+
|
|
273
|
+
## Override the model constant
|
|
274
|
+
|
|
275
|
+
Set `chronos4pm.MODEL` once before calling the functions. It is deliberately not
|
|
276
|
+
a parameter repeated on every task method.
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
from dataclasses import replace
|
|
280
|
+
import chronos4pm as cpm
|
|
281
|
+
|
|
282
|
+
cpm.MODEL = replace(cpm.MODEL, device_map="mps") # Apple Silicon; "cuda" for CUDA
|
|
283
|
+
|
|
284
|
+
# Or choose a different checkpoint:
|
|
285
|
+
cpm.MODEL = cpm.ModelConfig(
|
|
286
|
+
repository_id="amazon/chronos-2",
|
|
287
|
+
revision="29ec3766d36d6f73f0696f85560a422f50e8498c",
|
|
288
|
+
device_map="cpu",
|
|
289
|
+
)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
| Benchmark checkpoint | Revision |
|
|
293
|
+
| --- | --- |
|
|
294
|
+
| `autogluon/chronos-2-small` (default) | `ddec01313e50b6bc58ebaa92ede81bc24a3d9f9a` |
|
|
295
|
+
| `amazon/chronos-2` | `29ec3766d36d6f73f0696f85560a422f50e8498c` |
|
|
296
|
+
| `autogluon/chronos-2-synth` | `3607918a9fd027d5c465d8213e46b98e2c041cea` |
|
|
297
|
+
|
|
298
|
+
The last configuration's pipeline is cached. Changing the constant causes the
|
|
299
|
+
next call to load that configuration. Do not change the global constant while
|
|
300
|
+
other threads are forecasting. `ModelConfig.batch_size` controls the internal
|
|
301
|
+
series batch (default 256); a multivariate request may require a larger minimum.
|
|
302
|
+
The package performs one request at a time and propagates model/download/memory
|
|
303
|
+
errors. It does not substitute another model or shrink the process-element
|
|
304
|
+
support. Chronos-1/Bolt checkpoints are not supported by this Chronos-2 API.
|
|
305
|
+
|
|
306
|
+
## Method boundaries
|
|
307
|
+
|
|
308
|
+
The package retains native PM4Py/EBI target construction, one-step Chronos-2
|
|
309
|
+
median forecasts, Euclidean probability-simplex projection, binary edge
|
|
310
|
+
thresholding, and none/sequence/parallel argmax decoding. Missing performance
|
|
311
|
+
observations remain NaN in history. Distributions cannot introduce unseen
|
|
312
|
+
activities, edges, or variants. Unknown activities in an observed prefix have
|
|
313
|
+
zero entries in the context-supported one-hot channels.
|
|
314
|
+
|
|
315
|
+
Duration and EBI scalar forecasts are returned raw, as in the benchmark. They
|
|
316
|
+
can be negative or outside a statistic's natural bounds; temporal standard
|
|
317
|
+
deviations are not silently clipped. Use these methods for experimentation and
|
|
318
|
+
evaluate them on your own held-out data. A successful forecast does not establish
|
|
319
|
+
accuracy. Remaining-time prediction was implemented in the benchmark but excluded
|
|
320
|
+
from the current paper's 15-task evaluation.
|
|
321
|
+
|
|
322
|
+
The package does not reproduce the paper's experiment orchestration, metrics,
|
|
323
|
+
quantile reports, data selection, or runtime measurements. Use the original
|
|
324
|
+
repository for those. No benchmark artifacts or results are bundled here.
|
|
325
|
+
|
|
326
|
+
## Development and building a release
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
python -m pip install -e '.[dev]'
|
|
330
|
+
python -m pytest -q
|
|
331
|
+
python -m ruff check .
|
|
332
|
+
python -m ruff format --check .
|
|
333
|
+
python -m mypy chronos4pm tests examples main.py
|
|
334
|
+
RUN_CHRONOS_INTEGRATION=1 python -m pytest -q
|
|
335
|
+
python -m build
|
|
336
|
+
python -m twine check dist/*
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Default tests isolate decoding with explicit test doubles and call real PM4Py
|
|
340
|
+
and EBI. The opt-in integration tests execute all 16 tasks in all three covariate
|
|
341
|
+
arms with the real default checkpoint. Set `HF_HUB_OFFLINE=1` to use only already
|
|
342
|
+
cached Hugging Face files. Tests use illustrative logs, not the paper's datasets.
|
|
343
|
+
Wheel and source archives are created in `dist/`; building does not publish them.
|
|
344
|
+
|
|
345
|
+
The implementation is divided by responsibility: public functions in `api.py`,
|
|
346
|
+
native histories/decoders in `tasks.py`, prefix mappings in `predictive.py`,
|
|
347
|
+
covariate construction in `covariates.py`, input validation in `logs.py`, and
|
|
348
|
+
lazy model inference in `inference.py`. `main.py` only starts the example.
|