meds-algorithm 0.4.0a4__py3-none-any.whl
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.
- meds_algorithm/ARCHITECTURE.md +376 -0
- meds_algorithm/CONTRACT.md +567 -0
- meds_algorithm/__init__.py +94 -0
- meds_algorithm/algorithms.py +157 -0
- meds_algorithm/artifacts/__init__.py +1 -0
- meds_algorithm/artifacts/inputs.py +38 -0
- meds_algorithm/artifacts/manifest.py +142 -0
- meds_algorithm/artifacts/publication.py +68 -0
- meds_algorithm/artifacts/references.py +79 -0
- meds_algorithm/artifacts/results.py +76 -0
- meds_algorithm/configuration.py +64 -0
- meds_algorithm/conformance/__init__.py +1 -0
- meds_algorithm/conformance/assertions.py +62 -0
- meds_algorithm/conformance/end_to_end.py +150 -0
- meds_algorithm/conformance/meds_dev.py +127 -0
- meds_algorithm/conformance/reports.py +49 -0
- meds_algorithm/conformance/signal.py +141 -0
- meds_algorithm/conformance/types.py +29 -0
- meds_algorithm/contracts/__init__.py +1 -0
- meds_algorithm/contracts/commands.py +182 -0
- meds_algorithm/contracts/enums.py +28 -0
- meds_algorithm/data/__init__.py +1 -0
- meds_algorithm/data/index.py +56 -0
- meds_algorithm/data/labels.py +55 -0
- meds_algorithm/data/predicates.py +60 -0
- meds_algorithm/data/validation.py +25 -0
- meds_algorithm/evaluation/__init__.py +1 -0
- meds_algorithm/evaluation/predictions.py +56 -0
- meds_algorithm/integrations/__init__.py +1 -0
- meds_algorithm/integrations/meds_dev.py +51 -0
- meds_algorithm/requests.py +262 -0
- meds_algorithm/runner.py +232 -0
- meds_algorithm/runtime/__init__.py +1 -0
- meds_algorithm/runtime/process.py +50 -0
- meds_algorithm/runtime/provenance.py +31 -0
- meds_algorithm/runtime/resources.py +97 -0
- meds_algorithm/serialization.py +122 -0
- meds_algorithm/spec.py +23 -0
- meds_algorithm/tasks/__init__.py +1 -0
- meds_algorithm/tasks/spec.py +136 -0
- meds_algorithm/version.py +3 -0
- meds_algorithm-0.4.0a4.dist-info/METADATA +212 -0
- meds_algorithm-0.4.0a4.dist-info/RECORD +46 -0
- meds_algorithm-0.4.0a4.dist-info/WHEEL +4 -0
- meds_algorithm-0.4.0a4.dist-info/entry_points.txt +4 -0
- meds_algorithm-0.4.0a4.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
# MEDS Algorithm Repository Contract, version 4
|
|
2
|
+
|
|
3
|
+
This document is the single authoritative contract shipped with meds-algorithm. Algorithm repositories
|
|
4
|
+
pin a core version and refer to its contract; they do not maintain copies of these rules. A conforming repository turns a MEDS dataset, an optional task, and an optional semantic
|
|
5
|
+
specification into MEDS predictions through one or more of six fixed algorithm profiles. How a command performs its
|
|
6
|
+
work is deliberately outside this contract.
|
|
7
|
+
|
|
8
|
+
## 1. Principles
|
|
9
|
+
|
|
10
|
+
- The input and final output are interoperable; intermediate payloads are implementation-owned.
|
|
11
|
+
- Commands have stable meanings, but do not prescribe Python, batching, tensors, training frameworks,
|
|
12
|
+
checkpoint formats, or execution hardware.
|
|
13
|
+
- Every intermediate artifact has a standard manifest envelope even when its payload is opaque.
|
|
14
|
+
- A repository is operational: it declares itself through `algorithms/<profile>/model.yaml`, tests its real implementation end
|
|
15
|
+
to end, runs locally or through SLURM, and can exchange structured run results through GitHub.
|
|
16
|
+
- The six algorithm profiles are the supported command lifecycles. A repository declares a nonempty set; it does not invent an
|
|
17
|
+
undocumented profile.
|
|
18
|
+
|
|
19
|
+
## 2. Inputs
|
|
20
|
+
|
|
21
|
+
### 2.1 MEDS dataset
|
|
22
|
+
|
|
23
|
+
`external_meds_dir` MUST be a valid, split-sharded MEDS dataset. Event semantics come from the versioned
|
|
24
|
+
MEDS standard. Implementations MUST NOT reinterpret `subject_id`, `time`, `code`, value columns, static
|
|
25
|
+
events (`time = null`), or code metadata incompatibly. MIMIC-IV demo in MEDS form is the canonical real
|
|
26
|
+
data example, not an additional schema.
|
|
27
|
+
|
|
28
|
+
The `train`, `tuning`, and `held_out` splits are a boundary, not a convention. Any statistic fitted over a
|
|
29
|
+
population — vocabularies, code frequencies, quantile bins, normalization constants, feature selections —
|
|
30
|
+
MUST be fitted on the training split alone. Fitting one over all splits is *transductive* leakage: it is
|
|
31
|
+
not label leakage, because quantities like code frequency are label-independent, so an implementation can
|
|
32
|
+
satisfy every label-leakage check while carrying it. Where the fitting scope is not the implementation's
|
|
33
|
+
to control, because preprocessing is delegated upstream, it MUST declare which quantity was fitted over
|
|
34
|
+
which population rather than leave the scope unstated.
|
|
35
|
+
|
|
36
|
+
### 2.2 Task
|
|
37
|
+
|
|
38
|
+
A task input is an index of `(subject_id, prediction_time)` and, for training/evaluation only, a value
|
|
39
|
+
column such as `boolean_value`. Labels of an **evaluated split** MUST never be read to produce a
|
|
40
|
+
prediction. Which other labels a command may read depends on the profile:
|
|
41
|
+
|
|
42
|
+
The per-step table in section 9 specifies access to **ground-truth target values**, such as
|
|
43
|
+
`boolean_value`. These are different from index keys `(subject_id, prediction_time)` and from the
|
|
44
|
+
algorithm's predicted probability. Inference and ordinary scoring receive `external_index_dir` and project
|
|
45
|
+
only its keys. Training receives `external_labels_dir`; in-context prediction may also receive that
|
|
46
|
+
argument solely for explicitly permitted train/tuning context examples. Zero-shot commands read none.
|
|
47
|
+
|
|
48
|
+
MEDS-DEV may map its existing `{labels_dir}` source to `external_index_dir`. That is a key-only view of
|
|
49
|
+
the same files, not permission to load their outcome columns. A physically separate keys-only index is
|
|
50
|
+
also supported. Neither representation rebuilds or filters the upstream cohort.
|
|
51
|
+
|
|
52
|
+
Once scores are fixed, an evaluation adapter MAY use `external_evaluation_labels_dir` to join truth onto the
|
|
53
|
+
predictions by key (`meds_algorithm.attach_ground_truth`), because meds-evaluation reads ground truth
|
|
54
|
+
from the predictions file. Nothing computed from that join may feed back into a prediction.
|
|
55
|
+
|
|
56
|
+
The cohort is built upstream, not in the algorithm repository. The index and its labels come from one
|
|
57
|
+
extraction run outside every algorithm: MEDS-DEV's `meds-dev-task` for the MIMIC-IV demo, and a shared, reviewed
|
|
58
|
+
task bundle for full-data runs, whose tasks may be clinical tasks defined in ACES or randomly sampled
|
|
59
|
+
code-by-horizon tasks. That extraction applies the trigger, inclusion/exclusion criteria, and splits once,
|
|
60
|
+
so every algorithm scores the same keys. A algorithm repository
|
|
61
|
+
MUST NOT re-extract, filter, or extend the index; it predicts every requested row (section 5). This holds
|
|
62
|
+
for zero-shot profiles too: they receive the ACES task (section 2.4) to build their *query*, never to
|
|
63
|
+
rebuild their cohort.
|
|
64
|
+
|
|
65
|
+
### 2.3 Dataset predicates
|
|
66
|
+
|
|
67
|
+
Dataset-specific predicates are external inputs, supplied through the established
|
|
68
|
+
`external_predicates_file` argument. When MEDS-DEV provides predicates for a dataset, the repository MUST
|
|
69
|
+
reuse them rather than duplicating dataset knowledge in the algorithm template. In particular, the MIMIC-IV
|
|
70
|
+
demo MUST use MEDS-DEV's MIMIC-IV predicates. A algorithm decides whether and how to consume them: token
|
|
71
|
+
selection, SQL, columns, time-series extraction, direct event matching, or no use at all are equally valid.
|
|
72
|
+
Any command that consumes the file MUST record its digest and origin.
|
|
73
|
+
|
|
74
|
+
A algorithm that depends on particular predicate names declares and validates those requirements in its own
|
|
75
|
+
configuration and tests. The contract does not prescribe a predicate-derived feature representation.
|
|
76
|
+
|
|
77
|
+
`AlgorithmConfig.additional_predicates_file` MAY select additional feature predicates for the current
|
|
78
|
+
dataset. It defaults to `None`; relative paths in `config_file` resolve against that file's parent.
|
|
79
|
+
During `preprocess_data` only, the runner composes the optional base `external_predicates_file` and the
|
|
80
|
+
additions. Both documents MUST contain only a `predicates` mapping of names to nonempty definitions.
|
|
81
|
+
Duplicate YAML keys and names shared across the files MUST fail, even for identical definitions.
|
|
82
|
+
The helper validates structure, not expression semantics or dataset compatibility.
|
|
83
|
+
|
|
84
|
+
The preprocessing implementation and its `validate_inputs` hook receive the resolved file as
|
|
85
|
+
`request.predicates_file`. Core owns this file, saves it as `resolved_feature_predicates.yaml` inside
|
|
86
|
+
the prepared-data artifact, and records source paths/digests plus the resolved relative path/digest
|
|
87
|
+
under `inputs.feature_predicates`. The configuration digest includes these identities. Implementations
|
|
88
|
+
MUST NOT modify or delete the resolved file; the original request retains the external base path.
|
|
89
|
+
When composing, the compatibility hook runs inside staging after resolution and is included in measurement.
|
|
90
|
+
|
|
91
|
+
Feature additions MUST remain task-independent and respect temporal cutoffs. They MUST NOT redefine
|
|
92
|
+
the target/cohort or supply outcomes to preprocessing. The runner never composes additions for training,
|
|
93
|
+
prediction, or `TaskSpec`; task bindings and evaluated keys remain unchanged. Later stages consume
|
|
94
|
+
persisted feature artifacts and do not reopen the additions file. Keep the same resolved configuration
|
|
95
|
+
across the lifecycle. A preprocessing rerun still requires its original source files.
|
|
96
|
+
|
|
97
|
+
### 2.4 Task specification (zero-shot profiles)
|
|
98
|
+
|
|
99
|
+
A supervised algorithm learns what to predict from labels. A zero-shot algorithm never sees labels, so the task
|
|
100
|
+
definition itself is an input. The task language is [ACES](https://eventstreamaces.readthedocs.io/): a task
|
|
101
|
+
is an ACES criteria file, supplied through `external_task_criteria_file`, bound to the dataset predicates of
|
|
102
|
+
section 2.3 when the criteria do not define their own. The pair is the *task specification*
|
|
103
|
+
(`meds_algorithm.TaskSpec`).
|
|
104
|
+
|
|
105
|
+
- Every command of a `zero_shot_*` profile whose output depends on the task (`ZERO_SHOT_TASK_COMMANDS`:
|
|
106
|
+
`predict_zero_shot_direct` and `predict_zero_shot_materialized`) MUST receive `external_task_criteria_file`, MUST
|
|
107
|
+
validate it before expensive work, and MUST record `TaskSpec.provenance()` under `inputs.task` and
|
|
108
|
+
`TaskSpec.semantics_digest()` as the manifest `semantics_digest`.
|
|
109
|
+
- The predicates bound to the task can define the label itself (a task-suite layer defining, say, `aki`).
|
|
110
|
+
Such a file MUST reach only task-conditioned commands, never a command that builds algorithm inputs:
|
|
111
|
+
`preprocess_data` receives dataset-level predicates only. Through SLURM the two are `PREDICATES_FILE` and
|
|
112
|
+
`TASK_PREDICATES_FILE`. Through MEDS-DEV there is no conflict, because its task YAMLs carry their label
|
|
113
|
+
predicates and `{predicates_path}` holds dataset facts only.
|
|
114
|
+
- Those commands receive the task index through `external_index_dir` for its keys only. They MUST read it
|
|
115
|
+
through `meds_algorithm.read_index`, or an equivalent that never selects a label column.
|
|
116
|
+
- Through MEDS-DEV, the criteria path reaches `algorithms/<profile>/model.yaml` as `{task_criteria_path}` (MEDS-DEV PR #330):
|
|
117
|
+
the `task_criteria_path` argument, else the registered criteria file of `task_name`. MEDS-DEV forwards
|
|
118
|
+
the original task; relaxing it is the algorithm's job.
|
|
119
|
+
|
|
120
|
+
`predict_only` MAY accept the same argument as provenance without requiring it. Other non-zero-shot
|
|
121
|
+
commands reject it. Only zero-shot prediction commands bind `semantics_digest` to a task.
|
|
122
|
+
|
|
123
|
+
## 3. Commands and algorithm profiles
|
|
124
|
+
|
|
125
|
+
A repository registers the union of its declared profiles once. Only `preprocess_data` and `pretrain`
|
|
126
|
+
are shared step names. Every other step has a distinct meaning and name. Unsupported steps fail; the
|
|
127
|
+
old `infer`, `supervised_train`, and `predict` names are not aliases.
|
|
128
|
+
|
|
129
|
+
| Profile | Commands in dependency order |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `supervised` | `preprocess_data → train_supervised → predict_supervised` |
|
|
132
|
+
| `finetune` | `preprocess_data → pretrain → train_finetune → predict_finetune` |
|
|
133
|
+
| `probe` | `preprocess_data → pretrain → infer_embeddings → train_probe → predict_probe` |
|
|
134
|
+
| `zero_shot_direct` | `preprocess_data → pretrain → predict_zero_shot_direct` |
|
|
135
|
+
| `zero_shot_materialized` | `preprocess_data → pretrain → infer_trajectories → predict_zero_shot_materialized` |
|
|
136
|
+
| `predict_only` | `preprocess_data → predict_only` |
|
|
137
|
+
|
|
138
|
+
The CLI is `meds-algorithm <step> --profile <profile> key=value ...`. `meds-algorithm profiles` lists declared
|
|
139
|
+
profiles; `meds-algorithm commands --profile <profile>` lists their steps in dependency order. Profile
|
|
140
|
+
selection is mandatory when more than one is declared, including for shared commands. The dispatcher
|
|
141
|
+
MUST reject a step belonging to another profile before invoking any algorithm code.
|
|
142
|
+
|
|
143
|
+
`predict_only` preserves the former packaged lifecycle: preprocessing followed by prediction, with no
|
|
144
|
+
training command. Fixed published algorithms and in-context learners can both use it. In-context examples
|
|
145
|
+
MUST come only from explicitly declared train/tuning splits disjoint from evaluated splits; there is no
|
|
146
|
+
persistent task-head training hidden in this profile.
|
|
147
|
+
|
|
148
|
+
The required Python boundary consists of `Command`, `CommandName`, `ArtifactType`, `ArtifactInput`,
|
|
149
|
+
`StepSpec`, `STEP_SPECS`, and `LegacyAlgorithmRepository`. Their signatures and the detailed per-step software
|
|
150
|
+
requirements are specified in section 9 below. Implementations MUST meet
|
|
151
|
+
those requirements even when their backend is an external process. Framework internals are algorithm-owned.
|
|
152
|
+
|
|
153
|
+
### 3.1 Zero-shot prediction
|
|
154
|
+
|
|
155
|
+
A zero-shot algorithm maps *(task specification, label-blind index, MEDS dataset)* to *predictions* with no
|
|
156
|
+
task-specific training. The two zero-shot profiles differ in **how the algorithm answers**, not in how the
|
|
157
|
+
code is organized:
|
|
158
|
+
|
|
159
|
+
| Profile | The algorithm... | Materialization | Prediction | Examples |
|
|
160
|
+
|---|---|---|---|---|
|
|
161
|
+
| `zero_shot_direct` | answers a query derived from the task directly (a probability, hazard, or score per query) | none | translates the task into the algorithm's queries, runs the algorithm, decodes probabilities | MOTOR (time-to-event hazards), EveryQuery (code-in-window queries) |
|
|
162
|
+
| `zero_shot_materialized` | generates (*materializes*) possible futures, and the task is evaluated on them | task-independent: futures at the index's prediction times, reusable across tasks | applies the task to the materialized futures (e.g. ACES over each sampled trajectory) and aggregates | autoregressive EHR generators |
|
|
163
|
+
|
|
164
|
+
In `zero_shot_materialized`, `infer_trajectories` never receives the task and records `semantics_digest: null`. Its `predict_zero_shot_materialized`
|
|
165
|
+
receives `external_meds_dir`, because the task is evaluated on the real history plus each generated future. Its
|
|
166
|
+
output serves every task over the same index. Only the prediction step is task-conditioned. A materialized algorithm
|
|
167
|
+
can usually evaluate the task exactly, past criteria included, because ACES runs on the real history plus
|
|
168
|
+
the generated future. Its ledger then lists only the sampling approximation. A direct algorithm reduces the
|
|
169
|
+
task to its query language, and its ledger lists every reduction. Intermediate payloads are
|
|
170
|
+
implementation-defined, as in section 4.
|
|
171
|
+
|
|
172
|
+
**Relaxations.** Most zero-shot algorithms cannot answer an arbitrary ACES task exactly; they answer a related
|
|
173
|
+
question their query language can express. Every zero-shot run MUST therefore publish `relaxations.yaml`
|
|
174
|
+
(`meds_algorithm.RelaxationLedger`) in a task-conditioned artifact. Three fields are required:
|
|
175
|
+
|
|
176
|
+
```yaml
|
|
177
|
+
query_language: MOTOR first-occurrence time-to-event over task-head codes # required
|
|
178
|
+
decoded_quantity: P(any of {MEDS_DEATH} first occurs before the first of {ICU_DISCHARGE, MEDS_DEATH}) # required
|
|
179
|
+
exact: false # required
|
|
180
|
+
steps: # free-form, recommended
|
|
181
|
+
- {name: normalize, kind: label_preserving, direction: exact, detail: re-rooted at the prediction time}
|
|
182
|
+
- {name: label_only, kind: algorithm_assumption, direction: unknown, detail: dropped 2 criteria branches}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`exact: true` is a claim that the decoded quantity is the requested label's probability under the algorithm;
|
|
186
|
+
an exact algorithm lists no steps. Each entry of `steps` describes one rewrite or assumption; its keys are not
|
|
187
|
+
validated, and the implementation guide recommends a vocabulary for them. A algorithm MUST raise rather than
|
|
188
|
+
answer a task it cannot pose (for example, a direct algorithm given a task whose label is not future-only):
|
|
189
|
+
the command fails and writes no predictions. A algorithm MUST NOT omit a step because it is expected to be
|
|
190
|
+
small.
|
|
191
|
+
|
|
192
|
+
## 4. Intermediate artifacts
|
|
193
|
+
|
|
194
|
+
Every artifact directory MUST contain `manifest.yaml`, written last in staging before publication. Required
|
|
195
|
+
envelope fields are:
|
|
196
|
+
|
|
197
|
+
```yaml
|
|
198
|
+
contract_version: "4"
|
|
199
|
+
artifact:
|
|
200
|
+
type: patients | pretrained_algorithm | embeddings | trajectories | supervised_algorithm | finetuned_algorithm | probe_algorithm | predictions
|
|
201
|
+
payload_format: implementation-defined/version
|
|
202
|
+
producer: importable-or-external-implementation-id
|
|
203
|
+
command:
|
|
204
|
+
name: <one exact CommandName from the selected profile>
|
|
205
|
+
config_digest: sha256:... # digest_config(arguments + resolved algorithm-owned settings)
|
|
206
|
+
code:
|
|
207
|
+
git_commit: <sha> | null # null outside a git checkout
|
|
208
|
+
dirty: true | false | null # whether the working tree had uncommitted changes
|
|
209
|
+
inputs: {}
|
|
210
|
+
semantics_digest: null | sha256:... # TaskSpec digest for task-conditioned artifacts (section 2.4)
|
|
211
|
+
resources: {}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
`config_digest` is `meds_algorithm.digest_config` over the command's arguments plus any algorithm-owned
|
|
215
|
+
settings it resolved (defaults, configuration files), so two artifacts made with the same configuration
|
|
216
|
+
share it. `code` is recorded by `measured_artifact(..., repo=algorithm_root)` from the explicitly supplied algorithm
|
|
217
|
+
checkout. The core installation path and current directory MUST NOT be used to infer algorithm identity.
|
|
218
|
+
Without a checkout, revision and dirty state remain null; deployed algorithms must retain their build provenance. Inputs MUST include stable identifiers or digests, including an external predicates
|
|
219
|
+
digest when the command consumes one. Consumers MUST reject incompatible artifact type, contract version,
|
|
220
|
+
or payload format before doing expensive work.
|
|
221
|
+
|
|
222
|
+
Each artifact is its own directory. New outputs are published by one rename from unique staging.
|
|
223
|
+
Overwriting an existing output MUST preserve or restore the previous artifact if publication fails.
|
|
224
|
+
The core serializes cooperating writers with an exclusive destination lock and retains an old backup
|
|
225
|
+
until replacement succeeds. Its two-rename overwrite can briefly hide the destination from readers;
|
|
226
|
+
use immutable output paths when concurrent readers require uninterrupted access. A process crash can
|
|
227
|
+
leave a lock/staging/backup for explicit recovery; this is not a power-loss transaction. Artifacts MUST NOT
|
|
228
|
+
be nested inside one another: `infer_embeddings` writes to `output_embeddings_dir` and `infer_trajectories` to `output_trajectories_dir`, a sibling of the data and
|
|
229
|
+
predictions directories, never to a subdirectory of the shared `patients` artifact, so runs over different
|
|
230
|
+
indexes or splits cannot overwrite each other. In a MEDS-DEV run directory the layout is `data/`,
|
|
231
|
+
`pretrained/`, `algorithm/`, `embeddings/` or `trajectories/`, `predictions/`, next to MEDS-DEV's own files.
|
|
232
|
+
|
|
233
|
+
## 5. Final predictions
|
|
234
|
+
|
|
235
|
+
Predictions MUST conform to the prediction schema of the meds-evaluation version MEDS-DEV evaluates with
|
|
236
|
+
(currently `meds-evaluation==0.0.3`, `validate_binary_classification_schema`). MEDS-DEV evaluates every
|
|
237
|
+
`**/*.parquet` under the predictions directory, so every parquet file in the predictions artifact MUST be a
|
|
238
|
+
predictions file; supporting tables (for example a zero-shot query bundle) use another format, such as
|
|
239
|
+
Arrow IPC. Predictions MUST contain exactly one
|
|
240
|
+
row for every requested `(subject_id, prediction_time)` unless an explicitly declared exclusion policy
|
|
241
|
+
permits otherwise. Keys MUST be unique. Row order is not meaningful and MUST never be used to associate
|
|
242
|
+
outputs with keys. Extra output columns are permitted only when documented by the selected task/output
|
|
243
|
+
kind. Conformance tests MUST compare actual prediction keys directly with the requested evaluation index;
|
|
244
|
+
self-reported coverage counts are not proof of coverage. Manifests MAY include coverage counts as diagnostic
|
|
245
|
+
metadata. Any exclusion policy MUST identify its excluded keys so tests can validate the resulting index.
|
|
246
|
+
|
|
247
|
+
Zero-shot predictions are evaluated against the labels of the *requested* task, never the relaxed one: the
|
|
248
|
+
relaxation is part of the algorithm. The prediction artifact MUST carry or reference the `relaxations.yaml` that
|
|
249
|
+
produced it, so a reader can tell algorithm error from relaxation error.
|
|
250
|
+
|
|
251
|
+
## 6. Measurements
|
|
252
|
+
|
|
253
|
+
Every command invocation MUST record measurements, whether run locally, in tests, through MEDS-DEV, or on
|
|
254
|
+
SLURM:
|
|
255
|
+
|
|
256
|
+
```yaml
|
|
257
|
+
resources:
|
|
258
|
+
wall_seconds: 1.25
|
|
259
|
+
memory:
|
|
260
|
+
peak_process_tree_pss_bytes: 123456
|
|
261
|
+
peak_process_tree_rss_bytes: 234567
|
|
262
|
+
sampling_interval_seconds: 0.25
|
|
263
|
+
source: linux_proc_smaps_rollup
|
|
264
|
+
includes_descendants: true
|
|
265
|
+
gpu:
|
|
266
|
+
peak_allocated_bytes: null
|
|
267
|
+
peak_reserved_bytes: null
|
|
268
|
+
source: null
|
|
269
|
+
measurement:
|
|
270
|
+
schema_version: "1"
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Wall time uses a monotonic clock. On Linux, memory is sampled over the live process tree and PSS is the
|
|
274
|
+
primary comparison value because it apportions shared pages. RSS is retained as a diagnostic. Scheduler
|
|
275
|
+
`MaxRSS`, when available, is a separate value with different semantics. `null` means not measured or not
|
|
276
|
+
applicable; zero means measured with no allocation. Manifests MAY also report meaningful work units such
|
|
277
|
+
as subjects, events, rows, timepoints, or optimizer steps. Resource values are observations, never
|
|
278
|
+
portable pass/fail thresholds.
|
|
279
|
+
|
|
280
|
+
## 7. Required repository interfaces
|
|
281
|
+
|
|
282
|
+
- Every declared profile MUST have `algorithms/<profile>/model.yaml`, valid for MEDS-DEV. Its external
|
|
283
|
+
`unsupervised`/`supervised` and `train`/`predict` slots are unchanged; each command selects its profile.
|
|
284
|
+
Registration uses `<algorithm-name>__<profile>` so separate descriptors coexist in MEDS-DEV.
|
|
285
|
+
- `tests/test_end_to_end.py` MUST execute each declared profile independently and validate final
|
|
286
|
+
prediction keys, schema, manifests, and resource blocks. A stub MAY skip explicitly during initial
|
|
287
|
+
implementation; a completed port MUST have zero stub skips.
|
|
288
|
+
- The algorithm-owned end-to-end adapters MUST identify the labels/evaluation index and evaluated splits so
|
|
289
|
+
generic tests can compare requested and written prediction keys directly. `run_e2e` MUST also return the
|
|
290
|
+
external inputs and integer fixture seed in `E2EResult.inputs`, and MUST apply
|
|
291
|
+
`meds_algorithm.conformance.signal.add_split_canaries` to its fixture and
|
|
292
|
+
return the canaries. `fitted_codes` MUST report every code the algorithm fitted a population statistic for,
|
|
293
|
+
read from its artifacts.
|
|
294
|
+
- `meds-algorithm-add-to-meds-dev` (`meds_algorithm.integrations.meds_dev.register`) installs `algorithms/<profile>/model.yaml` and
|
|
295
|
+
`requirements.txt`, with the repository as an editable requirement, into a MEDS-DEV checkout. A
|
|
296
|
+
top-level `predicates.yaml` is copied as well when the repository has one. MEDS-DEV's own dataset
|
|
297
|
+
predicates remain the default (section 2.3).
|
|
298
|
+
- `slurm/submit.sh --dry-run` MUST print the algorithm-profile submission without mutation. `slurm/submit.sh`
|
|
299
|
+
MUST submit the selected algorithm profile with dependencies, per-stage resources, durable results, and no interactive-shell
|
|
300
|
+
dependency.
|
|
301
|
+
- Cluster runs MUST record the exact Git commit, dirty state, environment, machine, scheduler job id, and
|
|
302
|
+
references to command manifests.
|
|
303
|
+
- GitHub synchronization MUST use a run branch, never push results directly to the default branch, commit
|
|
304
|
+
structured specifications/results/manifests rather than data, checkpoints, credentials, or raw logs,
|
|
305
|
+
and leave results recoverable on disk if authentication or push fails.
|
|
306
|
+
- `tests/test_meds_dev_e2e.py` and `tests/test_mimic_demo_e2e.py` MUST exercise the completed algorithm through
|
|
307
|
+
MEDS-DEV and the MIMIC-IV demo respectively. Both skip only the profiles in `STUB_PROFILES`. The MIMIC
|
|
308
|
+
test runs the full algorithm profile on MEDS-DEV's `mortality/in_icu/first_24h` task and validates only standard
|
|
309
|
+
boundaries; preprocessing payloads remain opaque.
|
|
310
|
+
|
|
311
|
+
## 8. Conformance
|
|
312
|
+
|
|
313
|
+
The generated repository MUST test command discovery, selected-algorithm-profile consistency, artifact compatibility,
|
|
314
|
+
publication and rollback, predicate provenance, prediction key coverage/uniqueness, absence of label
|
|
315
|
+
leakage and of transductive fitting (section 2.1), resource measurement presence, `algorithms/<profile>/model.yaml`, SLURM
|
|
316
|
+
dry-run, and its real end-to-end chain. The rendered `tests/test_end_to_end.py` checks the original run and a fresh rerun:
|
|
317
|
+
|
|
318
|
+
- **Label leakage:** the complete lifecycle runs again with evaluated outcome columns removed (all
|
|
319
|
+
outcomes for zero-shot profiles). Each external input root is copied separately, preserving permitted
|
|
320
|
+
train/tuning outcomes. Both runs MUST cover every key, and their probabilities MUST agree by key
|
|
321
|
+
(`rtol=1e-6`, `atol=1e-8`); optional Boolean decisions agree exactly. `run_e2e` MUST honor and record
|
|
322
|
+
the integer `seed` override, seed every RNG/framework/subprocess and use deterministic fixture settings.
|
|
323
|
+
`attach_ground_truth` returns predictions unchanged on an unlabelled index. This tests outcome
|
|
324
|
+
independence on the exercised fixture, not every possible code path.
|
|
325
|
+
- **Prediction validity:** validate every Parquet shard in both runs, including unique/non-null keys and
|
|
326
|
+
finite probabilities in [0, 1]. No particular shard filename is required.
|
|
327
|
+
- **Transductive fitting:** every tuning and held-out subject carries a canary code that occurs in no
|
|
328
|
+
training subject. None of the canaries may appear in `fitted_codes`.
|
|
329
|
+
- **Configuration:** every manifest carries a `config_digest`.
|
|
330
|
+
|
|
331
|
+
A zero-shot repository additionally tests that task-conditioned manifests carry the task's semantics
|
|
332
|
+
digest and that a valid `relaxations.yaml` is published.
|
|
333
|
+
MIMIC-IV demo conformance is opt-in through a `real_data` pytest marker; a normal test run MUST NOT
|
|
334
|
+
download it.
|
|
335
|
+
|
|
336
|
+
## 9. Software interfaces
|
|
337
|
+
|
|
338
|
+
### Public classes and ownership
|
|
339
|
+
|
|
340
|
+
New implementations use the typed algorithm API. Each profile class owns its ordered lifecycle and
|
|
341
|
+
abstract typed method signatures. Each request class owns its fields, CLI names, output argument and
|
|
342
|
+
result artifact type. Existing `ALGORITHM_PROFILES` and `STEP_SPECS` are derived read-only views, not another
|
|
343
|
+
hand-maintained specification.
|
|
344
|
+
|
|
345
|
+
| Symbol | Responsibility |
|
|
346
|
+
|---|---|
|
|
347
|
+
| `Algorithm` | Common algorithm identity/configuration, abstract `preprocess_data`, compatibility hook. |
|
|
348
|
+
| `SupervisedAlgorithm`, `FinetuneAlgorithm`, `ProbeAlgorithm`, `ZeroShotDirectAlgorithm`, `ZeroShotMaterializedAlgorithm`, `PredictOnlyAlgorithm` | Require exactly the operations of each profile. Pretrained profiles share `PretrainedAlgorithm.pretrain`. |
|
|
349
|
+
| `AlgorithmConfig` | Base for a algorithm-owned frozen dataclass: typed fields, defaults, `validate`, strict serialization. |
|
|
350
|
+
| `ExecutionOptions` | Nonnegative integer seed and boolean overwrite policy. Algorithms apply the seed to their RNGs. |
|
|
351
|
+
| `StepRequest` subclasses | Frozen, typed inputs plus output destination and execution options for each operation. |
|
|
352
|
+
| `ArtifactReference` subclasses | Lazy references to prepared data, pretrained/fitted algorithms, embeddings, trajectories and predictions. |
|
|
353
|
+
| `PredictionIndex`, `TrainingLabels`, `PredictionContext` | Distinct key-only, train/tuning target and explicit disjoint-context boundaries. |
|
|
354
|
+
| `ArtifactDestination`, `PayloadMetadata` | Staging destination supplied to algorithm code; algorithm-returned payload format/version. |
|
|
355
|
+
| `AlgorithmRepository` | Profile-to-concrete-class association; fresh instance per dispatch, no duplicate step registry. |
|
|
356
|
+
| `StepRunner` | Validate, call compatibility hook, stage/measure algorithm work, validate predictions, attach optional truth, save configuration/request and publish. Returns a typed artifact. |
|
|
357
|
+
| `TaskSpec`, `RelaxationLedger` | Bind task-conditioned predictions and record semantic approximations. |
|
|
358
|
+
|
|
359
|
+
Concrete algorithm methods MUST write payloads only to the staging destination supplied by the runner and
|
|
360
|
+
return `PayloadMetadata`. The runner alone writes `manifest.yaml`, `config.json`, `request.json` and
|
|
361
|
+
publishes the destination. Adapters and the CLI MUST use the same runner path; directly calling a algorithm
|
|
362
|
+
method bypasses validation and publication. Algorithm methods MUST NOT emit `boolean_value`; evaluation
|
|
363
|
+
truth is attached by the runner after all scores have been validated, using a runner-only label path.
|
|
364
|
+
Zero-shot algorithm methods write `relaxations.yaml` at the prediction artifact root.
|
|
365
|
+
|
|
366
|
+
`validate_inputs(request)` is the algorithm's explicit compatibility hook, invoked before algorithm computation.
|
|
367
|
+
Its default rejects fitted-algorithm inputs with a different algorithm name or resolved configuration.
|
|
368
|
+
Extend it for vocabulary, payload format, shape and scientific compatibility. A deliberate override for
|
|
369
|
+
external pretrained algorithms or compatible configurations MUST be documented and tested. Existing
|
|
370
|
+
artifact-type checks cannot establish these scientific properties automatically.
|
|
371
|
+
|
|
372
|
+
Algorithm configuration MUST be a frozen `AlgorithmConfig` dataclass with algorithm-owned fields and validation.
|
|
373
|
+
Use immutable nested dataclasses/tuples, supported scalar types and paths. Reject unknown settings,
|
|
374
|
+
wrong types, invalid values and unsupported serialized objects. Persist all resolved defaults, schema
|
|
375
|
+
version and concrete configuration type. A serialized request/configuration MUST round-trip through its
|
|
376
|
+
explicit class; loaders MUST NOT import a class named by a document. Relative paths in configuration
|
|
377
|
+
files resolve against that file's parent. Methods reopen persisted inputs and MUST NOT depend on prior
|
|
378
|
+
calls on the same Python object. Algorithm tests MUST exercise fresh-process reconstruction and execution.
|
|
379
|
+
|
|
380
|
+
Neural algorithms MAY extend `NNConfig`, a child of `AlgorithmConfig`, for shared `capacity`,
|
|
381
|
+
`learning_rate`, `batch_size`, `weight_decay` and `dropout` settings. Capacity is a positive finite multiplier
|
|
382
|
+
relative to a documented reference architecture, defaulting to `1.0`. Implementations MUST document and
|
|
383
|
+
test its mapping to architecture dimensions, rounding and minimums; it is not a measured parameter count
|
|
384
|
+
or a universal linear scaling of parameters/compute. Batch size means
|
|
385
|
+
examples per device per microbatch before accumulation. Learning rate is the base rate before scheduling;
|
|
386
|
+
dropout is a drop probability, and weight decay is the optimizer's decay coefficient. Implementations
|
|
387
|
+
MUST document and test how these settings control the actual architecture/training code. Subclasses that
|
|
388
|
+
override `validate()` MUST call `super().validate()` to preserve inherited constraints. Reference dimensions
|
|
389
|
+
and architecture-specific settings belong in the concrete algorithm configuration.
|
|
390
|
+
The shared configuration does not select training cohorts or implement a scaling-law experiment runner.
|
|
391
|
+
|
|
392
|
+
`Command.run(mapping) -> Path` and `LegacyAlgorithmRepository` provide mapping-based dispatch after an
|
|
393
|
+
explicit naming migration. Their validation is limited to interface shapes and routing; they do not gain the
|
|
394
|
+
typed runner's guarantees automatically. New generated algorithms use typed profile classes. The external
|
|
395
|
+
CLI step names remain unchanged, but contract version 4 renames package imports, entry points, artifact
|
|
396
|
+
types and input/output arguments to algorithm terminology. This does not migrate existing repositories.
|
|
397
|
+
|
|
398
|
+
### Step arguments and artifacts
|
|
399
|
+
|
|
400
|
+
Every step accepts optional boolean `do_overwrite` (default false), integer `seed` (default 0), and
|
|
401
|
+
`config_file` (a JSON/YAML algorithm-configuration mapping or saved JSON envelope). The typed CLI rejects
|
|
402
|
+
unknown step arguments; algorithm hyperparameters belong in the typed configuration, not arbitrary extra
|
|
403
|
+
step keys. `predict_only` context requires explicit `context_splits` with train and/or tuning. Every step
|
|
404
|
+
has a typed request carrying the arguments below. Dataset predicates may be supplied to
|
|
405
|
+
preprocessing; task predicates may be supplied to zero-shot prediction. Inference and prediction require
|
|
406
|
+
an explicit nonempty `splits` list. `external_index_dir` identifies the upstream keys-only view; `external_labels_dir` supplies permitted
|
|
407
|
+
training/context outcomes. Optional `external_evaluation_labels_dir` is evaluation-only, after scoring.
|
|
408
|
+
|
|
409
|
+
| Step | Required inputs | Output argument → type | Ground-truth target values the algorithm may use |
|
|
410
|
+
|---|---|---|---|
|
|
411
|
+
| `preprocess_data` | `external_meds_dir` | `output_data_dir` → `patients` | None |
|
|
412
|
+
| `pretrain` | `input_data_dir` | `output_pretrained_algorithm_dir` → `pretrained_algorithm` | None |
|
|
413
|
+
| `train_supervised` | `input_data_dir`, `external_labels_dir` | `output_supervised_algorithm_dir` → `supervised_algorithm` | Training for fitting; tuning for selection |
|
|
414
|
+
| `predict_supervised` | `input_supervised_algorithm_dir`, `input_data_dir`, `external_index_dir`, `splits` | `output_predictions_dir` → `predictions` | None |
|
|
415
|
+
| `train_finetune` | `input_data_dir`, `input_pretrained_algorithm_dir`, `external_labels_dir` | `output_finetuned_algorithm_dir` → `finetuned_algorithm` | Training for fitting; tuning for selection |
|
|
416
|
+
| `predict_finetune` | `input_finetuned_algorithm_dir`, `input_data_dir`, `external_index_dir`, `splits` | `output_predictions_dir` → `predictions` | None |
|
|
417
|
+
| `infer_embeddings` | `input_data_dir`, `input_pretrained_algorithm_dir`, `external_index_dir`, `splits` | `output_embeddings_dir` → `embeddings` | None; read keys only |
|
|
418
|
+
| `train_probe` | `input_embeddings_dir`, `external_labels_dir` | `output_probe_algorithm_dir` → `probe_algorithm` | Training for fitting; tuning for selection |
|
|
419
|
+
| `predict_probe` | `input_probe_algorithm_dir`, `input_embeddings_dir`, `external_index_dir`, `splits` | `output_predictions_dir` → `predictions` | None |
|
|
420
|
+
| `infer_trajectories` | `input_data_dir`, `input_pretrained_algorithm_dir`, `external_index_dir`, `splits` | `output_trajectories_dir` → `trajectories` | None; read keys only |
|
|
421
|
+
| `predict_zero_shot_direct` | `input_data_dir`, `input_pretrained_algorithm_dir`, `external_index_dir`, `external_task_criteria_file`, `splits` | `output_predictions_dir` → `predictions` | None |
|
|
422
|
+
| `predict_zero_shot_materialized` | `input_data_dir`, `input_trajectories_dir`, `external_meds_dir`, `external_index_dir`, `external_task_criteria_file`, `splits` | `output_predictions_dir` → `predictions` | None |
|
|
423
|
+
| `predict_only` | `input_data_dir`, `external_index_dir`, `splits` | `output_predictions_dir` → `predictions` | None for fixed algorithms; explicitly selected disjoint train/tuning context for in-context algorithms |
|
|
424
|
+
|
|
425
|
+
All prediction commands may attach evaluation truth by key **after** probabilities are final. That
|
|
426
|
+
evaluation-only join cannot influence scores, algorithm selection, preprocessing, or query generation.
|
|
427
|
+
|
|
428
|
+
### Preprocessing and pretraining
|
|
429
|
+
|
|
430
|
+
`PreprocessData` MUST separate fitting from transformation internally. Fit vocabularies, bins,
|
|
431
|
+
normalization and feature selection on training subjects only; freeze them before transforming tuning
|
|
432
|
+
or held-out subjects. No task labels or label-defining task predicates are inputs to this shared step.
|
|
433
|
+
The artifact records the fitted state, training population identity, code/predicate semantics and
|
|
434
|
+
transformation configuration. Transforming a new dataset must reuse that state, not refit it.
|
|
435
|
+
|
|
436
|
+
`Pretrain` learns a task-independent algorithm from the allowed training population. Self-supervised
|
|
437
|
+
targets derived from permitted training histories are allowed; benchmark task labels are not. Tuning
|
|
438
|
+
histories may support unsupervised early stopping when explicitly documented. Imported weights are
|
|
439
|
+
allowed only as a documented materialization mode with source revision, weight digest and compatibility
|
|
440
|
+
checks; this is not a silent no-op. Store everything needed to reconstruct the algorithm.
|
|
441
|
+
|
|
442
|
+
### Training and prediction bundles
|
|
443
|
+
|
|
444
|
+
`TrainSupervised` fits the task algorithm from scratch. `TrainFinetune` initializes from the specified
|
|
445
|
+
pretrained algorithm and explicitly records which parameters are updated or frozen. `TrainProbe` MUST
|
|
446
|
+
leave encoder and preprocessing weights unchanged; only the head and training-fitted head transforms
|
|
447
|
+
may change. All three fit on training labels only and use tuning labels for algorithm selection, never
|
|
448
|
+
for gradient updates or population statistics.
|
|
449
|
+
|
|
450
|
+
Task-algorithm artifacts carry fitted weights/head state, preprocessing/code-map identities, output
|
|
451
|
+
semantics and upstream provenance. They MUST NOT be assumed to contain the patients or evaluated features.
|
|
452
|
+
`PredictSupervised` and `PredictFinetune` explicitly consume `input_data_dir`; `PredictProbe` consumes
|
|
453
|
+
`input_embeddings_dir` and its fitted probe. The probe does not rerun an encoder or require a GPU simply
|
|
454
|
+
to apply its head. Frozen feature materialization belongs to `InferEmbeddings`.
|
|
455
|
+
|
|
456
|
+
Every producer records each upstream artifact as `inputs.<argument>.path` plus its content/compatibility
|
|
457
|
+
identity. MEDS-DEV's previous-stage-only placeholder can use `meds-algorithm-resolve-input` to resolve that
|
|
458
|
+
record into an explicit CLI argument. This checks the envelope type; the consumer must additionally
|
|
459
|
+
validate content, feature schema, vocabulary and algorithm identity. Other orchestrators can pass paths
|
|
460
|
+
directly. No reliance on current working directories or unrecorded global state is permitted.
|
|
461
|
+
|
|
462
|
+
### Embeddings and trajectories
|
|
463
|
+
|
|
464
|
+
`InferEmbeddings` performs frozen inference. Each representation is associated explicitly with
|
|
465
|
+
`(subject_id, prediction_time)`; row order cannot establish that association. Record encoder and
|
|
466
|
+
preprocessing identities, representation dimension/dtype or opaque schema version, pooling rule and
|
|
467
|
+
temporal cutoff convention. Histories must stop at the prediction boundary; boundary inclusion must
|
|
468
|
+
match the task protocol. Probe training requires train/tuning coverage; probe prediction requires evaluated-key coverage. The
|
|
469
|
+
generated wiring materializes `splits=[train,tuning,held_out]` without reading any label values. Separate
|
|
470
|
+
train and evaluation materializations may instead be supplied explicitly, with the same frozen encoder
|
|
471
|
+
and feature schema. Set `EMBEDDING_SPLITS` for another requested split set.
|
|
472
|
+
|
|
473
|
+
`InferTrajectories` generates futures from each requested history without receiving the ACES task.
|
|
474
|
+
Record key-to-sample mapping, sample identifiers, seed/sampling policy, generation horizon, time units,
|
|
475
|
+
termination/truncation rules, code mapping, and generating-algorithm identity. Reject a later task whose
|
|
476
|
+
requested window cannot be answered by the artifact, or explicitly record the approximation; do not
|
|
477
|
+
silently treat ungenerated time as event-free. An embedding artifact cannot substitute for trajectories.
|
|
478
|
+
|
|
479
|
+
### Zero-shot and predict-only
|
|
480
|
+
|
|
481
|
+
`PredictZeroShotDirect` validates `TaskSpec`, translates the task to supported algorithm queries, runs the
|
|
482
|
+
algorithm and decodes one probability per key. Publish the query, decoder settings, task digest and
|
|
483
|
+
relaxation ledger. Internal encode/infer/decode methods are not extra CLI stages.
|
|
484
|
+
|
|
485
|
+
`PredictZeroShotMaterialized` validates task and trajectory coverage, evaluates each requested task on
|
|
486
|
+
real history plus the generated futures, and aggregates. Keep the future artifact unchanged. Tasks
|
|
487
|
+
with the same key set can reuse it only when horizon and generation semantics also match.
|
|
488
|
+
|
|
489
|
+
`PredictOnly` is a lifecycle, not a algorithm family: preprocess then predict. Fixed weights/coefficients
|
|
490
|
+
must be supplied and identified. In-context learners explicitly declare context selection and can read
|
|
491
|
+
only train/tuning labels disjoint from evaluated splits. They do not publish or train a persistent
|
|
492
|
+
task-specific algorithm. Optional task criteria may be recorded as provenance.
|
|
493
|
+
`read_context_labels(labels_dir, context_splits, evaluated_splits, evaluation_index_dir=...)`
|
|
494
|
+
checks overlap against the supplied evaluation index; omitting it uses `labels_dir` for a combined layout.
|
|
495
|
+
|
|
496
|
+
### Additional compatibility requirements
|
|
497
|
+
|
|
498
|
+
Before consuming an artifact, check version 4, expected `ArtifactType`, supported `payload_format`,
|
|
499
|
+
required files, preprocessing/code-map identity and relevant upstream content digests. For task algorithms,
|
|
500
|
+
check task/output identity; for indexed inference, check keys, split selection and temporal cutoff.
|
|
501
|
+
Record the checked identities under manifest `inputs`. A filename/size fingerprint is a layout hint,
|
|
502
|
+
not a content digest. A configuration hash alone does not establish data or weights identity.
|
|
503
|
+
|
|
504
|
+
Shared `preprocess_data` and `pretrain` names do not authorize automatic reuse. Profiles with different
|
|
505
|
+
tokenization, normalization, populations, algorithm configurations or weights require separate artifacts.
|
|
506
|
+
Default SLURM paths include the profile; `SHARED_DIR` is an explicit reuse request that still requires
|
|
507
|
+
the same validation. MEDS-DEV descriptors use independent registered algorithm names.
|
|
508
|
+
|
|
509
|
+
Missing split files, duplicate/conflicting keys, incompatible formats, unsupported tasks and partial
|
|
510
|
+
coverage are errors. Failed commands must not publish success manifests. Output directories are
|
|
511
|
+
siblings, never nested within an upstream artifact or MEDS-DEV's run-control directory.
|
|
512
|
+
|
|
513
|
+
### Algorithm-owned internal interfaces
|
|
514
|
+
|
|
515
|
+
The following is a recommended class decomposition, not a mandatory framework. Document equivalent
|
|
516
|
+
responsibilities when the upstream algorithm already has suitable classes:
|
|
517
|
+
|
|
518
|
+
```python
|
|
519
|
+
class Preprocessor:
|
|
520
|
+
def fit(self, training_events, config): ... # returns immutable fitted state
|
|
521
|
+
def transform(self, events, index, state): ... # label-blind, cutoff-aware
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
class FrozenEncoder:
|
|
525
|
+
def encode(self, features, index): ... # keyed representations, no updates
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
class TaskTrainer:
|
|
529
|
+
def fit(self, training_features, training_labels, tuning, config): ...
|
|
530
|
+
def save_algorithm(self, fitted, destination): ... # fitted state and upstream identities
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
class TaskPredictor:
|
|
534
|
+
def load_bundle(self, source): ... # validates compatibility first
|
|
535
|
+
def predict(self, prepared_data_or_embeddings, index): ... # keyed probabilities, never labels
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
class TrajectoryGenerator:
|
|
539
|
+
def sample(self, histories, index, sampling_config): ...
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
Keep labels out of `transform`, `encode`, `sample`, and ordinary `predict` method signatures.
|
|
543
|
+
An in-context predictor should have a separate explicit `context` argument. Any types represented by
|
|
544
|
+
ellipses above must be concretely documented in the algorithm repository: key schema, feature schema,
|
|
545
|
+
batching ownership, missing-data semantics, save/load compatibility and exception behavior.
|
|
546
|
+
|
|
547
|
+
### Completion evidence per profile
|
|
548
|
+
|
|
549
|
+
`PROFILES` and `IMPLEMENTATIONS` declare capability; `STUB_PROFILES` records unfinished implementations.
|
|
550
|
+
Acceptance tests are parametrized over every declared profile. Removing one stub flag must not hide
|
|
551
|
+
another profile's missing implementation. `run_e2e(tmp_path, *, profile, **inputs)` and
|
|
552
|
+
`prepare_meds_dev_run(meds_dev, tmp_path, *, profile)` must honor profile selection and external overrides.
|
|
553
|
+
Report validation checks shared sections and each completed profile even when another profile remains
|
|
554
|
+
unfinished. Only unfinished profile sections and their profile-specific zero-shot sections may retain TODOs.
|
|
555
|
+
|
|
556
|
+
Each completed profile needs full lifecycle, schema/key coverage, manifest/compatibility, temporal
|
|
557
|
+
cutoff, train-only preprocessing, primary behavior and negative-control evidence. Probe tests must
|
|
558
|
+
verify the encoder remains frozen; finetuning tests must verify the declared update policy; trajectory
|
|
559
|
+
tests must verify per-key samples and horizon handling. The template cannot infer these from opaque
|
|
560
|
+
payloads. Implement these algorithm-specific assertions rather than relying only on dispatch tests.
|
|
561
|
+
|
|
562
|
+
The shared `assert_profile_run` conformance helper reruns the full lifecycle through `run_e2e` with
|
|
563
|
+
forbidden label columns removed. It requires fresh artifacts below a new run directory and preserves
|
|
564
|
+
permitted training/context labels. Include `seed`, `external_meds_dir` and all task inputs in `E2EResult.inputs`
|
|
565
|
+
so the check uses the same histories and task. This detects forbidden reads on the exercised path;
|
|
566
|
+
it does not prove all possible code paths, temporal cutoffs, or absence of labels encoded in other
|
|
567
|
+
features. Implement the corresponding algorithm-specific checks as well.
|