AQIT
0.1.0
Toggle main menu visibility
Loading...
Searching...
No Matches
run.py
Go to the documentation of this file.
1
# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2
# This file is part of the Aquin Engine. Unauthorized copying, modification,
3
# distribution, or use of this file, via any medium, is strictly prohibited.
4
# Proprietary and confidential. See LICENSE for terms.
5
6
from
__future__
import
annotations
7
8
import
json
9
import
os
10
import
threading
11
import
time
12
import
uuid
13
from
pathlib
import
Path
14
from
typing
import
Any
15
16
17
def
init
(
18
base_model: str |
None
=
None
,
19
run_name: str |
None
=
None
,
20
config: dict[str, Any] |
None
=
None
,
21
) ->
"Run"
:
22
"""Start recording a training run. Call this before your training loop."""
23
return
Run
(base_model=base_model, run_name=run_name, config=config)
24
25
26
class
Run
:
27
"""
28
Records metrics and checkpoints locally during training.
29
Call aquin.init() to create one.
30
31
Writes under ``./aquin_run/`` (metrics, config, checkpoint).
32
33
Example
34
-------
35
run = aquin.init(
36
base_model="meta-llama/Llama-3.2-1B-Instruct",
37
run_name="my-run",
38
config={"lr": 2e-4, "epochs": 3, "rank": 16, "lora_alpha": 32,
39
"method": "qlora", "per_device_train_batch_size": 2,
40
"gradient_accumulation_steps": 8, "dataset": "data.jsonl"},
41
)
42
for step, batch in enumerate(dataloader):
43
loss = train_step(batch)
44
run.log(step, loss=loss.item(), learning_rate=scheduler.get_last_lr()[0],
45
grad_norm=grad_norm, epoch=epoch)
46
run.checkpoint(model, step=step)
47
run.finish()
48
"""
49
50
def
__init__
(
51
self,
52
base_model: str |
None
=
None
,
53
run_name: str |
None
=
None
,
54
config: dict[str, Any] |
None
=
None
,
55
*,
56
quant: str =
"none"
,
57
mode: str =
"external"
,
58
run_dir: str | Path |
None
=
None
,
59
) ->
None
:
60
_ = quant, mode
# reserved for future recipe / runtime tags
61
self.
_run_id
= str(uuid.uuid4())
62
self.
_run_name
= run_name
or
f
"run-{self._run_id[:8]}"
63
self.
_base_model
= base_model
or
os.environ.get(
"AQUIN_BASE_MODEL"
)
or
""
64
self.
_started_at
= time.time()
65
66
self.
_run_dir
= Path(run_dir)
if
run_dir
is
not
None
else
Path.cwd() /
"aquin_run"
67
self.
_run_dir
.mkdir(parents=
True
, exist_ok=
True
)
68
(self.
_run_dir
/
"checkpoints"
).mkdir(exist_ok=
True
)
69
70
self.
_metrics
: list[dict[str, Any]] = []
71
self.
_obs
: list[dict[str, Any]] = []
72
self.
_signals
: list[dict[str, Any]] = []
73
self.
_metrics_lock
= threading.Lock()
74
75
self.
_write_meta
()
76
if
config:
77
self.
_write_config
(config)
78
79
print(f
"[aquin] Recording run '{self._run_name}' (id: {self._run_id})"
)
80
print(f
"[aquin] Run data: {self._run_dir}"
)
81
82
def
log
(
83
self,
84
step: int,
85
*,
86
loss: float,
87
learning_rate: float |
None
=
None
,
88
grad_norm: float |
None
=
None
,
89
momentum_norm: float |
None
=
None
,
90
epoch: int |
None
=
None
,
91
batch: int |
None
=
None
,
92
total_batches: int |
None
=
None
,
93
step_ms: float |
None
=
None
,
94
**extra: float,
95
) ->
None
:
96
"""Record metrics for one training step. Call every step inside your loop."""
97
entry: dict[str, Any] = {
"step"
: step,
"metrics"
: {
"loss"
: loss}}
98
if
learning_rate
is
not
None
:
99
entry[
"metrics"
][
"learning_rate"
] = learning_rate
100
if
grad_norm
is
not
None
:
101
entry[
"metrics"
][
"grad_norm"
] = grad_norm
102
if
momentum_norm
is
not
None
:
103
entry[
"metrics"
][
"momentum_norm"
] = momentum_norm
104
if
step_ms
is
not
None
:
105
entry[
"metrics"
][
"step_ms"
] = step_ms
106
if
extra:
107
entry[
"metrics"
].update(extra)
108
if
epoch
is
not
None
:
109
entry[
"epoch"
] = epoch
110
if
batch
is
not
None
:
111
entry[
"batch"
] = batch
112
if
total_batches
is
not
None
:
113
entry[
"total_batches"
] = total_batches
114
115
with
self.
_metrics_lock
:
116
self.
_metrics
.append(entry)
117
self.
_write_metrics
()
118
119
def
observe
(self, step: int, channel: str, value: float) ->
None
:
120
"""Emit a custom scalar observation (eval metrics, etc.)."""
121
row = {
"step"
: step,
"channel"
: channel,
"value"
: float(value),
"ts"
: time.time()}
122
with
self.
_metrics_lock
:
123
self.
_obs
.append(row)
124
self.
_write_obs
()
125
126
def
signal
(self, step: int, message: str, *, severity: str =
"info"
) ->
None
:
127
"""Emit a non-scalar training signal (checkpoint saved, OOM, etc.)."""
128
row = {
129
"step"
: step,
130
"message"
: message,
131
"severity"
: severity,
132
"ts"
: time.time(),
133
}
134
with
self.
_metrics_lock
:
135
self.
_signals
.append(row)
136
self.
_write_signals
()
137
138
def
checkpoint
(self, model: Any, step: int) ->
None
:
139
"""Save the final model checkpoint. One per run — replaces the previous save."""
140
try
:
141
import
torch
142
except
ImportError:
143
raise
ImportError(
"torch is required to save checkpoints."
)
144
145
ckpt_path = self.
_run_dir
/
"checkpoints"
/
"checkpoint.pt"
146
print(f
"[aquin] Saving checkpoint (step {step})..."
)
147
torch.save({
"step"
: step,
"state_dict"
: model.state_dict()}, ckpt_path)
148
self.
_write_metrics
()
149
self.
signal
(step, f
"checkpoint saved (step {step})"
, severity=
"info"
)
150
print(f
"[aquin] Checkpoint saved (step {step})."
)
151
152
def
finish
(self, config: dict[str, Any] |
None
=
None
) ->
None
:
153
"""Finalise the run. Flushes metrics and optional config to disk."""
154
self.
_write_metrics
()
155
if
config:
156
self.
_write_config
(config)
157
elapsed = round(time.time() - self.
_started_at
)
158
print(f
"[aquin] Run finished. {len(self._metrics)} steps recorded in {elapsed}s."
)
159
print(f
"[aquin] Data: {self._run_dir}"
)
160
161
@property
162
def
run_id
(self) -> str:
163
return
self.
_run_id
164
165
def
_write_meta
(self) -> None:
166
meta = {
167
"run_id"
: self.
_run_id
,
168
"run_name"
: self.
_run_name
,
169
"base_model"
: self.
_base_model
,
170
"started_at"
: self.
_started_at
,
171
}
172
with
open(self.
_run_dir
/
"meta.json"
,
"w"
)
as
f:
173
json.dump(meta, f, indent=2)
174
175
def
_write_metrics
(self) -> None:
176
with
self.
_metrics_lock
:
177
data = list(self.
_metrics
)
178
with
open(self.
_run_dir
/
"metrics.json"
,
"w"
)
as
f:
179
json.dump(data, f)
180
181
def
_write_obs
(self) -> None:
182
with
self.
_metrics_lock
:
183
data = list(self.
_obs
)
184
with
open(self.
_run_dir
/
"observations.json"
,
"w"
)
as
f:
185
json.dump(data, f)
186
187
def
_write_signals
(self) -> None:
188
with
self.
_metrics_lock
:
189
data = list(self.
_signals
)
190
with
open(self.
_run_dir
/
"signals.json"
,
"w"
)
as
f:
191
json.dump(data, f)
192
193
def
_write_config
(self, config: dict[str, Any]) ->
None
:
194
with
open(self.
_run_dir
/
"config.json"
,
"w"
)
as
f:
195
json.dump(config, f, indent=2)
aquin.run.Run
Definition
run.py:30
aquin.run.Run._run_name
str _run_name
Definition
run.py:66
aquin.run.Run.observe
None observe(self, int step, str channel, float value)
Definition
run.py:123
aquin.run.Run.run_id
str run_id(self)
Definition
run.py:166
aquin.run.Run._write_signals
None _write_signals(self)
Definition
run.py:191
aquin.run.Run.checkpoint
None checkpoint(self, Any model, int step)
Definition
run.py:142
aquin.run.Run._base_model
str _base_model
Definition
run.py:67
aquin.run.Run.__init__
None __init__(self, str|None base_model=None, str|None run_name=None, dict[str, Any]|None config=None, *, str quant="none", str mode="external", str|Path|None run_dir=None)
Definition
run.py:63
aquin.run.Run._obs
list _obs
Definition
run.py:75
aquin.run.Run._signals
list _signals
Definition
run.py:76
aquin.run.Run._metrics
list _metrics
Definition
run.py:74
aquin.run.Run._started_at
_started_at
Definition
run.py:68
aquin.run.Run._write_config
None _write_config(self, dict[str, Any] config)
Definition
run.py:197
aquin.run.Run._metrics_lock
_metrics_lock
Definition
run.py:77
aquin.run.Run._write_obs
None _write_obs(self)
Definition
run.py:185
aquin.run.Run._write_meta
None _write_meta(self)
Definition
run.py:169
aquin.run.Run._write_metrics
None _write_metrics(self)
Definition
run.py:179
aquin.run.Run.signal
None signal(self, int step, str message, *, str severity="info")
Definition
run.py:130
aquin.run.Run._run_dir
str _run_dir
Definition
run.py:70
aquin.run.Run._run_id
_run_id
Definition
run.py:65
aquin.run.Run.finish
None finish(self, dict[str, Any]|None config=None)
Definition
run.py:156
aquin.run.Run.log
None log(self, int step, *, float loss, float|None learning_rate=None, float|None grad_norm=None, float|None momentum_norm=None, int|None epoch=None, int|None batch=None, int|None total_batches=None, float|None step_ms=None, **float extra)
Definition
run.py:99
aquin.run.init
"Run" init(str|None base_model=None, str|None run_name=None, dict[str, Any]|None config=None)
Definition
run.py:25
aquin
run.py
AQIT · Aquin Labs Private Limited · Apache 2.0 · Generated by
1.18.0