AQIT
0.1.0
Toggle main menu visibility
Loading...
Searching...
No Matches
model_runtime.py
Go to the documentation of this file.
1
# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2
"""
3
Unified model lifecycle — one resident model in VRAM, Ollama-style.
4
5
Owns phase transitions (idle → loading → ready → unloading), coordinates LLM
6
loaders, and is the single source of truth for daemon + CLI load/unload.
7
"""
8
from
__future__
import
annotations
9
10
import
threading
11
import
time
12
from
dataclasses
import
dataclass
13
from
enum
import
Enum
14
from
typing
import
Any, Callable, Literal
15
16
ProgressFn = Callable[[str, float],
None
]
17
18
_lock = threading.Lock()
19
# Serialize load_weights / unload_weights so two builds never share the process.
20
_load_serial = threading.RLock()
21
_phase =
"idle"
22
_target_id: str |
None
=
None
23
_resident_id: str |
None
=
None
24
_kind: Literal[
"llm"
] |
None
=
None
25
_error: str |
None
=
None
26
_started_at: float |
None
=
None
27
_loaded_at: float |
None
=
None
28
_load_message: str |
None
=
None
29
# Bumped on unload/cancel — in-flight builds check this and discard weights.
30
_load_epoch = 0
31
_load_epoch_at_start = 0
32
33
34
class
ModelPhase
(str, Enum):
35
IDLE =
"idle"
36
LOADING =
"loading"
37
READY =
"ready"
38
UNLOADING =
"unloading"
39
ERROR =
"error"
40
41
42
@dataclass(frozen=True)
43
class
RuntimeSnapshot
:
44
phase: ModelPhase
45
model_id: str |
None
46
target_id: str |
None
47
kind: Literal[
"llm"
] |
None
48
error: str |
None
49
elapsed_s: float
50
loaded_for_s: float |
None
51
52
53
def
snapshot
() -> RuntimeSnapshot:
54
"""Thread-safe view of the in-process lifecycle state."""
55
with
_lock:
56
now = time.monotonic()
57
elapsed = (now - _started_at)
if
_started_at
is
not
None
else
0.0
58
loaded_for = (now - _loaded_at)
if
_loaded_at
is
not
None
else
None
59
return
RuntimeSnapshot
(
60
phase=
ModelPhase
(_phase),
61
model_id=_resident_id,
62
target_id=_target_id
if
_phase ==
"loading"
else
None
,
63
kind=_kind,
64
error=_error,
65
elapsed_s=elapsed,
66
loaded_for_s=loaded_for,
67
)
68
69
70
def
_set_phase
(
71
phase: str,
72
*,
73
model_id: str |
None
=
None
,
74
target_id: str |
None
=
None
,
75
kind: Literal[
"llm"
] |
None
=
None
,
76
error: str |
None
=
None
,
77
) ->
None
:
78
global
_phase, _resident_id, _target_id, _kind, _error, _started_at, _loaded_at
79
with
_lock:
80
_phase = phase
81
if
model_id
is
not
None
:
82
_resident_id = model_id
83
if
target_id
is
not
None
:
84
_target_id = target_id
85
if
kind
is
not
None
:
86
_kind = kind
87
_error = error
88
if
phase ==
"loading"
:
89
_started_at = time.monotonic()
90
_loaded_at =
None
91
elif
phase ==
"ready"
:
92
_loaded_at = time.monotonic()
93
_error =
None
94
elif
phase
in
(
"idle"
,
"unloading"
):
95
if
phase ==
"idle"
:
96
_resident_id =
None
97
_target_id =
None
98
_kind =
None
99
_loaded_at =
None
100
_error =
None
if
phase ==
"idle"
else
_error
101
102
103
def
reset_state
() -> None:
104
"""Clear lifecycle markers (tests / daemon shutdown)."""
105
with
_lock:
106
global
_phase, _target_id, _resident_id, _kind, _error, _started_at, _loaded_at, _load_message
107
global
_load_epoch, _load_epoch_at_start
108
_phase =
"idle"
109
_target_id =
None
110
_resident_id =
None
111
_kind =
None
112
_error =
None
113
_started_at =
None
114
_loaded_at =
None
115
_load_message =
None
116
_load_epoch = 0
117
_load_epoch_at_start = 0
118
119
120
def
resolve_kind
(model_id: str) -> tuple[str, Literal[
"llm"
]]:
121
"""Resolve slug + model family for any supported id."""
122
from
aquin.compute.model_loader
import
resolve_model_id
123
124
return
resolve_model_id(model_id),
"llm"
125
126
127
def
resident_from_cache
() -> tuple[str | None, Literal["llm"] | None]:
128
"""What is actually resident in this process's VRAM caches."""
129
try
:
130
from
aquin.compute.model_loader
import
get_loaded_llm_id
131
132
llm = get_loaded_llm_id()
133
if
llm:
134
return
llm,
"llm"
135
except
Exception:
136
pass
137
return
None
,
None
138
139
140
def
sync_from_cache
() -> RuntimeSnapshot:
141
"""Reconcile lifecycle state with actual VRAM caches (health checks)."""
142
global
_phase, _resident_id, _target_id, _kind, _error, _loaded_at
143
resident, kind =
resident_from_cache
()
144
with
_lock:
145
if
_phase ==
"loading"
:
146
pass
147
elif
resident:
148
_resident_id = resident
149
_kind = kind
150
if
_phase !=
"error"
:
151
_phase =
"ready"
152
_error =
None
153
elif
_phase ==
"ready"
:
154
_phase =
"idle"
155
_resident_id =
None
156
_target_id =
None
157
_kind =
None
158
_loaded_at =
None
159
return
snapshot
()
160
161
162
def
begin_load
(model_id: str) -> tuple[str, Literal[
"llm"
]]:
163
global
_load_message, _load_epoch_at_start
164
slug, kind =
resolve_kind
(model_id)
165
_set_phase
(
"loading"
, target_id=slug, kind=kind, error=
None
)
166
with
_lock:
167
_load_message = f
"resolving {slug}"
168
_load_epoch_at_start = _load_epoch
169
return
slug, kind
170
171
172
def
finish_load
(slug: str, kind: Literal[
"llm"
]) ->
None
:
173
global
_load_message
174
_set_phase
(
"ready"
, model_id=slug, kind=kind, error=
None
)
175
with
_lock:
176
_load_message =
None
177
178
179
def
fail_load
(model_id: str, error: str) ->
None
:
180
global
_load_message
181
_set_phase
(
"error"
, model_id=model_id, error=error)
182
with
_lock:
183
_load_message =
None
184
185
186
def
begin_unload
() -> None:
187
snap =
snapshot
()
188
_set_phase
(
"unloading"
, model_id=snap.model_id, kind=snap.kind)
189
190
191
def
finish_unload
() -> None:
192
global
_load_message
193
_set_phase
(
"idle"
)
194
with
_lock:
195
_load_message =
None
196
197
198
def
request_load_cancel
() -> None:
199
"""Mark any in-flight build as cancelled (checked after from_pretrained)."""
200
global
_load_epoch
201
with
_lock:
202
_load_epoch += 1
203
204
205
def
is_load_cancelled
() -> bool:
206
"""True if unload/cancel happened after this load began."""
207
with
_lock:
208
return
_load_epoch != _load_epoch_at_start
209
210
211
def
_emit
(progress: ProgressFn |
None
, message: str) ->
None
:
212
global
_load_message
213
with
_lock:
214
_load_message = message
215
if
progress:
216
snap =
snapshot
()
217
progress(message, snap.elapsed_s)
218
219
220
def
load_weights
(
221
model_id: str,
222
*,
223
progress: ProgressFn |
None
=
None
,
224
) -> str:
225
"""
226
Load model_id into this process. Returns resolved slug. Updates lifecycle state.
227
228
Process-wide serialized — concurrent builds on MPS exhaust unified memory.
229
"""
230
with
_load_serial:
231
slug, kind =
begin_load
(model_id)
232
try
:
233
_emit
(progress, f
"resolving {slug}"
)
234
from
aquin.compute.model_loader
import
clear_sae_cache, load_model
235
236
clear_sae_cache()
237
if
is_load_cancelled
():
238
raise
RuntimeError(f
"Model load cancelled ({slug})"
)
239
_emit
(progress, f
"loading model weights"
)
240
load_model(slug)
241
242
if
is_load_cancelled
():
243
from
aquin.compute.model_loader
import
clear_llm_models, clear_sae_cache
244
245
clear_llm_models()
246
clear_sae_cache()
247
finish_unload
()
248
raise
RuntimeError(f
"Model load cancelled ({slug})"
)
249
250
from
aquin.compute.model_loader
import
_save_active_model
251
252
_save_active_model(slug)
253
finish_load
(slug, kind)
254
_emit
(progress, f
"{slug} ready"
)
255
return
slug
256
except
Exception
as
exc:
257
msg = str(exc)
or
exc.__class__.__name__
258
if
"cancelled"
in
msg.lower():
259
finish_unload
()
260
else
:
261
fail_load
(slug, msg)
262
raise
263
264
265
def
unload_weights
(*, progress: ProgressFn |
None
=
None
, clear_active: bool =
True
) ->
None
:
266
"""Drop all resident weights from VRAM in this process."""
267
request_load_cancel
()
268
with
_load_serial:
269
begin_unload
()
270
try
:
271
_emit
(progress,
"releasing VRAM"
)
272
from
aquin.compute.model_loader
import
clear_active_model_file, clear_llm_models, clear_sae_cache
273
274
clear_llm_models()
275
clear_sae_cache()
276
if
clear_active:
277
clear_active_model_file()
278
finally
:
279
finish_unload
()
280
281
282
def
release_foreign_daemon
() -> bool:
283
"""
284
Optionally unload a background engine so this process can claim VRAM.
285
286
Default is **never** — the desktop app keeps a resident model in the daemon.
287
Headless CLI tools that try load_model in a short-lived process used to call
288
model_daemon.unload() here, which looked like the model “randomly disappearing”.
289
290
Opt-in only: set AQUIN_CLAIM_DAEMON_VRAM=1 when you intentionally want an
291
exclusive in-process load that frees the background engine first.
292
"""
293
import
os
294
295
if
os.environ.get(
"AQUIN_DAEMON"
) ==
"1"
:
296
return
False
297
claim = (os.environ.get(
"AQUIN_CLAIM_DAEMON_VRAM"
)
or
""
).strip().lower()
298
if
claim
not
in
(
"1"
,
"true"
,
"yes"
,
"on"
):
299
return
False
300
try
:
301
from
aquin.engine
import
model_daemon
302
303
if
model_daemon.is_running():
304
model_daemon.unload()
305
return
True
306
except
Exception:
307
pass
308
return
False
309
310
311
def
vram_line
() -> str | None:
312
"""Short VRAM summary for status output."""
313
try
:
314
from
aquin.compute.vram_guard
import
accelerator_vram_gib
315
from
aquin.compute.device
import
resolve_compute_device
316
317
info = accelerator_vram_gib()
318
dev = resolve_compute_device()
319
if
info:
320
free_g, total_g = info
321
return
f
"{free_g:.1f} / {total_g:.1f} GiB free ({dev})"
322
if
dev ==
"mps"
:
323
return
"Metal unified memory"
324
except
Exception:
325
pass
326
return
None
327
328
329
def
health_payload
(*, daemon: bool, port: int) -> dict[str, Any]:
330
"""JSON health block for the local engine server."""
331
sync_from_cache
()
332
snap =
snapshot
()
333
resident, _ =
resident_from_cache
()
334
with
_lock:
335
load_message = _load_message
336
return
{
337
"status"
:
"ok"
,
338
"port"
: port,
339
"daemon"
: daemon,
340
"model_id"
: resident,
341
"model_status"
: snap.phase.value,
342
"loading_model_id"
: snap.target_id
if
snap.phase == ModelPhase.LOADING
else
None
,
343
"load_message"
: load_message
if
snap.phase == ModelPhase.LOADING
else
None
,
344
"model_kind"
: snap.kind,
345
"last_error"
: snap.error,
346
"elapsed_s"
: round(snap.elapsed_s, 1)
if
snap.phase == ModelPhase.LOADING
else
None
,
347
"loaded_for_s"
: round(snap.loaded_for_s, 1)
if
snap.loaded_for_s
is
not
None
else
None
,
348
"vram"
:
vram_line
(),
349
}
aquin.compute.model_runtime.ModelPhase
Definition
model_runtime.py:38
aquin.compute.model_runtime.RuntimeSnapshot
Definition
model_runtime.py:47
aquin.compute.device
Definition
device.py:1
aquin.compute.model_loader
Definition
model_loader.py:1
aquin.compute.model_runtime._set_phase
None _set_phase(str phase, *, str|None model_id=None, str|None target_id=None, Literal["llm"]|None kind=None, str|None error=None)
Definition
model_runtime.py:81
aquin.compute.model_runtime.begin_load
tuple[str, Literal["llm"]] begin_load(str model_id)
Definition
model_runtime.py:166
aquin.compute.model_runtime.release_foreign_daemon
bool release_foreign_daemon()
Definition
model_runtime.py:286
aquin.compute.model_runtime.snapshot
RuntimeSnapshot snapshot()
Definition
model_runtime.py:57
aquin.compute.model_runtime.finish_unload
None finish_unload()
Definition
model_runtime.py:195
aquin.compute.model_runtime.resolve_kind
tuple[str, Literal["llm"]] resolve_kind(str model_id)
Definition
model_runtime.py:124
aquin.compute.model_runtime.sync_from_cache
RuntimeSnapshot sync_from_cache()
Definition
model_runtime.py:144
aquin.compute.model_runtime.begin_unload
None begin_unload()
Definition
model_runtime.py:190
aquin.compute.model_runtime.health_payload
dict[str, Any] health_payload(*, bool daemon, int port)
Definition
model_runtime.py:333
aquin.compute.model_runtime.is_load_cancelled
bool is_load_cancelled()
Definition
model_runtime.py:209
aquin.compute.model_runtime.vram_line
str|None vram_line()
Definition
model_runtime.py:315
aquin.compute.model_runtime.reset_state
None reset_state()
Definition
model_runtime.py:107
aquin.compute.model_runtime.load_weights
str load_weights(str model_id, *, ProgressFn|None progress=None)
Definition
model_runtime.py:228
aquin.compute.model_runtime.resident_from_cache
tuple[str|None, Literal["llm"]|None] resident_from_cache()
Definition
model_runtime.py:131
aquin.compute.model_runtime._emit
None _emit(ProgressFn|None progress, str message)
Definition
model_runtime.py:215
aquin.compute.model_runtime.unload_weights
None unload_weights(*, ProgressFn|None progress=None, bool clear_active=True)
Definition
model_runtime.py:269
aquin.compute.model_runtime.fail_load
None fail_load(str model_id, str error)
Definition
model_runtime.py:183
aquin.compute.model_runtime.finish_load
None finish_load(str slug, Literal["llm"] kind)
Definition
model_runtime.py:176
aquin.compute.model_runtime.request_load_cancel
None request_load_cancel()
Definition
model_runtime.py:202
aquin.compute.vram_guard
Definition
vram_guard.py:1
aquin.engine
Definition
__init__.py:1
aquin
compute
model_runtime.py
AQIT · Aquin Labs Private Limited · Apache 2.0 · Generated by
1.18.0