programasweights 0.4.2__tar.gz → 0.4.4__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 (73) hide show
  1. programasweights-0.4.4/.github/workflows/test.yml +43 -0
  2. {programasweights-0.4.2 → programasweights-0.4.4}/AGENTS.md +16 -4
  3. programasweights-0.4.4/CHANGELOG.md +65 -0
  4. {programasweights-0.4.2 → programasweights-0.4.4}/PKG-INFO +25 -1
  5. {programasweights-0.4.2 → programasweights-0.4.4}/PYPI_README.md +23 -0
  6. {programasweights-0.4.2 → programasweights-0.4.4}/README.md +24 -0
  7. {programasweights-0.4.2 → programasweights-0.4.4}/docs/api-reference/cli.md +18 -3
  8. programasweights-0.4.4/docs/api-reference/python-sdk.md +244 -0
  9. {programasweights-0.4.2 → programasweights-0.4.4}/docs/api-reference/rest-api.md +6 -1
  10. programasweights-0.4.4/docs/case-studies/alien-taboo.md +117 -0
  11. {programasweights-0.4.2 → programasweights-0.4.4}/docs/getting-started/installation.md +18 -0
  12. {programasweights-0.4.2 → programasweights-0.4.4}/docs/guide/local-inference.md +9 -1
  13. {programasweights-0.4.2 → programasweights-0.4.4}/mkdocs.yml +1 -0
  14. programasweights-0.4.4/programasweights/__init__.py +645 -0
  15. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/_output.py +29 -0
  16. programasweights-0.4.4/programasweights/cache.py +1422 -0
  17. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/cli.py +82 -27
  18. programasweights-0.4.4/programasweights/client.py +722 -0
  19. programasweights-0.4.4/programasweights/runtime_llamacpp.py +568 -0
  20. {programasweights-0.4.2 → programasweights-0.4.4}/pyproject.toml +2 -1
  21. programasweights-0.4.4/tests/test_base_interpreter.py +643 -0
  22. programasweights-0.4.4/tests/test_cli_auth.py +265 -0
  23. programasweights-0.4.4/tests/test_desktop_sdk.py +1221 -0
  24. {programasweights-0.4.2 → programasweights-0.4.4}/tests/test_runtime_registry_sdk.py +46 -4
  25. {programasweights-0.4.2 → programasweights-0.4.4}/tests/test_sdk.py +60 -102
  26. programasweights-0.4.2/CHANGELOG.md +0 -32
  27. programasweights-0.4.2/docs/api-reference/python-sdk.md +0 -139
  28. programasweights-0.4.2/programasweights/__init__.py +0 -325
  29. programasweights-0.4.2/programasweights/cache.py +0 -323
  30. programasweights-0.4.2/programasweights/client.py +0 -274
  31. programasweights-0.4.2/programasweights/runtime_llamacpp.py +0 -243
  32. {programasweights-0.4.2 → programasweights-0.4.4}/.gitignore +0 -0
  33. {programasweights-0.4.2 → programasweights-0.4.4}/.readthedocs.yaml +0 -0
  34. {programasweights-0.4.2 → programasweights-0.4.4}/LICENSE +0 -0
  35. {programasweights-0.4.2 → programasweights-0.4.4}/docs/adr/001-llama-cpp-over-pytorch.md +0 -0
  36. {programasweights-0.4.2 → programasweights-0.4.4}/docs/adr/002-q4_0-adapter-format.md +0 -0
  37. {programasweights-0.4.2 → programasweights-0.4.4}/docs/adr/003-single-spec-field.md +0 -0
  38. {programasweights-0.4.2 → programasweights-0.4.4}/docs/adr/004-compiler-naming.md +0 -0
  39. {programasweights-0.4.2 → programasweights-0.4.4}/docs/adr/005-vllm-hidden-states.md +0 -0
  40. {programasweights-0.4.2 → programasweights-0.4.4}/docs/adr/006-email-api-key-auth.md +0 -0
  41. {programasweights-0.4.2 → programasweights-0.4.4}/docs/advanced/adrs.md +0 -0
  42. {programasweights-0.4.2 → programasweights-0.4.4}/docs/advanced/architecture.md +0 -0
  43. {programasweights-0.4.2 → programasweights-0.4.4}/docs/architecture.md +0 -0
  44. {programasweights-0.4.2 → programasweights-0.4.4}/docs/case-studies/log-monitoring.md +0 -0
  45. {programasweights-0.4.2 → programasweights-0.4.4}/docs/case-studies/semantic-search.md +0 -0
  46. {programasweights-0.4.2 → programasweights-0.4.4}/docs/case-studies/site-navigation.md +0 -0
  47. {programasweights-0.4.2 → programasweights-0.4.4}/docs/case-studies/tool-calling.md +0 -0
  48. {programasweights-0.4.2 → programasweights-0.4.4}/docs/getting-started/first-program.md +0 -0
  49. {programasweights-0.4.2 → programasweights-0.4.4}/docs/getting-started/naming-programs.md +0 -0
  50. {programasweights-0.4.2 → programasweights-0.4.4}/docs/guide/browser-inference.md +0 -0
  51. {programasweights-0.4.2 → programasweights-0.4.4}/docs/guide/how-it-works.md +0 -0
  52. {programasweights-0.4.2 → programasweights-0.4.4}/docs/guide/writing-good-specs.md +0 -0
  53. {programasweights-0.4.2 → programasweights-0.4.4}/docs/hub/browsing-programs.md +0 -0
  54. {programasweights-0.4.2 → programasweights-0.4.4}/docs/hub/feedback-cases.md +0 -0
  55. {programasweights-0.4.2 → programasweights-0.4.4}/docs/hub/publishing-programs.md +0 -0
  56. {programasweights-0.4.2 → programasweights-0.4.4}/docs/index.md +0 -0
  57. {programasweights-0.4.2 → programasweights-0.4.4}/docs/requirements.txt +0 -0
  58. {programasweights-0.4.2 → programasweights-0.4.4}/examples/flask_app.py +0 -0
  59. {programasweights-0.4.2 → programasweights-0.4.4}/examples/jupyter_notebook.py +0 -0
  60. {programasweights-0.4.2 → programasweights-0.4.4}/examples/langchain_integration.py +0 -0
  61. {programasweights-0.4.2 → programasweights-0.4.4}/examples/paw_monitor.py +0 -0
  62. {programasweights-0.4.2 → programasweights-0.4.4}/examples/replace_openai.py +0 -0
  63. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/artifacts.py +0 -0
  64. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/compiler/__init__.py +0 -0
  65. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/compiler/dummy.py +0 -0
  66. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/config.py +0 -0
  67. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/convert_peft_to_paw.py +0 -0
  68. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/paw_format.py +0 -0
  69. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/runtime/__init__.py +0 -0
  70. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/runtime/interpreter.py +0 -0
  71. {programasweights-0.4.2 → programasweights-0.4.4}/programasweights/runtime/interpreter_onnx.py +0 -0
  72. {programasweights-0.4.2 → programasweights-0.4.4}/tests/test_offline_cache.py +0 -0
  73. {programasweights-0.4.2 → programasweights-0.4.4}/tests/test_sdk.sh +0 -0
@@ -0,0 +1,43 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Python ${{ matrix.python-version }}
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+
23
+ - name: Install (hermetic deps only)
24
+ # Install httpx + pytest and the package itself without pulling the heavy
25
+ # llama-cpp-python build. Runtime tests inject a fake llama_cpp module,
26
+ # so CI needs neither the native extension nor a model download.
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ python -m pip install httpx pytest
30
+ python -m pip install -e . --no-deps
31
+
32
+ - name: Run hermetic tests
33
+ # Scoped to tests that need no network, no model download, and no
34
+ # PAW_API_KEY. Auth tests (@needs_auth) auto-skip without a key; the
35
+ # network/model-download tests in test_sdk.py are excluded here and can
36
+ # be run separately against a live server.
37
+ run: |
38
+ pytest \
39
+ tests/test_base_interpreter.py \
40
+ tests/test_cli_auth.py \
41
+ tests/test_desktop_sdk.py \
42
+ tests/test_runtime_registry_sdk.py \
43
+ tests/test_sdk.py::TestInstallAndImport
@@ -93,13 +93,18 @@ Output: delete
93
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
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
95
  - Cache root is `~/.cache/programasweights/`. Override with `PAW_CACHE_DIR`.
96
- - After the first download, inference works offline.
96
+ - After the first download, inference works offline. Pass `offline=True` or set
97
+ `PAW_OFFLINE=1` to prohibit network access and fail if any validated asset is
98
+ missing.
99
+ - Advanced only: `paw.function(None, interpreter="gpt2")` runs a supported
100
+ base model without a compiled adapter; consult the Python API reference for
101
+ its strict prompt and offline semantics.
97
102
 
98
103
  ## Common Errors
99
104
 
100
105
  | Error | Cause | Fix |
101
106
  |-------|-------|-----|
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. |
107
+ | `RuntimeError: assets not ready` on download | Program is still generating after compile | The SDK polls automatically for up to 60s. If it still fails, retry shortly or recompile. |
103
108
  | `httpx.HTTPStatusError: 422` on compile | Spec too short (<10 chars) or request validation failed | Adjust spec length or request shape. |
104
109
  | `httpx.HTTPStatusError: 429` | Hosted compile API limit exceeded | Wait, or sign in for higher compile limits. |
105
110
  | 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. |
@@ -142,7 +147,7 @@ Hosted API limits apply to compile requests. Most inference should run locally t
142
147
 
143
148
  ## CLI
144
149
 
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.
150
+ Commands: `paw compile --spec "..." --json`, `paw run --program <id> --input "..." [--offline]`, `paw info <id>`, `paw rename <id> <slug>`, `paw login`. All support `--json` for structured output.
146
151
 
147
152
  ## Versioning
148
153
 
@@ -164,7 +169,7 @@ Pinned versions (`@v1`) are immutable and cached locally forever. Bare slugs alw
164
169
 
165
170
  ```python
166
171
  program = paw.compile(
167
- spec, # natural language specification (str)
172
+ spec, # natural language specification (10-16000 chars)
168
173
  compiler=None, # omit to use the current server default (today: paw-4b-qwen3-0.6b)
169
174
  slug=None, # URL-safe handle (requires auth)
170
175
  public=True, # list on public hub
@@ -179,8 +184,15 @@ fn = paw.function("da03/my-classifier", offline=True) # skip server check
179
184
 
180
185
  result: str = fn(input_text: str, max_tokens=None, temperature=0.0)
181
186
 
187
+ prepared = paw.prepare_program("da03/my-classifier")
188
+ ready = paw.is_offline_ready("da03/my-classifier") # zero network
189
+ cached = paw.list_cached_programs()
190
+
182
191
  fn = paw.compile_and_load(spec)
183
192
 
193
+ job = paw.compile_async(spec, compiler="paw-ft-bs48") # explicit finetune compiler required
194
+ status = paw.get_compile_status(job["job_id"])
195
+
184
196
  versions = paw.list_versions("da03/my-classifier") # version history
185
197
  programs = paw.list_programs(sort="recent", per_page=20) # requires auth
186
198
  compilers = paw.list_compilers() # discover available compilers at runtime
@@ -0,0 +1,65 @@
1
+ # Changelog
2
+
3
+ ## 0.4.4 (2026-07-18)
4
+
5
+ - Add desktop preparation and cache inspection APIs with structured progress:
6
+ `prepare_program`, `is_offline_ready`, and `list_cached_programs`.
7
+ - Make program/runtime/model caching strict and race-safe: immutable IDs win
8
+ over slugs, streamed bundles are bounded and validated before atomic
9
+ installation, runtime manifests are versioned, prefix state is atomically
10
+ locked, and known GGUF runtimes enforce canonical size/SHA-256 metadata.
11
+ - Enforce true offline behavior through `offline=True` or `PAW_OFFLINE=1`;
12
+ missing assets now fail clearly without a network call.
13
+ - Add precheck, explicit-finetune `compile_async`, status, and cancellation
14
+ helpers for long-running compiles. Async compilation now requires a compiler
15
+ and exposes ready slug/version metadata in its typed responses.
16
+ - Extend `paw run` with mutually exclusive compiled/base routing, `--offline`,
17
+ and mode/program/interpreter fields in JSON output.
18
+ - Add an advanced, explicit adapter-free path with
19
+ `paw.function(None, interpreter=...)` for Qwen3-0.6B and GPT-2. It uses
20
+ versioned built-in prompts and never silently replaces compiled execution.
21
+ - Expand hermetic cache/runtime/CLI tests, add a fake-llama base-runtime suite,
22
+ and test Python 3.9 through 3.13 in CI.
23
+
24
+ ## 0.4.3 (2026-07-06)
25
+
26
+ - Fix `paw info` / `paw rename` crashing with `AttributeError` when run without
27
+ `--api-url`/`--api-key` (they read the removed `paw.api_url`/`paw.api_key`
28
+ module attributes; now resolved via the function-based config API).
29
+ - `--api-url` / `--api-key` now take effect on `compile`, `run`, and `login`
30
+ (previously accepted but silently ignored on those commands).
31
+ - Docs: reference `paw.get_api_url()` / `paw.get_api_key()` instead of the
32
+ removed module attributes.
33
+ - Add hermetic CLI auth test suite (`tests/test_cli_auth.py`) and a GitHub
34
+ Actions CI workflow running it on Python 3.9-3.12.
35
+
36
+ ## 0.2.4 (2026-04-01)
37
+
38
+ - Download reliability: asset endpoints return 202 Retry-After when program is still generating, eliminating 404 race conditions
39
+ - Guard local cleanup on HF upload success: files persist locally if upload fails
40
+ - Stderr suppression now covers LoRA adapter loading (fixes CPU_REPACK warnings on 0.2.3)
41
+ - Browser: fix LoRA switching bug (free old adapter + clear KV before loading new program)
42
+
43
+ ## 0.2.3 (2026-04-01)
44
+
45
+ - Python 3.9 compatibility fix (`from __future__ import annotations`)
46
+
47
+ ## 0.2.2 (2026-03-19)
48
+
49
+ - Add `paw.compile_and_load()` convenience method (compile + load in one call)
50
+ - `paw.function()` now accepts a `Program` object directly (not just string ID)
51
+ - Add `paw.list_programs()` for authenticated users to list their programs
52
+ - Suppress `llama.cpp` stderr noise by default; use `verbose=True` to enable
53
+ - Rewritten AGENTS.md with spec-writing tips, full API reference, common errors, and performance notes
54
+
55
+ ## 0.2.0 (2026-04-01)
56
+
57
+ First public release.
58
+
59
+ - Compile natural language specs into neural programs via `paw.compile()`
60
+ - Load and run programs locally via `paw.function()` (llama.cpp backend)
61
+ - HuggingFace-style slug naming: `paw.function("da03/my-classifier")`
62
+ - Offline support: slug cache + program cache, no internet after first use
63
+ - CLI: `paw compile`, `paw run`, `paw info`, `paw rename`, `paw login`
64
+ - Pre-built wheels via pypi.programasweights.com for fast install
65
+ - Privacy enforcement: private programs only accessible by owner
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: programasweights
3
- Version: 0.4.2
3
+ Version: 0.4.4
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
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.9
19
19
  Classifier: Programming Language :: Python :: 3.10
20
20
  Classifier: Programming Language :: Python :: 3.11
21
21
  Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
22
23
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
24
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
25
  Requires-Python: >=3.9
@@ -83,6 +84,28 @@ If you need to inspect available compiler aliases programmatically, use `paw.lis
83
84
 
84
85
  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.
85
86
 
87
+ ## Desktop and Offline Workflows
88
+
89
+ Prepare and inspect validated local assets without keeping a model loaded:
90
+
91
+ ```python
92
+ prepared = paw.prepare_program("da03/my-classifier")
93
+ assert prepared["offline_ready"]
94
+
95
+ fn = paw.function("da03/my-classifier", offline=True)
96
+ cached = paw.list_cached_programs()
97
+ ```
98
+
99
+ `offline=True` (or `PAW_OFFLINE=1`) makes zero network calls and fails clearly
100
+ if a required validated program, runtime, adapter, or base model is missing. Long-running
101
+ finetune compiles can be queued with
102
+ `paw.compile_async(spec, compiler="paw-ft-bs48")`; an explicit finetune
103
+ compiler is required.
104
+
105
+ Advanced adapter-free inference is available with
106
+ `paw.function(None, interpreter="gpt2")`; see the Python API reference for
107
+ its intentionally strict semantics.
108
+
86
109
  ## Browser SDK
87
110
 
88
111
  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.
@@ -140,6 +163,7 @@ Generate API keys at [programasweights.com/settings](https://programasweights.co
140
163
  ```bash
141
164
  paw compile --spec "Extract error lines from logs" --json
142
165
  paw run --program <program_id> --input "[ERROR] timeout" --json
166
+ paw run --program <program_id> --input "[ERROR] timeout" --offline --json
143
167
  paw login
144
168
  ```
145
169
 
@@ -53,6 +53,28 @@ If you need to inspect available compiler aliases programmatically, use `paw.lis
53
53
 
54
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.
55
55
 
56
+ ## Desktop and Offline Workflows
57
+
58
+ Prepare and inspect validated local assets without keeping a model loaded:
59
+
60
+ ```python
61
+ prepared = paw.prepare_program("da03/my-classifier")
62
+ assert prepared["offline_ready"]
63
+
64
+ fn = paw.function("da03/my-classifier", offline=True)
65
+ cached = paw.list_cached_programs()
66
+ ```
67
+
68
+ `offline=True` (or `PAW_OFFLINE=1`) makes zero network calls and fails clearly
69
+ if a required validated program, runtime, adapter, or base model is missing. Long-running
70
+ finetune compiles can be queued with
71
+ `paw.compile_async(spec, compiler="paw-ft-bs48")`; an explicit finetune
72
+ compiler is required.
73
+
74
+ Advanced adapter-free inference is available with
75
+ `paw.function(None, interpreter="gpt2")`; see the Python API reference for
76
+ its intentionally strict semantics.
77
+
56
78
  ## Browser SDK
57
79
 
58
80
  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.
@@ -110,6 +132,7 @@ Generate API keys at [programasweights.com/settings](https://programasweights.co
110
132
  ```bash
111
133
  paw compile --spec "Extract error lines from logs" --json
112
134
  paw run --program <program_id> --input "[ERROR] timeout" --json
135
+ paw run --program <program_id> --input "[ERROR] timeout" --offline --json
113
136
  paw login
114
137
  ```
115
138
 
@@ -53,6 +53,29 @@ If you need to inspect available compiler aliases programmatically, use `paw.lis
53
53
 
54
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.
55
55
 
56
+ ## Desktop and Offline Workflows
57
+
58
+ Prepare and inspect validated local assets without keeping a model loaded:
59
+
60
+ ```python
61
+ prepared = paw.prepare_program("da03/my-classifier")
62
+ assert prepared["offline_ready"]
63
+
64
+ fn = paw.function("da03/my-classifier", offline=True)
65
+ cached = paw.list_cached_programs()
66
+ ```
67
+
68
+ `offline=True` (or `PAW_OFFLINE=1`) makes zero network calls and fails clearly
69
+ if a required validated program, runtime, adapter, or base model is missing. Long-running
70
+ finetune compiles can be queued with
71
+ `paw.compile_async(spec, compiler="paw-ft-bs48")`; an explicit finetune
72
+ compiler is required.
73
+
74
+ Advanced adapter-free inference is available with
75
+ `paw.function(None, interpreter="gpt2")`; see the
76
+ [Python API reference](docs/api-reference/python-sdk.md#advanced-adapter-free-base-interpreter)
77
+ for its intentionally strict semantics.
78
+
56
79
  ## Browser SDK
57
80
 
58
81
  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.
@@ -110,6 +133,7 @@ Generate API keys at [programasweights.com/settings](https://programasweights.co
110
133
  ```bash
111
134
  paw compile --spec "Extract error lines from logs" --json
112
135
  paw run --program <program_id> --input "[ERROR] timeout" --json
136
+ paw run --program <program_id> --input "[ERROR] timeout" --offline --json
113
137
  paw login
114
138
  ```
115
139
 
@@ -31,20 +31,35 @@ paw compile --spec "Classify message urgency" [--compiler paw-4b-qwen3-0.6b] [--
31
31
 
32
32
  ## `paw run`
33
33
 
34
- Run inference locally against a compiled program.
34
+ Run inference locally against a compiled program (the normal mode), or
35
+ explicitly against a bare base interpreter (advanced mode).
35
36
 
36
37
  ```bash
37
- paw run --program <id_or_slug> --input "your text" [--max-tokens 512] [--temperature 0.0] [--json]
38
+ paw run --program <id_or_slug> --input "your text" [--offline] [--json]
39
+
40
+ # Advanced adapter-free mode
41
+ paw run --base --interpreter gpt2 --input "raw prompt" [--offline] [--json]
38
42
  ```
39
43
 
40
44
  | Option | Description |
41
45
  |--------|-------------|
42
46
  | `--program` | Program hash ID, slug (e.g. `da03/my-classifier`), or official name (e.g. `email-triage`). |
47
+ | `--base` | Select adapter-free base mode. Mutually exclusive with `--program` and requires `--interpreter`. |
48
+ | `--interpreter` | Base interpreter: `Qwen/Qwen3-0.6B` or `gpt2`. Only valid with `--base`. |
43
49
  | `--input` | Input text for the program. |
44
50
  | `--max-tokens` | Maximum tokens to generate (default: 512). |
45
51
  | `--temperature` | Sampling temperature (default: 0.0). |
46
52
  | `--verbose` | Print llama.cpp debug output. |
47
- | `--json` | JSON output with `program`, `input`, `output`. |
53
+ | `--offline` | Require all selected assets to already be cached and make zero network calls. |
54
+ | `--json` | JSON output with `mode`, `program`, `interpreter`, `input`, and `output`. |
55
+
56
+ Exactly one of `--program` and `--base` is required. An empty or
57
+ whitespace-only `--program` is rejected. Base mode makes no PAW API, slug,
58
+ program, adapter, or prefix-cache calls; online it may download only the
59
+ selected base GGUF. It resets state and tokenizes the complete versioned
60
+ runtime prompt on every invocation. See the
61
+ [Python SDK reference](python-sdk.md#advanced-adapter-free-base-interpreter)
62
+ for the exact prompt bytes and error semantics.
48
63
 
49
64
  ## `paw rename`
50
65
 
@@ -0,0 +1,244 @@
1
+ # Python SDK Reference
2
+
3
+ The `programasweights` package compiles natural language specs into neural programs that run locally.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install programasweights --extra-index-url https://pypi.programasweights.com/simple/
9
+ ```
10
+
11
+ ## Import
12
+
13
+ ```python
14
+ import programasweights as paw
15
+ ```
16
+
17
+ ## `paw.function`
18
+
19
+ ```python
20
+ fn = paw.function(
21
+ program_id,
22
+ n_ctx=2048,
23
+ n_gpu_layers=None,
24
+ verbose=False,
25
+ offline=False,
26
+ *,
27
+ interpreter=None,
28
+ )
29
+ ```
30
+
31
+ Loads a compiled program and returns a callable. Downloads the program and base model on first use; cached locally after that. Works offline after first download.
32
+
33
+ | Parameter | Description |
34
+ |-----------|-------------|
35
+ | `program_id` | Required. A `Program` object, hash ID (e.g. `a6b454023d41ac9ca845`), slug (e.g. `da03/my-classifier`), or official shorthand (e.g. `email-triage`). A `Program` resolves by immutable `id`, not its mutable slug. |
36
+ | `n_ctx` | Context length for the local runtime (default `2048`). |
37
+ | `n_gpu_layers` | GPU layers to offload (`0` = CPU-only, `-1` = all). The default is `-1`, or `PAW_GPU_LAYERS` when set. |
38
+ | `verbose` | Enable verbose logging (default `False`). |
39
+ | `offline` | Require all program/runtime/model assets to already be cached and make zero network calls. `PAW_OFFLINE=1` has the same effect. |
40
+ | `interpreter` | Advanced adapter-free mode only. Must be passed by keyword and only when `program_id` is explicitly `None`. Supported values are `Qwen/Qwen3-0.6B` and `gpt2`. |
41
+
42
+ The returned callable:
43
+
44
+ ```python
45
+ output: str = fn(input_text, max_tokens=None, temperature=0.0)
46
+ ```
47
+
48
+ | Parameter | Description |
49
+ |-----------|-------------|
50
+ | `input_text` | Input string for the program. |
51
+ | `max_tokens` | Maximum tokens to generate. `None` (default) = use all remaining context window. |
52
+ | `temperature` | Sampling temperature (default `0.0`). |
53
+
54
+ **Context limits:** Spec + input + output share a ~2048 token window. Inputs that exceed it will error. `max_tokens` defaults to `None`: generation runs until EOS or the context limit.
55
+
56
+ Compiled mode is strict: the adapter, prompt template, matching metadata,
57
+ runtime manifest, and runtime-compatible base-model file must all validate. Version 0.4.4
58
+ accepts runtime manifest version 1 with `adapter_format="gguf_lora"`.
59
+ Built-in models are checked against pinned size/SHA-256 metadata and GGUF
60
+ magic. Historical manifests for those known runtime IDs are normalized to the
61
+ same canonical integrity metadata, so missing server-side checksum fields
62
+ cannot weaken validation. Missing or failed adapters raise an error; the SDK
63
+ never silently falls back to an unadapted base model.
64
+
65
+ ### Advanced: adapter-free base interpreter
66
+
67
+ Pass explicit `None` plus an interpreter to run the supported base GGUF without a compiled PAW program:
68
+
69
+ ```python
70
+ base = paw.function(None, interpreter="gpt2")
71
+ output = base("raw prompt text")
72
+ ```
73
+
74
+ This mode is intentionally explicit:
75
+
76
+ - `paw.function()` still requires the `program_id` argument.
77
+ - `program_id=None` without `interpreter` raises `ValueError`.
78
+ - `program_id=""` raises `ValueError` and explains that base mode requires explicit `None`.
79
+ - A non-empty program reference together with `interpreter` raises `ValueError`.
80
+ - No PAW API, slug lookup, program download, adapter load, or disk prefix cache is used.
81
+ - Online mode may download only the selected base GGUF from its built-in runtime manifest. Offline mode never downloads.
82
+ - Every invocation resets model state, renders the complete prompt, and tokenizes that complete rendered prompt in one call.
83
+
84
+ The built-in prompt contract is versioned with each runtime manifest and must contain exactly one `{INPUT_PLACEHOLDER}`:
85
+
86
+ ```text
87
+ # Qwen/Qwen3-0.6B
88
+ <|im_start|>user
89
+ {INPUT_PLACEHOLDER}<|im_end|>
90
+ <|im_start|>assistant
91
+ <think>
92
+
93
+ </think>
94
+
95
+
96
+ # gpt2
97
+ {INPUT_PLACEHOLDER}
98
+ ```
99
+
100
+ The Qwen bytes are the exact raw-user rendering of
101
+ `apply_chat_template(add_generation_prompt=True, enable_thinking=False)`.
102
+ Zero-token prompts and prompts that consume the full context window raise
103
+ `ValueError`.
104
+
105
+ ## Preparing programs for offline use
106
+
107
+ ```python
108
+ prepared = paw.prepare_program("da03/my-classifier")
109
+ assert prepared["offline_ready"]
110
+
111
+ ready = paw.is_offline_ready("da03/my-classifier") # local check; no network
112
+ cached = paw.list_cached_programs()
113
+ ```
114
+
115
+ `prepare_program` resolves and downloads the program, runtime manifest, and shared base model without retaining a loaded `PawFunction`. Pass `offline=True` to require an already complete local cache and prohibit network access.
116
+
117
+ Desktop applications can receive structured progress without parsing stderr:
118
+
119
+ ```python
120
+ paw.prepare_program(
121
+ "da03/my-classifier",
122
+ progress=lambda event: print(event["stage"], event["status"]),
123
+ )
124
+ ```
125
+
126
+ Without a callback, downloads keep using the existing CLI-style status output on stderr.
127
+
128
+ ## `paw.compile`
129
+
130
+ ```python
131
+ program = paw.compile(
132
+ spec,
133
+ compiler="paw-4b-qwen3-0.6b",
134
+ name=None,
135
+ tags=None,
136
+ public=True,
137
+ slug=None,
138
+ )
139
+ ```
140
+
141
+ Compiles a natural language spec on the server. Returns a `Program` object.
142
+
143
+ | Parameter | Description |
144
+ |-----------|-------------|
145
+ | `spec` | Natural language specification (10-16000 chars). |
146
+ | `compiler` | Compiler name: `paw-4b-qwen3-0.6b` (Standard) or `paw-4b-gpt2` (Compact). |
147
+ | `name` | Display title for the hub (auto-generated if omitted). |
148
+ | `tags` | Tags for discovery (list of strings, max 10). |
149
+ | `public` | Whether to list on the public hub (default `True`). |
150
+ | `slug` | URL-safe handle (e.g. `my-classifier`). Creates a `username/slug` alias. Requires authentication. |
151
+
152
+ **Return value** -- `Program` object:
153
+
154
+ | Attribute | Description |
155
+ |-----------|-------------|
156
+ | `id` | Hash-based program identifier. Use with `paw.function(program.id)`. |
157
+ | `slug` | Full slug handle (e.g. `da03/my-classifier`) if one was created, `None` otherwise. |
158
+ | `status` | `"ready"` on success, `"failed"` on error. |
159
+ | `compiler_snapshot` | Exact compiler version used. |
160
+ | `timings` | Timing metadata from the server. |
161
+ | `error` | Error message when compilation fails. |
162
+
163
+ ## Long-running compile jobs
164
+
165
+ The asynchronous compile endpoint is available through both `PAWClient` and top-level helpers:
166
+
167
+ ```python
168
+ check = paw.precheck_compile(SPEC, compiler="paw-ft-bs48")
169
+ job = paw.compile_async(
170
+ SPEC,
171
+ compiler="paw-ft-bs48",
172
+ public=False,
173
+ )
174
+
175
+ status = paw.get_compile_status(job["job_id"])
176
+ if status["status"] == "queued":
177
+ paw.cancel_compile(job["job_id"])
178
+ ```
179
+
180
+ `compile_async` requires an explicit finetune compiler. It submits the request synchronously and returns the queued job metadata immediately; mapper compilers must use `compile`. Poll `get_compile_status` for `queued`, `compiling`, `ready`, `failed`, or `cancelled`. Ready status data includes the immutable program ID and, when naming was requested, `slug`, `version`, and `version_action`.
181
+
182
+ Status and cancellation requests must use the same authenticated account as
183
+ submission. Anonymous jobs are bound to the validated client IP that submitted
184
+ them.
185
+
186
+ ## `paw.compile_and_load`
187
+
188
+ ```python
189
+ fn = paw.compile_and_load(spec, compiler="paw-4b-qwen3-0.6b", **kwargs)
190
+ ```
191
+
192
+ Convenience method that compiles a spec and immediately loads the result for local inference. Equivalent to `paw.function(paw.compile(spec, ...).id)`. Returns a callable.
193
+
194
+ Accepts all the same parameters as `paw.compile`.
195
+
196
+ ## `paw.list_programs`
197
+
198
+ ```python
199
+ result = paw.list_programs(sort="recent", per_page=20)
200
+ ```
201
+
202
+ Returns a dict with the authenticated user's compiled programs. Requires authentication.
203
+
204
+ | Parameter | Description |
205
+ |-----------|-------------|
206
+ | `sort` | Sort order: `"recent"` (default), `"votes"`, `"recommended"`. |
207
+ | `per_page` | Number of results per page (default `20`). |
208
+
209
+ **Return value** -- dict:
210
+
211
+ | Key | Description |
212
+ |-----|-------------|
213
+ | `programs` | List of program dicts with `id`, `spec`, `name`, `compiler`, etc. |
214
+ | `total` | Total number of programs. |
215
+
216
+ ## `paw.login`
217
+
218
+ ```python
219
+ paw.login(key=None)
220
+ ```
221
+
222
+ Saves an API key for authenticated requests. If `key` is provided, saves it directly. If omitted, opens the browser to generate a key at `programasweights.com/settings`.
223
+
224
+ Keys are stored in `~/.config/programasweights/config.json` and loaded automatically on subsequent imports.
225
+
226
+ You can also set the `PAW_API_KEY` environment variable instead:
227
+
228
+ ```bash
229
+ export PAW_API_KEY=paw_sk_...
230
+ ```
231
+
232
+ ## Configuration
233
+
234
+ | Name | Description |
235
+ |------|-------------|
236
+ | `paw.get_api_url()` | Base URL for API requests. Default: `https://programasweights.com`. Override with `PAW_API_URL` env var. |
237
+ | `paw.get_api_key()` | API key for authenticated calls. Set via `paw.login()` or `PAW_API_KEY` env var. |
238
+ | `paw.__version__` | Installed package version string. |
239
+
240
+ ## Related
241
+
242
+ - [CLI Reference](cli.md)
243
+ - [REST API Reference](rest-api.md)
244
+ - [Naming Programs](../getting-started/naming-programs.md)
@@ -158,7 +158,12 @@ Successful responses may include:
158
158
  | `X-RateLimit-Limit` | Maximum requests per window. |
159
159
  | `X-RateLimit-Remaining` | Remaining requests in the current window. |
160
160
 
161
- Clients should backoff when receiving `429 Too Many Requests` and respect `Retry-After` when present.
161
+ Hosted compile quotas:
162
+
163
+ - Anonymous: **20 compiles/hour**, **1 concurrent compile**
164
+ - Authenticated: **60 compiles/hour**, **2 concurrent compiles**
165
+
166
+ Hosted server-side endpoints may also enforce additional operational concurrency or safety limits. Clients should back off when receiving `429 Too Many Requests` and respect `Retry-After` when present.
162
167
 
163
168
  ## Related
164
169