programasweights 0.1.0.dev7__py3-none-any.whl → 0.1.0.dev9__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.
- programasweights/__init__.py +21 -11
- programasweights/cache.py +35 -0
- programasweights/cli.py +45 -3
- programasweights/client.py +10 -3
- {programasweights-0.1.0.dev7.dist-info → programasweights-0.1.0.dev9.dist-info}/METADATA +5 -4
- {programasweights-0.1.0.dev7.dist-info → programasweights-0.1.0.dev9.dist-info}/RECORD +8 -8
- {programasweights-0.1.0.dev7.dist-info → programasweights-0.1.0.dev9.dist-info}/WHEEL +0 -0
- {programasweights-0.1.0.dev7.dist-info → programasweights-0.1.0.dev9.dist-info}/entry_points.txt +0 -0
programasweights/__init__.py
CHANGED
|
@@ -22,7 +22,7 @@ API reference:
|
|
|
22
22
|
paw.api_key API key (set via login() or PAW_API_KEY env var)
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
-
__version__ = "0.1.0.
|
|
25
|
+
__version__ = "0.1.0.dev9"
|
|
26
26
|
|
|
27
27
|
from .config import get_api_url, get_api_key, set_api_key
|
|
28
28
|
|
|
@@ -37,33 +37,38 @@ def compile(
|
|
|
37
37
|
name: str | None = None,
|
|
38
38
|
tags: list[str] | None = None,
|
|
39
39
|
public: bool = True,
|
|
40
|
+
slug: str | None = None,
|
|
40
41
|
):
|
|
41
42
|
"""Compile a natural language specification into a neural program.
|
|
42
43
|
|
|
43
44
|
The compilation runs on the PAW server. The resulting program can be
|
|
44
|
-
downloaded and run locally via ``paw.function(program.id)
|
|
45
|
+
downloaded and run locally via ``paw.function(program.id)`` or
|
|
46
|
+
``paw.function(program.slug)`` if a slug was provided.
|
|
45
47
|
|
|
46
48
|
Args:
|
|
47
49
|
spec: Full specification text. Include examples in the text if desired.
|
|
48
50
|
compiler: Compiler model (alias or snapshot name).
|
|
49
|
-
name: Human-readable program name for the hub.
|
|
51
|
+
name: Human-readable program name (display title for the hub).
|
|
50
52
|
tags: Tags for hub discovery.
|
|
51
53
|
public: Whether to list on the public hub.
|
|
54
|
+
slug: URL-safe handle (e.g. 'message-classifier'). Creates a
|
|
55
|
+
``username/slug`` alias. Requires authentication.
|
|
52
56
|
|
|
53
57
|
Returns:
|
|
54
|
-
A ``Program`` object with ``id``, ``status``, and ``timings``.
|
|
58
|
+
A ``Program`` object with ``id``, ``slug``, ``status``, and ``timings``.
|
|
55
59
|
|
|
56
60
|
Example:
|
|
57
61
|
>>> program = paw.compile(
|
|
58
|
-
... "Fix malformed JSON: repair missing quotes and trailing commas"
|
|
62
|
+
... "Fix malformed JSON: repair missing quotes and trailing commas",
|
|
63
|
+
... slug="json-fixer"
|
|
59
64
|
... )
|
|
60
|
-
>>> fn = paw.function(program.id)
|
|
65
|
+
>>> fn = paw.function(program.slug) # or paw.function(program.id)
|
|
61
66
|
>>> fn("{name: 'Alice',}")
|
|
62
67
|
'{"name": "Alice"}'
|
|
63
68
|
"""
|
|
64
69
|
from .client import PAWClient
|
|
65
70
|
client = PAWClient(api_url=api_url, api_key=api_key)
|
|
66
|
-
return client.compile(spec, compiler=compiler, name=name, tags=tags, public=public)
|
|
71
|
+
return client.compile(spec, compiler=compiler, name=name, tags=tags, public=public, slug=slug)
|
|
67
72
|
|
|
68
73
|
|
|
69
74
|
def function(
|
|
@@ -94,7 +99,7 @@ def function(
|
|
|
94
99
|
"""
|
|
95
100
|
import os
|
|
96
101
|
import re
|
|
97
|
-
from .cache import is_program_cached, get_program_dir
|
|
102
|
+
from .cache import is_program_cached, get_program_dir, get_cached_slug, save_slug_mapping
|
|
98
103
|
from .runtime_llamacpp import PawFunction
|
|
99
104
|
|
|
100
105
|
if n_gpu_layers is None:
|
|
@@ -102,9 +107,14 @@ def function(
|
|
|
102
107
|
|
|
103
108
|
resolved_id = program_id
|
|
104
109
|
if not re.fullmatch(r"[a-f0-9]{16,64}", program_id):
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
cached = get_cached_slug(program_id)
|
|
111
|
+
if cached:
|
|
112
|
+
resolved_id = cached
|
|
113
|
+
else:
|
|
114
|
+
from .client import PAWClient
|
|
115
|
+
client = PAWClient(api_url=api_url, api_key=api_key)
|
|
116
|
+
resolved_id = client.resolve_slug(program_id)
|
|
117
|
+
save_slug_mapping(program_id, resolved_id)
|
|
108
118
|
|
|
109
119
|
if not is_program_cached(resolved_id):
|
|
110
120
|
from .client import PAWClient
|
programasweights/cache.py
CHANGED
|
@@ -10,10 +10,12 @@ Cache structure:
|
|
|
10
10
|
adapter.gguf # ~23 MB, Q4_0 LoRA
|
|
11
11
|
prompt_template.txt
|
|
12
12
|
meta.json
|
|
13
|
+
slug_cache.json # slug -> program_id mapping
|
|
13
14
|
"""
|
|
14
15
|
|
|
15
16
|
from __future__ import annotations
|
|
16
17
|
|
|
18
|
+
import json
|
|
17
19
|
import os
|
|
18
20
|
from pathlib import Path
|
|
19
21
|
|
|
@@ -80,3 +82,36 @@ def _download_file(url: str, dest: Path):
|
|
|
80
82
|
mb = downloaded / 1024 / 1024
|
|
81
83
|
print(f"\r {mb:.1f} MB ({pct:.0f}%)", end="", flush=True)
|
|
82
84
|
print()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _slug_cache_path() -> Path:
|
|
88
|
+
return config.get_cache_dir() / "slug_cache.json"
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def get_cached_slug(slug: str) -> str | None:
|
|
92
|
+
"""Look up a slug in the local cache. Returns program_id or None."""
|
|
93
|
+
path = _slug_cache_path()
|
|
94
|
+
if not path.exists():
|
|
95
|
+
return None
|
|
96
|
+
try:
|
|
97
|
+
data = json.loads(path.read_text())
|
|
98
|
+
program_id = data.get(slug)
|
|
99
|
+
if program_id and is_program_cached(program_id):
|
|
100
|
+
return program_id
|
|
101
|
+
except (json.JSONDecodeError, OSError):
|
|
102
|
+
pass
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def save_slug_mapping(slug: str, program_id: str) -> None:
|
|
107
|
+
"""Save a slug -> program_id mapping to the local cache."""
|
|
108
|
+
path = _slug_cache_path()
|
|
109
|
+
data: dict = {}
|
|
110
|
+
if path.exists():
|
|
111
|
+
try:
|
|
112
|
+
data = json.loads(path.read_text())
|
|
113
|
+
except (json.JSONDecodeError, OSError):
|
|
114
|
+
pass
|
|
115
|
+
data[slug] = program_id
|
|
116
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
117
|
+
path.write_text(json.dumps(data))
|
programasweights/cli.py
CHANGED
|
@@ -26,11 +26,12 @@ def cmd_compile(args):
|
|
|
26
26
|
if not args.json:
|
|
27
27
|
print(f"Compiling: {args.spec[:80]}...")
|
|
28
28
|
|
|
29
|
-
program = paw.compile(args.spec, compiler=args.compiler)
|
|
29
|
+
program = paw.compile(args.spec, compiler=args.compiler, slug=getattr(args, 'slug', None))
|
|
30
30
|
|
|
31
31
|
if args.json:
|
|
32
32
|
print(json.dumps({
|
|
33
33
|
"program_id": program.id,
|
|
34
|
+
"slug": program.slug,
|
|
34
35
|
"status": program.status,
|
|
35
36
|
"error": program.error,
|
|
36
37
|
"timings": program.timings,
|
|
@@ -42,15 +43,18 @@ def cmd_compile(args):
|
|
|
42
43
|
return 1
|
|
43
44
|
|
|
44
45
|
print(f"Program ID: {program.id}")
|
|
46
|
+
if program.slug:
|
|
47
|
+
print(f"Slug: {program.slug}")
|
|
45
48
|
print(f"Status: {program.status}")
|
|
46
49
|
if program.timings:
|
|
47
50
|
total = program.timings.get("total_ms", 0)
|
|
48
51
|
print(f"Total time: {total:.0f}ms")
|
|
52
|
+
ref = program.slug or program.id
|
|
49
53
|
print(f"\nTo run locally:")
|
|
50
|
-
print(f" paw run {
|
|
54
|
+
print(f" paw run --program \"{ref}\" --input \"your input here\"")
|
|
51
55
|
print(f"\nOr in Python:")
|
|
52
56
|
print(f" import programasweights as paw")
|
|
53
|
-
print(f" fn = paw.function(\"{
|
|
57
|
+
print(f" fn = paw.function(\"{ref}\")")
|
|
54
58
|
print(f" fn(\"your input here\")")
|
|
55
59
|
return 0
|
|
56
60
|
|
|
@@ -80,6 +84,37 @@ def cmd_login(args):
|
|
|
80
84
|
return 0
|
|
81
85
|
|
|
82
86
|
|
|
87
|
+
def cmd_rename(args):
|
|
88
|
+
import programasweights as paw
|
|
89
|
+
if args.api_url:
|
|
90
|
+
paw.api_url = args.api_url
|
|
91
|
+
if args.api_key:
|
|
92
|
+
paw.api_key = args.api_key
|
|
93
|
+
|
|
94
|
+
import httpx
|
|
95
|
+
from programasweights.client import PAWClient
|
|
96
|
+
client = PAWClient(api_url=paw.api_url, api_key=paw.api_key)
|
|
97
|
+
|
|
98
|
+
resp = httpx.patch(
|
|
99
|
+
f"{client._api_url}/api/v1/programs/{args.program}",
|
|
100
|
+
json={"slug": args.new_slug},
|
|
101
|
+
headers=client._headers(),
|
|
102
|
+
timeout=10.0,
|
|
103
|
+
)
|
|
104
|
+
resp.raise_for_status()
|
|
105
|
+
data = resp.json()
|
|
106
|
+
|
|
107
|
+
if args.json:
|
|
108
|
+
print(json.dumps(data))
|
|
109
|
+
else:
|
|
110
|
+
slug = data.get("slug")
|
|
111
|
+
if slug:
|
|
112
|
+
print(f"Renamed to: {slug}")
|
|
113
|
+
else:
|
|
114
|
+
print("Slug removed.")
|
|
115
|
+
return 0
|
|
116
|
+
|
|
117
|
+
|
|
83
118
|
def cmd_info(args):
|
|
84
119
|
import programasweights as paw
|
|
85
120
|
if args.api_url:
|
|
@@ -129,6 +164,7 @@ def main():
|
|
|
129
164
|
p = sub.add_parser("compile", help="Compile a spec on the server")
|
|
130
165
|
p.add_argument("--spec", required=True, help="Natural language specification")
|
|
131
166
|
p.add_argument("--compiler", default="paw-4b-qwen3-0.6b", help="Compiler model")
|
|
167
|
+
p.add_argument("--slug", default=None, help="URL-safe handle (e.g. 'message-classifier')")
|
|
132
168
|
p.add_argument("--json", action="store_true", help="JSON output")
|
|
133
169
|
|
|
134
170
|
p = sub.add_parser("run", help="Run a program locally via llama.cpp")
|
|
@@ -142,6 +178,11 @@ def main():
|
|
|
142
178
|
p = sub.add_parser("login", help="Save API key for authentication")
|
|
143
179
|
p.add_argument("key", nargs="?", default=None, help="API key (paw_sk_...). Omit to open browser.")
|
|
144
180
|
|
|
181
|
+
p = sub.add_parser("rename", help="Set or change a program's slug")
|
|
182
|
+
p.add_argument("program", help="Program ID or current slug")
|
|
183
|
+
p.add_argument("new_slug", help="New slug (e.g. 'message-classifier') or empty string to remove")
|
|
184
|
+
p.add_argument("--json", action="store_true", help="JSON output")
|
|
185
|
+
|
|
145
186
|
p = sub.add_parser("info", help="Show program info")
|
|
146
187
|
p.add_argument("program", help="Program name or ID")
|
|
147
188
|
p.add_argument("--json", action="store_true", help="JSON output")
|
|
@@ -156,6 +197,7 @@ def main():
|
|
|
156
197
|
"compile": cmd_compile,
|
|
157
198
|
"run": cmd_run,
|
|
158
199
|
"login": cmd_login,
|
|
200
|
+
"rename": cmd_rename,
|
|
159
201
|
"info": cmd_info,
|
|
160
202
|
}
|
|
161
203
|
|
programasweights/client.py
CHANGED
|
@@ -23,6 +23,7 @@ class Program:
|
|
|
23
23
|
"""Result of a compilation."""
|
|
24
24
|
id: str
|
|
25
25
|
status: str
|
|
26
|
+
slug: Optional[str] = None
|
|
26
27
|
compiler_snapshot: Optional[str] = None
|
|
27
28
|
timings: Optional[dict] = None
|
|
28
29
|
error: Optional[str] = None
|
|
@@ -48,27 +49,32 @@ class PAWClient:
|
|
|
48
49
|
name: str | None = None,
|
|
49
50
|
tags: list[str] | None = None,
|
|
50
51
|
public: bool = True,
|
|
52
|
+
slug: str | None = None,
|
|
51
53
|
) -> Program:
|
|
52
54
|
"""Compile a spec into a neural program on the server.
|
|
53
55
|
|
|
54
56
|
Args:
|
|
55
57
|
spec: Natural language specification. Include examples in the text.
|
|
56
58
|
compiler: Compiler name (alias or snapshot).
|
|
57
|
-
name: Human-readable program name.
|
|
59
|
+
name: Human-readable program name (display title).
|
|
58
60
|
tags: Tags for hub discovery.
|
|
59
61
|
public: Whether to list on the public hub.
|
|
62
|
+
slug: URL-safe handle (e.g. 'message-classifier'). Creates a
|
|
63
|
+
``username/slug`` alias for easy reference. Requires auth.
|
|
60
64
|
|
|
61
65
|
Returns:
|
|
62
|
-
Program with id, status, and timings.
|
|
66
|
+
Program with id, slug, status, and timings.
|
|
63
67
|
|
|
64
68
|
Raises:
|
|
65
69
|
httpx.HTTPStatusError: On API errors (422 for validation, 429 for rate limit).
|
|
66
70
|
"""
|
|
67
|
-
body = {"spec": spec, "compiler": compiler, "public": public}
|
|
71
|
+
body: dict = {"spec": spec, "compiler": compiler, "public": public}
|
|
68
72
|
if name:
|
|
69
73
|
body["name"] = name
|
|
70
74
|
if tags:
|
|
71
75
|
body["tags"] = tags
|
|
76
|
+
if slug:
|
|
77
|
+
body["slug"] = slug
|
|
72
78
|
|
|
73
79
|
resp = httpx.post(
|
|
74
80
|
f"{self._api_url}/api/v1/compile",
|
|
@@ -82,6 +88,7 @@ class PAWClient:
|
|
|
82
88
|
return Program(
|
|
83
89
|
id=data.get("program_id", ""),
|
|
84
90
|
status=data.get("status", "unknown"),
|
|
91
|
+
slug=data.get("slug"),
|
|
85
92
|
compiler_snapshot=data.get("compiler_snapshot"),
|
|
86
93
|
timings=data.get("timings"),
|
|
87
94
|
error=data.get("error"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: programasweights
|
|
3
|
-
Version: 0.1.0.
|
|
3
|
+
Version: 0.1.0.dev9
|
|
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
|
|
@@ -22,7 +22,7 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
23
|
Requires-Python: >=3.9
|
|
24
24
|
Requires-Dist: httpx<1.0,>=0.27.0
|
|
25
|
-
Requires-Dist: llama-cpp-python
|
|
25
|
+
Requires-Dist: llama-cpp-python<=0.3.18,>=0.3.0
|
|
26
26
|
Provides-Extra: test
|
|
27
27
|
Requires-Dist: pytest; extra == 'test'
|
|
28
28
|
Description-Content-Type: text/markdown
|
|
@@ -60,7 +60,7 @@ fn("{name: 'Alice',}") # '{"name": "Alice"}'
|
|
|
60
60
|
|
|
61
61
|
## Two Compilers
|
|
62
62
|
|
|
63
|
-
| | Qwen3 0.6B
|
|
63
|
+
| | Standard (Qwen3 0.6B) | Compact (GPT-2 124M) |
|
|
64
64
|
|--------------------|-------------------------|------------------------|
|
|
65
65
|
| Compiler name | `paw-4b-qwen3-0.6b` | `paw-4b-gpt2` |
|
|
66
66
|
| Accuracy | Higher | Lower |
|
|
@@ -69,7 +69,7 @@ fn("{name: 'Alice',}") # '{"name": "Alice"}'
|
|
|
69
69
|
| Inference speed | ~90ms (server) | ~50ms (server) |
|
|
70
70
|
| Runs in browser | No | Yes |
|
|
71
71
|
|
|
72
|
-
Default is Qwen3 0.6B. Use GPT-2 when you need smaller files or browser deployment.
|
|
72
|
+
Default is Standard (Qwen3 0.6B). Use Compact (GPT-2) when you need smaller files or browser deployment.
|
|
73
73
|
|
|
74
74
|
## Browser SDK
|
|
75
75
|
|
|
@@ -104,6 +104,7 @@ Or save [`AGENTS.md`](https://programasweights.com/agents) to your project root
|
|
|
104
104
|
- **Classification** — sentiment, urgency, categories defined in your own words
|
|
105
105
|
- **Extraction** — emails, names, dates from messy unstructured text
|
|
106
106
|
- **Log triage** — extract errors from verbose output, filter noise
|
|
107
|
+
- **Intent routing** — map user descriptions to the closest URL, menu item, or setting
|
|
107
108
|
- **Agent preprocessing** — parse tool calls, validate outputs, route tasks
|
|
108
109
|
|
|
109
110
|
## Authentication
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
programasweights/__init__.py,sha256=
|
|
1
|
+
programasweights/__init__.py,sha256=b1St5bbuKs0dXCYGiMEsqUrs2zbNyGoqvmgN11qkOvg,5952
|
|
2
2
|
programasweights/artifacts.py,sha256=bSRZgYadAYyuH9aIW6P3VocExfGDGAHeDuj8vod5-Bo,1968
|
|
3
|
-
programasweights/cache.py,sha256=
|
|
4
|
-
programasweights/cli.py,sha256=
|
|
5
|
-
programasweights/client.py,sha256=
|
|
3
|
+
programasweights/cache.py,sha256=69mOsx2Aqi3sQjFXjeBvhKySXDKdvKSINis2FprVDw4,3711
|
|
4
|
+
programasweights/cli.py,sha256=_HCBRXfn9at7a4oTvVOAi2lPMMKaDxleLngdc6WKi2c,6480
|
|
5
|
+
programasweights/client.py,sha256=Qk0ubKW54robuVnvEf0AyED5zX2Rw-W4HefBg_GQp8s,4391
|
|
6
6
|
programasweights/config.py,sha256=zQFnVNfYR4bFx2DsZheMnPy2yd9T4-fe0u2sG1GluE8,1553
|
|
7
7
|
programasweights/convert_peft_to_paw.py,sha256=yvavaAzLUqc-lFHEC_9AOhsuI-fCobu6k-GDMVQdOHk,6521
|
|
8
8
|
programasweights/paw_format.py,sha256=wRXolwtnPgKoopiJC8-yMVZZtiwB-PoAqaWpDFKMoj8,10679
|
|
@@ -12,7 +12,7 @@ programasweights/compiler/dummy.py,sha256=PcLwijRNM4q2E9PNUcfCPf_y08QjsteVENR0TV
|
|
|
12
12
|
programasweights/runtime/__init__.py,sha256=S4jp7-eWAcMa0X417U7P6HkTL1j3v8ffQA-nneh9wY0,549
|
|
13
13
|
programasweights/runtime/interpreter.py,sha256=brYCtatSsu23lq87cuki4MViqZX6U32LBw7Z3USbQmA,19632
|
|
14
14
|
programasweights/runtime/interpreter_onnx.py,sha256=kzYKmwg_h0tVhoQlixJGKoHPVhcCK22AcHG59oeYX2Q,21559
|
|
15
|
-
programasweights-0.1.0.
|
|
16
|
-
programasweights-0.1.0.
|
|
17
|
-
programasweights-0.1.0.
|
|
18
|
-
programasweights-0.1.0.
|
|
15
|
+
programasweights-0.1.0.dev9.dist-info/METADATA,sha256=1WwaxDSpm7CGFxuzkCQcxlntjEnFrfmNBaN9p9oFHO8,5578
|
|
16
|
+
programasweights-0.1.0.dev9.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
17
|
+
programasweights-0.1.0.dev9.dist-info/entry_points.txt,sha256=l4ZnfCPU0oMzhGB9T2Fv9AnDbSCMM70KUUJVtSvMJBc,50
|
|
18
|
+
programasweights-0.1.0.dev9.dist-info/RECORD,,
|
|
File without changes
|
{programasweights-0.1.0.dev7.dist-info → programasweights-0.1.0.dev9.dist-info}/entry_points.txt
RENAMED
|
File without changes
|