programasweights 0.4.3__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 (72) hide show
  1. {programasweights-0.4.3 → programasweights-0.4.4}/.github/workflows/test.yml +5 -3
  2. {programasweights-0.4.3 → programasweights-0.4.4}/AGENTS.md +16 -4
  3. {programasweights-0.4.3 → programasweights-0.4.4}/CHANGELOG.md +21 -0
  4. {programasweights-0.4.3 → programasweights-0.4.4}/PKG-INFO +25 -1
  5. {programasweights-0.4.3 → programasweights-0.4.4}/PYPI_README.md +23 -0
  6. {programasweights-0.4.3 → programasweights-0.4.4}/README.md +24 -0
  7. {programasweights-0.4.3 → 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.3 → programasweights-0.4.4}/docs/getting-started/installation.md +18 -0
  10. {programasweights-0.4.3 → programasweights-0.4.4}/docs/guide/local-inference.md +9 -1
  11. programasweights-0.4.4/programasweights/__init__.py +645 -0
  12. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/_output.py +29 -0
  13. programasweights-0.4.4/programasweights/cache.py +1422 -0
  14. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/cli.py +66 -3
  15. programasweights-0.4.4/programasweights/client.py +722 -0
  16. programasweights-0.4.4/programasweights/runtime_llamacpp.py +568 -0
  17. {programasweights-0.4.3 → programasweights-0.4.4}/pyproject.toml +2 -1
  18. programasweights-0.4.4/tests/test_base_interpreter.py +643 -0
  19. {programasweights-0.4.3 → programasweights-0.4.4}/tests/test_cli_auth.py +79 -0
  20. programasweights-0.4.4/tests/test_desktop_sdk.py +1221 -0
  21. {programasweights-0.4.3 → programasweights-0.4.4}/tests/test_runtime_registry_sdk.py +46 -4
  22. programasweights-0.4.3/docs/api-reference/python-sdk.md +0 -139
  23. programasweights-0.4.3/programasweights/__init__.py +0 -325
  24. programasweights-0.4.3/programasweights/cache.py +0 -323
  25. programasweights-0.4.3/programasweights/client.py +0 -274
  26. programasweights-0.4.3/programasweights/runtime_llamacpp.py +0 -243
  27. {programasweights-0.4.3 → programasweights-0.4.4}/.gitignore +0 -0
  28. {programasweights-0.4.3 → programasweights-0.4.4}/.readthedocs.yaml +0 -0
  29. {programasweights-0.4.3 → programasweights-0.4.4}/LICENSE +0 -0
  30. {programasweights-0.4.3 → programasweights-0.4.4}/docs/adr/001-llama-cpp-over-pytorch.md +0 -0
  31. {programasweights-0.4.3 → programasweights-0.4.4}/docs/adr/002-q4_0-adapter-format.md +0 -0
  32. {programasweights-0.4.3 → programasweights-0.4.4}/docs/adr/003-single-spec-field.md +0 -0
  33. {programasweights-0.4.3 → programasweights-0.4.4}/docs/adr/004-compiler-naming.md +0 -0
  34. {programasweights-0.4.3 → programasweights-0.4.4}/docs/adr/005-vllm-hidden-states.md +0 -0
  35. {programasweights-0.4.3 → programasweights-0.4.4}/docs/adr/006-email-api-key-auth.md +0 -0
  36. {programasweights-0.4.3 → programasweights-0.4.4}/docs/advanced/adrs.md +0 -0
  37. {programasweights-0.4.3 → programasweights-0.4.4}/docs/advanced/architecture.md +0 -0
  38. {programasweights-0.4.3 → programasweights-0.4.4}/docs/api-reference/rest-api.md +0 -0
  39. {programasweights-0.4.3 → programasweights-0.4.4}/docs/architecture.md +0 -0
  40. {programasweights-0.4.3 → programasweights-0.4.4}/docs/case-studies/alien-taboo.md +0 -0
  41. {programasweights-0.4.3 → programasweights-0.4.4}/docs/case-studies/log-monitoring.md +0 -0
  42. {programasweights-0.4.3 → programasweights-0.4.4}/docs/case-studies/semantic-search.md +0 -0
  43. {programasweights-0.4.3 → programasweights-0.4.4}/docs/case-studies/site-navigation.md +0 -0
  44. {programasweights-0.4.3 → programasweights-0.4.4}/docs/case-studies/tool-calling.md +0 -0
  45. {programasweights-0.4.3 → programasweights-0.4.4}/docs/getting-started/first-program.md +0 -0
  46. {programasweights-0.4.3 → programasweights-0.4.4}/docs/getting-started/naming-programs.md +0 -0
  47. {programasweights-0.4.3 → programasweights-0.4.4}/docs/guide/browser-inference.md +0 -0
  48. {programasweights-0.4.3 → programasweights-0.4.4}/docs/guide/how-it-works.md +0 -0
  49. {programasweights-0.4.3 → programasweights-0.4.4}/docs/guide/writing-good-specs.md +0 -0
  50. {programasweights-0.4.3 → programasweights-0.4.4}/docs/hub/browsing-programs.md +0 -0
  51. {programasweights-0.4.3 → programasweights-0.4.4}/docs/hub/feedback-cases.md +0 -0
  52. {programasweights-0.4.3 → programasweights-0.4.4}/docs/hub/publishing-programs.md +0 -0
  53. {programasweights-0.4.3 → programasweights-0.4.4}/docs/index.md +0 -0
  54. {programasweights-0.4.3 → programasweights-0.4.4}/docs/requirements.txt +0 -0
  55. {programasweights-0.4.3 → programasweights-0.4.4}/examples/flask_app.py +0 -0
  56. {programasweights-0.4.3 → programasweights-0.4.4}/examples/jupyter_notebook.py +0 -0
  57. {programasweights-0.4.3 → programasweights-0.4.4}/examples/langchain_integration.py +0 -0
  58. {programasweights-0.4.3 → programasweights-0.4.4}/examples/paw_monitor.py +0 -0
  59. {programasweights-0.4.3 → programasweights-0.4.4}/examples/replace_openai.py +0 -0
  60. {programasweights-0.4.3 → programasweights-0.4.4}/mkdocs.yml +0 -0
  61. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/artifacts.py +0 -0
  62. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/compiler/__init__.py +0 -0
  63. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/compiler/dummy.py +0 -0
  64. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/config.py +0 -0
  65. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/convert_peft_to_paw.py +0 -0
  66. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/paw_format.py +0 -0
  67. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/runtime/__init__.py +0 -0
  68. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/runtime/interpreter.py +0 -0
  69. {programasweights-0.4.3 → programasweights-0.4.4}/programasweights/runtime/interpreter_onnx.py +0 -0
  70. {programasweights-0.4.3 → programasweights-0.4.4}/tests/test_offline_cache.py +0 -0
  71. {programasweights-0.4.3 → programasweights-0.4.4}/tests/test_sdk.py +0 -0
  72. {programasweights-0.4.3 → programasweights-0.4.4}/tests/test_sdk.sh +0 -0
@@ -11,7 +11,7 @@ jobs:
11
11
  strategy:
12
12
  fail-fast: false
13
13
  matrix:
14
- python-version: ["3.9", "3.10", "3.11", "3.12"]
14
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
15
15
  steps:
16
16
  - uses: actions/checkout@v4
17
17
 
@@ -22,8 +22,8 @@ jobs:
22
22
 
23
23
  - name: Install (hermetic deps only)
24
24
  # Install httpx + pytest and the package itself without pulling the heavy
25
- # llama-cpp-python build. The hermetic tests below never import the
26
- # llama.cpp runtime (it is imported lazily only when running inference).
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
27
  run: |
28
28
  python -m pip install --upgrade pip
29
29
  python -m pip install httpx pytest
@@ -36,6 +36,8 @@ jobs:
36
36
  # be run separately against a live server.
37
37
  run: |
38
38
  pytest \
39
+ tests/test_base_interpreter.py \
39
40
  tests/test_cli_auth.py \
41
+ tests/test_desktop_sdk.py \
40
42
  tests/test_runtime_registry_sdk.py \
41
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
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
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
+
3
24
  ## 0.4.3 (2026-07-06)
4
25
 
5
26
  - Fix `paw info` / `paw rename` crashing with `AttributeError` when run without
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: programasweights
3
- Version: 0.4.3
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)
@@ -11,6 +11,10 @@ The `--extra-index-url` flag provides pre-built binaries for `llama-cpp-python`,
11
11
  ## Requirements
12
12
 
13
13
  - **Python:** 3.9 through 3.13.
14
+ - **Local runtime:** `llama-cpp-python` is installed with the package.
15
+
16
+ GPU offload defaults to all available layers (`n_gpu_layers=-1`). Set
17
+ `PAW_GPU_LAYERS=0` to force CPU-only execution.
14
18
 
15
19
  ## Anaconda on Linux: OpenMP / libgomp errors
16
20
 
@@ -27,6 +31,20 @@ CMAKE_ARGS="-DGGML_OPENMP=OFF" pip install programasweights --extra-index-url ht
27
31
  | `~/.cache/programasweights/` | Downloaded models and compiled programs |
28
32
  | `~/.config/programasweights/` | Local configuration |
29
33
 
34
+ Program bundles, runtime manifests, slug mappings, and base models are
35
+ validated before use and installed with atomic cache updates. Built-in base
36
+ models must match their pinned Hugging Face LFS byte size and SHA-256 digest
37
+ and have GGUF magic; adapters must also be nontrivial GGUF files. To prohibit
38
+ all network access, pass `offline=True` to
39
+ `paw.function`/`paw.prepare_program` or set:
40
+
41
+ ```bash
42
+ export PAW_OFFLINE=1
43
+ ```
44
+
45
+ Offline mode fails clearly when any required validated bundle, runtime
46
+ manifest, adapter, or base-model file is missing.
47
+
30
48
  ## Verify the install
31
49
 
32
50
  ```bash
@@ -22,8 +22,9 @@ Common options exposed by the runtime include:
22
22
  | Option | Role |
23
23
  |--------|------|
24
24
  | `n_ctx` | Context window size (default often **2048**). |
25
- | `n_gpu_layers` | Offload layers to **Metal** or **CUDA** when available. |
25
+ | `n_gpu_layers` | Offload layers to **Metal** or **CUDA** when available (default **-1**, all layers). |
26
26
  | `verbose` | Enable detailed logging from the inference backend. |
27
+ | `offline` | Prohibit network access and require validated cached assets. |
27
28
 
28
29
  Exact names and defaults follow the SDK; refer to the package API for the authoritative list.
29
30
 
@@ -35,6 +36,13 @@ Models and program bundles are stored under:
35
36
 
36
37
  Manage disk usage by removing cached files there if you need to reclaim space or force a fresh download.
37
38
 
39
+ Downloads use unique staging directories and per-program locks. The SDK
40
+ streams `.paw` bytes directly to staging with a compressed-size cap, then
41
+ validates adapter, prompt, metadata, member-count, and expansion limits before
42
+ atomically installing them. Incomplete or stale files are never treated as a
43
+ runnable program. Built-in base GGUFs are checked against canonical pinned byte
44
+ sizes and SHA-256 digests before use.
45
+
38
46
  ## Backend
39
47
 
40
48
  Inference uses **llama.cpp**. Platform-specific optimizations (Metal on Apple GPUs, CUDA on NVIDIA, SIMD such as AVX on CPU) are selected by the build you install; you do not configure those low-level details separately.