programasweights 0.4.3__tar.gz → 0.4.5__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 (80) hide show
  1. programasweights-0.4.5/.github/workflows/test.yml +82 -0
  2. {programasweights-0.4.3 → programasweights-0.4.5}/AGENTS.md +16 -4
  3. programasweights-0.4.5/CHANGELOG.md +79 -0
  4. {programasweights-0.4.3 → programasweights-0.4.5}/PKG-INFO +40 -3
  5. {programasweights-0.4.3 → programasweights-0.4.5}/PYPI_README.md +37 -1
  6. {programasweights-0.4.3 → programasweights-0.4.5}/README.md +38 -1
  7. {programasweights-0.4.3 → programasweights-0.4.5}/docs/api-reference/cli.md +18 -3
  8. programasweights-0.4.5/docs/api-reference/python-sdk.md +329 -0
  9. {programasweights-0.4.3 → programasweights-0.4.5}/docs/getting-started/installation.md +18 -0
  10. {programasweights-0.4.3 → programasweights-0.4.5}/docs/guide/local-inference.md +9 -1
  11. programasweights-0.4.5/programasweights/__init__.py +668 -0
  12. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/_output.py +29 -0
  13. programasweights-0.4.5/programasweights/_program_reference.py +61 -0
  14. programasweights-0.4.5/programasweights/cache.py +1422 -0
  15. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/cli.py +66 -3
  16. programasweights-0.4.5/programasweights/client.py +726 -0
  17. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/convert_peft_to_paw.py +12 -14
  18. programasweights-0.4.5/programasweights/errors.py +79 -0
  19. programasweights-0.4.5/programasweights/local_program.py +196 -0
  20. programasweights-0.4.5/programasweights/runtime_llamacpp.py +568 -0
  21. {programasweights-0.4.3 → programasweights-0.4.5}/pyproject.toml +2 -1
  22. programasweights-0.4.5/tests/test_api_errors.py +222 -0
  23. programasweights-0.4.5/tests/test_base_interpreter.py +643 -0
  24. {programasweights-0.4.3 → programasweights-0.4.5}/tests/test_cli_auth.py +79 -0
  25. programasweights-0.4.5/tests/test_compile_timeouts.py +129 -0
  26. programasweights-0.4.5/tests/test_desktop_sdk.py +1221 -0
  27. programasweights-0.4.5/tests/test_local_program.py +676 -0
  28. {programasweights-0.4.3 → programasweights-0.4.5}/tests/test_runtime_registry_sdk.py +46 -4
  29. programasweights-0.4.3/.github/workflows/test.yml +0 -41
  30. programasweights-0.4.3/CHANGELOG.md +0 -44
  31. programasweights-0.4.3/docs/api-reference/python-sdk.md +0 -139
  32. programasweights-0.4.3/programasweights/__init__.py +0 -325
  33. programasweights-0.4.3/programasweights/cache.py +0 -323
  34. programasweights-0.4.3/programasweights/client.py +0 -274
  35. programasweights-0.4.3/programasweights/runtime_llamacpp.py +0 -243
  36. {programasweights-0.4.3 → programasweights-0.4.5}/.gitignore +0 -0
  37. {programasweights-0.4.3 → programasweights-0.4.5}/.readthedocs.yaml +0 -0
  38. {programasweights-0.4.3 → programasweights-0.4.5}/LICENSE +0 -0
  39. {programasweights-0.4.3 → programasweights-0.4.5}/docs/adr/001-llama-cpp-over-pytorch.md +0 -0
  40. {programasweights-0.4.3 → programasweights-0.4.5}/docs/adr/002-q4_0-adapter-format.md +0 -0
  41. {programasweights-0.4.3 → programasweights-0.4.5}/docs/adr/003-single-spec-field.md +0 -0
  42. {programasweights-0.4.3 → programasweights-0.4.5}/docs/adr/004-compiler-naming.md +0 -0
  43. {programasweights-0.4.3 → programasweights-0.4.5}/docs/adr/005-vllm-hidden-states.md +0 -0
  44. {programasweights-0.4.3 → programasweights-0.4.5}/docs/adr/006-email-api-key-auth.md +0 -0
  45. {programasweights-0.4.3 → programasweights-0.4.5}/docs/advanced/adrs.md +0 -0
  46. {programasweights-0.4.3 → programasweights-0.4.5}/docs/advanced/architecture.md +0 -0
  47. {programasweights-0.4.3 → programasweights-0.4.5}/docs/api-reference/rest-api.md +0 -0
  48. {programasweights-0.4.3 → programasweights-0.4.5}/docs/architecture.md +0 -0
  49. {programasweights-0.4.3 → programasweights-0.4.5}/docs/case-studies/alien-taboo.md +0 -0
  50. {programasweights-0.4.3 → programasweights-0.4.5}/docs/case-studies/log-monitoring.md +0 -0
  51. {programasweights-0.4.3 → programasweights-0.4.5}/docs/case-studies/semantic-search.md +0 -0
  52. {programasweights-0.4.3 → programasweights-0.4.5}/docs/case-studies/site-navigation.md +0 -0
  53. {programasweights-0.4.3 → programasweights-0.4.5}/docs/case-studies/tool-calling.md +0 -0
  54. {programasweights-0.4.3 → programasweights-0.4.5}/docs/getting-started/first-program.md +0 -0
  55. {programasweights-0.4.3 → programasweights-0.4.5}/docs/getting-started/naming-programs.md +0 -0
  56. {programasweights-0.4.3 → programasweights-0.4.5}/docs/guide/browser-inference.md +0 -0
  57. {programasweights-0.4.3 → programasweights-0.4.5}/docs/guide/how-it-works.md +0 -0
  58. {programasweights-0.4.3 → programasweights-0.4.5}/docs/guide/writing-good-specs.md +0 -0
  59. {programasweights-0.4.3 → programasweights-0.4.5}/docs/hub/browsing-programs.md +0 -0
  60. {programasweights-0.4.3 → programasweights-0.4.5}/docs/hub/feedback-cases.md +0 -0
  61. {programasweights-0.4.3 → programasweights-0.4.5}/docs/hub/publishing-programs.md +0 -0
  62. {programasweights-0.4.3 → programasweights-0.4.5}/docs/index.md +0 -0
  63. {programasweights-0.4.3 → programasweights-0.4.5}/docs/requirements.txt +0 -0
  64. {programasweights-0.4.3 → programasweights-0.4.5}/examples/flask_app.py +0 -0
  65. {programasweights-0.4.3 → programasweights-0.4.5}/examples/jupyter_notebook.py +0 -0
  66. {programasweights-0.4.3 → programasweights-0.4.5}/examples/langchain_integration.py +0 -0
  67. {programasweights-0.4.3 → programasweights-0.4.5}/examples/paw_monitor.py +0 -0
  68. {programasweights-0.4.3 → programasweights-0.4.5}/examples/replace_openai.py +0 -0
  69. {programasweights-0.4.3 → programasweights-0.4.5}/mkdocs.yml +0 -0
  70. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/artifacts.py +0 -0
  71. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/compiler/__init__.py +0 -0
  72. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/compiler/dummy.py +0 -0
  73. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/config.py +0 -0
  74. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/paw_format.py +0 -0
  75. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/runtime/__init__.py +0 -0
  76. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/runtime/interpreter.py +0 -0
  77. {programasweights-0.4.3 → programasweights-0.4.5}/programasweights/runtime/interpreter_onnx.py +0 -0
  78. {programasweights-0.4.3 → programasweights-0.4.5}/tests/test_offline_cache.py +0 -0
  79. {programasweights-0.4.3 → programasweights-0.4.5}/tests/test_sdk.py +0 -0
  80. {programasweights-0.4.3 → programasweights-0.4.5}/tests/test_sdk.sh +0 -0
@@ -0,0 +1,82 @@
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_api_errors.py \
40
+ tests/test_compile_timeouts.py \
41
+ tests/test_local_program.py \
42
+ tests/test_base_interpreter.py \
43
+ tests/test_cli_auth.py \
44
+ tests/test_desktop_sdk.py \
45
+ tests/test_runtime_registry_sdk.py \
46
+ tests/test_sdk.py::TestInstallAndImport
47
+
48
+ local-files-windows:
49
+ runs-on: windows-latest
50
+ strategy:
51
+ fail-fast: false
52
+ matrix:
53
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+ - uses: actions/setup-python@v5
57
+ with:
58
+ python-version: ${{ matrix.python-version }}
59
+ - name: Install hermetic test dependencies
60
+ run: |
61
+ python -m pip install httpx pytest
62
+ python -m pip install -e . --no-deps
63
+ - name: Test Windows local paths, cache locks, and compile errors
64
+ run: python -m pytest tests/test_api_errors.py tests/test_compile_timeouts.py tests/test_local_program.py --junitxml=test-results.xml
65
+ - name: Annotate Windows test failures
66
+ if: failure()
67
+ shell: python
68
+ run: |
69
+ from pathlib import Path
70
+ import xml.etree.ElementTree as ET
71
+
72
+ report = Path("test-results.xml")
73
+ if report.exists():
74
+ for case in ET.parse(report).iter("testcase"):
75
+ for result in case:
76
+ if result.tag in {"failure", "error"}:
77
+ # GitHub truncates annotations, so retain the actual
78
+ # exception at the end of long pytest tracebacks.
79
+ detail = result.text or result.get("message", "")
80
+ message = f"{case.get('name')}: {detail[-3500:]}"
81
+ message = message.replace("%", "%25").replace("\r", "%0D").replace("\n", "%0A")
82
+ print(f"::error::{message}")
@@ -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,79 @@
1
+ # Changelog
2
+
3
+ ## 0.4.5 (2026-09-10)
4
+
5
+ - Expose structured compile API failures as `paw.APIError`, compatible with
6
+ `httpx.HTTPStatusError`, preserving server code, message, request ID, and the
7
+ original response. Transport errors propagate unchanged; no automatic retries.
8
+ - Allow synchronous compilation a 2,400-second read timeout while keeping
9
+ connect, write, and pool timeouts at 120 seconds. Async submission stays at
10
+ 30 seconds; precheck, status, and cancellation stay at 10 seconds.
11
+ - Load current GGUF ZIP `.paw` files through `paw.function` using explicit
12
+ local paths or `Path` objects. Validated imports use a separate SHA-256 cache
13
+ without replacing Hub caches or source files; invalid local files never fall
14
+ back to Hub lookup. Shared base-model assets may still need downloading unless
15
+ offline mode is requested. Legacy tensor-format `.paw` files are unsupported.
16
+
17
+ ## 0.4.4 (2026-07-18)
18
+
19
+ - Add desktop preparation and cache inspection APIs with structured progress:
20
+ `prepare_program`, `is_offline_ready`, and `list_cached_programs`.
21
+ - Make program/runtime/model caching strict and race-safe: immutable IDs win
22
+ over slugs, streamed bundles are bounded and validated before atomic
23
+ installation, runtime manifests are versioned, prefix state is atomically
24
+ locked, and known GGUF runtimes enforce canonical size/SHA-256 metadata.
25
+ - Enforce true offline behavior through `offline=True` or `PAW_OFFLINE=1`;
26
+ missing assets now fail clearly without a network call.
27
+ - Add precheck, explicit-finetune `compile_async`, status, and cancellation
28
+ helpers for long-running compiles. Async compilation now requires a compiler
29
+ and exposes ready slug/version metadata in its typed responses.
30
+ - Extend `paw run` with mutually exclusive compiled/base routing, `--offline`,
31
+ and mode/program/interpreter fields in JSON output.
32
+ - Add an advanced, explicit adapter-free path with
33
+ `paw.function(None, interpreter=...)` for Qwen3-0.6B and GPT-2. It uses
34
+ versioned built-in prompts and never silently replaces compiled execution.
35
+ - Expand hermetic cache/runtime/CLI tests, add a fake-llama base-runtime suite,
36
+ and test Python 3.9 through 3.13 in CI.
37
+
38
+ ## 0.4.3 (2026-07-06)
39
+
40
+ - Fix `paw info` / `paw rename` crashing with `AttributeError` when run without
41
+ `--api-url`/`--api-key` (they read the removed `paw.api_url`/`paw.api_key`
42
+ module attributes; now resolved via the function-based config API).
43
+ - `--api-url` / `--api-key` now take effect on `compile`, `run`, and `login`
44
+ (previously accepted but silently ignored on those commands).
45
+ - Docs: reference `paw.get_api_url()` / `paw.get_api_key()` instead of the
46
+ removed module attributes.
47
+ - Add hermetic CLI auth test suite (`tests/test_cli_auth.py`) and a GitHub
48
+ Actions CI workflow running it on Python 3.9-3.12.
49
+
50
+ ## 0.2.4 (2026-04-01)
51
+
52
+ - Download reliability: asset endpoints return 202 Retry-After when program is still generating, eliminating 404 race conditions
53
+ - Guard local cleanup on HF upload success: files persist locally if upload fails
54
+ - Stderr suppression now covers LoRA adapter loading (fixes CPU_REPACK warnings on 0.2.3)
55
+ - Browser: fix LoRA switching bug (free old adapter + clear KV before loading new program)
56
+
57
+ ## 0.2.3 (2026-04-01)
58
+
59
+ - Python 3.9 compatibility fix (`from __future__ import annotations`)
60
+
61
+ ## 0.2.2 (2026-03-19)
62
+
63
+ - Add `paw.compile_and_load()` convenience method (compile + load in one call)
64
+ - `paw.function()` now accepts a `Program` object directly (not just string ID)
65
+ - Add `paw.list_programs()` for authenticated users to list their programs
66
+ - Suppress `llama.cpp` stderr noise by default; use `verbose=True` to enable
67
+ - Rewritten AGENTS.md with spec-writing tips, full API reference, common errors, and performance notes
68
+
69
+ ## 0.2.0 (2026-04-01)
70
+
71
+ First public release.
72
+
73
+ - Compile natural language specs into neural programs via `paw.compile()`
74
+ - Load and run programs locally via `paw.function()` (llama.cpp backend)
75
+ - HuggingFace-style slug naming: `paw.function("da03/my-classifier")`
76
+ - Offline support: slug cache + program cache, no internet after first use
77
+ - CLI: `paw compile`, `paw run`, `paw info`, `paw rename`, `paw login`
78
+ - Pre-built wheels via pypi.programasweights.com for fast install
79
+ - Privacy enforcement: private programs only accessible by owner
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: programasweights
3
- Version: 0.4.3
3
+ Version: 0.4.5
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,41 @@ 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
+ Load a saved current GGUF ZIP `.paw` bundle directly (SDK 0.4.5+):
106
+
107
+ ```python
108
+ from pathlib import Path
109
+ fn = paw.function(Path("classifier.paw"))
110
+ ```
111
+
112
+ Local files are validated into a separate SHA-256 cache without changing the
113
+ source or falling back to Hub lookup. Runtime metadata or the shared base model
114
+ may still download; `offline=True` prohibits those requests. Legacy tensor-format
115
+ `.paw` files are unsupported. Local-file inputs are supported by `function`,
116
+ not `prepare_program` or `is_offline_ready`.
117
+
118
+ Advanced adapter-free inference is available with
119
+ `paw.function(None, interpreter="gpt2")`; see the Python API reference for
120
+ its intentionally strict semantics.
121
+
86
122
  ## Browser SDK
87
123
 
88
124
  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 +176,7 @@ Generate API keys at [programasweights.com/settings](https://programasweights.co
140
176
  ```bash
141
177
  paw compile --spec "Extract error lines from logs" --json
142
178
  paw run --program <program_id> --input "[ERROR] timeout" --json
179
+ paw run --program <program_id> --input "[ERROR] timeout" --offline --json
143
180
  paw login
144
181
  ```
145
182
 
@@ -155,4 +192,4 @@ paw login
155
192
 
156
193
  ## License
157
194
 
158
- MIT
195
+ MIT
@@ -53,6 +53,41 @@ 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
+ Load a saved current GGUF ZIP `.paw` bundle directly (SDK 0.4.5+):
75
+
76
+ ```python
77
+ from pathlib import Path
78
+ fn = paw.function(Path("classifier.paw"))
79
+ ```
80
+
81
+ Local files are validated into a separate SHA-256 cache without changing the
82
+ source or falling back to Hub lookup. Runtime metadata or the shared base model
83
+ may still download; `offline=True` prohibits those requests. Legacy tensor-format
84
+ `.paw` files are unsupported. Local-file inputs are supported by `function`,
85
+ not `prepare_program` or `is_offline_ready`.
86
+
87
+ Advanced adapter-free inference is available with
88
+ `paw.function(None, interpreter="gpt2")`; see the Python API reference for
89
+ its intentionally strict semantics.
90
+
56
91
  ## Browser SDK
57
92
 
58
93
  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 +145,7 @@ Generate API keys at [programasweights.com/settings](https://programasweights.co
110
145
  ```bash
111
146
  paw compile --spec "Extract error lines from logs" --json
112
147
  paw run --program <program_id> --input "[ERROR] timeout" --json
148
+ paw run --program <program_id> --input "[ERROR] timeout" --offline --json
113
149
  paw login
114
150
  ```
115
151
 
@@ -125,4 +161,4 @@ paw login
125
161
 
126
162
  ## License
127
163
 
128
- MIT
164
+ MIT
@@ -53,6 +53,42 @@ 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
+ Load a saved current GGUF ZIP `.paw` bundle directly (SDK 0.4.5+):
75
+
76
+ ```python
77
+ from pathlib import Path
78
+ fn = paw.function(Path("classifier.paw"))
79
+ ```
80
+
81
+ Local files are validated into a separate SHA-256 cache without changing the
82
+ source or falling back to Hub lookup. Runtime metadata or the shared base model
83
+ may still download; `offline=True` prohibits those requests. Legacy tensor-format
84
+ `.paw` files are unsupported. Local-file inputs are supported by `function`,
85
+ not `prepare_program` or `is_offline_ready`.
86
+
87
+ Advanced adapter-free inference is available with
88
+ `paw.function(None, interpreter="gpt2")`; see the
89
+ [Python API reference](docs/api-reference/python-sdk.md#advanced-adapter-free-base-interpreter)
90
+ for its intentionally strict semantics.
91
+
56
92
  ## Browser SDK
57
93
 
58
94
  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 +146,7 @@ Generate API keys at [programasweights.com/settings](https://programasweights.co
110
146
  ```bash
111
147
  paw compile --spec "Extract error lines from logs" --json
112
148
  paw run --program <program_id> --input "[ERROR] timeout" --json
149
+ paw run --program <program_id> --input "[ERROR] timeout" --offline --json
113
150
  paw login
114
151
  ```
115
152
 
@@ -125,4 +162,4 @@ paw login
125
162
 
126
163
  ## License
127
164
 
128
- MIT
165
+ MIT
@@ -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