singularity-grid 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/PKG-INFO +1 -1
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/pyproject.toml +1 -1
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/singularity_grid/client.py +36 -5
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/.github/workflows/publish.yml +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/.gitignore +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/LICENSE +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/README.md +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/examples/check_capacity.py +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/examples/openai_compatible.py +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/examples/quickstart.py +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/singularity_grid/__init__.py +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/singularity_grid/e2e.py +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/singularity_grid/models.py +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/singularity_grid/openai_compat.py +0 -0
- {singularity_grid-0.3.0 → singularity_grid-0.4.0}/singularity_grid/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: singularity-grid
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Python SDK for the SGL Network confidential compute grid (end-to-end encrypted + streaming)
|
|
5
5
|
Project-URL: Homepage, https://singularitylayer.xyz
|
|
6
6
|
Project-URL: Repository, https://github.com/SingularityLayer/sgl-network-sdk
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "singularity-grid"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "Python SDK for the SGL Network confidential compute grid (end-to-end encrypted + streaming)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -211,9 +211,25 @@ class GridClient:
|
|
|
211
211
|
|
|
212
212
|
# -- chat (end-to-end encrypted) ---------------------------------------
|
|
213
213
|
|
|
214
|
-
def
|
|
215
|
-
"""
|
|
216
|
-
|
|
214
|
+
def providers(self, model: str, cluster: Optional[str] = None) -> List[Dict[str, Any]]:
|
|
215
|
+
"""List nodes serving ``model`` with their effective price + reputation,
|
|
216
|
+
cheapest first — pick one and pass its ``node_id`` to ``chat_completions(node=...)``."""
|
|
217
|
+
q = f"/v1/providers?model={model}" + (f"&cluster={cluster}" if cluster else "")
|
|
218
|
+
data = self._request("GET", q)
|
|
219
|
+
return data.get("providers", [])
|
|
220
|
+
|
|
221
|
+
def _reserve(self, model: str, cluster: Optional[str] = None, node: Optional[str] = None) -> Dict[str, Any]:
|
|
222
|
+
"""Reserve a node + learn its X25519 key so we can seal the prompt to it.
|
|
223
|
+
|
|
224
|
+
When ``cluster`` is given, a node *inside that cluster* (a Tokenised Compute
|
|
225
|
+
Market) is reserved. When ``node`` is given, that specific provider is reserved.
|
|
226
|
+
"""
|
|
227
|
+
payload: Dict[str, Any] = {"model": model}
|
|
228
|
+
if cluster is not None:
|
|
229
|
+
payload["cluster"] = cluster
|
|
230
|
+
if node is not None:
|
|
231
|
+
payload["node"] = node
|
|
232
|
+
data = self._request("POST", "/v1/reserve", json=payload)
|
|
217
233
|
if not data.get("node_x25519_pubkey"):
|
|
218
234
|
raise SGLAPIError(503, "Reserved node does not support E2E encryption")
|
|
219
235
|
return data
|
|
@@ -225,6 +241,9 @@ class GridClient:
|
|
|
225
241
|
*,
|
|
226
242
|
temperature: float = 0.7,
|
|
227
243
|
max_tokens: int = 512,
|
|
244
|
+
cluster: Optional[str] = None,
|
|
245
|
+
node: Optional[str] = None,
|
|
246
|
+
pay_in_coin: bool = False,
|
|
228
247
|
) -> Dict[str, Any]:
|
|
229
248
|
"""End-to-end encrypted chat completion.
|
|
230
249
|
|
|
@@ -232,14 +251,24 @@ class GridClient:
|
|
|
232
251
|
decrypts inside its TEE — the orchestrator only relays ciphertext. Requires
|
|
233
252
|
``api_key`` (credits); x402 pay-per-call isn't signed here (use the wallet
|
|
234
253
|
flow). Returns an OpenAI-style dict with an extra ``attestation`` field.
|
|
254
|
+
|
|
255
|
+
Parameters
|
|
256
|
+
----------
|
|
257
|
+
cluster:
|
|
258
|
+
Optional cluster slug — route to a node inside that Tokenised Compute
|
|
259
|
+
Market (only nodes that joined the cluster serve it).
|
|
260
|
+
pay_in_coin:
|
|
261
|
+
When ``True`` and the cluster has a tradeable coin, pay for the request
|
|
262
|
+
in that coin (the believer lane) instead of USDC/credits. Falls back to
|
|
263
|
+
USDC if the coin's oracle price is untrusted.
|
|
235
264
|
"""
|
|
236
|
-
reservation = self._reserve(model)
|
|
265
|
+
reservation = self._reserve(model, cluster=cluster, node=node)
|
|
237
266
|
resp_sk, resp_pub = e2e.new_response_keypair()
|
|
238
267
|
sealed_ct, eph = e2e.seal_input(
|
|
239
268
|
reservation["node_x25519_pubkey"], resp_pub,
|
|
240
269
|
_json.dumps({"messages": messages, "temperature": temperature, "max_tokens": max_tokens}).encode(),
|
|
241
270
|
)
|
|
242
|
-
body = {
|
|
271
|
+
body: Dict[str, Any] = {
|
|
243
272
|
"reservation_token": reservation["reservation_token"],
|
|
244
273
|
"max_tokens": max_tokens, # cleartext, only used to quote the x402 price
|
|
245
274
|
"enc": {
|
|
@@ -249,6 +278,8 @@ class GridClient:
|
|
|
249
278
|
"algorithm": e2e.ALGO_V2,
|
|
250
279
|
},
|
|
251
280
|
}
|
|
281
|
+
if pay_in_coin:
|
|
282
|
+
body["pay_in_coin"] = True
|
|
252
283
|
try:
|
|
253
284
|
data = self._request("POST", "/v1/chat/completions", json=body)
|
|
254
285
|
except SGLAPIError as err:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|