adaptcompile 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.
- adaptcompile-0.1.0/CHANGELOG.md +16 -0
- adaptcompile-0.1.0/CITATION.cff +10 -0
- adaptcompile-0.1.0/CONTRIBUTING.md +22 -0
- adaptcompile-0.1.0/LICENSE +21 -0
- adaptcompile-0.1.0/MANIFEST.in +11 -0
- adaptcompile-0.1.0/PKG-INFO +129 -0
- adaptcompile-0.1.0/README.md +98 -0
- adaptcompile-0.1.0/docs/architecture.md +32 -0
- adaptcompile-0.1.0/examples/basic_comparison.py +69 -0
- adaptcompile-0.1.0/examples/from_experiment_results.py +162 -0
- adaptcompile-0.1.0/pyproject.toml +62 -0
- adaptcompile-0.1.0/setup.cfg +4 -0
- adaptcompile-0.1.0/src/adaptcompile/__init__.py +30 -0
- adaptcompile-0.1.0/src/adaptcompile/_validation.py +46 -0
- adaptcompile-0.1.0/src/adaptcompile/dataset.py +160 -0
- adaptcompile-0.1.0/src/adaptcompile/episode.py +110 -0
- adaptcompile-0.1.0/src/adaptcompile/errors.py +13 -0
- adaptcompile-0.1.0/src/adaptcompile/family.py +103 -0
- adaptcompile-0.1.0/src/adaptcompile/geometry.py +111 -0
- adaptcompile-0.1.0/src/adaptcompile/model.py +93 -0
- adaptcompile-0.1.0/src/adaptcompile/program.py +121 -0
- adaptcompile-0.1.0/src/adaptcompile/py.typed +1 -0
- adaptcompile-0.1.0/src/adaptcompile/result.py +115 -0
- adaptcompile-0.1.0/src/adaptcompile/serialization.py +101 -0
- adaptcompile-0.1.0/src/adaptcompile/study.py +207 -0
- adaptcompile-0.1.0/src/adaptcompile.egg-info/PKG-INFO +129 -0
- adaptcompile-0.1.0/src/adaptcompile.egg-info/SOURCES.txt +41 -0
- adaptcompile-0.1.0/src/adaptcompile.egg-info/dependency_links.txt +1 -0
- adaptcompile-0.1.0/src/adaptcompile.egg-info/requires.txt +12 -0
- adaptcompile-0.1.0/src/adaptcompile.egg-info/top_level.txt +1 -0
- adaptcompile-0.1.0/tests/conftest.py +43 -0
- adaptcompile-0.1.0/tests/integration/test_experiment_slice.py +164 -0
- adaptcompile-0.1.0/tests/integration/test_multi_model_slice.py +387 -0
- adaptcompile-0.1.0/tests/test_dataset.py +199 -0
- adaptcompile-0.1.0/tests/test_episode.py +57 -0
- adaptcompile-0.1.0/tests/test_family.py +142 -0
- adaptcompile-0.1.0/tests/test_geometry.py +57 -0
- adaptcompile-0.1.0/tests/test_model.py +73 -0
- adaptcompile-0.1.0/tests/test_optional_dataframe.py +43 -0
- adaptcompile-0.1.0/tests/test_program.py +57 -0
- adaptcompile-0.1.0/tests/test_result.py +74 -0
- adaptcompile-0.1.0/tests/test_serialization.py +57 -0
- adaptcompile-0.1.0/tests/test_study.py +274 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable public changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
## 0.1.0 - 2026-09-05
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Declarative model and base-state contexts.
|
|
10
|
+
- Learning episodes with non-serialized dataset references.
|
|
11
|
+
- Conceptual program families and concrete program specifications.
|
|
12
|
+
- Arbitrary-dimensional adaptation geometry and before/after adaptation results.
|
|
13
|
+
- Controlled adaptation studies with ranking and Pareto analysis.
|
|
14
|
+
- Multi-model, multi-episode adaptation datasets with replicate-preserving grouping.
|
|
15
|
+
- JSON-safe serialization and stable conceptual/executable fingerprints.
|
|
16
|
+
- Optional pandas DataFrame exports.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use adaptcompile in your research, please cite this software."
|
|
3
|
+
title: "adaptcompile"
|
|
4
|
+
type: software
|
|
5
|
+
version: 0.1.0
|
|
6
|
+
date-released: 2026-09-05
|
|
7
|
+
license: MIT
|
|
8
|
+
authors:
|
|
9
|
+
- name: "Rebecca Ramnauth"
|
|
10
|
+
repository-code: "https://github.com/rramnauth2220/adaptcompile"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Install the project and development tools in an isolated environment:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
python -m pip install -e ".[dev]"
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Run the local checks before opening a pull request:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
python -m pytest
|
|
13
|
+
python -m ruff check .
|
|
14
|
+
python -m ruff format --check .
|
|
15
|
+
python -m mypy src
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The core runtime must remain independent of ML frameworks: do not add mandatory
|
|
19
|
+
PyTorch, Transformers, PEFT, TRL, model-download, network, or GPU requirements.
|
|
20
|
+
Arbitrary dataset objects referenced by `LearningEpisode` must not be serialized.
|
|
21
|
+
Public API additions should be deliberate and accompanied by tests and documentation.
|
|
22
|
+
Tests must run without network access, GPUs, or model downloads.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rebecca Ramnauth
|
|
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,11 @@
|
|
|
1
|
+
include CHANGELOG.md
|
|
2
|
+
include CITATION.cff
|
|
3
|
+
include CONTRIBUTING.md
|
|
4
|
+
include LICENSE
|
|
5
|
+
include README.md
|
|
6
|
+
include RELEASING.md
|
|
7
|
+
recursive-include docs *.md
|
|
8
|
+
recursive-include examples *.py
|
|
9
|
+
recursive-include tests *.py
|
|
10
|
+
global-exclude *.py[cod]
|
|
11
|
+
global-exclude __pycache__
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: adaptcompile
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Represent, measure, and compare the behavioral effects of model adaptation.
|
|
5
|
+
Author: Rebecca Ramnauth
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/rramnauth2220/adaptcompile
|
|
8
|
+
Keywords: machine-learning,model-adaptation,evaluation,research
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Typing :: Typed
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Provides-Extra: dataframe
|
|
21
|
+
Requires-Dist: pandas>=1.5; extra == "dataframe"
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
24
|
+
Requires-Dist: mypy>=1.8; extra == "dev"
|
|
25
|
+
Requires-Dist: pandas>=1.5; extra == "dev"
|
|
26
|
+
Requires-Dist: pandas-stubs>=1.5; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
29
|
+
Requires-Dist: twine>=5; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# adaptcompile
|
|
33
|
+
|
|
34
|
+
`adaptcompile` is a model-agnostic Python library for representing and comparing
|
|
35
|
+
observed model-adaptation experiments.
|
|
36
|
+
|
|
37
|
+
`adaptcompile` treats model adaptation as a behavioral transformation that can be
|
|
38
|
+
represented, measured, and compared independently of the training framework used to
|
|
39
|
+
produce it. It provides the representation and analysis foundation on which future
|
|
40
|
+
adaptation-compilation functionality can be built.
|
|
41
|
+
|
|
42
|
+
See the [architecture overview](https://github.com/rramnauth2220/adaptcompile/blob/main/docs/architecture.md) for how the objects fit
|
|
43
|
+
together.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install adaptcompile
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
DataFrame exports are optional:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install "adaptcompile[dataframe]"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
For contributor setup:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python -m pip install -e ".[dev]"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Minimal example
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from adaptcompile import (
|
|
67
|
+
AdaptationResult,
|
|
68
|
+
AdaptationStudy,
|
|
69
|
+
LearningEpisode,
|
|
70
|
+
ModelContext,
|
|
71
|
+
ProgramSpec,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
model = ModelContext("example/model", revision="v1", base_state_id="base-1")
|
|
75
|
+
episode = LearningEpisode(
|
|
76
|
+
"toy-task",
|
|
77
|
+
train=["example"],
|
|
78
|
+
evaluations={"accuracy": ["held-out example"]},
|
|
79
|
+
episode_id="toy-task-v1",
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
results = [
|
|
83
|
+
AdaptationResult(
|
|
84
|
+
model_context=model,
|
|
85
|
+
episode=episode,
|
|
86
|
+
program=ProgramSpec(name, "adapter", {"strength": strength}),
|
|
87
|
+
before={"accuracy": 0.40},
|
|
88
|
+
after={"accuracy": score},
|
|
89
|
+
)
|
|
90
|
+
for name, strength, score in [
|
|
91
|
+
("gentle", 0.25, 0.68),
|
|
92
|
+
("strong", 0.75, 0.81),
|
|
93
|
+
]
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
study = AdaptationStudy(results)
|
|
97
|
+
print(study.best("accuracy").program.name)
|
|
98
|
+
print(study.best("accuracy").delta.to_dict())
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
More runnable examples are available in [examples](https://github.com/rramnauth2220/adaptcompile/tree/main/examples).
|
|
102
|
+
|
|
103
|
+
## Core objects
|
|
104
|
+
|
|
105
|
+
- `ModelContext` identifies a model revision and pre-adaptation base state.
|
|
106
|
+
- `LearningEpisode` names a learning problem and references its datasets.
|
|
107
|
+
- `ProgramFamily` describes a conceptual adaptation family.
|
|
108
|
+
- `ProgramSpec` declares one concrete, backend-independent adaptation program.
|
|
109
|
+
- `AdaptationGeometry` stores arbitrary-dimensional behavioral measurements.
|
|
110
|
+
- `AdaptationResult` records before/after geometry for one observed adaptation.
|
|
111
|
+
- `AdaptationStudy` compares programs for one fixed model context and episode.
|
|
112
|
+
- `AdaptationDataset` stores observations across models, episodes, and programs.
|
|
113
|
+
|
|
114
|
+
Public records support JSON-safe serialization. Dataset-like objects attached to a
|
|
115
|
+
`LearningEpisode` are intentionally held by reference and are not serialized.
|
|
116
|
+
DataFrame export is available through the optional `dataframe` extra.
|
|
117
|
+
|
|
118
|
+
## What adaptcompile does not do
|
|
119
|
+
|
|
120
|
+
- It does not train or load models.
|
|
121
|
+
- It does not implement LoRA or replace PEFT, TRL, or another training framework.
|
|
122
|
+
- It does not currently predict outcomes or select adaptation programs.
|
|
123
|
+
- It does not require PyTorch, Transformers, pandas, or any other ML framework.
|
|
124
|
+
|
|
125
|
+
## Status
|
|
126
|
+
|
|
127
|
+
`0.1.0` is the first public release. The API is usable but may evolve during the
|
|
128
|
+
`0.x` series. Compiler functionality may be added in future releases without adding
|
|
129
|
+
ML-framework dependencies to the representation layer.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# adaptcompile
|
|
2
|
+
|
|
3
|
+
`adaptcompile` is a model-agnostic Python library for representing and comparing
|
|
4
|
+
observed model-adaptation experiments.
|
|
5
|
+
|
|
6
|
+
`adaptcompile` treats model adaptation as a behavioral transformation that can be
|
|
7
|
+
represented, measured, and compared independently of the training framework used to
|
|
8
|
+
produce it. It provides the representation and analysis foundation on which future
|
|
9
|
+
adaptation-compilation functionality can be built.
|
|
10
|
+
|
|
11
|
+
See the [architecture overview](https://github.com/rramnauth2220/adaptcompile/blob/main/docs/architecture.md) for how the objects fit
|
|
12
|
+
together.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install adaptcompile
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
DataFrame exports are optional:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install "adaptcompile[dataframe]"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For contributor setup:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
python -m pip install -e ".[dev]"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Minimal example
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from adaptcompile import (
|
|
36
|
+
AdaptationResult,
|
|
37
|
+
AdaptationStudy,
|
|
38
|
+
LearningEpisode,
|
|
39
|
+
ModelContext,
|
|
40
|
+
ProgramSpec,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
model = ModelContext("example/model", revision="v1", base_state_id="base-1")
|
|
44
|
+
episode = LearningEpisode(
|
|
45
|
+
"toy-task",
|
|
46
|
+
train=["example"],
|
|
47
|
+
evaluations={"accuracy": ["held-out example"]},
|
|
48
|
+
episode_id="toy-task-v1",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
results = [
|
|
52
|
+
AdaptationResult(
|
|
53
|
+
model_context=model,
|
|
54
|
+
episode=episode,
|
|
55
|
+
program=ProgramSpec(name, "adapter", {"strength": strength}),
|
|
56
|
+
before={"accuracy": 0.40},
|
|
57
|
+
after={"accuracy": score},
|
|
58
|
+
)
|
|
59
|
+
for name, strength, score in [
|
|
60
|
+
("gentle", 0.25, 0.68),
|
|
61
|
+
("strong", 0.75, 0.81),
|
|
62
|
+
]
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
study = AdaptationStudy(results)
|
|
66
|
+
print(study.best("accuracy").program.name)
|
|
67
|
+
print(study.best("accuracy").delta.to_dict())
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
More runnable examples are available in [examples](https://github.com/rramnauth2220/adaptcompile/tree/main/examples).
|
|
71
|
+
|
|
72
|
+
## Core objects
|
|
73
|
+
|
|
74
|
+
- `ModelContext` identifies a model revision and pre-adaptation base state.
|
|
75
|
+
- `LearningEpisode` names a learning problem and references its datasets.
|
|
76
|
+
- `ProgramFamily` describes a conceptual adaptation family.
|
|
77
|
+
- `ProgramSpec` declares one concrete, backend-independent adaptation program.
|
|
78
|
+
- `AdaptationGeometry` stores arbitrary-dimensional behavioral measurements.
|
|
79
|
+
- `AdaptationResult` records before/after geometry for one observed adaptation.
|
|
80
|
+
- `AdaptationStudy` compares programs for one fixed model context and episode.
|
|
81
|
+
- `AdaptationDataset` stores observations across models, episodes, and programs.
|
|
82
|
+
|
|
83
|
+
Public records support JSON-safe serialization. Dataset-like objects attached to a
|
|
84
|
+
`LearningEpisode` are intentionally held by reference and are not serialized.
|
|
85
|
+
DataFrame export is available through the optional `dataframe` extra.
|
|
86
|
+
|
|
87
|
+
## What adaptcompile does not do
|
|
88
|
+
|
|
89
|
+
- It does not train or load models.
|
|
90
|
+
- It does not implement LoRA or replace PEFT, TRL, or another training framework.
|
|
91
|
+
- It does not currently predict outcomes or select adaptation programs.
|
|
92
|
+
- It does not require PyTorch, Transformers, pandas, or any other ML framework.
|
|
93
|
+
|
|
94
|
+
## Status
|
|
95
|
+
|
|
96
|
+
`0.1.0` is the first public release. The API is usable but may evolve during the
|
|
97
|
+
`0.x` series. Compiler functionality may be added in future releases without adding
|
|
98
|
+
ML-framework dependencies to the representation layer.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
`adaptcompile` separates experiment identity, executable declarations, measurements,
|
|
4
|
+
and collections. It does not execute adaptations.
|
|
5
|
+
|
|
6
|
+
```text
|
|
7
|
+
ModelContext + LearningEpisode + ProgramSpec
|
|
8
|
+
|
|
|
9
|
+
v
|
|
10
|
+
AdaptationResult
|
|
11
|
+
/ \
|
|
12
|
+
v v
|
|
13
|
+
AdaptationStudy AdaptationDataset
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- `ModelContext` identifies the pre-adaptation model, revision, and base state.
|
|
17
|
+
- `LearningEpisode` identifies a learning problem and references its training and
|
|
18
|
+
evaluation datasets without serializing those datasets.
|
|
19
|
+
- `ProgramFamily` describes a conceptual adaptation family independently of a
|
|
20
|
+
model-specific realization.
|
|
21
|
+
- `ProgramSpec` describes a concrete, backend-independent executable declaration and
|
|
22
|
+
may reference a `ProgramFamily`.
|
|
23
|
+
- `AdaptationGeometry` is an immutable mapping of behavioral metric names to values.
|
|
24
|
+
- `AdaptationResult` records before and after geometry for one observed combination
|
|
25
|
+
of model context, episode, and program.
|
|
26
|
+
- `AdaptationStudy` compares programs while holding model context and episode fixed.
|
|
27
|
+
- `AdaptationDataset` stores a corpus whose models, episodes, programs, metric
|
|
28
|
+
dimensions, and replicate provenance may vary.
|
|
29
|
+
|
|
30
|
+
Names and metadata remain descriptive annotations. Stable identity is explicit:
|
|
31
|
+
model studies use `(model_id, revision, base_state_id)`, episodes may supply an
|
|
32
|
+
`episode_id`, and program/family fingerprints derive from their semantic parameters.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Compare two fake adaptation programs without a model or ML dependencies."""
|
|
2
|
+
|
|
3
|
+
from adaptcompile import (
|
|
4
|
+
AdaptationResult,
|
|
5
|
+
AdaptationStudy,
|
|
6
|
+
LearningEpisode,
|
|
7
|
+
ModelContext,
|
|
8
|
+
ProgramSpec,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
model_context = ModelContext(
|
|
12
|
+
model_id="example/model",
|
|
13
|
+
revision="synthetic-revision-1",
|
|
14
|
+
base_state_id="synthetic-base-state-1",
|
|
15
|
+
)
|
|
16
|
+
episode = LearningEpisode(
|
|
17
|
+
name="toy-task",
|
|
18
|
+
episode_id="toy-task-v1",
|
|
19
|
+
train=["example"],
|
|
20
|
+
evaluations={
|
|
21
|
+
"acquisition": ["a"],
|
|
22
|
+
"transfer": ["b"],
|
|
23
|
+
"preservation": ["c"],
|
|
24
|
+
},
|
|
25
|
+
metadata={"learning_family": "toy", "synthetic": True},
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
programs = [
|
|
29
|
+
ProgramSpec(
|
|
30
|
+
name="early",
|
|
31
|
+
method="localized_lora",
|
|
32
|
+
parameters={"layers": [2, 3, 4], "rank": 16},
|
|
33
|
+
),
|
|
34
|
+
ProgramSpec(
|
|
35
|
+
name="middle",
|
|
36
|
+
method="localized_lora",
|
|
37
|
+
parameters={"layers": [12, 13, 14], "rank": 16},
|
|
38
|
+
),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
results = [
|
|
42
|
+
AdaptationResult(
|
|
43
|
+
model_context=model_context,
|
|
44
|
+
episode=episode,
|
|
45
|
+
program=programs[0],
|
|
46
|
+
before={"acquisition": 0.10, "transfer": 0.10, "preservation": 0.98},
|
|
47
|
+
after={"acquisition": 0.81, "transfer": 0.77, "preservation": 0.99},
|
|
48
|
+
),
|
|
49
|
+
AdaptationResult(
|
|
50
|
+
model_context=model_context,
|
|
51
|
+
episode=episode,
|
|
52
|
+
program=programs[1],
|
|
53
|
+
before={"acquisition": 0.10, "transfer": 0.10, "preservation": 0.98},
|
|
54
|
+
after={"acquisition": 0.93, "transfer": 0.84, "preservation": 0.95},
|
|
55
|
+
),
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
study = AdaptationStudy(results)
|
|
59
|
+
print("\nBest transfer:", study.best("transfer").program.name)
|
|
60
|
+
print("Best transfer delta:", study.best("transfer").delta.to_dict())
|
|
61
|
+
print(
|
|
62
|
+
"Pareto front:",
|
|
63
|
+
[
|
|
64
|
+
result.program.name
|
|
65
|
+
for result in study.pareto_front(
|
|
66
|
+
maximize=["acquisition", "transfer", "preservation"]
|
|
67
|
+
)
|
|
68
|
+
],
|
|
69
|
+
)
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""Adapt already-computed synthetic experiment records into adaptcompile.
|
|
2
|
+
|
|
3
|
+
The values below are plausible test data, not published experimental results. This
|
|
4
|
+
example performs no training, model loading, downloads, or backend execution.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from collections import defaultdict
|
|
10
|
+
from collections.abc import Iterator, Mapping
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from adaptcompile import (
|
|
14
|
+
AdaptationResult,
|
|
15
|
+
AdaptationStudy,
|
|
16
|
+
LearningEpisode,
|
|
17
|
+
ModelContext,
|
|
18
|
+
ProgramSpec,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
METRICS = ("acquisition", "transfer", "boundedness", "preservation")
|
|
22
|
+
MODEL_CONTEXT = {
|
|
23
|
+
"model": "synthetic-research/base-model-8b",
|
|
24
|
+
"model_revision": "synthetic-revision-001",
|
|
25
|
+
"base_state_id": "synthetic-pre-adaptation-state-v1",
|
|
26
|
+
}
|
|
27
|
+
PROGRAMS = {
|
|
28
|
+
"early": {
|
|
29
|
+
"name": "early",
|
|
30
|
+
"method": "localized_lora",
|
|
31
|
+
"parameters": {
|
|
32
|
+
"layers": [2, 3, 4, 5],
|
|
33
|
+
"rank": 16,
|
|
34
|
+
"learning_rate": 2e-4,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
"middle": {
|
|
38
|
+
"name": "middle",
|
|
39
|
+
"method": "localized_lora",
|
|
40
|
+
"parameters": {
|
|
41
|
+
"layers": [12, 13, 14, 15],
|
|
42
|
+
"rank": 16,
|
|
43
|
+
"learning_rate": 2e-4,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
"late": {
|
|
47
|
+
"name": "late",
|
|
48
|
+
"method": "localized_lora",
|
|
49
|
+
"parameters": {
|
|
50
|
+
"layers": [24, 25, 26, 27],
|
|
51
|
+
"rank": 16,
|
|
52
|
+
"learning_rate": 2e-4,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
SYNTHETIC_OUTPUTS = {
|
|
57
|
+
"relation-001": {
|
|
58
|
+
"early": (0.78, 0.66, 0.94, 0.97),
|
|
59
|
+
"middle": (0.93, 0.85, 0.92, 0.95),
|
|
60
|
+
"late": (0.87, 0.74, 0.97, 0.97),
|
|
61
|
+
},
|
|
62
|
+
"relation-002": {
|
|
63
|
+
"early": (0.74, 0.62, 0.95, 0.98),
|
|
64
|
+
"middle": (0.89, 0.80, 0.93, 0.96),
|
|
65
|
+
"late": (0.84, 0.70, 0.97, 0.98),
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def scores(values: tuple[float, float, float, float]) -> dict[str, float]:
|
|
71
|
+
return dict(zip(METRICS, values, strict=True))
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def external_records() -> Iterator[dict[str, Any]]:
|
|
75
|
+
"""Stand in for records emitted by an external research pipeline."""
|
|
76
|
+
for episode_index, (episode_id, outputs) in enumerate(
|
|
77
|
+
SYNTHETIC_OUTPUTS.items(), start=1
|
|
78
|
+
):
|
|
79
|
+
for program_name, after in outputs.items():
|
|
80
|
+
yield {
|
|
81
|
+
"episode_id": episode_id,
|
|
82
|
+
"episode_name": f"synthetic relation episode {episode_index}",
|
|
83
|
+
"learning_family": "synthetic-relational-learning",
|
|
84
|
+
"program": PROGRAMS[program_name],
|
|
85
|
+
"before": scores((0.08, 0.06, 0.98, 0.98)),
|
|
86
|
+
"after": scores(after),
|
|
87
|
+
**MODEL_CONTEXT,
|
|
88
|
+
"experiment_id": "synthetic-adapter-example",
|
|
89
|
+
"seed": 100 + episode_index,
|
|
90
|
+
"synthetic": True,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def adapt_record(record: Mapping[str, Any]) -> AdaptationResult:
|
|
95
|
+
"""Convert one external result record without adding a core adapter API."""
|
|
96
|
+
before = record["before"]
|
|
97
|
+
after = record["after"]
|
|
98
|
+
program_data = record["program"]
|
|
99
|
+
if not isinstance(before, Mapping) or not isinstance(after, Mapping):
|
|
100
|
+
raise TypeError("external before/after values must be mappings")
|
|
101
|
+
if not isinstance(program_data, Mapping):
|
|
102
|
+
raise TypeError("external program value must be a mapping")
|
|
103
|
+
|
|
104
|
+
episode = LearningEpisode(
|
|
105
|
+
name=record["episode_name"],
|
|
106
|
+
episode_id=record["episode_id"],
|
|
107
|
+
train={"dataset_ref": f"memory://{record['episode_id']}/train"},
|
|
108
|
+
evaluations={
|
|
109
|
+
metric: {"dataset_ref": f"memory://{record['episode_id']}/{metric}"}
|
|
110
|
+
for metric in before
|
|
111
|
+
},
|
|
112
|
+
metadata={
|
|
113
|
+
"learning_family": record["learning_family"],
|
|
114
|
+
"synthetic": record["synthetic"],
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
program = ProgramSpec(
|
|
118
|
+
name=program_data["name"],
|
|
119
|
+
method=program_data["method"],
|
|
120
|
+
parameters=program_data["parameters"],
|
|
121
|
+
)
|
|
122
|
+
model_context = ModelContext(
|
|
123
|
+
model_id=record["model"],
|
|
124
|
+
revision=record["model_revision"],
|
|
125
|
+
base_state_id=record["base_state_id"],
|
|
126
|
+
)
|
|
127
|
+
return AdaptationResult(
|
|
128
|
+
model_context=model_context,
|
|
129
|
+
episode=episode,
|
|
130
|
+
program=program,
|
|
131
|
+
before=before,
|
|
132
|
+
after=after,
|
|
133
|
+
metadata={
|
|
134
|
+
"experiment_id": record["experiment_id"],
|
|
135
|
+
"seed": record["seed"],
|
|
136
|
+
"synthetic": record["synthetic"],
|
|
137
|
+
},
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
results = [adapt_record(record) for record in external_records()]
|
|
142
|
+
grouped: dict[str, list[AdaptationResult]] = defaultdict(list)
|
|
143
|
+
for result in results:
|
|
144
|
+
episode_id = result.episode.episode_id
|
|
145
|
+
if episode_id is None:
|
|
146
|
+
raise RuntimeError("experiment records require stable episode IDs")
|
|
147
|
+
grouped[episode_id].append(result)
|
|
148
|
+
|
|
149
|
+
studies = {
|
|
150
|
+
episode_id: AdaptationStudy(episode_results)
|
|
151
|
+
for episode_id, episode_results in grouped.items()
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
print(f"Converted {len(results)} synthetic records into {len(studies)} studies.")
|
|
155
|
+
for episode_id, study in studies.items():
|
|
156
|
+
ranking = [result.program.name for result in study.rank("acquisition")]
|
|
157
|
+
best_transfer = study.best("transfer").program.name
|
|
158
|
+
pareto = [result.program.name for result in study.pareto_front(maximize=METRICS)]
|
|
159
|
+
print(
|
|
160
|
+
f"{episode_id}: acquisition={ranking}, "
|
|
161
|
+
f"best_transfer={best_transfer}, pareto={pareto}"
|
|
162
|
+
)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "adaptcompile"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Represent, measure, and compare the behavioral effects of model adaptation."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Rebecca Ramnauth" }]
|
|
14
|
+
keywords = ["machine-learning", "model-adaptation", "evaluation", "research"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
23
|
+
"Typing :: Typed",
|
|
24
|
+
]
|
|
25
|
+
dependencies = []
|
|
26
|
+
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
dataframe = ["pandas>=1.5"]
|
|
29
|
+
dev = [
|
|
30
|
+
"build>=1.2",
|
|
31
|
+
"mypy>=1.8",
|
|
32
|
+
"pandas>=1.5",
|
|
33
|
+
"pandas-stubs>=1.5",
|
|
34
|
+
"pytest>=7",
|
|
35
|
+
"ruff>=0.4",
|
|
36
|
+
"twine>=5",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Repository = "https://github.com/rramnauth2220/adaptcompile"
|
|
41
|
+
|
|
42
|
+
[tool.setuptools.packages.find]
|
|
43
|
+
where = ["src"]
|
|
44
|
+
|
|
45
|
+
[tool.setuptools.package-data]
|
|
46
|
+
adaptcompile = ["py.typed"]
|
|
47
|
+
|
|
48
|
+
[tool.pytest.ini_options]
|
|
49
|
+
addopts = "-ra"
|
|
50
|
+
testpaths = ["tests"]
|
|
51
|
+
|
|
52
|
+
[tool.ruff]
|
|
53
|
+
line-length = 88
|
|
54
|
+
target-version = "py310"
|
|
55
|
+
|
|
56
|
+
[tool.ruff.lint]
|
|
57
|
+
select = ["B", "E", "F", "I", "UP"]
|
|
58
|
+
|
|
59
|
+
[tool.mypy]
|
|
60
|
+
python_version = "3.10"
|
|
61
|
+
strict = true
|
|
62
|
+
packages = ["adaptcompile"]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Public API for adaptcompile."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import version as _distribution_version
|
|
4
|
+
|
|
5
|
+
from .dataset import AdaptationDataset
|
|
6
|
+
from .episode import LearningEpisode
|
|
7
|
+
from .errors import AdaptCompileError, SerializationError, ValidationError
|
|
8
|
+
from .family import ProgramFamily
|
|
9
|
+
from .geometry import AdaptationGeometry
|
|
10
|
+
from .model import ModelContext
|
|
11
|
+
from .program import ProgramSpec
|
|
12
|
+
from .result import AdaptationResult
|
|
13
|
+
from .study import AdaptationStudy
|
|
14
|
+
|
|
15
|
+
__version__ = _distribution_version("adaptcompile")
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"AdaptCompileError",
|
|
19
|
+
"AdaptationDataset",
|
|
20
|
+
"AdaptationGeometry",
|
|
21
|
+
"AdaptationResult",
|
|
22
|
+
"AdaptationStudy",
|
|
23
|
+
"LearningEpisode",
|
|
24
|
+
"ModelContext",
|
|
25
|
+
"ProgramFamily",
|
|
26
|
+
"ProgramSpec",
|
|
27
|
+
"SerializationError",
|
|
28
|
+
"ValidationError",
|
|
29
|
+
"__version__",
|
|
30
|
+
]
|