hugpy-resources 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hugpy_resources/__init__.py +3 -0
- hugpy_resources/imports/__init__.py +35 -0
- hugpy_resources/imports/classes/__init__.py +24 -0
- hugpy_resources/imports/classes/database.py +49 -0
- hugpy_resources/imports/classes/errors.py +74 -0
- hugpy_resources/imports/classes/http.py +116 -0
- hugpy_resources/imports/classes/nvml.py +32 -0
- hugpy_resources/imports/classes/thinking.py +77 -0
- hugpy_resources/imports/classes/tool_calls.py +53 -0
- hugpy_resources/imports/constants/__init__.py +45 -0
- hugpy_resources/imports/constants/admission.py +19 -0
- hugpy_resources/imports/constants/architecture.py +84 -0
- hugpy_resources/imports/constants/audit.py +6 -0
- hugpy_resources/imports/constants/comfy.py +15 -0
- hugpy_resources/imports/constants/context.py +37 -0
- hugpy_resources/imports/constants/contracts.py +279 -0
- hugpy_resources/imports/constants/cpu.py +19 -0
- hugpy_resources/imports/constants/drives.py +26 -0
- hugpy_resources/imports/constants/engines.py +15 -0
- hugpy_resources/imports/constants/formats.py +114 -0
- hugpy_resources/imports/constants/gguf.py +88 -0
- hugpy_resources/imports/constants/hardware.py +21 -0
- hugpy_resources/imports/constants/identity.py +16 -0
- hugpy_resources/imports/constants/math.py +38 -0
- hugpy_resources/imports/constants/memory.py +31 -0
- hugpy_resources/imports/constants/placement.py +140 -0
- hugpy_resources/imports/constants/platform.py +29 -0
- hugpy_resources/imports/constants/runtime.py +175 -0
- hugpy_resources/imports/constants/tensors.py +53 -0
- hugpy_resources/imports/constants/terms.py +221 -0
- hugpy_resources/imports/constants/text.py +84 -0
- hugpy_resources/imports/constants/timing.py +39 -0
- hugpy_resources/imports/constants/tool_calls.py +22 -0
- hugpy_resources/imports/constants/transfer.py +28 -0
- hugpy_resources/imports/constants/validation.py +52 -0
- hugpy_resources/imports/functions/__init__.py +157 -0
- hugpy_resources/imports/functions/application_paths.py +185 -0
- hugpy_resources/imports/functions/argument_parsing.py +27 -0
- hugpy_resources/imports/functions/ast_utils.py +26 -0
- hugpy_resources/imports/functions/atomic_files.py +25 -0
- hugpy_resources/imports/functions/binary_data.py +39 -0
- hugpy_resources/imports/functions/block_io.py +78 -0
- hugpy_resources/imports/functions/cache.py +92 -0
- hugpy_resources/imports/functions/callables.py +10 -0
- hugpy_resources/imports/functions/coercion.py +22 -0
- hugpy_resources/imports/functions/comfy_metadata.py +101 -0
- hugpy_resources/imports/functions/configuration.py +29 -0
- hugpy_resources/imports/functions/content_proofs.py +57 -0
- hugpy_resources/imports/functions/cpu_activity.py +31 -0
- hugpy_resources/imports/functions/devices.py +10 -0
- hugpy_resources/imports/functions/engine_metadata.py +43 -0
- hugpy_resources/imports/functions/engine_probes.py +217 -0
- hugpy_resources/imports/functions/env_files.py +19 -0
- hugpy_resources/imports/functions/env_values.py +70 -0
- hugpy_resources/imports/functions/environment.py +82 -0
- hugpy_resources/imports/functions/evidence.py +37 -0
- hugpy_resources/imports/functions/executables.py +51 -0
- hugpy_resources/imports/functions/feasibility.py +130 -0
- hugpy_resources/imports/functions/file_transfer.py +94 -0
- hugpy_resources/imports/functions/file_types.py +256 -0
- hugpy_resources/imports/functions/filesystem.py +275 -0
- hugpy_resources/imports/functions/filesystems.py +30 -0
- hugpy_resources/imports/functions/formatting.py +55 -0
- hugpy_resources/imports/functions/geometry.py +217 -0
- hugpy_resources/imports/functions/gguf_cache.py +64 -0
- hugpy_resources/imports/functions/gguf_headers.py +323 -0
- hugpy_resources/imports/functions/gguf_moe.py +356 -0
- hugpy_resources/imports/functions/gguf_structure.py +288 -0
- hugpy_resources/imports/functions/gguf_variants.py +124 -0
- hugpy_resources/imports/functions/hardware_inventory.py +238 -0
- hugpy_resources/imports/functions/hashing.py +38 -0
- hugpy_resources/imports/functions/host_memory.py +121 -0
- hugpy_resources/imports/functions/http_auth.py +36 -0
- hugpy_resources/imports/functions/inference_children.py +108 -0
- hugpy_resources/imports/functions/inference_timings.py +182 -0
- hugpy_resources/imports/functions/integers.py +14 -0
- hugpy_resources/imports/functions/json_http.py +22 -0
- hugpy_resources/imports/functions/json_rows.py +75 -0
- hugpy_resources/imports/functions/json_utils.py +52 -0
- hugpy_resources/imports/functions/kv_cache.py +45 -0
- hugpy_resources/imports/functions/kv_cells.py +22 -0
- hugpy_resources/imports/functions/locking.py +21 -0
- hugpy_resources/imports/functions/memory.py +23 -0
- hugpy_resources/imports/functions/messages.py +38 -0
- hugpy_resources/imports/functions/model_config.py +58 -0
- hugpy_resources/imports/functions/model_files.py +94 -0
- hugpy_resources/imports/functions/nvml.py +192 -0
- hugpy_resources/imports/functions/openai_protocol.py +41 -0
- hugpy_resources/imports/functions/paths.py +245 -0
- hugpy_resources/imports/functions/placement.py +32 -0
- hugpy_resources/imports/functions/ports.py +21 -0
- hugpy_resources/imports/functions/processes.py +132 -0
- hugpy_resources/imports/functions/profile_metadata.py +30 -0
- hugpy_resources/imports/functions/python_environments.py +26 -0
- hugpy_resources/imports/functions/quantization.py +50 -0
- hugpy_resources/imports/functions/recurrent_state.py +33 -0
- hugpy_resources/imports/functions/requirements.py +204 -0
- hugpy_resources/imports/functions/row_history.py +77 -0
- hugpy_resources/imports/functions/row_values.py +29 -0
- hugpy_resources/imports/functions/runtime.py +236 -0
- hugpy_resources/imports/functions/safetensors.py +127 -0
- hugpy_resources/imports/functions/search.py +884 -0
- hugpy_resources/imports/functions/selected_artifacts.py +345 -0
- hugpy_resources/imports/functions/source_fingerprints.py +26 -0
- hugpy_resources/imports/functions/sql_quoting.py +11 -0
- hugpy_resources/imports/functions/sqlite.py +26 -0
- hugpy_resources/imports/functions/sqlite_callbacks.py +75 -0
- hugpy_resources/imports/functions/sqlite_connections.py +89 -0
- hugpy_resources/imports/functions/state.py +41 -0
- hugpy_resources/imports/functions/statistics.py +18 -0
- hugpy_resources/imports/functions/structured_data.py +72 -0
- hugpy_resources/imports/functions/tensor_files.py +193 -0
- hugpy_resources/imports/functions/tensors.py +25 -0
- hugpy_resources/imports/functions/terminal_text.py +82 -0
- hugpy_resources/imports/functions/text.py +104 -0
- hugpy_resources/imports/functions/thinking.py +45 -0
- hugpy_resources/imports/functions/time_utils.py +37 -0
- hugpy_resources/imports/functions/timing.py +415 -0
- hugpy_resources/imports/functions/tool_calls.py +86 -0
- hugpy_resources/imports/functions/tool_deltas.py +25 -0
- hugpy_resources/imports/functions/transformer_facts.py +336 -0
- hugpy_resources/imports/functions/units.py +25 -0
- hugpy_resources/imports/functions/urls.py +23 -0
- hugpy_resources/imports/init_imports.py +80 -0
- hugpy_resources/imports/mime_types.json +263 -0
- hugpy_resources/imports/terms.json +3841 -0
- hugpy_resources/lazy_imports.py +53 -0
- hugpy_resources-0.1.3.dist-info/METADATA +10 -0
- hugpy_resources-0.1.3.dist-info/RECORD +131 -0
- hugpy_resources-0.1.3.dist-info/WHEEL +5 -0
- hugpy_resources-0.1.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Public shared constants, classes and generic utilities.
|
|
2
|
+
|
|
3
|
+
Function/class ownership is declared only in their projections. Constants load
|
|
4
|
+
on first use; optional function implementations load only when requested.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from importlib import import_module as _import_module
|
|
8
|
+
|
|
9
|
+
from . import classes as _classes
|
|
10
|
+
from . import functions as _functions
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def __getattr__(name):
|
|
14
|
+
if name == "__all__":
|
|
15
|
+
constants = _import_module(f"{__name__}.constants")
|
|
16
|
+
value = list(dict.fromkeys([
|
|
17
|
+
*constants.__all__, *_functions.__all__, *_classes.__all__,
|
|
18
|
+
]))
|
|
19
|
+
elif name in _functions.__all__:
|
|
20
|
+
# A loaded child module can have the same name as an exported function
|
|
21
|
+
# (for example environment). Resolve the declared owner explicitly.
|
|
22
|
+
value = _functions.__getattr__(name)
|
|
23
|
+
elif name in _classes.__all__:
|
|
24
|
+
value = _classes.__getattr__(name)
|
|
25
|
+
else:
|
|
26
|
+
constants = _import_module(f"{__name__}.constants")
|
|
27
|
+
if name not in constants.__all__:
|
|
28
|
+
raise AttributeError(f"{__name__!r} has no attribute {name!r}") from None
|
|
29
|
+
value = getattr(constants, name)
|
|
30
|
+
globals()[name] = value
|
|
31
|
+
return value
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def __dir__():
|
|
35
|
+
return sorted(set(globals()) | set(__getattr__("__all__")))
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Canonical reusable errors, records, protocol parsers and HTTP scaffold."""
|
|
2
|
+
|
|
3
|
+
from hugpy_resources.lazy_imports import import_registry, resolve_import
|
|
4
|
+
|
|
5
|
+
from ..init_imports import import_module
|
|
6
|
+
|
|
7
|
+
_EXPORTS = import_registry({
|
|
8
|
+
'.errors': (
|
|
9
|
+
'GGUFHeaderError PathEscape LocalRequestError ChatRequestError TaskRequestError '
|
|
10
|
+
'StoreError'
|
|
11
|
+
),
|
|
12
|
+
'.database': 'Row Cursor',
|
|
13
|
+
'.nvml': '_MemV2 _Mem _ProcV3',
|
|
14
|
+
'.thinking': 'ThinkSplitter',
|
|
15
|
+
'.tool_calls': 'StreamSplitter',
|
|
16
|
+
'.http': 'make_child_handler',
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def __getattr__(name):
|
|
21
|
+
return resolve_import(globals(), _EXPORTS, name)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
__all__ = list(_EXPORTS)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Reusable database definitions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Row:
|
|
7
|
+
"""sqlite3.Row compatible access, including duplicate projection names."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, names, values):
|
|
10
|
+
self._names, self._values = tuple(names), tuple(values)
|
|
11
|
+
|
|
12
|
+
def __getitem__(self, key):
|
|
13
|
+
if isinstance(key, (int, slice)):
|
|
14
|
+
return self._values[key]
|
|
15
|
+
try:
|
|
16
|
+
return self._values[self._names.index(key)]
|
|
17
|
+
except ValueError:
|
|
18
|
+
raise KeyError(key) from None
|
|
19
|
+
|
|
20
|
+
def __iter__(self):
|
|
21
|
+
return iter(self._values)
|
|
22
|
+
|
|
23
|
+
def __len__(self):
|
|
24
|
+
return len(self._values)
|
|
25
|
+
|
|
26
|
+
def keys(self):
|
|
27
|
+
return self._names
|
|
28
|
+
|
|
29
|
+
def get(self, key, default=None):
|
|
30
|
+
try:
|
|
31
|
+
return self[key]
|
|
32
|
+
except KeyError:
|
|
33
|
+
return default
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Cursor:
|
|
37
|
+
def __init__(self, rows, rowcount=0, lastrowid=None, columns=(), values=()):
|
|
38
|
+
self.rows = iter(
|
|
39
|
+
[Row(columns, row) for row in values]
|
|
40
|
+
if columns
|
|
41
|
+
else [Row(row.keys(), row.values()) for row in rows]
|
|
42
|
+
)
|
|
43
|
+
self.rowcount, self.lastrowid = rowcount, lastrowid
|
|
44
|
+
|
|
45
|
+
def fetchone(self):
|
|
46
|
+
return next(self.rows, None)
|
|
47
|
+
|
|
48
|
+
def fetchall(self):
|
|
49
|
+
return list(self.rows)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Reusable parsing errors."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class GGUFHeaderError(ValueError):
|
|
5
|
+
"""The GGUF header is unreadable (magic, version, extent or EOF)."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
__all__ = ["GGUFHeaderError"]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PathEscape(ValueError):
|
|
12
|
+
"""A path resolved outside the confinement root."""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
__all__ += ["PathEscape"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class LocalRequestError(Exception):
|
|
19
|
+
"""Fallback request error so a runner / child module is importable and
|
|
20
|
+
py_compile-clean on its own (e.g. a unit test imports ``handle`` directly).
|
|
21
|
+
|
|
22
|
+
The child process INJECTS its own ``RequestError`` class into the runner's
|
|
23
|
+
namespace before serving; that class carries the same ``(status, message)``
|
|
24
|
+
and a ``.body`` dict, so ``raise RequestError(400, …)`` stays catchable.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, status: int, message: str, **extra):
|
|
28
|
+
super().__init__(message)
|
|
29
|
+
self.status = int(status)
|
|
30
|
+
self.message = message
|
|
31
|
+
self.extra = extra
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def body(self) -> dict:
|
|
35
|
+
err = {
|
|
36
|
+
"message": self.message,
|
|
37
|
+
"type": "invalid_request_error",
|
|
38
|
+
"code": self.status,
|
|
39
|
+
}
|
|
40
|
+
err.update(self.extra)
|
|
41
|
+
return {"error": err}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ChatRequestError(Exception):
|
|
45
|
+
"""An OpenAI-style client error: HTTP ``status`` + error body."""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self, status: int, message: str, etype: str = "invalid_request_error", **extra
|
|
49
|
+
):
|
|
50
|
+
super().__init__(message)
|
|
51
|
+
self.status = status
|
|
52
|
+
self.body = {
|
|
53
|
+
"error": {"code": status, "type": etype, "message": message, **extra}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class TaskRequestError(Exception):
|
|
58
|
+
"""An OpenAI-style client error: HTTP ``status`` + error body. INJECTED into
|
|
59
|
+
the runner module's namespace before use, so a runner raises
|
|
60
|
+
``RequestError(400, …)`` and it is caught here as a 4xx (never a 500)."""
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self, status: int, message: str, etype: str = "invalid_request_error", **extra
|
|
64
|
+
):
|
|
65
|
+
super().__init__(message)
|
|
66
|
+
self.status = int(status)
|
|
67
|
+
self.message = message
|
|
68
|
+
self.body = {
|
|
69
|
+
"error": {"code": int(status), "type": etype, "message": message, **extra}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class StoreError(RuntimeError):
|
|
74
|
+
"""The store could not be opened or migrated."""
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""HTTP scaffold for engine children."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from ..init_imports import json
|
|
5
|
+
from ..init_imports import traceback
|
|
6
|
+
from ..init_imports import BaseHTTPRequestHandler
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _not_found(path: str) -> dict:
|
|
10
|
+
return {
|
|
11
|
+
"error": {"code": 404, "type": "not_found_error", "message": f"no route {path}"}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def make_child_handler(server, request_error_cls, *, chat: bool = True, log=None):
|
|
16
|
+
"""Build the ``BaseHTTPRequestHandler`` subclass the child model servers use.
|
|
17
|
+
|
|
18
|
+
Shared across tf_child / vision_child / task_child: ``log_message`` (silent —
|
|
19
|
+
stderr is the loader-log channel), ``_json``, and the GET routes
|
|
20
|
+
(``/health``, ``/v1/models``, ``/props``). With ``chat=True`` (tf/vision) the
|
|
21
|
+
POST route is ``/v1/chat/completions``, errors fall back to a 500 (logged via
|
|
22
|
+
``log`` if given), and the subclass supplies ``_stream``; with ``chat=False``
|
|
23
|
+
(task) the subclass supplies its own ``do_POST``.
|
|
24
|
+
|
|
25
|
+
``server`` must expose ``models_doc()``/``props_doc()`` and, for chat,
|
|
26
|
+
``lock``/``prepare(body)``/``complete(job)``. ``request_error_cls`` is the
|
|
27
|
+
child's injected ``RequestError``; ``log`` is the child's ``_log``.
|
|
28
|
+
"""
|
|
29
|
+
RequestError = request_error_cls
|
|
30
|
+
|
|
31
|
+
class _Handler(BaseHTTPRequestHandler):
|
|
32
|
+
protocol_version = "HTTP/1.0"
|
|
33
|
+
|
|
34
|
+
def log_message(self, fmt, *args): # keep the loader log for errors only
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
def _json(self, status: int, doc: dict) -> None:
|
|
38
|
+
data = json.dumps(doc).encode()
|
|
39
|
+
self.send_response(status)
|
|
40
|
+
self.send_header("Content-Type", "application/json")
|
|
41
|
+
self.send_header("Content-Length", str(len(data)))
|
|
42
|
+
self.end_headers()
|
|
43
|
+
self.wfile.write(data)
|
|
44
|
+
|
|
45
|
+
def do_GET(self):
|
|
46
|
+
path = self.path.split("?", 1)[0]
|
|
47
|
+
if path == "/health":
|
|
48
|
+
return self._json(200, {"status": "ok"})
|
|
49
|
+
if path == "/v1/models":
|
|
50
|
+
return self._json(200, server.models_doc())
|
|
51
|
+
if path == "/props":
|
|
52
|
+
return self._json(200, server.props_doc())
|
|
53
|
+
return self._json(404, _not_found(path))
|
|
54
|
+
|
|
55
|
+
if chat:
|
|
56
|
+
|
|
57
|
+
def do_POST(self):
|
|
58
|
+
path = self.path.split("?", 1)[0]
|
|
59
|
+
if path not in ("/v1/chat/completions", "/tokenize"):
|
|
60
|
+
return self._json(404, _not_found(path))
|
|
61
|
+
try:
|
|
62
|
+
n = int(self.headers.get("Content-Length") or 0)
|
|
63
|
+
body = json.loads(self.rfile.read(n) or b"{}")
|
|
64
|
+
if not isinstance(body, dict):
|
|
65
|
+
raise RequestError(400, "request body must be a JSON object")
|
|
66
|
+
except (ValueError, RequestError) as exc:
|
|
67
|
+
err = (
|
|
68
|
+
exc
|
|
69
|
+
if isinstance(exc, RequestError)
|
|
70
|
+
else RequestError(400, f"bad JSON: {exc}")
|
|
71
|
+
)
|
|
72
|
+
return self._json(err.status, err.body)
|
|
73
|
+
if path == "/tokenize":
|
|
74
|
+
tokenize = getattr(server, "tokenize_doc", None)
|
|
75
|
+
if tokenize is None:
|
|
76
|
+
return self._json(404, _not_found(path))
|
|
77
|
+
if not server.lock.acquire(blocking=False):
|
|
78
|
+
return self._json(
|
|
79
|
+
409,
|
|
80
|
+
{
|
|
81
|
+
"error": {
|
|
82
|
+
"message": "Tokenizer preflight deferred while the engine is busy"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
)
|
|
86
|
+
try:
|
|
87
|
+
return self._json(200, tokenize(body))
|
|
88
|
+
except RequestError as exc:
|
|
89
|
+
return self._json(exc.status, exc.body)
|
|
90
|
+
except Exception as exc:
|
|
91
|
+
return self._json(400, {"error": {"message": str(exc)}})
|
|
92
|
+
finally:
|
|
93
|
+
server.lock.release()
|
|
94
|
+
with server.lock:
|
|
95
|
+
try:
|
|
96
|
+
job = server.prepare(body)
|
|
97
|
+
if not body.get("stream"):
|
|
98
|
+
return self._json(200, server.complete(job))
|
|
99
|
+
return self._stream(job)
|
|
100
|
+
except RequestError as exc:
|
|
101
|
+
return self._json(exc.status, exc.body)
|
|
102
|
+
except Exception as exc: # noqa: BLE001 — the real error, to the caller and the log
|
|
103
|
+
if log:
|
|
104
|
+
log(traceback.format_exc())
|
|
105
|
+
return self._json(
|
|
106
|
+
500,
|
|
107
|
+
{
|
|
108
|
+
"error": {
|
|
109
|
+
"code": 500,
|
|
110
|
+
"type": "server_error",
|
|
111
|
+
"message": f"{type(exc).__name__}: {exc}",
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
return _Handler
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Reusable nvml definitions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ..init_imports import ctypes
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class _MemV2(ctypes.Structure):
|
|
9
|
+
_fields_ = [
|
|
10
|
+
("version", ctypes.c_uint),
|
|
11
|
+
("total", ctypes.c_ulonglong),
|
|
12
|
+
("reserved", ctypes.c_ulonglong),
|
|
13
|
+
("free", ctypes.c_ulonglong),
|
|
14
|
+
("used", ctypes.c_ulonglong),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class _Mem(ctypes.Structure):
|
|
19
|
+
_fields_ = [
|
|
20
|
+
("total", ctypes.c_ulonglong),
|
|
21
|
+
("free", ctypes.c_ulonglong),
|
|
22
|
+
("used", ctypes.c_ulonglong),
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class _ProcV3(ctypes.Structure):
|
|
27
|
+
_fields_ = [
|
|
28
|
+
("pid", ctypes.c_uint),
|
|
29
|
+
("usedGpuMemory", ctypes.c_ulonglong),
|
|
30
|
+
("gpuInstanceId", ctypes.c_uint),
|
|
31
|
+
("computeInstanceId", ctypes.c_uint),
|
|
32
|
+
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Streaming sibling of no_think.strip_think: separate a model's <think> reasoning
|
|
2
|
+
# from its answer prose INCREMENTALLY, as content deltas arrive, so the front
|
|
3
|
+
# door can re-emit delta.reasoning_content vs delta.content live. The engine
|
|
4
|
+
# (llama-server --reasoning-format deepseek) usually separates reasoning itself;
|
|
5
|
+
# this is the fallback for inline-tag replies (reasoning-format none / a model
|
|
6
|
+
# whose template leaves <think> tags in message.content).
|
|
7
|
+
#
|
|
8
|
+
# Final-assembly semantics match no_think.strip_think (<think>...</think> blocks
|
|
9
|
+
# and an unclosed <think>...EOF are reasoning). An ORPHAN </think> (a template
|
|
10
|
+
# that opens <think> in the prompt, so the reply starts mid-reasoning with no
|
|
11
|
+
# opening tag) is handled downstream by hugpy_core.grader.strip_think on the
|
|
12
|
+
# assembled text; live, text before an orphan close streams as content and the
|
|
13
|
+
# answer after it streams as content too — the grader's rule salvages the answer.
|
|
14
|
+
"""Incremental <think> splitter for streamed content."""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from ..constants import THINK_CLOSE_TAG as _CLOSE
|
|
19
|
+
from ..constants import THINK_OPEN_TAG as _OPEN
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
from ..functions.thinking import _partial_tail
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ThinkSplitter:
|
|
26
|
+
"""Feed streamed content text; get back (channel, chunk) pairs where channel
|
|
27
|
+
is 'reasoning' (inside a <think> block) or 'content' (the answer). Holds back
|
|
28
|
+
a short tail when the buffer might end mid-tag, so a tag split across two
|
|
29
|
+
feeds is still recognised."""
|
|
30
|
+
|
|
31
|
+
def __init__(self) -> None:
|
|
32
|
+
self._buf = ""
|
|
33
|
+
self._mode = "content" # 'content' | 'reasoning'
|
|
34
|
+
|
|
35
|
+
def feed(self, text: str) -> "list[tuple[str, str]]":
|
|
36
|
+
out: "list[tuple[str, str]]" = []
|
|
37
|
+
if not text:
|
|
38
|
+
return out
|
|
39
|
+
self._buf += text
|
|
40
|
+
while True:
|
|
41
|
+
low = self._buf.lower()
|
|
42
|
+
i_open = low.find(_OPEN)
|
|
43
|
+
i_close = low.find(_CLOSE)
|
|
44
|
+
cands = [p for p in (i_open, i_close) if p != -1]
|
|
45
|
+
if cands:
|
|
46
|
+
idx = min(cands)
|
|
47
|
+
is_open = idx == i_open
|
|
48
|
+
tag = _OPEN if is_open else _CLOSE
|
|
49
|
+
before = self._buf[:idx]
|
|
50
|
+
if before:
|
|
51
|
+
out.append((self._mode, before))
|
|
52
|
+
self._buf = self._buf[idx + len(tag) :]
|
|
53
|
+
self._mode = "reasoning" if is_open else "content"
|
|
54
|
+
continue
|
|
55
|
+
hold = _partial_tail(self._buf)
|
|
56
|
+
if hold:
|
|
57
|
+
emit = self._buf[: len(self._buf) - hold]
|
|
58
|
+
if emit:
|
|
59
|
+
out.append((self._mode, emit))
|
|
60
|
+
self._buf = self._buf[len(self._buf) - hold :]
|
|
61
|
+
else:
|
|
62
|
+
if self._buf:
|
|
63
|
+
out.append((self._mode, self._buf))
|
|
64
|
+
self._buf = ""
|
|
65
|
+
break
|
|
66
|
+
return out
|
|
67
|
+
|
|
68
|
+
def close(self) -> "list[tuple[str, str]]":
|
|
69
|
+
"""Flush whatever is held (a dangling partial tag, treated as text)."""
|
|
70
|
+
out: "list[tuple[str, str]]" = []
|
|
71
|
+
if self._buf:
|
|
72
|
+
out.append((self._mode, self._buf))
|
|
73
|
+
self._buf = ""
|
|
74
|
+
return out
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
__all__ = ["ThinkSplitter"]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Reusable tool calls definitions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ..functions.tool_calls import _calls
|
|
6
|
+
from ..constants import _BLOCK
|
|
7
|
+
from ..constants import DSML_TOOLS_TAGS as _TAGS
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class StreamSplitter:
|
|
11
|
+
"""Streamed reply: feed() content pieces; yields ("content", text) for prose and
|
|
12
|
+
("tool_calls", [call, ...]) once a whole block has arrived. Text that may be the
|
|
13
|
+
start of a block is held back until it is known not to be one."""
|
|
14
|
+
|
|
15
|
+
def __init__(self):
|
|
16
|
+
self.buf = ""
|
|
17
|
+
self.emitted = 0 # tool calls sent so far (their stream index)
|
|
18
|
+
|
|
19
|
+
def _hold_from(self) -> int:
|
|
20
|
+
"""Index from which the buffer must be held (a block, or a possible tag start)."""
|
|
21
|
+
starts = [i for tag in _TAGS if (i := self.buf.find(tag)) >= 0]
|
|
22
|
+
if starts:
|
|
23
|
+
return min(starts)
|
|
24
|
+
for k in range(min(max(map(len, _TAGS)) - 1, len(self.buf)), 0, -1):
|
|
25
|
+
if any(tag.startswith(self.buf[-k:]) for tag in _TAGS):
|
|
26
|
+
return len(self.buf) - k
|
|
27
|
+
return len(self.buf)
|
|
28
|
+
|
|
29
|
+
def feed(self, piece: str):
|
|
30
|
+
self.buf += piece or ""
|
|
31
|
+
out = []
|
|
32
|
+
while True:
|
|
33
|
+
m = _BLOCK.search(self.buf)
|
|
34
|
+
if m:
|
|
35
|
+
if m.start():
|
|
36
|
+
out.append(("content", self.buf[: m.start()]))
|
|
37
|
+
calls = _calls(m.group(2))
|
|
38
|
+
if calls:
|
|
39
|
+
out.append(("tool_calls", calls))
|
|
40
|
+
else:
|
|
41
|
+
out.append(("content", m.group(0)))
|
|
42
|
+
self.buf = self.buf[m.end() :]
|
|
43
|
+
continue
|
|
44
|
+
cut = self._hold_from()
|
|
45
|
+
if cut:
|
|
46
|
+
out.append(("content", self.buf[:cut]))
|
|
47
|
+
self.buf = self.buf[cut:]
|
|
48
|
+
return out
|
|
49
|
+
|
|
50
|
+
def close(self):
|
|
51
|
+
"""End of stream: an unfinished block is passed through as text (never lost)."""
|
|
52
|
+
rest, self.buf = self.buf, ""
|
|
53
|
+
return [("content", rest)] if rest else []
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Typed constants projected from terms, exported once by each domain.
|
|
2
|
+
|
|
3
|
+
Domains load together when this projection is first requested. Public exports
|
|
4
|
+
come from their __all__ declarations; no second list of symbols is maintained.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from importlib import import_module as _import_module
|
|
8
|
+
|
|
9
|
+
_DOMAINS = (
|
|
10
|
+
'math',
|
|
11
|
+
'terms',
|
|
12
|
+
'platform',
|
|
13
|
+
'formats',
|
|
14
|
+
'gguf',
|
|
15
|
+
'tensors',
|
|
16
|
+
'architecture',
|
|
17
|
+
'memory',
|
|
18
|
+
'hardware',
|
|
19
|
+
'engines',
|
|
20
|
+
'text',
|
|
21
|
+
'tool_calls',
|
|
22
|
+
'identity',
|
|
23
|
+
'transfer',
|
|
24
|
+
'comfy',
|
|
25
|
+
'placement',
|
|
26
|
+
'cpu',
|
|
27
|
+
'context',
|
|
28
|
+
'admission',
|
|
29
|
+
'validation',
|
|
30
|
+
'drives',
|
|
31
|
+
'timing',
|
|
32
|
+
'audit',
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
__all__ = []
|
|
36
|
+
for _domain_name in _DOMAINS:
|
|
37
|
+
_domain = _import_module(f"{__name__}.{_domain_name}")
|
|
38
|
+
globals()[_domain_name] = _domain
|
|
39
|
+
for _name in _domain.__all__:
|
|
40
|
+
if _name in __all__:
|
|
41
|
+
raise ValueError(f"duplicate constant export: {_name}")
|
|
42
|
+
globals()[_name] = getattr(_domain, _name)
|
|
43
|
+
__all__.append(_name)
|
|
44
|
+
|
|
45
|
+
del _domain_name, _domain, _name
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Admission projections of terms.json; authored values belong to terms."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .terms import value as _value, group as _group
|
|
6
|
+
|
|
7
|
+
from .terms import knob_schema
|
|
8
|
+
|
|
9
|
+
RESIDENCY_MODES = _value('admission', 'residency_modes')
|
|
10
|
+
|
|
11
|
+
ADMISSION_KNOB_TERMS = _group('admission_knobs')
|
|
12
|
+
|
|
13
|
+
ADMISSION_KNOB_SCHEMA = knob_schema(ADMISSION_KNOB_TERMS)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
'RESIDENCY_MODES',
|
|
17
|
+
'ADMISSION_KNOB_TERMS',
|
|
18
|
+
'ADMISSION_KNOB_SCHEMA',
|
|
19
|
+
]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Architecture projections of terms.json; authored values belong to terms."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .terms import value as _value, group as _group
|
|
6
|
+
|
|
7
|
+
TRANSFORMERS_GATED_DELTA = _value('architecture', 'transformers_gated_delta')
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
NO_CONTEXT_HEADS = _value('architecture', 'no_context_heads')
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
DENSE_DECODERS = _value('architecture', 'dense_decoders')
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
MOE_DECODERS = _value('architecture', 'moe_decoders')
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
DTYPE_BITS = {key: term["bits"] for key, term in _group("tensor_dtypes").items()}
|
|
20
|
+
|
|
21
|
+
RECURRENT_COUNT_FIELDS = _value('architecture', 'recurrent_count_fields')
|
|
22
|
+
|
|
23
|
+
TEXT_CONFIG_KEYS = _value('architecture', 'text_config_keys')
|
|
24
|
+
|
|
25
|
+
DECODER_LAYER_KEYS = _value('architecture', 'decoder_layer_keys')
|
|
26
|
+
|
|
27
|
+
MODEL_LAYER_KEYS = _value('architecture', 'model_layer_keys')
|
|
28
|
+
|
|
29
|
+
DECODER_ATTENTION_HEAD_KEYS = _value('architecture', 'decoder_attention_head_keys')
|
|
30
|
+
|
|
31
|
+
ATTENTION_HEAD_KEYS = _value('architecture', 'attention_head_keys')
|
|
32
|
+
|
|
33
|
+
KV_HEAD_KEYS = _value('architecture', 'kv_head_keys')
|
|
34
|
+
|
|
35
|
+
HEAD_DIM_KEYS = _value('architecture', 'head_dim_keys')
|
|
36
|
+
|
|
37
|
+
HIDDEN_SIZE_KEYS = _value('architecture', 'hidden_size_keys')
|
|
38
|
+
|
|
39
|
+
ATTENTION_LAYER_TYPES = _value('architecture', 'attention_layer_types')
|
|
40
|
+
|
|
41
|
+
RECURRENT_LAYER_TYPES = _value('architecture', 'recurrent_layer_types')
|
|
42
|
+
|
|
43
|
+
RECURRENT_MODEL_TYPES = _value('architecture', 'recurrent_model_types')
|
|
44
|
+
|
|
45
|
+
CONTEXT_LENGTH_KEYS = _value('architecture', 'context_length_keys')
|
|
46
|
+
|
|
47
|
+
LINEAR_STATE_KEYS = _value('architecture', 'linear_state_keys')
|
|
48
|
+
|
|
49
|
+
UNSUPPORTED_OUTPUT_FLAGS = _value('architecture', 'unsupported_output_flags')
|
|
50
|
+
|
|
51
|
+
EXPERT_COUNT_KEYS = _value('architecture', 'expert_count_keys')
|
|
52
|
+
|
|
53
|
+
RUNTIME_DENSE_GEOMETRY_FIELDS = _value('architecture', 'runtime_dense_geometry_fields')
|
|
54
|
+
|
|
55
|
+
RUNTIME_EXPERT_GEOMETRY_FIELDS = _value('architecture', 'runtime_expert_geometry_fields')
|
|
56
|
+
|
|
57
|
+
RUNTIME_DENSE_DTYPES = _value('architecture', 'runtime_dense_dtypes')
|
|
58
|
+
|
|
59
|
+
__all__ = [
|
|
60
|
+
'TRANSFORMERS_GATED_DELTA',
|
|
61
|
+
'NO_CONTEXT_HEADS',
|
|
62
|
+
'DENSE_DECODERS',
|
|
63
|
+
'MOE_DECODERS',
|
|
64
|
+
'DTYPE_BITS',
|
|
65
|
+
'RECURRENT_COUNT_FIELDS',
|
|
66
|
+
'TEXT_CONFIG_KEYS',
|
|
67
|
+
'DECODER_LAYER_KEYS',
|
|
68
|
+
'MODEL_LAYER_KEYS',
|
|
69
|
+
'DECODER_ATTENTION_HEAD_KEYS',
|
|
70
|
+
'ATTENTION_HEAD_KEYS',
|
|
71
|
+
'KV_HEAD_KEYS',
|
|
72
|
+
'HEAD_DIM_KEYS',
|
|
73
|
+
'HIDDEN_SIZE_KEYS',
|
|
74
|
+
'ATTENTION_LAYER_TYPES',
|
|
75
|
+
'RECURRENT_LAYER_TYPES',
|
|
76
|
+
'RECURRENT_MODEL_TYPES',
|
|
77
|
+
'CONTEXT_LENGTH_KEYS',
|
|
78
|
+
'LINEAR_STATE_KEYS',
|
|
79
|
+
'UNSUPPORTED_OUTPUT_FLAGS',
|
|
80
|
+
'EXPERT_COUNT_KEYS',
|
|
81
|
+
'RUNTIME_DENSE_GEOMETRY_FIELDS',
|
|
82
|
+
'RUNTIME_EXPERT_GEOMETRY_FIELDS',
|
|
83
|
+
'RUNTIME_DENSE_DTYPES',
|
|
84
|
+
]
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"""Audit and row-history projections of terms.json."""
|
|
2
|
+
from .terms import value as _value
|
|
3
|
+
HISTORY_TABLE = _value('audit', 'history_table')
|
|
4
|
+
VOLATILE_COLUMNS = _value('audit', 'history_volatile_columns')
|
|
5
|
+
HISTORY_CHUNK = _value('audit', 'history_chunk')
|
|
6
|
+
__all__ = ['HISTORY_TABLE', 'VOLATILE_COLUMNS', 'HISTORY_CHUNK']
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Comfy projections of terms.json; authored values belong to terms."""
|
|
2
|
+
|
|
3
|
+
from .terms import value as _value
|
|
4
|
+
|
|
5
|
+
COMFY_REFERENCE_FAMILIES = _value('comfy', 'comfy_reference_families')
|
|
6
|
+
|
|
7
|
+
COMFY_REFERENCE_FIELDS = _value('comfy', 'comfy_reference_fields')
|
|
8
|
+
|
|
9
|
+
COMFY_REFERENCE_FILE_FIELDS = _value('comfy', 'comfy_reference_file_fields')
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
'COMFY_REFERENCE_FAMILIES',
|
|
13
|
+
'COMFY_REFERENCE_FIELDS',
|
|
14
|
+
'COMFY_REFERENCE_FILE_FIELDS',
|
|
15
|
+
]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Context projections of terms.json; authored values belong to terms."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .terms import value as _value, group as _group
|
|
6
|
+
|
|
7
|
+
from .terms import knob_schema
|
|
8
|
+
|
|
9
|
+
CONTEXT_PERCENT_KNOBS = _value('context', 'context_percent_knobs')
|
|
10
|
+
|
|
11
|
+
KV_CACHE_TYPES = _value('context', 'kv_cache_types')
|
|
12
|
+
|
|
13
|
+
CONTEXT_PRESETS = _value('context', 'context_presets')
|
|
14
|
+
|
|
15
|
+
CONTEXT_PERCENT_MIN = _value('context', 'context_percent_min')
|
|
16
|
+
|
|
17
|
+
PAIR_KNOB_RENAMES = _value('context', 'pair_knob_renames')
|
|
18
|
+
|
|
19
|
+
CONTEXT_KNOB_TERMS = _group('context_knobs')
|
|
20
|
+
|
|
21
|
+
CONTEXT_KNOB_SCHEMA = knob_schema(CONTEXT_KNOB_TERMS)
|
|
22
|
+
|
|
23
|
+
# Derived from the schema so they can never drift from the context knobs themselves.
|
|
24
|
+
CONTEXT_KEYS = tuple(knob["key"] for knob in CONTEXT_KNOB_SCHEMA)
|
|
25
|
+
CONTEXT_BOOLEAN_KNOBS = tuple(knob["key"] for knob in CONTEXT_KNOB_SCHEMA if knob["type"] == "bool")
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
'CONTEXT_PERCENT_KNOBS',
|
|
29
|
+
'KV_CACHE_TYPES',
|
|
30
|
+
'CONTEXT_PRESETS',
|
|
31
|
+
'CONTEXT_PERCENT_MIN',
|
|
32
|
+
'PAIR_KNOB_RENAMES',
|
|
33
|
+
'CONTEXT_KNOB_TERMS',
|
|
34
|
+
'CONTEXT_KNOB_SCHEMA',
|
|
35
|
+
'CONTEXT_KEYS',
|
|
36
|
+
'CONTEXT_BOOLEAN_KNOBS',
|
|
37
|
+
]
|