omnius 1.0.841 → 1.0.843
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.
- package/dist/api/py-embed.js +651 -91
- package/dist/computer-use/models.lock.yaml +495 -0
- package/dist/index.js +2 -2
- package/dist/library.d.ts +1 -0
- package/dist/library.js +176452 -55418
- package/dist/scripts/rapid-computer-use/gpu_lease.py +64 -0
- package/dist/scripts/rapid-computer-use/laya_service.py +483 -0
- package/dist/scripts/rapid-computer-use/model_gate.py +755 -0
- package/dist/scripts/rapid-computer-use/photon_service.py +700 -0
- package/dist/scripts/rapid-computer-use/point_benchmark.py +278 -0
- package/dist/update-worker.js +651 -91
- package/docs/DISCOVERY.json +1727 -828
- package/docs/DISCOVERY.md +23 -0
- package/docs/guides/bring-your-own-inference.md +128 -0
- package/docs/reference/slash-commands.md +138 -22
- package/docs/work-orders/WO-inference-fallback-20261012.md +89 -0
- package/docs/work-orders/WO-primary-checkout-fallback-delivery-20261012.md +94 -0
- package/docs/work-orders/WO-telegram-fallback-20261012.md +83 -0
- package/docs/work-orders/inference-fallback-bundle-20261012.json +75 -0
- package/docs/work-orders/inference-fallback-live-20261012.json +39 -0
- package/docs/work-orders/primary-inference-fallback-bundle-20261012.json +88 -0
- package/docs/work-orders/rapid-computer-use-20261011/README.md +125 -0
- package/docs/work-orders/rapid-computer-use-20261011/WO-01-native-save-recovery.md +86 -0
- package/docs/work-orders/rapid-computer-use-20261011/WO-02-semantic-control.md +93 -0
- package/docs/work-orders/rapid-computer-use-20261011/WO-03-policy-workflows.md +130 -0
- package/docs/work-orders/rapid-computer-use-20261011/WO-04-live-model-gates.md +322 -0
- package/docs/work-orders/rapid-computer-use-20261011/WO-05-verification-delivery.md +389 -0
- package/docs/work-orders/rapid-computer-use-20261011/WO-06-medium-horizon-runtime.md +166 -0
- package/docs/work-orders/rapid-computer-use-20261011/WO-07-tool-routing-prompts.md +81 -0
- package/docs/work-orders/rapid-computer-use-20261011/WO-08-cross-application-desktop.md +214 -0
- package/docs/work-orders/rapid-computer-use-20261011/architecture-source.md +871 -0
- package/docs/work-orders/telegram-progress-browser-20261011/README.md +79 -0
- package/docs/work-orders/telegram-progress-browser-20261011/WO-01-diagnostic-visibility.md +64 -0
- package/docs/work-orders/telegram-progress-browser-20261011/WO-02-task-narration.md +127 -0
- package/docs/work-orders/telegram-progress-browser-20261011/WO-03-browser-observation.md +51 -0
- package/docs/work-orders/telegram-progress-browser-20261011/WO-04-download-desktop-handoff.md +96 -0
- package/docs/work-orders/telegram-progress-browser-20261011/WO-05-verification-delivery.md +129 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/prompts/agentic/system-common.md +7 -0
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Host-staged local Moondream point service. Importing this file never loads CUDA.
|
|
3
|
+
|
|
4
|
+
Idle -> host load marker -> exact raw checkpoint tensors resident on CUDA.
|
|
5
|
+
Host placement statement/approval -> explicit engine activation (warmup counted).
|
|
6
|
+
A new placement statement/approval then admits each bounded point request.
|
|
7
|
+
"""
|
|
8
|
+
import argparse
|
|
9
|
+
import base64
|
|
10
|
+
import binascii
|
|
11
|
+
from contextlib import contextmanager
|
|
12
|
+
import ctypes
|
|
13
|
+
import hashlib
|
|
14
|
+
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
15
|
+
import importlib.metadata
|
|
16
|
+
import io
|
|
17
|
+
import json
|
|
18
|
+
import os
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
import secrets
|
|
21
|
+
import socket
|
|
22
|
+
import stat
|
|
23
|
+
import sys
|
|
24
|
+
import threading
|
|
25
|
+
import time
|
|
26
|
+
|
|
27
|
+
import model_gate as gate
|
|
28
|
+
import point_benchmark as points
|
|
29
|
+
import laya_service as host
|
|
30
|
+
import gpu_lease
|
|
31
|
+
|
|
32
|
+
MODEL = "moondream3.1-9B-A2B"
|
|
33
|
+
WEIGHTS_REVISION = "1da27e6c2d2f9118de14560df456881dc62d91f3"
|
|
34
|
+
WEIGHTS_SHA256 = "26dde16af961d3a486c7b86b9a34fc8487be7917f7e62324b751400ef4d391b4"
|
|
35
|
+
WEIGHTS_BYTES = 10505269576
|
|
36
|
+
RUNTIME_REVISION = "80640639279b18b2da61b08c06c550f8eaab6596d6d15978fd56f76707462cb7"
|
|
37
|
+
TOKENIZER_REVISION = "35192e10a54e36eabe0a7cc57a2c1aab371cafc5"
|
|
38
|
+
TOKENIZER_SHA256 = "0512fdcac4a5f9e7746cbefce4a468dc93bf0f93f11e701b84f8b31bff199e9c"
|
|
39
|
+
MAX_REQUEST_BYTES = 28 * 1024 * 1024
|
|
40
|
+
MAX_PIXELS = 16_777_216
|
|
41
|
+
POINT_DEADLINE = 45
|
|
42
|
+
STAGE_DEADLINE = 240 # Less than the broker's 300-second pending window.
|
|
43
|
+
REQUEST_READ_DEADLINE = 5
|
|
44
|
+
REQUIREMENTS_SHA256 = "87c1184a8f60b09040a6480b0ec421d386ca7b9cbb5034bb9ffb402c3c7d5aa9"
|
|
45
|
+
CUDA12_PACKAGE = "nvidia-cuda-runtime-cu12"
|
|
46
|
+
CUDA12_VERSION = "12.9.79"
|
|
47
|
+
CUDA12_SHA256 = "256e6409e4f06f618e1fb53d4844a6b81cdded1013afa8ade40c22f99eb133b7"
|
|
48
|
+
CUDA12_BYTES = 741088
|
|
49
|
+
CUDA12_REQUIREMENTS_SHA256 = "10852e9e96696e60210053304a2c202a3b5eee2c0dd4a07044e8ea10f7e9302d"
|
|
50
|
+
CUDA12_REQUIREMENTS = gate.DEFAULT_LOCK.with_name("photon-cuda12-compatibility.requirements.txt")
|
|
51
|
+
CUDA12_SYMBOLS = ("cudaLibraryLoadData", "cudaLibraryLoadFromFile", "cudaLibraryGetKernel", "cudaLibraryUnload")
|
|
52
|
+
RUNTIME_PACKAGES = {"moondream": "2.6.1", "kestrel": "0.9.1",
|
|
53
|
+
"kestrel-native": "0.1.8", "kestrel-kernels": "0.7.4",
|
|
54
|
+
CUDA12_PACKAGE: CUDA12_VERSION,
|
|
55
|
+
**{f"kestrel-kernels-bundle-{letter}": "0.7.4" for letter in "abcdefgh"}}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def installed_runtime_paths():
|
|
59
|
+
"""Inventory installed executable/data bytes without importing CUDA modules."""
|
|
60
|
+
paths = set()
|
|
61
|
+
for name in RUNTIME_PACKAGES:
|
|
62
|
+
distribution = importlib.metadata.distribution(name)
|
|
63
|
+
for item in distribution.files or ():
|
|
64
|
+
if str(item).endswith(".pyc") or "__pycache__" in Path(item).parts:
|
|
65
|
+
continue
|
|
66
|
+
path = Path(distribution.locate_file(item)).resolve(strict=True)
|
|
67
|
+
gate.require(path.is_file(), "runtime manifest contains a non-file entry")
|
|
68
|
+
paths.add(str(path))
|
|
69
|
+
return paths
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def validate_manifest(manifest):
|
|
73
|
+
gate.require(manifest.get("schema") == "omnius.computer-use.photon-checkpoint.v1"
|
|
74
|
+
and manifest.get("weights_revision") == WEIGHTS_REVISION
|
|
75
|
+
and manifest.get("runtime_revision") == RUNTIME_REVISION,
|
|
76
|
+
"Photon manifest differs from reviewed immutable pins")
|
|
77
|
+
weights, tokenizer = manifest.get("weights", {}), manifest.get("tokenizer", {})
|
|
78
|
+
gate.require(weights.get("sha256") == WEIGHTS_SHA256 and weights.get("bytes") == WEIGHTS_BYTES,
|
|
79
|
+
"exact Moondream checkpoint bytes are required")
|
|
80
|
+
gate.require(tokenizer.get("revision") == TOKENIZER_REVISION
|
|
81
|
+
and tokenizer.get("sha256") == TOKENIZER_SHA256, "exact Starmie tokenizer required")
|
|
82
|
+
versions = manifest.get("versions", {})
|
|
83
|
+
for name, version in RUNTIME_PACKAGES.items():
|
|
84
|
+
gate.require(versions.get(name) == version, f"missing exact runtime pin: {name}")
|
|
85
|
+
gate.require(4 <= len(versions) <= 200, "bounded runtime dependency manifest required")
|
|
86
|
+
for name, version in versions.items():
|
|
87
|
+
gate.require(importlib.metadata.version(name) == version, f"runtime dependency changed: {name}")
|
|
88
|
+
files = manifest.get("runtime_files", {})
|
|
89
|
+
gate.require(isinstance(files, dict) and 10 <= len(files) <= 5000,
|
|
90
|
+
"installed runtime file hashes are required")
|
|
91
|
+
gate.require(set(files) == installed_runtime_paths(), "installed runtime inventory changed")
|
|
92
|
+
for filename, sha in files.items():
|
|
93
|
+
path = Path(filename)
|
|
94
|
+
gate.require(path.is_absolute() and path.is_file()
|
|
95
|
+
and isinstance(sha, str) and len(sha) == 64
|
|
96
|
+
and host.file_sha256(path) == sha, "installed runtime file hash mismatch")
|
|
97
|
+
validate_cuda12_manifest(manifest)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def installed_cuda12_path():
|
|
101
|
+
distribution = importlib.metadata.distribution(CUDA12_PACKAGE)
|
|
102
|
+
return Path(distribution.locate_file("nvidia/cuda_runtime/lib/libcudart.so.12")).resolve(strict=True)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def validate_cuda12_manifest(manifest):
|
|
106
|
+
expected_path = str(installed_cuda12_path())
|
|
107
|
+
gate.require(manifest.get("cuda12_runtime") == {
|
|
108
|
+
"package": CUDA12_PACKAGE, "version": CUDA12_VERSION, "path": expected_path,
|
|
109
|
+
"sha256": CUDA12_SHA256, "bytes": CUDA12_BYTES}, "exact isolated CUDA12 runtime identity required")
|
|
110
|
+
gate.require(manifest.get("runtime_files", {}).get(expected_path) == CUDA12_SHA256
|
|
111
|
+
and manifest.get("compatibility_requirements_sha256") == CUDA12_REQUIREMENTS_SHA256,
|
|
112
|
+
"CUDA12 runtime must belong to the pinned installed inventory")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def loaded_cuda12_paths():
|
|
116
|
+
paths = set()
|
|
117
|
+
for line in Path("/proc/self/maps").read_text().splitlines():
|
|
118
|
+
fields = line.split(maxsplit=5)
|
|
119
|
+
if len(fields) == 6 and fields[5].startswith("/") and "libcudart.so.12" in Path(fields[5]).name:
|
|
120
|
+
paths.add(str(Path(fields[5]).resolve()))
|
|
121
|
+
return paths
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def prepare_manifest(weights, tokenizer, requirements, compatibility_requirements=CUDA12_REQUIREMENTS):
|
|
125
|
+
"""Build a host-local receipt using file I/O and package metadata only."""
|
|
126
|
+
with Path(requirements).open("rb") as stream:
|
|
127
|
+
raw = stream.read(32 * 1024 + 1)
|
|
128
|
+
gate.require(hashlib.sha256(raw).hexdigest() == REQUIREMENTS_SHA256,
|
|
129
|
+
"exact frozen CPython3.12 dependency plan required")
|
|
130
|
+
with Path(compatibility_requirements).open("rb") as stream:
|
|
131
|
+
compatibility_raw = stream.read(32 * 1024 + 1)
|
|
132
|
+
gate.require(hashlib.sha256(compatibility_raw).hexdigest() == CUDA12_REQUIREMENTS_SHA256,
|
|
133
|
+
"exact isolated CUDA12 compatibility dependency plan required")
|
|
134
|
+
versions = {}
|
|
135
|
+
for line in raw.decode().splitlines():
|
|
136
|
+
if line and not line.startswith("#"):
|
|
137
|
+
name, rest = line.split("==", 1)
|
|
138
|
+
versions[name] = rest.split()[0]
|
|
139
|
+
versions[CUDA12_PACKAGE] = CUDA12_VERSION
|
|
140
|
+
for path, sha, size in ((weights, WEIGHTS_SHA256, WEIGHTS_BYTES), (tokenizer, TOKENIZER_SHA256, None)):
|
|
141
|
+
pinned = PinnedFile(path, sha, size)
|
|
142
|
+
pinned.close()
|
|
143
|
+
manifest = {"schema": "omnius.computer-use.photon-checkpoint.v1",
|
|
144
|
+
"weights_revision": WEIGHTS_REVISION, "runtime_revision": RUNTIME_REVISION,
|
|
145
|
+
"weights": {"path": str(Path(weights).resolve()), "sha256": WEIGHTS_SHA256, "bytes": WEIGHTS_BYTES},
|
|
146
|
+
"tokenizer": {"path": str(Path(tokenizer).resolve()), "revision": TOKENIZER_REVISION,
|
|
147
|
+
"sha256": TOKENIZER_SHA256}, "versions": versions,
|
|
148
|
+
"requirements_sha256": REQUIREMENTS_SHA256,
|
|
149
|
+
"compatibility_requirements_sha256": CUDA12_REQUIREMENTS_SHA256,
|
|
150
|
+
"cuda12_runtime": {"package": CUDA12_PACKAGE, "version": CUDA12_VERSION,
|
|
151
|
+
"path": str(installed_cuda12_path()), "sha256": CUDA12_SHA256,
|
|
152
|
+
"bytes": CUDA12_BYTES},
|
|
153
|
+
"runtime_files": {path: host.file_sha256(path) for path in sorted(installed_runtime_paths())}}
|
|
154
|
+
validate_manifest(manifest)
|
|
155
|
+
return manifest
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class PinnedFile:
|
|
159
|
+
"""Keep the checked inode open; loading cannot follow a replaced pathname."""
|
|
160
|
+
def __init__(self, path, sha256, expected_bytes=None):
|
|
161
|
+
self.fd = os.open(Path(path).resolve(strict=True), os.O_RDONLY | os.O_NOFOLLOW)
|
|
162
|
+
try:
|
|
163
|
+
info = os.fstat(self.fd)
|
|
164
|
+
gate.require(stat.S_ISREG(info.st_mode), "checkpoint must be a regular file")
|
|
165
|
+
if expected_bytes is not None:
|
|
166
|
+
gate.require(info.st_size == expected_bytes, "checkpoint byte count changed")
|
|
167
|
+
self.identity = self.stat_identity(info)
|
|
168
|
+
self.sha256 = sha256
|
|
169
|
+
digest = hashlib.sha256()
|
|
170
|
+
with os.fdopen(os.dup(self.fd), "rb") as stream:
|
|
171
|
+
for block in iter(lambda: stream.read(8 * 1024 * 1024), b""):
|
|
172
|
+
digest.update(block)
|
|
173
|
+
gate.require(digest.hexdigest() == sha256, "checkpoint/tokenizer SHA-256 mismatch")
|
|
174
|
+
gate.require(self.stat_identity(os.fstat(self.fd)) == self.identity,
|
|
175
|
+
"pinned file changed while hashing")
|
|
176
|
+
except BaseException:
|
|
177
|
+
os.close(self.fd)
|
|
178
|
+
self.fd = None
|
|
179
|
+
raise
|
|
180
|
+
|
|
181
|
+
@staticmethod
|
|
182
|
+
def stat_identity(info):
|
|
183
|
+
return (info.st_dev, info.st_ino, info.st_nlink, info.st_size, info.st_mtime_ns, info.st_ctime_ns)
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def path(self):
|
|
187
|
+
return f"/proc/self/fd/{self.fd}"
|
|
188
|
+
|
|
189
|
+
def assert_unchanged(self):
|
|
190
|
+
gate.require(self.fd is not None and self.stat_identity(os.fstat(self.fd)) == self.identity,
|
|
191
|
+
"pinned file changed after hashing")
|
|
192
|
+
# Timestamp granularity can miss an equal-sized rewrite in the same tick.
|
|
193
|
+
gate.require(host.file_sha256(self.path) == self.sha256
|
|
194
|
+
and self.stat_identity(os.fstat(self.fd)) == self.identity,
|
|
195
|
+
"pinned file bytes changed after hashing")
|
|
196
|
+
|
|
197
|
+
def close(self):
|
|
198
|
+
if self.fd is not None:
|
|
199
|
+
os.close(self.fd)
|
|
200
|
+
self.fd = None
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def validate_request(value, model):
|
|
204
|
+
gate.require(isinstance(value, dict) and set(value) == {"model", "object", "image_url"},
|
|
205
|
+
"point request requires only model, object and image_url")
|
|
206
|
+
gate.require(value["model"] == model, "request model differs from resident model")
|
|
207
|
+
gate.require(isinstance(value["object"], str) and 0 < len(value["object"].strip()) <= 1000,
|
|
208
|
+
"bounded nonempty point query required")
|
|
209
|
+
encoded = value["image_url"]
|
|
210
|
+
prefix = "data:image/png;base64,"
|
|
211
|
+
gate.require(isinstance(encoded, str) and encoded.startswith(prefix)
|
|
212
|
+
and len(encoded) <= MAX_REQUEST_BYTES, "bounded inline PNG required; URLs are forbidden")
|
|
213
|
+
try:
|
|
214
|
+
raw = base64.b64decode(encoded[len(prefix):], validate=True)
|
|
215
|
+
except (ValueError, binascii.Error) as error:
|
|
216
|
+
raise gate.GateError("invalid PNG base64") from error
|
|
217
|
+
gate.require(0 < len(raw) <= points.MAX_IMAGE_BYTES, "PNG exceeds byte bound")
|
|
218
|
+
width, height = points.png_dimensions(raw)
|
|
219
|
+
gate.require(width * height <= MAX_PIXELS, "PNG exceeds pixel budget")
|
|
220
|
+
return {"model": model, "object": value["object"], "image_bytes": raw}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def validate_answer(value):
|
|
224
|
+
gate.require(isinstance(value, dict) and set(value) == {"points"}
|
|
225
|
+
and isinstance(value["points"], list) and len(value["points"]) <= 100,
|
|
226
|
+
"invalid bounded point result")
|
|
227
|
+
for point in value["points"]:
|
|
228
|
+
gate.require(isinstance(point, dict) and set(point) == {"x", "y"}
|
|
229
|
+
and all(points.number(point.get(key)) and 0 <= point[key] < 1 for key in ("x", "y")),
|
|
230
|
+
"model point is not finite normalized coordinates")
|
|
231
|
+
return value
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class LocalPhotonAdapter:
|
|
235
|
+
def __init__(self, manifest, authorized):
|
|
236
|
+
validate_manifest(manifest)
|
|
237
|
+
self.authorized = authorized
|
|
238
|
+
self.weights_file = PinnedFile(manifest["weights"]["path"], WEIGHTS_SHA256, WEIGHTS_BYTES)
|
|
239
|
+
self.tokenizer_file = PinnedFile(manifest["tokenizer"]["path"], TOKENIZER_SHA256)
|
|
240
|
+
self.cuda12_file = PinnedFile(manifest["cuda12_runtime"]["path"], CUDA12_SHA256, CUDA12_BYTES)
|
|
241
|
+
self.cuda12_library = None
|
|
242
|
+
self.manifest, self.client, self.runtime = manifest, None, None
|
|
243
|
+
self.warmup_requests = self.warmup_completed = 0
|
|
244
|
+
os.environ.update(HF_HUB_OFFLINE="1", TRANSFORMERS_OFFLINE="1",
|
|
245
|
+
HF_HUB_DISABLE_TELEMETRY="1", TOKENIZERS_PARALLELISM="false")
|
|
246
|
+
os.environ.pop("MOONDREAM_API_KEY", None)
|
|
247
|
+
host.deny_outbound_runtime_connections()
|
|
248
|
+
# These are the first CUDA-capable imports, after the host's load marker.
|
|
249
|
+
import torch
|
|
250
|
+
from safetensors.torch import load_file
|
|
251
|
+
gate.require(torch.cuda.is_available() and torch.cuda.device_count() == 1,
|
|
252
|
+
"strict CUDA requires exactly one reserved visible GPU")
|
|
253
|
+
props = torch.cuda.get_device_properties(0)
|
|
254
|
+
gate.require("A100" in props.name and props.total_memory >= 80_000 * 1024**2
|
|
255
|
+
and props.major >= 8, "strict CUDA requires the reserved A100 80 GB")
|
|
256
|
+
self.torch = torch
|
|
257
|
+
self.guard = host.StrictCudaGuard(authorized, torch.is_tensor)
|
|
258
|
+
self.weights = load_file(self.weights_file.path, device="cuda:0")
|
|
259
|
+
self.weights_file.assert_unchanged()
|
|
260
|
+
gate.require(0 < len(self.weights) <= 10_000, "checkpoint tensor inventory exceeds bound")
|
|
261
|
+
self.assert_resident()
|
|
262
|
+
gate.require(sum(t.numel() * t.element_size() for t in self.weights.values()) > WEIGHTS_BYTES * .95,
|
|
263
|
+
"full checkpoint tensors were not made resident")
|
|
264
|
+
|
|
265
|
+
@property
|
|
266
|
+
def engine_initialized(self):
|
|
267
|
+
return self.client is not None
|
|
268
|
+
|
|
269
|
+
def assert_resident(self):
|
|
270
|
+
if self.weights:
|
|
271
|
+
for tensor in self.weights.values():
|
|
272
|
+
self.guard.require_device(tensor.device)
|
|
273
|
+
else:
|
|
274
|
+
gate.require(self.runtime is not None, "no resident checkpoint or initialized engine")
|
|
275
|
+
if self.runtime is not None:
|
|
276
|
+
self.guard.require_device(self.runtime.device)
|
|
277
|
+
self.guard.assert_resident(self.runtime.model)
|
|
278
|
+
self.guard.assert_resident(self.runtime.region)
|
|
279
|
+
if self.cuda12_library is not None:
|
|
280
|
+
gate.require(loaded_cuda12_paths() == {self.manifest["cuda12_runtime"]["path"]},
|
|
281
|
+
"loaded CUDA12 runtime differs from the exact isolated library")
|
|
282
|
+
|
|
283
|
+
def synchronize(self):
|
|
284
|
+
self.torch.cuda.synchronize(0)
|
|
285
|
+
|
|
286
|
+
def load_cuda12_runtime(self):
|
|
287
|
+
gate.require(self.authorized(), "CUDA library loading requires host engine authorization")
|
|
288
|
+
self.cuda12_file.assert_unchanged()
|
|
289
|
+
expected = {self.manifest["cuda12_runtime"]["path"]}
|
|
290
|
+
gate.require(loaded_cuda12_paths().issubset(expected), "competing CUDA12 runtime is already loaded")
|
|
291
|
+
# Use the checked inode. Its ELF SONAME satisfies Kestrel's later
|
|
292
|
+
# dlopen("libcudart.so.12") without consulting the old system runtime.
|
|
293
|
+
self.cuda12_library = ctypes.CDLL(self.cuda12_file.path, mode=ctypes.RTLD_GLOBAL)
|
|
294
|
+
gate.require(all(hasattr(self.cuda12_library, name) for name in CUDA12_SYMBOLS),
|
|
295
|
+
"isolated CUDA12 runtime lacks required Library API symbols")
|
|
296
|
+
gate.require(loaded_cuda12_paths() == expected, "exact isolated CUDA12 library was not mapped")
|
|
297
|
+
|
|
298
|
+
def initialize_engine(self):
|
|
299
|
+
gate.require(self.authorized() and not self.engine_initialized,
|
|
300
|
+
"engine activation requires fresh host inference authorization")
|
|
301
|
+
self.assert_resident()
|
|
302
|
+
self.weights_file.assert_unchanged()
|
|
303
|
+
self.tokenizer_file.assert_unchanged()
|
|
304
|
+
self.load_cuda12_runtime()
|
|
305
|
+
# No Kestrel/Moondream import or constructor ran before actual placement.
|
|
306
|
+
from kestrel.engine import core
|
|
307
|
+
from kestrel.models.moondream import runtime as md_runtime, weights as md_weights
|
|
308
|
+
from kestrel import model_download
|
|
309
|
+
from moondream.photon_client import PhotonClient
|
|
310
|
+
|
|
311
|
+
class LocalReporter:
|
|
312
|
+
"""No cloud client, telemetry, credentials or external validation."""
|
|
313
|
+
@staticmethod
|
|
314
|
+
def _normalize_api_key(_key): return None
|
|
315
|
+
def __init__(self, *_args, **_kwargs): pass
|
|
316
|
+
async def validate_api_key(self): return False
|
|
317
|
+
def start(self): pass
|
|
318
|
+
async def shutdown(self): pass
|
|
319
|
+
def record_success(self, **_kwargs): pass
|
|
320
|
+
def record_error(self, **_kwargs): pass
|
|
321
|
+
|
|
322
|
+
@contextmanager
|
|
323
|
+
def resident_weights(path):
|
|
324
|
+
gate.require(self.authorized() and path == self.manifest["weights"]["path"],
|
|
325
|
+
"engine requested unapproved checkpoint bytes")
|
|
326
|
+
self.assert_resident()
|
|
327
|
+
def get_tensor(name):
|
|
328
|
+
gate.require(name in self.weights, "engine requested a missing checkpoint tensor")
|
|
329
|
+
return self.weights[name]
|
|
330
|
+
get_tensor.keys = lambda: list(self.weights)
|
|
331
|
+
yield get_tensor
|
|
332
|
+
|
|
333
|
+
def no_download(*_args, **_kwargs):
|
|
334
|
+
raise host.StrictCudaError("implicit checkpoint downloads are disabled")
|
|
335
|
+
|
|
336
|
+
original_model, original_region = md_runtime.MoondreamModel, md_runtime.build_region_module
|
|
337
|
+
def guarded_model(*args, **kwargs):
|
|
338
|
+
return self.guard.install(original_model(*args, **kwargs))
|
|
339
|
+
def guarded_region(*args, **kwargs):
|
|
340
|
+
return self.guard.install(original_region(*args, **kwargs))
|
|
341
|
+
original_query = core.InferenceEngine.query
|
|
342
|
+
async def recorded_query(engine, *args, **kwargs):
|
|
343
|
+
gate.require(self.authorized() and not args and kwargs.get("settings", {}).get("max_tokens") == 1,
|
|
344
|
+
"only the declared one-token startup query is allowed during activation")
|
|
345
|
+
self.warmup_requests += 1
|
|
346
|
+
result = await original_query(engine, **kwargs)
|
|
347
|
+
self.warmup_completed += 1
|
|
348
|
+
return result
|
|
349
|
+
|
|
350
|
+
# This is a dedicated owned service; patches persist for its lifetime.
|
|
351
|
+
core.PhotonReporter = LocalReporter
|
|
352
|
+
model_download.ensure_model_weights = no_download
|
|
353
|
+
model_download.probe_supported_model_configs = lambda *_args, **_kwargs: None
|
|
354
|
+
md_runtime.MoondreamModel, md_runtime.build_region_module = guarded_model, guarded_region
|
|
355
|
+
md_weights.safetensors_open = resident_weights
|
|
356
|
+
core.InferenceEngine.query = recorded_query
|
|
357
|
+
self.client = PhotonClient(model=MODEL, api_key=None, device="cuda:0",
|
|
358
|
+
model_path=self.manifest["weights"]["path"],
|
|
359
|
+
tokenizer_path=self.tokenizer_file.path,
|
|
360
|
+
max_batch_size=1, kv_cache_pages=8192,
|
|
361
|
+
enable_cuda_graphs=False, enable_prefix_cache=True,
|
|
362
|
+
decode_path="native", service_name="omnius_point_eval")
|
|
363
|
+
self.runtime = self.client._engine._runtimes[MODEL]
|
|
364
|
+
self.assert_resident()
|
|
365
|
+
gate.require(self.warmup_requests == self.warmup_completed == 1,
|
|
366
|
+
"expected startup warmup was not measured exactly once")
|
|
367
|
+
# Engine parameters retain any shared tensors; discard only extra refs.
|
|
368
|
+
self.weights = {}
|
|
369
|
+
self.synchronize()
|
|
370
|
+
self.torch.cuda.empty_cache()
|
|
371
|
+
self.assert_resident()
|
|
372
|
+
|
|
373
|
+
def predict(self, request):
|
|
374
|
+
gate.require(self.authorized() and self.engine_initialized, "point inference is not authorized")
|
|
375
|
+
self.assert_resident()
|
|
376
|
+
from PIL import Image
|
|
377
|
+
with Image.open(io.BytesIO(request["image_bytes"])) as image:
|
|
378
|
+
gate.require(image.format == "PNG" and image.width * image.height <= MAX_PIXELS,
|
|
379
|
+
"decoded image violates the PNG pixel bound")
|
|
380
|
+
image.load()
|
|
381
|
+
result = self.client.point(image.convert("RGB"), request["object"],
|
|
382
|
+
settings={"max_tokens": 64, "temperature": 0.0})
|
|
383
|
+
self.assert_resident()
|
|
384
|
+
return result
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
class StagedPointService:
|
|
388
|
+
def __init__(self, selection, lock, manifest, manifest_sha, state_dir, lease_owner,
|
|
389
|
+
adapter_factory=LocalPhotonAdapter, identity=None, cuda_scope=None,
|
|
390
|
+
boot_id=None, clock=time.time, preflight=None, lease=None,
|
|
391
|
+
timer_factory=threading.Timer, terminate=os._exit):
|
|
392
|
+
gate.validate_selection(selection, lock)
|
|
393
|
+
endpoint = gate.local_endpoint(selection["endpoint"])
|
|
394
|
+
gate.require(selection["model_id"] == "moondream-3.1" and selection["model"] == MODEL
|
|
395
|
+
and selection["protocol"] == "moondream-point"
|
|
396
|
+
and selection["weights_revision"] == WEIGHTS_REVISION
|
|
397
|
+
and selection["runtime_revision"] == RUNTIME_REVISION,
|
|
398
|
+
"service requires the exact pinned Moondream selection")
|
|
399
|
+
gate.require(endpoint.hostname == "127.0.0.1" and endpoint.path == "/v1/point"
|
|
400
|
+
and len(selection["gpu_uuids"]) == 1, "one leased GPU and exact loopback point endpoint required")
|
|
401
|
+
self.identity = identity or gate.process_identity(os.getpid())
|
|
402
|
+
self.cuda_scope = cuda_scope or gate.process_cuda_scope(os.getpid())
|
|
403
|
+
gate.require(self.cuda_scope == selection["gpu_uuids"], "actual CUDA visibility differs from selection")
|
|
404
|
+
self.boot_id = boot_id or Path("/proc/sys/kernel/random/boot_id").read_text().strip()
|
|
405
|
+
self.selection, self.lock, self.manifest, self.manifest_sha = selection, lock, manifest, manifest_sha
|
|
406
|
+
self.state_dir = Path(state_dir)
|
|
407
|
+
self.state_dir.mkdir(parents=True, exist_ok=True, mode=0o700)
|
|
408
|
+
info = self.state_dir.stat()
|
|
409
|
+
gate.require(info.st_uid == os.getuid() and stat.S_IMODE(info.st_mode) & 0o077 == 0,
|
|
410
|
+
"state directory must be owner-only")
|
|
411
|
+
self.lease_owner, self.clock, self.adapter_factory = lease_owner, clock, adapter_factory
|
|
412
|
+
self.lease = lease or gpu_lease.ScopedGpuLease(lease_owner, selection["gpu_uuids"])
|
|
413
|
+
self.preflight = preflight or (lambda receipt: gate.verify_preflight(
|
|
414
|
+
selection, lock, receipt, gate.collect_snapshot(selection, receipt)))
|
|
415
|
+
self.timer_factory, self.terminate = timer_factory, terminate
|
|
416
|
+
self.stage, self.adapter, self.receipt = "idle", None, None
|
|
417
|
+
self.inference_active = False
|
|
418
|
+
self.mutex, self.nonce = threading.Lock(), secrets.token_hex(24)
|
|
419
|
+
self.service_code_hashes = self.current_code_hashes()
|
|
420
|
+
self.idle = {"schema": "omnius.computer-use.photon-idle.v1", "stage": "idle", "loaded": False,
|
|
421
|
+
"server": self.identity, "startup_nonce": self.nonce, "selection": selection,
|
|
422
|
+
"manifest_sha256": manifest_sha, "cuda_visible_devices": self.cuda_scope,
|
|
423
|
+
"service_code_hashes": self.service_code_hashes, "lease_owner": lease_owner,
|
|
424
|
+
"strict_cuda": True, "engine_initialized": False, "warmup_requests": 0}
|
|
425
|
+
gate.write_json(self.state_dir / "idle.json", self.idle)
|
|
426
|
+
self.write_state()
|
|
427
|
+
|
|
428
|
+
@staticmethod
|
|
429
|
+
def current_code_hashes():
|
|
430
|
+
return {Path(module.__file__).name: host.file_sha256(module.__file__)
|
|
431
|
+
for module in (sys.modules[__name__], gate, points, host, gpu_lease)}
|
|
432
|
+
|
|
433
|
+
def verify_service_code(self):
|
|
434
|
+
gate.require(self.current_code_hashes() == self.service_code_hashes,
|
|
435
|
+
"reviewed service or shared gate source changed after startup")
|
|
436
|
+
|
|
437
|
+
def write_state(self, error=None):
|
|
438
|
+
gate.write_json(self.state_dir / "state.json", {
|
|
439
|
+
"schema": "omnius.computer-use.photon-service-state.v1", "stage": self.stage,
|
|
440
|
+
"server": self.identity, "startup_nonce": self.nonce,
|
|
441
|
+
"loaded": self.receipt is not None, "strict_cuda": True,
|
|
442
|
+
"engine_initialized": bool(self.adapter and self.adapter.engine_initialized),
|
|
443
|
+
"warmup_requests": getattr(self.adapter, "warmup_requests", 0),
|
|
444
|
+
"warmup_completed": getattr(self.adapter, "warmup_completed", 0),
|
|
445
|
+
**({"error": str(error)[:2000]} if error else {})})
|
|
446
|
+
|
|
447
|
+
def fail(self, error, fatal=False):
|
|
448
|
+
self.stage, self.inference_active = "failed", False
|
|
449
|
+
self.write_state(error)
|
|
450
|
+
if fatal:
|
|
451
|
+
self.terminate(124)
|
|
452
|
+
|
|
453
|
+
def timer(self, seconds, label):
|
|
454
|
+
timer = self.timer_factory(seconds, lambda: self.fail(f"{label} hard deadline exceeded", fatal=True))
|
|
455
|
+
timer.daemon = True
|
|
456
|
+
timer.start()
|
|
457
|
+
return timer
|
|
458
|
+
|
|
459
|
+
def verify_load_marker(self, marker):
|
|
460
|
+
gate.require(marker.get("schema") == "omnius.computer-use.load-authorization.v1",
|
|
461
|
+
"host load authorization required")
|
|
462
|
+
for key in ("server", "startup_nonce", "manifest_sha256", "selection", "cuda_visible_devices", "service_code_hashes"):
|
|
463
|
+
gate.require(marker.get(key) == self.idle[key], f"load authorization mismatch: {key}")
|
|
464
|
+
issued, expires = marker.get("issued_at", 0), marker.get("expires_at", 0)
|
|
465
|
+
gate.require(points.number(issued) and points.number(expires)
|
|
466
|
+
and issued <= self.clock() < expires and 0 < expires - issued <= 120,
|
|
467
|
+
"load authorization is stale")
|
|
468
|
+
gate.require(isinstance(marker.get("preload_statement"), str)
|
|
469
|
+
and 20 <= len(marker["preload_statement"]) <= 2000,
|
|
470
|
+
"record actual process CUDA environment inspection before load")
|
|
471
|
+
|
|
472
|
+
def advance(self):
|
|
473
|
+
if self.stage == "idle" and (self.state_dir / "load-authorization.json").exists():
|
|
474
|
+
with self.mutex:
|
|
475
|
+
watchdog = None
|
|
476
|
+
try:
|
|
477
|
+
self.verify_service_code()
|
|
478
|
+
self.verify_load_marker(host.private_json(self.state_dir / "load-authorization.json"))
|
|
479
|
+
self.stage = "loading_weights"
|
|
480
|
+
self.write_state()
|
|
481
|
+
watchdog = self.timer(STAGE_DEADLINE, "weight loading")
|
|
482
|
+
self.adapter = self.adapter_factory(self.manifest, lambda: self.inference_active)
|
|
483
|
+
self.adapter.assert_resident()
|
|
484
|
+
self.adapter.synchronize()
|
|
485
|
+
self.receipt = {**self.selection, "schema": "omnius.computer-use.resident-runtime.v1",
|
|
486
|
+
"service_mode": "leased-external", "loaded": True,
|
|
487
|
+
"attestation_source": "host-launcher", "server": self.identity,
|
|
488
|
+
"runners": [self.identity], "boot_id": self.boot_id,
|
|
489
|
+
"cuda_visible_devices": self.cuda_scope, "lease_owner": self.lease_owner,
|
|
490
|
+
"manifest_sha256": self.manifest_sha, "strict_cuda": True,
|
|
491
|
+
"resident_stage": "resident_weights", "engine_initialized": False,
|
|
492
|
+
"cuda12_runtime": self.manifest.get("cuda12_runtime"),
|
|
493
|
+
"cuda12_runtime_loaded": False,
|
|
494
|
+
"warmup_performed": False, "service_code_hashes": self.service_code_hashes}
|
|
495
|
+
gate.write_json(self.state_dir / "resident-runtime.json", self.receipt)
|
|
496
|
+
self.stage = "resident_weights"
|
|
497
|
+
self.write_state()
|
|
498
|
+
except Exception as error:
|
|
499
|
+
self.fail(error, fatal=watchdog is not None)
|
|
500
|
+
finally:
|
|
501
|
+
if watchdog: watchdog.cancel()
|
|
502
|
+
return
|
|
503
|
+
if self.stage == "resident_weights" and (self.state_dir / "engine-authorization.json").exists():
|
|
504
|
+
try:
|
|
505
|
+
self.activate_engine()
|
|
506
|
+
except Exception:
|
|
507
|
+
pass # State records the failure; unsafe CUDA failures terminate.
|
|
508
|
+
|
|
509
|
+
def active_approval(self, filename):
|
|
510
|
+
self.verify_service_code()
|
|
511
|
+
approval = host.private_json(self.state_dir / filename)
|
|
512
|
+
preflight = self.preflight(self.receipt)
|
|
513
|
+
gate.verify_approval(approval, preflight, self.clock())
|
|
514
|
+
return preflight
|
|
515
|
+
|
|
516
|
+
def activate_engine(self):
|
|
517
|
+
gate.require(self.mutex.acquire(blocking=False), "another operation is in progress")
|
|
518
|
+
watchdog = None
|
|
519
|
+
try:
|
|
520
|
+
gate.require(self.stage == "resident_weights", "engine requires resident weights and a new host approval")
|
|
521
|
+
self.active_approval("engine-authorization.json")
|
|
522
|
+
self.adapter.assert_resident()
|
|
523
|
+
watchdog = self.timer(STAGE_DEADLINE, "engine activation")
|
|
524
|
+
try:
|
|
525
|
+
self.lease.prepare()
|
|
526
|
+
self.stage, self.inference_active = "initializing_engine", True
|
|
527
|
+
self.write_state()
|
|
528
|
+
self.adapter.initialize_engine()
|
|
529
|
+
self.adapter.assert_resident()
|
|
530
|
+
self.adapter.synchronize()
|
|
531
|
+
self.lease.ready()
|
|
532
|
+
self.receipt = {**self.receipt, "resident_stage": "engine_ready", "engine_initialized": True,
|
|
533
|
+
"cuda12_runtime_loaded": True,
|
|
534
|
+
"cuda12_runtime_maps": sorted(loaded_cuda12_paths()),
|
|
535
|
+
"warmup_performed": True, "warmup_requests": self.adapter.warmup_requests,
|
|
536
|
+
"warmup_completed": self.adapter.warmup_completed,
|
|
537
|
+
"warmup_max_output_tokens": 1, "activation_deadline_seconds": STAGE_DEADLINE}
|
|
538
|
+
gate.write_json(self.state_dir / "resident-runtime.json", self.receipt)
|
|
539
|
+
self.stage = "engine_ready"
|
|
540
|
+
self.write_state()
|
|
541
|
+
except Exception as error:
|
|
542
|
+
self.fail(error, fatal=True)
|
|
543
|
+
raise
|
|
544
|
+
finally:
|
|
545
|
+
self.inference_active = False
|
|
546
|
+
if watchdog: watchdog.cancel()
|
|
547
|
+
self.mutex.release()
|
|
548
|
+
|
|
549
|
+
def infer(self, value):
|
|
550
|
+
request = validate_request(value, self.selection["model"])
|
|
551
|
+
gate.require(self.mutex.acquire(blocking=False), "another operation is in progress")
|
|
552
|
+
watchdog = None
|
|
553
|
+
try:
|
|
554
|
+
gate.require(self.stage == "engine_ready" and self.adapter.engine_initialized,
|
|
555
|
+
"engine initialization and fresh placement approval are required")
|
|
556
|
+
self.active_approval("inference-approval.json")
|
|
557
|
+
self.adapter.assert_resident()
|
|
558
|
+
watchdog = self.timer(POINT_DEADLINE, "point inference")
|
|
559
|
+
try:
|
|
560
|
+
self.lease.prepare()
|
|
561
|
+
self.inference_active = True
|
|
562
|
+
answer = validate_answer(self.adapter.predict(request))
|
|
563
|
+
self.adapter.assert_resident()
|
|
564
|
+
self.adapter.synchronize()
|
|
565
|
+
self.lease.ready()
|
|
566
|
+
return answer
|
|
567
|
+
except Exception as error:
|
|
568
|
+
self.fail(error, fatal=True)
|
|
569
|
+
raise
|
|
570
|
+
finally:
|
|
571
|
+
self.inference_active = False
|
|
572
|
+
if watchdog: watchdog.cancel()
|
|
573
|
+
self.mutex.release()
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
class LocalServer(HTTPServer):
|
|
577
|
+
allow_reuse_address = False
|
|
578
|
+
request_queue_size = 4
|
|
579
|
+
|
|
580
|
+
def service_actions(self):
|
|
581
|
+
self.service.advance()
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
class Handler(BaseHTTPRequestHandler):
|
|
585
|
+
def setup(self):
|
|
586
|
+
super().setup()
|
|
587
|
+
self.connection.settimeout(REQUEST_READ_DEADLINE)
|
|
588
|
+
# Socket inactivity timeouts alone allow a byte-drip request to run forever.
|
|
589
|
+
self.read_watchdog = threading.Timer(
|
|
590
|
+
getattr(self.server, "read_deadline", REQUEST_READ_DEADLINE), self.end_read)
|
|
591
|
+
self.read_watchdog.daemon = True
|
|
592
|
+
self.read_watchdog.start()
|
|
593
|
+
|
|
594
|
+
def end_read(self):
|
|
595
|
+
try:
|
|
596
|
+
self.connection.shutdown(socket.SHUT_RDWR)
|
|
597
|
+
except OSError:
|
|
598
|
+
pass
|
|
599
|
+
|
|
600
|
+
def finish_read(self):
|
|
601
|
+
self.read_watchdog.cancel()
|
|
602
|
+
|
|
603
|
+
def finish(self):
|
|
604
|
+
self.finish_read()
|
|
605
|
+
super().finish()
|
|
606
|
+
|
|
607
|
+
def log_message(self, *_args): pass
|
|
608
|
+
|
|
609
|
+
def reply(self, status, value):
|
|
610
|
+
raw = json.dumps(value, allow_nan=False, separators=(",", ":")).encode()
|
|
611
|
+
self.send_response(status)
|
|
612
|
+
self.send_header("Content-Type", "application/json")
|
|
613
|
+
self.send_header("Content-Length", str(len(raw)))
|
|
614
|
+
self.send_header("Connection", "close")
|
|
615
|
+
self.end_headers()
|
|
616
|
+
self.wfile.write(raw)
|
|
617
|
+
|
|
618
|
+
def do_GET(self):
|
|
619
|
+
self.finish_read()
|
|
620
|
+
if self.path != "/health": return self.reply(404, {"error": "unknown route"})
|
|
621
|
+
self.reply(200, {"stage": self.server.service.stage, "strict_cuda": True, "pid": os.getpid()})
|
|
622
|
+
|
|
623
|
+
def do_POST(self):
|
|
624
|
+
if self.path != "/v1/point": return self.reply(404, {"error": "unknown route"})
|
|
625
|
+
try:
|
|
626
|
+
gate.require(not self.headers.get("Transfer-Encoding"), "chunked requests are unsupported")
|
|
627
|
+
lengths = self.headers.get_all("Content-Length", [])
|
|
628
|
+
gate.require(len(lengths) == 1 and lengths[0].isascii() and lengths[0].isdigit(),
|
|
629
|
+
"one bounded Content-Length is required")
|
|
630
|
+
length = int(lengths[0])
|
|
631
|
+
gate.require(0 < length <= MAX_REQUEST_BYTES, "request body exceeds bound")
|
|
632
|
+
gate.require(self.headers.get_content_type() == "application/json", "JSON content type required")
|
|
633
|
+
raw = self.rfile.read(length)
|
|
634
|
+
gate.require(len(raw) == length, "request body ended early")
|
|
635
|
+
value = gate.strict_json(raw)
|
|
636
|
+
validate_request(value, self.server.service.selection["model"])
|
|
637
|
+
except (gate.GateError, OSError, ValueError) as error:
|
|
638
|
+
return self.reply(400, {"error": str(error)[:1000]})
|
|
639
|
+
finally:
|
|
640
|
+
self.finish_read()
|
|
641
|
+
try:
|
|
642
|
+
self.reply(200, self.server.service.infer(value))
|
|
643
|
+
except Exception as error:
|
|
644
|
+
self.reply(503, {"error": str(error)[:1000], "stage": self.server.service.stage})
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
def authorize_load(state_dir, statement, now=None):
|
|
648
|
+
now = time.time() if now is None else now
|
|
649
|
+
idle = host.private_json(Path(state_dir) / "idle.json")
|
|
650
|
+
gate.require(idle.get("schema") == "omnius.computer-use.photon-idle.v1" and idle.get("loaded") is False,
|
|
651
|
+
"fresh Photon idle process receipt required")
|
|
652
|
+
gate.require(isinstance(statement, str) and 20 <= len(statement) <= 2000,
|
|
653
|
+
"record actual process CUDA visibility before load")
|
|
654
|
+
marker = {**{key: idle[key] for key in ("server", "startup_nonce", "manifest_sha256", "selection", "cuda_visible_devices", "service_code_hashes")},
|
|
655
|
+
"schema": "omnius.computer-use.load-authorization.v1", "issued_at": now,
|
|
656
|
+
"expires_at": now + 120, "preload_statement": statement}
|
|
657
|
+
gate.write_json(Path(state_dir) / "load-authorization.json", marker)
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
def main(argv=None):
|
|
661
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
662
|
+
commands = parser.add_subparsers(dest="command", required=True)
|
|
663
|
+
serve = commands.add_parser("serve")
|
|
664
|
+
for name in ("selection", "manifest", "state-dir"):
|
|
665
|
+
serve.add_argument("--" + name, type=Path, required=True)
|
|
666
|
+
serve.add_argument("--lease-owner", required=True)
|
|
667
|
+
serve.add_argument("--lock", type=Path, default=gate.DEFAULT_LOCK)
|
|
668
|
+
authorize = commands.add_parser("authorize-load")
|
|
669
|
+
authorize.add_argument("--state-dir", type=Path, required=True)
|
|
670
|
+
authorize.add_argument("--statement", required=True)
|
|
671
|
+
prepare = commands.add_parser("prepare-manifest", help="hash local files and metadata without importing CUDA")
|
|
672
|
+
for name in ("weights", "tokenizer", "requirements", "output"):
|
|
673
|
+
prepare.add_argument("--" + name, type=Path, required=True)
|
|
674
|
+
prepare.add_argument("--compatibility-requirements", type=Path, default=CUDA12_REQUIREMENTS)
|
|
675
|
+
args = parser.parse_args(argv)
|
|
676
|
+
try:
|
|
677
|
+
if args.command == "authorize-load":
|
|
678
|
+
authorize_load(args.state_dir, args.statement)
|
|
679
|
+
return 0
|
|
680
|
+
if args.command == "prepare-manifest":
|
|
681
|
+
gate.write_json(args.output, prepare_manifest(args.weights, args.tokenizer, args.requirements,
|
|
682
|
+
args.compatibility_requirements))
|
|
683
|
+
print(json.dumps({"status": "prepared", "manifest": str(args.output),
|
|
684
|
+
"manifest_sha256": host.file_sha256(args.output), "model_loaded": False}))
|
|
685
|
+
return 0
|
|
686
|
+
selection, lock = gate.read_json(args.selection), gate.read_json(args.lock)
|
|
687
|
+
manifest, sha = gate.read_json_hashed(args.manifest)
|
|
688
|
+
service = StagedPointService(selection, lock, manifest, sha, args.state_dir, args.lease_owner)
|
|
689
|
+
endpoint = gate.local_endpoint(selection["endpoint"])
|
|
690
|
+
with LocalServer(("127.0.0.1", endpoint.port), Handler) as server:
|
|
691
|
+
server.service = service
|
|
692
|
+
server.serve_forever(poll_interval=.25)
|
|
693
|
+
return 0
|
|
694
|
+
except (gate.GateError, OSError, ValueError) as error:
|
|
695
|
+
print(json.dumps({"status": "blocked", "error": str(error)}), file=sys.stderr)
|
|
696
|
+
return 2
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
if __name__ == "__main__":
|
|
700
|
+
raise SystemExit(main())
|