programasweights 0.3.2__tar.gz → 0.4.1__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.
Files changed (64) hide show
  1. {programasweights-0.3.2 → programasweights-0.4.1}/AGENTS.md +84 -74
  2. {programasweights-0.3.2 → programasweights-0.4.1}/PKG-INFO +13 -6
  3. {programasweights-0.3.2 → programasweights-0.4.1}/PYPI_README.md +12 -5
  4. programasweights-0.4.1/README.md +186 -0
  5. {programasweights-0.3.2 → programasweights-0.4.1}/docs/case-studies/site-navigation.md +21 -21
  6. {programasweights-0.3.2 → programasweights-0.4.1}/docs/guide/browser-inference.md +10 -8
  7. {programasweights-0.3.2 → programasweights-0.4.1}/docs/index.md +2 -2
  8. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/__init__.py +24 -7
  9. programasweights-0.4.1/programasweights/cache.py +323 -0
  10. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/cli.py +1 -1
  11. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/client.py +65 -2
  12. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/runtime_llamacpp.py +16 -2
  13. {programasweights-0.3.2 → programasweights-0.4.1}/pyproject.toml +1 -1
  14. programasweights-0.4.1/tests/test_runtime_registry_sdk.py +81 -0
  15. programasweights-0.3.2/README.md +0 -113
  16. programasweights-0.3.2/programasweights/cache.py +0 -132
  17. {programasweights-0.3.2 → programasweights-0.4.1}/.gitignore +0 -0
  18. {programasweights-0.3.2 → programasweights-0.4.1}/.readthedocs.yaml +0 -0
  19. {programasweights-0.3.2 → programasweights-0.4.1}/CHANGELOG.md +0 -0
  20. {programasweights-0.3.2 → programasweights-0.4.1}/LICENSE +0 -0
  21. {programasweights-0.3.2 → programasweights-0.4.1}/docs/adr/001-llama-cpp-over-pytorch.md +0 -0
  22. {programasweights-0.3.2 → programasweights-0.4.1}/docs/adr/002-q4_0-adapter-format.md +0 -0
  23. {programasweights-0.3.2 → programasweights-0.4.1}/docs/adr/003-single-spec-field.md +0 -0
  24. {programasweights-0.3.2 → programasweights-0.4.1}/docs/adr/004-compiler-naming.md +0 -0
  25. {programasweights-0.3.2 → programasweights-0.4.1}/docs/adr/005-vllm-hidden-states.md +0 -0
  26. {programasweights-0.3.2 → programasweights-0.4.1}/docs/adr/006-email-api-key-auth.md +0 -0
  27. {programasweights-0.3.2 → programasweights-0.4.1}/docs/advanced/adrs.md +0 -0
  28. {programasweights-0.3.2 → programasweights-0.4.1}/docs/advanced/architecture.md +0 -0
  29. {programasweights-0.3.2 → programasweights-0.4.1}/docs/api-reference/cli.md +0 -0
  30. {programasweights-0.3.2 → programasweights-0.4.1}/docs/api-reference/python-sdk.md +0 -0
  31. {programasweights-0.3.2 → programasweights-0.4.1}/docs/api-reference/rest-api.md +0 -0
  32. {programasweights-0.3.2 → programasweights-0.4.1}/docs/architecture.md +0 -0
  33. {programasweights-0.3.2 → programasweights-0.4.1}/docs/case-studies/log-monitoring.md +0 -0
  34. {programasweights-0.3.2 → programasweights-0.4.1}/docs/case-studies/semantic-search.md +0 -0
  35. {programasweights-0.3.2 → programasweights-0.4.1}/docs/case-studies/tool-calling.md +0 -0
  36. {programasweights-0.3.2 → programasweights-0.4.1}/docs/getting-started/first-program.md +0 -0
  37. {programasweights-0.3.2 → programasweights-0.4.1}/docs/getting-started/installation.md +0 -0
  38. {programasweights-0.3.2 → programasweights-0.4.1}/docs/getting-started/naming-programs.md +0 -0
  39. {programasweights-0.3.2 → programasweights-0.4.1}/docs/guide/how-it-works.md +0 -0
  40. {programasweights-0.3.2 → programasweights-0.4.1}/docs/guide/local-inference.md +0 -0
  41. {programasweights-0.3.2 → programasweights-0.4.1}/docs/guide/writing-good-specs.md +0 -0
  42. {programasweights-0.3.2 → programasweights-0.4.1}/docs/hub/browsing-programs.md +0 -0
  43. {programasweights-0.3.2 → programasweights-0.4.1}/docs/hub/feedback-cases.md +0 -0
  44. {programasweights-0.3.2 → programasweights-0.4.1}/docs/hub/publishing-programs.md +0 -0
  45. {programasweights-0.3.2 → programasweights-0.4.1}/docs/requirements.txt +0 -0
  46. {programasweights-0.3.2 → programasweights-0.4.1}/examples/flask_app.py +0 -0
  47. {programasweights-0.3.2 → programasweights-0.4.1}/examples/jupyter_notebook.py +0 -0
  48. {programasweights-0.3.2 → programasweights-0.4.1}/examples/langchain_integration.py +0 -0
  49. {programasweights-0.3.2 → programasweights-0.4.1}/examples/paw_monitor.py +0 -0
  50. {programasweights-0.3.2 → programasweights-0.4.1}/examples/replace_openai.py +0 -0
  51. {programasweights-0.3.2 → programasweights-0.4.1}/mkdocs.yml +0 -0
  52. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/_output.py +0 -0
  53. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/artifacts.py +0 -0
  54. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/compiler/__init__.py +0 -0
  55. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/compiler/dummy.py +0 -0
  56. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/config.py +0 -0
  57. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/convert_peft_to_paw.py +0 -0
  58. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/paw_format.py +0 -0
  59. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/runtime/__init__.py +0 -0
  60. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/runtime/interpreter.py +0 -0
  61. {programasweights-0.3.2 → programasweights-0.4.1}/programasweights/runtime/interpreter_onnx.py +0 -0
  62. {programasweights-0.3.2 → programasweights-0.4.1}/tests/test_offline_cache.py +0 -0
  63. {programasweights-0.3.2 → programasweights-0.4.1}/tests/test_sdk.py +0 -0
  64. {programasweights-0.3.2 → programasweights-0.4.1}/tests/test_sdk.sh +0 -0
@@ -5,27 +5,35 @@ PAW compiles natural language specifications into tiny neural functions that run
5
5
  Website: https://programasweights.com
6
6
  Full documentation: https://programasweights.readthedocs.io
7
7
 
8
+ ## When to Use PAW
9
+
10
+ - **Fuzzy search** — typo-tolerant matching, semantic search, near-duplicate detection
11
+ - **Format repair** — fix broken JSON, normalize dates, repair malformed inputs
12
+ - **Classification** — sentiment, urgency, categories defined in your own words
13
+ - **Extraction** — emails, names, dates from messy unstructured text
14
+ - **Log triage** — extract errors from verbose output, filter noise
15
+ - **Intent routing** — map user descriptions to the closest URL, menu item, or setting
16
+ - **Agent preprocessing** — parse tool calls, validate outputs, route tasks
17
+
8
18
  ## Install
9
19
 
10
20
  ```bash
11
21
  pip install programasweights --extra-index-url https://pypi.programasweights.com/simple/
12
22
  ```
13
23
 
14
- ## Usage
24
+ ## Quickstart
15
25
 
16
26
  ```python
17
27
  import programasweights as paw
18
28
 
19
29
  # Use a pre-compiled function (downloads once, runs locally forever)
20
- # "email-triage" is an official pre-compiled program (slug)
21
30
  fn = paw.function("email-triage")
22
31
  fn("Urgent: server is down!") # "immediate"
23
32
  fn("Newsletter: spring picnic") # "wait"
24
33
 
25
34
  # Compile your own from a description
26
35
  program = paw.compile(
27
- "Fix malformed JSON: repair missing quotes and trailing commas",
28
- compiler="paw-4b-qwen3-0.6b" # or "paw-4b-gpt2" for smaller/faster
36
+ "Fix malformed JSON: repair missing quotes and trailing commas"
29
37
  )
30
38
  fn = paw.function(program.id)
31
39
  fn("{name: 'Alice',}") # '{"name":"Alice"}'
@@ -35,20 +43,18 @@ fn = paw.compile_and_load("Classify sentiment as positive or negative")
35
43
  fn("I love this!") # "positive"
36
44
  ```
37
45
 
38
- ## Two Compilers
46
+ If you want the smaller browser-compatible runtime explicitly, pass `compiler="paw-4b-gpt2"`. Otherwise, omit `compiler` and let the server default decide.
47
+
48
+ ## Current Public Compilers
39
49
 
40
- - **Standard** (`paw-4b-qwen3-0.6b`) — higher accuracy, 594 MB base + ~22 MB/program. Default.
50
+ - **Standard** (`paw-4b-qwen3-0.6b`) — higher accuracy, 594 MB base + ~22 MB/program. This is the current server default.
41
51
  - **Compact** (`paw-4b-gpt2`) — smaller (134 MB base + ~5 MB/program), runs in browser via WebAssembly.
42
52
 
43
- ## When to Use PAW
53
+ Best practice:
44
54
 
45
- - **Fuzzy search** typo-tolerant matching, semantic search, near-duplicate detection
46
- - **Format repair** fix broken JSON, normalize dates, repair malformed inputs
47
- - **Classification** sentiment, urgency, categories defined in your own words
48
- - **Extraction** — emails, names, dates from messy unstructured text
49
- - **Log triage** — extract errors from verbose output, filter noise
50
- - **Intent routing** — map user descriptions to the closest URL, menu item, or setting
51
- - **Agent preprocessing** — parse tool calls, validate outputs, route tasks
55
+ - For quickstarts and reusable agent workflows, prefer `paw.compile(spec)` with no explicit compiler.
56
+ - If you need to target a specific runtime, pass `compiler="paw-4b-gpt2"` or another supported alias explicitly.
57
+ - If you need to inspect current server-supported compiler names at runtime, call `paw.list_compilers()`.
52
58
 
53
59
  ## Writing Good Specs
54
60
 
@@ -73,58 +79,30 @@ Output: delete
73
79
 
74
80
  **Spec-tuning tips:**
75
81
 
76
- - Each function is stateless: one text input, one text output. No conversation history.
77
82
  - **State output constraints explicitly**: "Return ONLY one of: X, Y, Z". Without this the model may produce free-form text.
78
83
  - **Include examples from your actual data**: Examples outperform prose-only descriptions.
79
84
  - **Debug failures before sweeping**: Look at specific failing examples and understand WHY before trying many variants.
80
85
 
81
- ## Context Window
86
+ ## Constraints And Runtime Behavior
82
87
 
88
+ - Each PAW function is stateless: one text input, one text output. No conversation history.
83
89
  - Spec + input + output share a ~2048 token context window. Inputs that exceed it will error.
84
90
  - `max_tokens` defaults to `None`: generation runs until EOS or the context limit.
91
+ - Compile runs on the hosted PAW API. Inference should usually run locally through the SDK.
92
+ - **GPU acceleration** is enabled by default (`n_gpu_layers=-1`). Uses Metal on Mac, CUDA on Linux, and falls back to CPU automatically. If GPU causes issues, set `PAW_GPU_LAYERS=0` or pass `n_gpu_layers=0`.
93
+ - **First call** is usually ~1-5s because it loads the base model. Subsequent calls are typically ~0.05-0.5s depending on input length and GPU availability.
94
+ - **Base model files are shared** across programs on disk. Each Standard LoRA adapter is ~22 MB; each Compact LoRA adapter is ~5 MB.
95
+ - Cache root is `~/.cache/programasweights/`. Override with `PAW_CACHE_DIR`.
96
+ - After the first download, inference works offline.
85
97
 
86
- ## Chaining Functions
87
-
88
- Multiple PAW functions can be composed for multi-step tasks:
89
-
90
- ```python
91
- classifier = paw.compile_and_load("Classify the bug type. Return ONLY one of: off-by-one, type-error, other")
92
- fixer = paw.compile_and_load("Fix the bug described in the first line. Return only the corrected code.")
93
-
94
- label = classifier(code_snippet)
95
- if label != "other":
96
- fix = fixer(f"{label}: {code_snippet}")
97
- ```
98
-
99
- Chain them with regular Python logic.
100
-
101
- ## Log Monitoring
102
-
103
- PAW functions can classify log output. Compile once with examples from your specific logs, then reuse the function locally forever:
104
-
105
- ```python
106
- program = paw.compile("""
107
- Classify log lines. Return ONLY one word: ALERT or QUIET.
108
-
109
- Input: [step 100] loss=0.05 lr=0.0001
110
- Output: QUIET
111
-
112
- Input: [Checkpoint] Saved model at step 1000
113
- Output: ALERT
114
-
115
- Input: Traceback (most recent call last):
116
- Output: ALERT
117
-
118
- Input: Training complete. Final loss: 0.11
119
- Output: ALERT
120
- """)
121
-
122
- fn = paw.function(program.id) # reuse with saved program.id
123
- fn("[step 200] loss=0.04") # "QUIET"
124
- fn("[Checkpoint] Saved model") # "ALERT"
125
- ```
98
+ ## Common Errors
126
99
 
127
- Full tool with file watching, truncation, and stall detection: [examples/paw_monitor.py](https://github.com/programasweights/programasweights-python/blob/main/examples/paw_monitor.py)
100
+ | Error | Cause | Fix |
101
+ |-------|-------|-----|
102
+ | `RuntimeError: assets not ready` on download | Program is still generating after compile | The SDK polls automatically for up to 30s. If it still fails, retry shortly or recompile. |
103
+ | `httpx.HTTPStatusError: 422` on compile | Spec too short (<10 chars) or request validation failed | Adjust spec length or request shape. |
104
+ | `httpx.HTTPStatusError: 429` | Hosted compile API limit exceeded | Wait, or sign in for higher compile limits. |
105
+ | GPU/Metal errors on load | GPU backend not available or incompatible | Set `PAW_GPU_LAYERS=0` or pass `n_gpu_layers=0` to force CPU. |
128
106
 
129
107
  ## Browser / JavaScript SDK
130
108
 
@@ -137,11 +115,13 @@ npm install @programasweights/web
137
115
  ```javascript
138
116
  import paw from '@programasweights/web';
139
117
 
140
- const fn = await paw.function('programasweights/email-triage');
118
+ const fn = await paw.function('email-triage-browser');
141
119
  const result = await fn('Urgent: server is down!');
142
120
  // result: "immediate"
143
121
  ```
144
122
 
123
+ The browser SDK resolves slugs through the PAW API, then downloads browser assets from Hugging Face and runs inference client-side. If you load by program ID, browser inference stays independent of the PAW API at runtime.
124
+
145
125
  ## Authentication (optional)
146
126
 
147
127
  Sign in for higher rate limits and program naming. Everything works without it.
@@ -155,8 +135,11 @@ Generate API keys at https://programasweights.com/settings.
155
135
  | | Anonymous | Authenticated |
156
136
  |---|---|---|
157
137
  | Compile rate limit | 20/hr | 60/hr |
138
+ | Concurrent compile requests | 1 | 2 |
158
139
  | Name programs (slugs) | No | Yes |
159
140
 
141
+ Hosted API limits apply to compile requests. Most inference should run locally through the SDK.
142
+
160
143
  ## CLI
161
144
 
162
145
  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.
@@ -175,14 +158,14 @@ fn = paw.function("da03/word-counter@v1") # pinned to v1
175
158
  versions = paw.list_versions("da03/word-counter") # all versions
176
159
  ```
177
160
 
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).
161
+ Pinned versions (`@v1`) are immutable and cached locally forever. Bare slugs always check the server for the latest main version and fall back to cache if offline.
179
162
 
180
163
  ## Full API Reference
181
164
 
182
165
  ```python
183
166
  program = paw.compile(
184
167
  spec, # natural language specification (str)
185
- compiler="paw-4b-qwen3-0.6b",
168
+ compiler=None, # omit to use the current server default (today: paw-4b-qwen3-0.6b)
186
169
  slug=None, # URL-safe handle (requires auth)
187
170
  public=True, # list on public hub
188
171
  )
@@ -196,30 +179,57 @@ fn = paw.function("da03/my-classifier", offline=True) # skip server check
196
179
 
197
180
  result: str = fn(input_text: str, max_tokens=None, temperature=0.0)
198
181
 
199
- fn = paw.compile_and_load(spec, compiler="paw-4b-qwen3-0.6b")
182
+ fn = paw.compile_and_load(spec)
200
183
 
201
184
  versions = paw.list_versions("da03/my-classifier") # version history
202
185
  programs = paw.list_programs(sort="recent", per_page=20) # requires auth
186
+ compilers = paw.list_compilers() # discover available compilers at runtime
203
187
 
204
188
  paw.login()
205
189
  ```
206
190
 
207
- ## Common Errors
191
+ ## Chaining Functions
208
192
 
209
- | Error | Cause | Fix |
210
- |-------|-------|-----|
211
- | `RuntimeError: assets not ready` on download | Program still generating after compile | SDK polls automatically for up to 30s. If persistent, recompile. |
212
- | `httpx.HTTPStatusError: 422` on compile | Spec too short (<10 chars) | Adjust spec length. |
213
- | `httpx.HTTPStatusError: 429` | Rate limit exceeded | Wait, or sign in for higher limits. |
214
- | GPU/Metal errors on load | GPU backend not available or incompatible | Set `PAW_GPU_LAYERS=0` or pass `n_gpu_layers=0` to force CPU. |
193
+ Multiple PAW functions can be composed for multi-step tasks:
194
+
195
+ ```python
196
+ classifier = paw.compile_and_load("Classify the bug type. Return ONLY one of: off-by-one, type-error, other")
197
+ fixer = paw.compile_and_load("Fix the bug described in the first line. Return only the corrected code.")
215
198
 
216
- ## Performance
199
+ label = classifier(code_snippet)
200
+ if label != "other":
201
+ fix = fixer(f"{label}: {code_snippet}")
202
+ ```
203
+
204
+ Chain them with regular Python logic.
217
205
 
218
- - **GPU acceleration** enabled by default (`n_gpu_layers=-1`). Uses Metal on Mac, CUDA on Linux, falls back to CPU automatically. If GPU causes issues, set `PAW_GPU_LAYERS=0` or pass `n_gpu_layers=0`.
219
- - **First call** ~1-5s (loads base model). Subsequent calls ~0.05-0.5s depending on input length and GPU availability.
220
- - **Base model shared** across functions on disk. Each LoRA adapter adds ~22 MB.
221
- - **Cache**: `~/.cache/programasweights/`. Override with `PAW_CACHE_DIR`.
222
- - **Offline** after first download.
206
+ ## Worked Example: Log Monitoring
207
+
208
+ PAW functions can classify log output. Compile once with examples from your specific logs, then reuse the function locally forever:
209
+
210
+ ```python
211
+ program = paw.compile("""
212
+ Classify log lines. Return ONLY one word: ALERT or QUIET.
213
+
214
+ Input: [step 100] loss=0.05 lr=0.0001
215
+ Output: QUIET
216
+
217
+ Input: [Checkpoint] Saved model at step 1000
218
+ Output: ALERT
219
+
220
+ Input: Traceback (most recent call last):
221
+ Output: ALERT
222
+
223
+ Input: Training complete. Final loss: 0.11
224
+ Output: ALERT
225
+ """)
226
+
227
+ fn = paw.function(program.id) # reuse with saved program.id
228
+ fn("[step 200] loss=0.04") # "QUIET"
229
+ fn("[Checkpoint] Saved model") # "ALERT"
230
+ ```
231
+
232
+ Full tool with file watching, truncation, and stall detection: [examples/paw_monitor.py](https://github.com/programasweights/programasweights-python/blob/main/examples/paw_monitor.py)
223
233
 
224
234
  ## Case Studies
225
235
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: programasweights
3
- Version: 0.3.2
3
+ Version: 0.4.1
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
@@ -53,7 +53,6 @@ fn("Newsletter: spring picnic") # "wait"
53
53
  # Compile your own from a description
54
54
  program = paw.compile(
55
55
  "Fix malformed JSON: repair missing quotes and trailing commas",
56
- compiler="paw-4b-qwen3-0.6b", # or "paw-4b-gpt2" for smaller/faster
57
56
  slug="json-fixer" # optional: creates username/json-fixer handle
58
57
  )
59
58
  fn = paw.function(program.slug) # or paw.function(program.id)
@@ -64,7 +63,9 @@ fn = paw.compile_and_load("Classify sentiment as positive or negative")
64
63
  fn("I love this!") # "positive"
65
64
  ```
66
65
 
67
- ## Two Compilers
66
+ If you specifically want the smaller browser-compatible runtime, pass `compiler="paw-4b-gpt2"`. Otherwise, omit `compiler` and let the server default decide.
67
+
68
+ ## Current Public Compilers
68
69
 
69
70
 
70
71
  | | Standard (Qwen3 0.6B) | Compact (GPT-2 124M) |
@@ -76,13 +77,15 @@ fn("I love this!") # "positive"
76
77
  | Local inference | ~0.05-0.5s per call | ~0.03-0.3s per call |
77
78
  | Runs in browser | No | Yes (WebAssembly) |
78
79
 
79
- Default is Standard (Qwen3 0.6B). Use Compact (GPT-2) when you need smaller files or browser deployment.
80
+ The current server default is Standard (`paw-4b-qwen3-0.6b`). Use Compact (`paw-4b-gpt2`) when you need smaller files or browser deployment.
81
+
82
+ If you need to inspect available compiler aliases programmatically, use `paw.list_compilers()`.
80
83
 
81
84
  GPU acceleration is enabled by default (Metal on Mac, CUDA on Linux, falls back to CPU). Set `PAW_GPU_LAYERS=0` to force CPU if GPU causes issues.
82
85
 
83
86
  ## Browser SDK
84
87
 
85
- Programs compiled with GPT-2 also run entirely in the browser via WebAssembly no server needed, data never leaves the user's device.
88
+ Programs compiled with GPT-2 also run in the browser via WebAssembly. The initial model and program assets download automatically; inference then runs client-side.
86
89
 
87
90
  ```bash
88
91
  npm install @programasweights/web
@@ -91,11 +94,15 @@ npm install @programasweights/web
91
94
  ```javascript
92
95
  import paw from '@programasweights/web';
93
96
 
94
- const fn = await paw.function('programasweights/email-triage');
97
+ const fn = await paw.function('email-triage-browser');
95
98
  const result = await fn('Urgent: the server is down!');
96
99
  // result: "immediate"
97
100
  ```
98
101
 
102
+ If you load by program ID, browser inference only depends on Hugging Face-hosted assets. Slugs still need one PAW API lookup.
103
+
104
+ New browser-compatible programs are uploaded to Hugging Face asynchronously after compile. They are usually ready within a minute or two, but under load can take a few minutes, so a freshly compiled browser program may need a short wait before the JS SDK can load it.
105
+
99
106
  See the [browser SDK repo](https://github.com/programasweights/programasweights-js) for full documentation.
100
107
 
101
108
  ## Use with AI Agents
@@ -23,7 +23,6 @@ fn("Newsletter: spring picnic") # "wait"
23
23
  # Compile your own from a description
24
24
  program = paw.compile(
25
25
  "Fix malformed JSON: repair missing quotes and trailing commas",
26
- compiler="paw-4b-qwen3-0.6b", # or "paw-4b-gpt2" for smaller/faster
27
26
  slug="json-fixer" # optional: creates username/json-fixer handle
28
27
  )
29
28
  fn = paw.function(program.slug) # or paw.function(program.id)
@@ -34,7 +33,9 @@ fn = paw.compile_and_load("Classify sentiment as positive or negative")
34
33
  fn("I love this!") # "positive"
35
34
  ```
36
35
 
37
- ## Two Compilers
36
+ If you specifically want the smaller browser-compatible runtime, pass `compiler="paw-4b-gpt2"`. Otherwise, omit `compiler` and let the server default decide.
37
+
38
+ ## Current Public Compilers
38
39
 
39
40
 
40
41
  | | Standard (Qwen3 0.6B) | Compact (GPT-2 124M) |
@@ -46,13 +47,15 @@ fn("I love this!") # "positive"
46
47
  | Local inference | ~0.05-0.5s per call | ~0.03-0.3s per call |
47
48
  | Runs in browser | No | Yes (WebAssembly) |
48
49
 
49
- Default is Standard (Qwen3 0.6B). Use Compact (GPT-2) when you need smaller files or browser deployment.
50
+ The current server default is Standard (`paw-4b-qwen3-0.6b`). Use Compact (`paw-4b-gpt2`) when you need smaller files or browser deployment.
51
+
52
+ If you need to inspect available compiler aliases programmatically, use `paw.list_compilers()`.
50
53
 
51
54
  GPU acceleration is enabled by default (Metal on Mac, CUDA on Linux, falls back to CPU). Set `PAW_GPU_LAYERS=0` to force CPU if GPU causes issues.
52
55
 
53
56
  ## Browser SDK
54
57
 
55
- Programs compiled with GPT-2 also run entirely in the browser via WebAssembly no server needed, data never leaves the user's device.
58
+ Programs compiled with GPT-2 also run in the browser via WebAssembly. The initial model and program assets download automatically; inference then runs client-side.
56
59
 
57
60
  ```bash
58
61
  npm install @programasweights/web
@@ -61,11 +64,15 @@ npm install @programasweights/web
61
64
  ```javascript
62
65
  import paw from '@programasweights/web';
63
66
 
64
- const fn = await paw.function('programasweights/email-triage');
67
+ const fn = await paw.function('email-triage-browser');
65
68
  const result = await fn('Urgent: the server is down!');
66
69
  // result: "immediate"
67
70
  ```
68
71
 
72
+ If you load by program ID, browser inference only depends on Hugging Face-hosted assets. Slugs still need one PAW API lookup.
73
+
74
+ New browser-compatible programs are uploaded to Hugging Face asynchronously after compile. They are usually ready within a minute or two, but under load can take a few minutes, so a freshly compiled browser program may need a short wait before the JS SDK can load it.
75
+
69
76
  See the [browser SDK repo](https://github.com/programasweights/programasweights-js) for full documentation.
70
77
 
71
78
  ## Use with AI Agents
@@ -0,0 +1,186 @@
1
+ # ProgramAsWeights
2
+
3
+ Programs as small weight blobs; a fixed interpreter runs them.
4
+
5
+ ## Development
6
+
7
+ ```
8
+ pip install -e .
9
+ ```
10
+
11
+ ```
12
+ python test_compile.py
13
+ ```
14
+
15
+ ```
16
+ python test_execute.py
17
+ ```
18
+
19
+
20
+ ## Quickstart
21
+
22
+ ```bash
23
+ pip install programasweights
24
+ ```
25
+
26
+ ```python
27
+ import programasweights
28
+ f = programasweights.function("/path/to/weights")
29
+ print(f("Hello"))
30
+ ```
31
+
32
+ - weights = programs; base model = interpreter.
33
+ - Deterministic by default (greedy generation).
34
+
35
+ ## 🌐 Web Interface
36
+
37
+ ProgramAsWeights includes a modern web interface for easy interaction with the system. The web app provides a user-friendly way to compile specifications, test neural programs, and manage models without writing code.
38
+
39
+ ### Features
40
+
41
+ - **Interactive Model Selection**: Choose from available compiler and interpreter models
42
+ - **Natural Language Specifications**: Describe your program in plain English
43
+ - **GPT-Powered Examples**: Auto-generate test data using OpenAI's API
44
+ - **Real-time Compilation**: Compile specs into neural programs instantly
45
+ - **Interactive Testing**: Test compiled programs with custom inputs
46
+ - **Model Downloads**: Download compiled models as `.tgz` files
47
+ - **Community Sharing**: Publish and discover programs on the leaderboard
48
+
49
+ ### Quick Start
50
+
51
+ 1. **Prerequisites**: Ensure you have Python 3.8+, Node.js 16+, and npm installed
52
+
53
+ 2. **Start the application**:
54
+ ```bash
55
+ cd web-app
56
+ ./start.sh
57
+ ```
58
+
59
+ 3. **Access the interface**:
60
+ - **Web App**: http://localhost:5173
61
+ - **API Docs**: http://localhost:8000/docs
62
+
63
+ The startup script automatically:
64
+ - Installs Python and Node.js dependencies
65
+ - Starts the FastAPI backend server
66
+ - Starts the React frontend development server
67
+
68
+ ### Manual Setup (Alternative)
69
+
70
+ If you prefer manual setup:
71
+
72
+ ```bash
73
+ # Backend
74
+ cd web-app/backend
75
+ pip install -r requirements.txt
76
+ python run_server.py
77
+
78
+ # Frontend (in another terminal)
79
+ cd web-app/frontend
80
+ npm install
81
+ npm run dev
82
+ ```
83
+
84
+ ### Configuration
85
+
86
+ Create `web-app/backend/.env` with:
87
+ ```bash
88
+ OPENAI_API_KEY=your_openai_api_key_here # Optional: for GPT test generation
89
+ CHECKPOINT_DIR=../../outputs_1spec/prefix_kv # Path to trained models
90
+ ```
91
+
92
+ ### Example Workflow
93
+
94
+ 1. Select "Qwen 2.5 Coder 0.5B" as compiler and "PAW Interpreter" as interpreter
95
+ 2. Enter specification: *"Parse a string like '(A) cat (B) dog' into a JSON list"*
96
+ 3. Generate examples with GPT or add manually
97
+ 4. Click "Compile" to create your neural program
98
+ 5. Test with input: *"(A) red apple (B) green banana"*
99
+ 6. Download or publish your compiled model
100
+
101
+ For detailed documentation, see [`web-app/README.md`](web-app/README.md).
102
+
103
+ ## Train a compiler→KV prefix→interpreter (defaults)
104
+
105
+ ```bash
106
+ # installs training extras
107
+ pip install -e .[train]
108
+
109
+ # trains on data/samples_train.jsonl with Qwen defaults
110
+ paw-train
111
+ ```
112
+
113
+ - Produces checkpoint under `outputs/prefix_kv/checkpoint/`.
114
+
115
+ ## Compile then run (qualitative eval)
116
+
117
+ ```bash
118
+ # compile a prompt into a KV-prefix artifact
119
+ paw-eval
120
+ ```
121
+
122
+ Or programmatically:
123
+
124
+ ```python
125
+ import programasweights as paw
126
+
127
+ prompt = (
128
+ "Parse a string like '(A) ... (B) ... (C) ...' into a JSON list of options. "
129
+ "Be robust to noise: extra spaces, bullets, and phrases like 'both (A) and (B)'."
130
+ )
131
+
132
+ artifact_dir = paw.compile(
133
+ out_dir="outputs/prefix_kv/demo_program",
134
+ spec=prompt,
135
+ checkpoint_dir="outputs/prefix_kv/checkpoint",
136
+ )
137
+
138
+ f = paw.function(artifact_dir, interpreter_name="Qwen/Qwen2.5-Coder-0.5B-Instruct", max_new_tokens=128)
139
+ print(f("(A) cat (B) dog (C) both (A) and (B) are possible"))
140
+ ```
141
+
142
+ - The dummy compiler is still available as `compile_dummy` for tests and demos.
143
+
144
+ ## API
145
+
146
+ ```python
147
+ import programasweights
148
+ parse_func = programasweights.function(
149
+ "/path/to/weights.safetensors",
150
+ interpreter_name="google/flan-t5-small",
151
+ max_new_tokens=128,
152
+ )
153
+ output = parse_func("input string")
154
+ ```
155
+
156
+ - Accepts `str` or `List[str]` and returns the same shape.
157
+ - Aliasing works: `import programasweights as paw`.
158
+
159
+ ## Local development
160
+
161
+ ```bash
162
+ pip install -e .[test]
163
+ pytest -q
164
+ ```
165
+
166
+ ```bash
167
+ # smoke check
168
+ python -c "import programasweights as paw; print(paw.__version__)"
169
+ ```
170
+
171
+ - `pip install -e .` installs in editable mode so code changes are picked up without reinstalling.
172
+ - If you do not need editable mode: `pip install .` (you must reinstall after changes).
173
+
174
+ ## Notes
175
+
176
+ - MVP runtime uses a single in-process interpreter (loads the base model once and stays warm).
177
+ - Program artifact can be a prompt/prefix (text file) or a KV-prefix directory with `program.json` and `kv_prefix.pt`.
178
+ - Device selection: CUDA if available, else CPU. Override with env var `PROGRAMASWEIGHTS_DEVICE`.
179
+ - Simple global lock around `generate()` for thread safety.
180
+
181
+ ## Roadmap
182
+
183
+ - Compiler: spec → weights
184
+ - LoRA support
185
+ - JSON-constrained decoding
186
+ - Server mode (multi-tenant)
@@ -21,20 +21,20 @@ Pages: /playground, /hub, /browser, /docs, /settings, /about
21
21
 
22
22
  ### Attempt 2: Reframe as classification
23
23
 
24
- Instead of generating URLs, output a digit: 1 = Playground, 2 = Hub, 3 = Browser, etc. The frontend maps digits to actual routes.
24
+ Instead of generating URLs, output a short semantic label such as `playground`, `docs`, or `feedback`. The frontend maps those labels to actual destinations.
25
25
 
26
26
  ```
27
- Classify the user's intent. Return ONLY a single digit.
28
- 1 = Create or compile a new program
29
- 2 = Browse or search existing programs
30
- 3 = Run a program in the browser
27
+ Classify the user's intent. Return ONLY a single label.
28
+ playground = Create or compile a new program
29
+ hub = Browse or search existing programs
30
+ browser = Run a program in the browser
31
31
  ...
32
- 0 = None of the above
32
+ none = None of the above
33
33
  ```
34
34
 
35
35
  **Result:** Accuracy jumped from ~67% to ~88%. Classification is far more reliable than generation for routing.
36
36
 
37
- **Lesson:** Reframe generation tasks as classification whenever possible. Output a label or digit, map it to the real value in your code.
37
+ **Lesson:** Reframe generation tasks as classification whenever possible. Output a short label, map it to the real value in your code.
38
38
 
39
39
  ### Attempt 3: Add Q&A support
40
40
 
@@ -71,8 +71,8 @@ validator = paw.function("my-answer-validator")
71
71
 
72
72
  def handle_query(user_query: str):
73
73
  destination = router(user_query)
74
- if destination != "0":
75
- return {"action": "navigate", "page": PAGES[int(destination)]}
74
+ if destination != "none":
75
+ return {"action": "navigate", "page": PAGE_MAP[destination]}
76
76
 
77
77
  category = q_type(user_query)
78
78
  if category == "yes_no":
@@ -92,36 +92,36 @@ Each program has a focused spec. For example, the page classifier:
92
92
 
93
93
  ```python
94
94
  router = paw.compile("""
95
- Classify the user's intent. Return ONLY a single digit.
96
- 1 = Create or compile something new
97
- 2 = Browse or search existing items
98
- 3 = Run something in the browser
99
- 4 = Read documentation
100
- 5 = Manage account or API keys
101
- 0 = None of the above (likely a question)
95
+ Classify the user's intent. Return ONLY a single label.
96
+ playground = Create or compile something new
97
+ hub = Browse or search existing items
98
+ browser = Run something in the browser
99
+ docs = Read documentation
100
+ settings = Manage account or API keys
101
+ none = None of the above (likely a question)
102
102
 
103
103
  Input: how do I get started
104
- Output: 4
104
+ Output: docs
105
105
 
106
106
  Input: browse community programs
107
- Output: 2
107
+ Output: hub
108
108
 
109
109
  Input: is it free?
110
- Output: 0
110
+ Output: none
111
111
  """)
112
112
  ```
113
113
 
114
114
  ## Adapting this for your site
115
115
 
116
116
  1. **List your pages** with short descriptions of what users do there
117
- 2. **Compile a classifier** that maps intents to page numbers
117
+ 2. **Compile a classifier** that maps intents to short labels
118
118
  3. **Test with 20-30 real queries** your users would type — iterate on the spec wording
119
119
  4. If users also ask questions, add Q&A programs and a validator
120
120
  5. Each program compiles once and is cached forever — the pipeline runs locally with no API calls
121
121
 
122
122
  ## Takeaways
123
123
 
124
- - **Classification beats generation** for routing. Output a label, map it in code.
124
+ - **Classification beats generation** for routing. Output a short label, map it in code.
125
125
  - **Multiple small programs beat one complex program.** When accuracy drops, split.
126
126
  - **A validator catches failures** the other programs miss — cheap insurance.
127
127
  - **Iterate with real queries.** Build a small test set, measure, adjust wording, repeat.