superlinear 0.1.0__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.
- apps/__init__.py +4 -0
- apps/cli/__init__.py +8 -0
- apps/cli/bm25_rag.py +471 -0
- apps/cli/chat_repl.py +1497 -0
- apps/cli/client.py +195 -0
- apps/cli/docs_repl.py +2275 -0
- apps/cli/light_rag.py +729 -0
- apps/cli/local_snapshots.py +139 -0
- apps/cli/locks.py +214 -0
- apps/cli/main.py +457 -0
- apps/cli/output.py +32 -0
- apps/cli/server_cmds.py +516 -0
- apps/cli/session_cmds.py +491 -0
- apps/cli/snapshot_cmds.py +303 -0
- apps/cli/state.py +265 -0
- apps/server/__init__.py +4 -0
- apps/server/app.py +1363 -0
- apps/server/main.py +313 -0
- superlinear/__init__.py +114 -0
- superlinear/_version.py +3 -0
- superlinear/engine/__init__.py +10 -0
- superlinear/engine/adapters/__init__.py +12 -0
- superlinear/engine/adapters/base.py +91 -0
- superlinear/engine/adapters/superlinear.py +1233 -0
- superlinear/engine/chat_engine.py +1173 -0
- superlinear/engine/chat_types.py +130 -0
- superlinear/engine/registry.py +51 -0
- superlinear/engine/repetition.py +203 -0
- superlinear/engine/session_snapshots.py +451 -0
- superlinear/engine/tool_parser.py +83 -0
- superlinear/engine/types.py +42 -0
- superlinear/kernels/__init__.py +2 -0
- superlinear/kernels/common/__init__.py +21 -0
- superlinear/kernels/common/adjustment.py +106 -0
- superlinear/kernels/common/power.py +154 -0
- superlinear/kernels/superlinear/__init__.py +10 -0
- superlinear/kernels/superlinear/attention/__init__.py +78 -0
- superlinear/kernels/superlinear/attention/_prefill.py +940 -0
- superlinear/kernels/superlinear/attention/_sliding_window.py +1167 -0
- superlinear/kernels/superlinear/attention/api.py +433 -0
- superlinear/kernels/superlinear/search/__init__.py +33 -0
- superlinear/kernels/superlinear/search/_reference.py +204 -0
- superlinear/kernels/superlinear/search/_triton.py +488 -0
- superlinear/kernels/superlinear/search/_triton_gqa.py +534 -0
- superlinear/kernels/superlinear/search/api.py +200 -0
- superlinear/kernels/superlinear/span/__init__.py +41 -0
- superlinear/kernels/superlinear/span/_triton_bucketed_gqa.py +1461 -0
- superlinear/kernels/superlinear/span/_triton_forward.py +22 -0
- superlinear/kernels/superlinear/span/_triton_gqa.py +1226 -0
- superlinear/kernels/superlinear/span/_triton_impl.py +928 -0
- superlinear/kernels/superlinear/span/_triton_precomputed_sw.py +460 -0
- superlinear/kernels/superlinear/span/_triton_precomputed_sw_gqa.py +598 -0
- superlinear/kernels/superlinear/span/api.py +296 -0
- superlinear/kernels/superlinear/span/masks.py +187 -0
- superlinear/py.typed +0 -0
- superlinear/runtime.py +71 -0
- superlinear-0.1.0.dist-info/METADATA +469 -0
- superlinear-0.1.0.dist-info/RECORD +62 -0
- superlinear-0.1.0.dist-info/WHEEL +5 -0
- superlinear-0.1.0.dist-info/entry_points.txt +2 -0
- superlinear-0.1.0.dist-info/licenses/LICENSE +202 -0
- superlinear-0.1.0.dist-info/top_level.txt +2 -0
apps/cli/client.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""HTTP client wrapper for communicating with the Superlinear HTTP server.
|
|
2
|
+
|
|
3
|
+
This module provides small, dependency-free primitives for JSON requests and SSE streaming.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import socket
|
|
10
|
+
import urllib.error
|
|
11
|
+
import urllib.parse
|
|
12
|
+
import urllib.request
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
from typing import Any, BinaryIO, Iterator
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
DEFAULT_URL = "http://127.0.0.1:8787"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class HttpError(RuntimeError):
|
|
22
|
+
message: str
|
|
23
|
+
url: str | None = None
|
|
24
|
+
status_code: int | None = None
|
|
25
|
+
body: str | None = None
|
|
26
|
+
|
|
27
|
+
def __str__(self) -> str: # pragma: no cover
|
|
28
|
+
parts = [self.message]
|
|
29
|
+
if self.status_code is not None:
|
|
30
|
+
parts.append(f"status={self.status_code}")
|
|
31
|
+
if self.url:
|
|
32
|
+
parts.append(f"url={self.url}")
|
|
33
|
+
if self.body:
|
|
34
|
+
parts.append(f"body={self.body}")
|
|
35
|
+
return " ".join(parts)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _join_url(base_url: str, path: str) -> str:
|
|
39
|
+
if not path.startswith("/"):
|
|
40
|
+
path = "/" + path
|
|
41
|
+
# Ensure base_url ends with "/" so urljoin doesn't drop the path.
|
|
42
|
+
return urllib.parse.urljoin(base_url.rstrip("/") + "/", path.lstrip("/"))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def iter_sse_data(stream: BinaryIO) -> Iterator[str]:
|
|
46
|
+
"""Yield decoded SSE `data:` payloads, one per event (without the trailing blank line)."""
|
|
47
|
+
data_lines: list[str] = []
|
|
48
|
+
for raw in stream:
|
|
49
|
+
try:
|
|
50
|
+
line = raw.decode("utf-8", errors="replace")
|
|
51
|
+
except Exception:
|
|
52
|
+
continue
|
|
53
|
+
line = line.rstrip("\r\n")
|
|
54
|
+
if not line:
|
|
55
|
+
if data_lines:
|
|
56
|
+
yield "\n".join(data_lines)
|
|
57
|
+
data_lines = []
|
|
58
|
+
continue
|
|
59
|
+
if line.startswith("data:"):
|
|
60
|
+
data_lines.append(line[5:].lstrip())
|
|
61
|
+
continue
|
|
62
|
+
|
|
63
|
+
if data_lines:
|
|
64
|
+
yield "\n".join(data_lines)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def iter_sse_json(stream: BinaryIO) -> Iterator[dict[str, Any]]:
|
|
68
|
+
"""Yield JSON-decoded SSE `data:` payloads; stops on `[DONE]`."""
|
|
69
|
+
for payload in iter_sse_data(stream):
|
|
70
|
+
if payload == "[DONE]":
|
|
71
|
+
return
|
|
72
|
+
yield json.loads(payload)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class SuperlinearClient:
|
|
76
|
+
def __init__(self, *, base_url: str = DEFAULT_URL, timeout_s: float = 300.0):
|
|
77
|
+
self.base_url = base_url.rstrip("/")
|
|
78
|
+
self.timeout_s = float(timeout_s)
|
|
79
|
+
|
|
80
|
+
def request_json(
|
|
81
|
+
self,
|
|
82
|
+
method: str,
|
|
83
|
+
path: str,
|
|
84
|
+
*,
|
|
85
|
+
payload: Any | None = None,
|
|
86
|
+
timeout_s: float | None = None,
|
|
87
|
+
headers: dict[str, str] | None = None,
|
|
88
|
+
) -> Any:
|
|
89
|
+
url = _join_url(self.base_url, path)
|
|
90
|
+
|
|
91
|
+
body: bytes | None = None
|
|
92
|
+
if payload is not None:
|
|
93
|
+
body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
|
|
94
|
+
|
|
95
|
+
req = urllib.request.Request(url=url, method=method.upper(), data=body)
|
|
96
|
+
req.add_header("Accept", "application/json")
|
|
97
|
+
if payload is not None:
|
|
98
|
+
req.add_header("Content-Type", "application/json")
|
|
99
|
+
if headers:
|
|
100
|
+
for k, v in headers.items():
|
|
101
|
+
req.add_header(k, v)
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
with urllib.request.urlopen(req, timeout=self.timeout_s if timeout_s is None else timeout_s) as resp:
|
|
105
|
+
raw = resp.read()
|
|
106
|
+
try:
|
|
107
|
+
return json.loads(raw.decode("utf-8"))
|
|
108
|
+
except Exception as exc:
|
|
109
|
+
raise HttpError(
|
|
110
|
+
"Invalid JSON response",
|
|
111
|
+
url=url,
|
|
112
|
+
status_code=getattr(resp, "status", None),
|
|
113
|
+
body=raw.decode("utf-8", errors="replace"),
|
|
114
|
+
) from exc
|
|
115
|
+
except urllib.error.HTTPError as exc:
|
|
116
|
+
body_text: str | None
|
|
117
|
+
try:
|
|
118
|
+
body_text = exc.read().decode("utf-8", errors="replace")
|
|
119
|
+
except Exception:
|
|
120
|
+
body_text = None
|
|
121
|
+
raise HttpError(
|
|
122
|
+
"HTTP error",
|
|
123
|
+
url=url,
|
|
124
|
+
status_code=getattr(exc, "code", None),
|
|
125
|
+
body=body_text,
|
|
126
|
+
) from exc
|
|
127
|
+
except urllib.error.URLError as exc:
|
|
128
|
+
raise HttpError("Failed to reach server", url=url) from exc
|
|
129
|
+
except socket.timeout as exc:
|
|
130
|
+
raise HttpError("Request timed out", url=url) from exc
|
|
131
|
+
|
|
132
|
+
def request_sse(
|
|
133
|
+
self,
|
|
134
|
+
method: str,
|
|
135
|
+
path: str,
|
|
136
|
+
*,
|
|
137
|
+
payload: Any | None = None,
|
|
138
|
+
timeout_s: float | None = None,
|
|
139
|
+
headers: dict[str, str] | None = None,
|
|
140
|
+
) -> Iterator[dict[str, Any]]:
|
|
141
|
+
url = _join_url(self.base_url, path)
|
|
142
|
+
body: bytes | None = None
|
|
143
|
+
if payload is not None:
|
|
144
|
+
body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
|
|
145
|
+
|
|
146
|
+
req = urllib.request.Request(url=url, method=method.upper(), data=body)
|
|
147
|
+
req.add_header("Accept", "text/event-stream")
|
|
148
|
+
if payload is not None:
|
|
149
|
+
req.add_header("Content-Type", "application/json")
|
|
150
|
+
if headers:
|
|
151
|
+
for k, v in headers.items():
|
|
152
|
+
req.add_header(k, v)
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
resp = urllib.request.urlopen(req, timeout=self.timeout_s if timeout_s is None else timeout_s)
|
|
156
|
+
except urllib.error.HTTPError as exc:
|
|
157
|
+
body_text: str | None
|
|
158
|
+
try:
|
|
159
|
+
body_text = exc.read().decode("utf-8", errors="replace")
|
|
160
|
+
except Exception:
|
|
161
|
+
body_text = None
|
|
162
|
+
raise HttpError(
|
|
163
|
+
"HTTP error",
|
|
164
|
+
url=url,
|
|
165
|
+
status_code=getattr(exc, "code", None),
|
|
166
|
+
body=body_text,
|
|
167
|
+
) from exc
|
|
168
|
+
except urllib.error.URLError as exc:
|
|
169
|
+
raise HttpError("Failed to reach server", url=url) from exc
|
|
170
|
+
except socket.timeout as exc:
|
|
171
|
+
raise HttpError("Request timed out", url=url) from exc
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
yield from iter_sse_json(resp)
|
|
175
|
+
finally:
|
|
176
|
+
try:
|
|
177
|
+
resp.close()
|
|
178
|
+
except Exception:
|
|
179
|
+
pass
|
|
180
|
+
|
|
181
|
+
def health(self) -> dict[str, Any]:
|
|
182
|
+
result = self.request_json("GET", "/health", timeout_s=min(self.timeout_s, 5.0))
|
|
183
|
+
if not isinstance(result, dict):
|
|
184
|
+
raise HttpError("Invalid /health response", url=_join_url(self.base_url, "/health"))
|
|
185
|
+
return result
|
|
186
|
+
|
|
187
|
+
def list_models(self) -> list[dict[str, Any]]:
|
|
188
|
+
result = self.request_json("GET", "/v1/models")
|
|
189
|
+
if not isinstance(result, dict) or not isinstance(result.get("data"), list):
|
|
190
|
+
raise HttpError("Invalid /v1/models response", url=_join_url(self.base_url, "/v1/models"))
|
|
191
|
+
out: list[dict[str, Any]] = []
|
|
192
|
+
for item in result["data"]:
|
|
193
|
+
if isinstance(item, dict):
|
|
194
|
+
out.append(item)
|
|
195
|
+
return out
|