programasweights 0.2.8__tar.gz → 0.3.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.
- {programasweights-0.2.8 → programasweights-0.3.0}/AGENTS.md +20 -1
- {programasweights-0.2.8 → programasweights-0.3.0}/PKG-INFO +1 -1
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/__init__.py +67 -11
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/client.py +14 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/pyproject.toml +1 -1
- {programasweights-0.2.8 → programasweights-0.3.0}/.gitignore +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/.readthedocs.yaml +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/CHANGELOG.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/LICENSE +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/PYPI_README.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/README.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/adr/001-llama-cpp-over-pytorch.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/adr/002-q4_0-adapter-format.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/adr/003-single-spec-field.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/adr/004-compiler-naming.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/adr/005-vllm-hidden-states.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/adr/006-email-api-key-auth.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/advanced/adrs.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/advanced/architecture.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/api-reference/cli.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/api-reference/python-sdk.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/api-reference/rest-api.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/architecture.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/case-studies/log-monitoring.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/case-studies/semantic-search.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/case-studies/site-navigation.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/case-studies/tool-calling.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/getting-started/first-program.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/getting-started/installation.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/getting-started/naming-programs.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/guide/browser-inference.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/guide/how-it-works.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/guide/local-inference.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/guide/writing-good-specs.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/hub/browsing-programs.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/hub/feedback-cases.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/hub/publishing-programs.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/index.md +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/docs/requirements.txt +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/examples/flask_app.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/examples/jupyter_notebook.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/examples/langchain_integration.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/examples/paw_monitor.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/examples/replace_openai.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/mkdocs.yml +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/_output.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/artifacts.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/cache.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/cli.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/compiler/__init__.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/compiler/dummy.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/config.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/convert_peft_to_paw.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/paw_format.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/runtime/__init__.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/runtime/interpreter.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/runtime/interpreter_onnx.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/programasweights/runtime_llamacpp.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/tests/test_offline_cache.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/tests/test_sdk.py +0 -0
- {programasweights-0.2.8 → programasweights-0.3.0}/tests/test_sdk.sh +0 -0
|
@@ -161,6 +161,22 @@ Generate API keys at https://programasweights.com/settings.
|
|
|
161
161
|
|
|
162
162
|
Commands: `paw compile --spec "..." --json`, `paw run --program <id> --input "..."`, `paw info <id>`, `paw rename <id> <slug>`, `paw login`. All support `--json` for structured output.
|
|
163
163
|
|
|
164
|
+
## Versioning
|
|
165
|
+
|
|
166
|
+
Slugs support version history. Recompiling with the same slug creates a new version:
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
p1 = paw.compile("Count words v1", slug="word-counter") # v1
|
|
170
|
+
p2 = paw.compile("Count words v2", slug="word-counter") # v2 (auto-bumps)
|
|
171
|
+
|
|
172
|
+
fn = paw.function("da03/word-counter") # resolves to main (latest)
|
|
173
|
+
fn = paw.function("da03/word-counter@v1") # pinned to v1
|
|
174
|
+
|
|
175
|
+
versions = paw.list_versions("da03/word-counter") # all versions
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Pinned versions (`@v1`) are immutable and cached locally forever. Bare slugs always check the server for the latest main version (falls back to cache if offline).
|
|
179
|
+
|
|
164
180
|
## Full API Reference
|
|
165
181
|
|
|
166
182
|
```python
|
|
@@ -170,16 +186,19 @@ program = paw.compile(
|
|
|
170
186
|
slug=None, # URL-safe handle (requires auth)
|
|
171
187
|
public=True, # list on public hub
|
|
172
188
|
)
|
|
173
|
-
# Returns: Program(id, slug, status, timings, error)
|
|
189
|
+
# Returns: Program(id, slug, status, version, version_action, timings, error)
|
|
174
190
|
|
|
175
191
|
fn = paw.function(program) # accepts Program object, hash ID, or slug
|
|
176
192
|
fn = paw.function("a6b454023d41ac9ca845")
|
|
177
193
|
fn = paw.function("da03/my-classifier")
|
|
194
|
+
fn = paw.function("da03/my-classifier@v2") # pinned version
|
|
195
|
+
fn = paw.function("da03/my-classifier", offline=True) # skip server check
|
|
178
196
|
|
|
179
197
|
result: str = fn(input_text: str, max_tokens=None, temperature=0.0)
|
|
180
198
|
|
|
181
199
|
fn = paw.compile_and_load(spec, compiler="paw-4b-qwen3-0.6b")
|
|
182
200
|
|
|
201
|
+
versions = paw.list_versions("da03/my-classifier") # version history
|
|
183
202
|
programs = paw.list_programs(sort="recent", per_page=20) # requires auth
|
|
184
203
|
|
|
185
204
|
paw.login()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: programasweights
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Compile natural language specifications into neural programs that run locally via llama.cpp.
|
|
5
5
|
Project-URL: Homepage, https://programasweights.com
|
|
6
6
|
Project-URL: Repository, https://github.com/programasweights/programasweights-python
|
|
@@ -27,7 +27,7 @@ try:
|
|
|
27
27
|
from importlib.metadata import version as _meta_version
|
|
28
28
|
__version__ = _meta_version("programasweights")
|
|
29
29
|
except Exception:
|
|
30
|
-
__version__ = "0.
|
|
30
|
+
__version__ = "0.3.0"
|
|
31
31
|
|
|
32
32
|
from .config import get_api_url, get_api_key, set_api_key
|
|
33
33
|
|
|
@@ -74,7 +74,13 @@ def compile(
|
|
|
74
74
|
result = client.compile(spec, compiler=compiler, name=name, tags=tags, public=public, slug=slug)
|
|
75
75
|
label = f"{result.id}"
|
|
76
76
|
if result.slug:
|
|
77
|
-
|
|
77
|
+
ver_str = f" v{result.version}" if result.version and result.version > 1 else ""
|
|
78
|
+
action_str = ""
|
|
79
|
+
if result.version_action == "no_change":
|
|
80
|
+
action_str = " (no changes)"
|
|
81
|
+
elif result.version_action == "promoted":
|
|
82
|
+
action_str = " set as main"
|
|
83
|
+
label = f"{result.slug}{ver_str}{action_str}"
|
|
78
84
|
status(f"Compiled: {label}")
|
|
79
85
|
return result
|
|
80
86
|
|
|
@@ -84,6 +90,7 @@ def function(
|
|
|
84
90
|
n_ctx: int = 2048,
|
|
85
91
|
n_gpu_layers: int | None = None,
|
|
86
92
|
verbose: bool = False,
|
|
93
|
+
offline: bool = False,
|
|
87
94
|
):
|
|
88
95
|
"""Load a compiled program for local inference via llama.cpp.
|
|
89
96
|
|
|
@@ -91,11 +98,14 @@ def function(
|
|
|
91
98
|
Subsequent calls use the local cache.
|
|
92
99
|
|
|
93
100
|
Args:
|
|
94
|
-
program_id: Program ID (str), slug
|
|
101
|
+
program_id: Program ID (str), slug (``da03/my-program``), pinned version
|
|
102
|
+
(``da03/my-program@v3``), or a ``Program`` object from compile().
|
|
95
103
|
n_ctx: Context window size for llama.cpp.
|
|
96
104
|
n_gpu_layers: GPU layers (-1 = all, 0 = CPU only). Defaults to CPU.
|
|
97
105
|
Set ``PAW_GPU_LAYERS`` env var or pass explicitly for GPU acceleration.
|
|
98
106
|
verbose: Print llama.cpp debug output.
|
|
107
|
+
offline: Skip server check for slug resolution and use local cache only.
|
|
108
|
+
Also set via ``PAW_OFFLINE=1`` env var.
|
|
99
109
|
|
|
100
110
|
Returns:
|
|
101
111
|
A callable ``PawFunction`` that takes an input string and returns output.
|
|
@@ -105,8 +115,7 @@ def function(
|
|
|
105
115
|
>>> fn("Urgent: the server is down!")
|
|
106
116
|
'immediate'
|
|
107
117
|
|
|
108
|
-
>>>
|
|
109
|
-
>>> fn = paw.function(program) # accepts Program object directly
|
|
118
|
+
>>> fn = paw.function("da03/my-program@v2") # pinned version
|
|
110
119
|
"""
|
|
111
120
|
if hasattr(program_id, 'id'):
|
|
112
121
|
program_id = program_id.slug or program_id.id
|
|
@@ -122,15 +131,42 @@ def function(
|
|
|
122
131
|
|
|
123
132
|
resolved_id = program_id
|
|
124
133
|
if not re.fullmatch(r"[a-f0-9]{16,64}", program_id):
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
is_pinned = bool(re.search(r"@v\d+$", program_id))
|
|
135
|
+
use_offline = offline or os.environ.get("PAW_OFFLINE", "").strip() in ("1", "true", "yes")
|
|
136
|
+
|
|
137
|
+
if is_pinned:
|
|
138
|
+
cached = get_cached_slug(program_id)
|
|
139
|
+
if cached:
|
|
140
|
+
resolved_id = cached
|
|
141
|
+
else:
|
|
142
|
+
status(f"Resolving {program_id}...")
|
|
143
|
+
from .client import PAWClient
|
|
144
|
+
client = PAWClient(api_url=get_api_url(), api_key=get_api_key())
|
|
145
|
+
resolved_id = client.resolve_slug(program_id)
|
|
146
|
+
save_slug_mapping(program_id, resolved_id)
|
|
147
|
+
elif use_offline:
|
|
148
|
+
cached = get_cached_slug(program_id)
|
|
149
|
+
if cached:
|
|
150
|
+
resolved_id = cached
|
|
151
|
+
else:
|
|
152
|
+
raise RuntimeError(
|
|
153
|
+
f"No cached version of '{program_id}'. Cannot resolve offline. "
|
|
154
|
+
"Run once with internet to populate the cache."
|
|
155
|
+
)
|
|
128
156
|
else:
|
|
129
|
-
status(f"Resolving {program_id}...")
|
|
130
157
|
from .client import PAWClient
|
|
131
158
|
client = PAWClient(api_url=get_api_url(), api_key=get_api_key())
|
|
132
|
-
|
|
133
|
-
|
|
159
|
+
try:
|
|
160
|
+
status(f"Resolving {program_id}...")
|
|
161
|
+
resolved_id = client.resolve_slug(program_id)
|
|
162
|
+
save_slug_mapping(program_id, resolved_id)
|
|
163
|
+
except Exception:
|
|
164
|
+
cached = get_cached_slug(program_id)
|
|
165
|
+
if cached:
|
|
166
|
+
status(f"Warning: could not reach server, using cached version of {program_id}")
|
|
167
|
+
resolved_id = cached
|
|
168
|
+
else:
|
|
169
|
+
raise
|
|
134
170
|
|
|
135
171
|
if not is_program_cached(resolved_id):
|
|
136
172
|
from .client import PAWClient
|
|
@@ -221,6 +257,25 @@ def compile_and_load(
|
|
|
221
257
|
return function(program, n_ctx=n_ctx, n_gpu_layers=n_gpu_layers, verbose=verbose)
|
|
222
258
|
|
|
223
259
|
|
|
260
|
+
def list_versions(slug: str) -> dict:
|
|
261
|
+
"""List all versions of a named program (slug).
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
slug: Slug in ``username/slug-name`` or bare ``slug-name`` format.
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
Dict with ``slug``, ``main_version``, and ``versions`` list.
|
|
268
|
+
|
|
269
|
+
Example:
|
|
270
|
+
>>> versions = paw.list_versions("da03/bibtex-normalizer")
|
|
271
|
+
>>> for v in versions["versions"]:
|
|
272
|
+
... print(f"v{v['version']}: {v['program_id'][:12]} {'(main)' if v['is_main'] else ''}")
|
|
273
|
+
"""
|
|
274
|
+
from .client import PAWClient
|
|
275
|
+
client = PAWClient(api_url=get_api_url(), api_key=get_api_key())
|
|
276
|
+
return client.list_slug_versions(slug)
|
|
277
|
+
|
|
278
|
+
|
|
224
279
|
def list_programs(sort: str = "recent", per_page: int = 20, page: int = 1) -> dict:
|
|
225
280
|
"""List your compiled programs. Requires authentication (PAW_API_KEY).
|
|
226
281
|
|
|
@@ -242,6 +297,7 @@ __all__ = [
|
|
|
242
297
|
"compile_and_load",
|
|
243
298
|
"function",
|
|
244
299
|
"list_programs",
|
|
300
|
+
"list_versions",
|
|
245
301
|
"login",
|
|
246
302
|
"get_api_url",
|
|
247
303
|
"get_api_key",
|
|
@@ -27,6 +27,8 @@ class Program:
|
|
|
27
27
|
compiler_snapshot: Optional[str] = None
|
|
28
28
|
timings: Optional[dict] = None
|
|
29
29
|
error: Optional[str] = None
|
|
30
|
+
version: Optional[int] = None
|
|
31
|
+
version_action: Optional[str] = None
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
class PAWClient:
|
|
@@ -92,6 +94,8 @@ class PAWClient:
|
|
|
92
94
|
compiler_snapshot=data.get("compiler_snapshot"),
|
|
93
95
|
timings=data.get("timings"),
|
|
94
96
|
error=data.get("error"),
|
|
97
|
+
version=data.get("version"),
|
|
98
|
+
version_action=data.get("version_action"),
|
|
95
99
|
)
|
|
96
100
|
|
|
97
101
|
def resolve_slug(self, slug: str) -> str:
|
|
@@ -182,6 +186,16 @@ class PAWClient:
|
|
|
182
186
|
resp.raise_for_status()
|
|
183
187
|
return resp.json()
|
|
184
188
|
|
|
189
|
+
def list_slug_versions(self, slug: str) -> dict:
|
|
190
|
+
"""List all versions of a slug. Slug format: 'username/slug-name' or bare 'slug-name'."""
|
|
191
|
+
resp = httpx.get(
|
|
192
|
+
f"{self._api_url}/api/v1/programs/{slug}/versions",
|
|
193
|
+
headers=self._headers(),
|
|
194
|
+
timeout=10.0,
|
|
195
|
+
)
|
|
196
|
+
resp.raise_for_status()
|
|
197
|
+
return resp.json()
|
|
198
|
+
|
|
185
199
|
def list_programs(self, sort: str = "recent", per_page: int = 20, page: int = 1) -> dict:
|
|
186
200
|
"""List programs for the authenticated user."""
|
|
187
201
|
resp = httpx.get(
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "programasweights"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "Compile natural language specifications into neural programs that run locally via llama.cpp."
|
|
9
9
|
readme = "PYPI_README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programasweights-0.2.8 → programasweights-0.3.0}/programasweights/runtime/interpreter_onnx.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|