zelt-ai 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zelt_ai-0.2.1/LICENSE +21 -0
- zelt_ai-0.2.1/PKG-INFO +307 -0
- zelt_ai-0.2.1/README.md +250 -0
- zelt_ai-0.2.1/earlystop/__init__.py +74 -0
- zelt_ai-0.2.1/earlystop/__main__.py +6 -0
- zelt_ai-0.2.1/earlystop/adapters.py +8 -0
- zelt_ai-0.2.1/earlystop/answers.py +5 -0
- zelt_ai-0.2.1/earlystop/api.py +19 -0
- zelt_ai-0.2.1/earlystop/cli.py +8 -0
- zelt_ai-0.2.1/earlystop/core.py +5 -0
- zelt_ai-0.2.1/earlystop/decider.py +31 -0
- zelt_ai-0.2.1/earlystop/synthetic.py +5 -0
- zelt_ai-0.2.1/earlystop/web.py +5 -0
- zelt_ai-0.2.1/pyproject.toml +99 -0
- zelt_ai-0.2.1/setup.cfg +4 -0
- zelt_ai-0.2.1/tests/test_answers.py +33 -0
- zelt_ai-0.2.1/tests/test_api.py +53 -0
- zelt_ai-0.2.1/tests/test_compat.py +59 -0
- zelt_ai-0.2.1/tests/test_decider.py +40 -0
- zelt_ai-0.2.1/tests/test_factories.py +112 -0
- zelt_ai-0.2.1/tests/test_features.py +37 -0
- zelt_ai-0.2.1/zelt/__init__.py +380 -0
- zelt_ai-0.2.1/zelt/__main__.py +3 -0
- zelt_ai-0.2.1/zelt/adapters.py +236 -0
- zelt_ai-0.2.1/zelt/answers.py +75 -0
- zelt_ai-0.2.1/zelt/api.py +882 -0
- zelt_ai-0.2.1/zelt/cli.py +449 -0
- zelt_ai-0.2.1/zelt/core.py +261 -0
- zelt_ai-0.2.1/zelt/data/decider.joblib +0 -0
- zelt_ai-0.2.1/zelt/data/gsm8k_real_deepseek_r1.jsonl +1319 -0
- zelt_ai-0.2.1/zelt/data/pretrained_decider.joblib +0 -0
- zelt_ai-0.2.1/zelt/data/report.json +1573 -0
- zelt_ai-0.2.1/zelt/data/report.png +0 -0
- zelt_ai-0.2.1/zelt/data/summary.csv +6 -0
- zelt_ai-0.2.1/zelt/decider.py +577 -0
- zelt_ai-0.2.1/zelt/py.typed +0 -0
- zelt_ai-0.2.1/zelt/server.py +155 -0
- zelt_ai-0.2.1/zelt/synthetic.py +56 -0
- zelt_ai-0.2.1/zelt/web.py +571 -0
- zelt_ai-0.2.1/zelt_ai.egg-info/PKG-INFO +307 -0
- zelt_ai-0.2.1/zelt_ai.egg-info/SOURCES.txt +43 -0
- zelt_ai-0.2.1/zelt_ai.egg-info/dependency_links.txt +1 -0
- zelt_ai-0.2.1/zelt_ai.egg-info/entry_points.txt +3 -0
- zelt_ai-0.2.1/zelt_ai.egg-info/requires.txt +31 -0
- zelt_ai-0.2.1/zelt_ai.egg-info/top_level.txt +2 -0
zelt_ai-0.2.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Zelt Authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
zelt_ai-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zelt-ai
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Calibrated, risk-controlled early exit for reasoning LLMs — stop thinking when the answer is ready
|
|
5
|
+
Author-email: "Ulavayya K. Karaguppi" <ulaveshk2@gmail.com>
|
|
6
|
+
Maintainer-email: "Ulavayya K. Karaguppi" <ulaveshk2@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/codewithulavesh/zelt
|
|
9
|
+
Project-URL: Documentation, https://github.com/codewithulavesh/zelt/blob/main/DOCUMENTATION.md
|
|
10
|
+
Project-URL: Repository, https://github.com/codewithulavesh/zelt.git
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/codewithulavesh/zelt/issues
|
|
12
|
+
Project-URL: Research Paper, https://github.com/codewithulavesh/zelt/blob/main/PAPER.md
|
|
13
|
+
Project-URL: Changelog, https://github.com/codewithulavesh/zelt/blob/main/CHANGELOG.md
|
|
14
|
+
Keywords: llm,early-exit,reasoning,efficiency,deepseek,deepseek-r1,cot,conformal-prediction,risk-control,test-time-compute,nlp,ai
|
|
15
|
+
Classifier: Development Status :: 4 - Beta
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Science/Research
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.9
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: numpy
|
|
30
|
+
Requires-Dist: scipy
|
|
31
|
+
Requires-Dist: scikit-learn
|
|
32
|
+
Requires-Dist: joblib
|
|
33
|
+
Requires-Dist: matplotlib
|
|
34
|
+
Provides-Extra: model
|
|
35
|
+
Requires-Dist: torch; extra == "model"
|
|
36
|
+
Requires-Dist: transformers>=4.45; extra == "model"
|
|
37
|
+
Requires-Dist: datasets; extra == "model"
|
|
38
|
+
Provides-Extra: server
|
|
39
|
+
Requires-Dist: fastapi; extra == "server"
|
|
40
|
+
Requires-Dist: uvicorn; extra == "server"
|
|
41
|
+
Provides-Extra: full
|
|
42
|
+
Requires-Dist: torch; extra == "full"
|
|
43
|
+
Requires-Dist: transformers>=4.45; extra == "full"
|
|
44
|
+
Requires-Dist: datasets; extra == "full"
|
|
45
|
+
Requires-Dist: fastapi; extra == "full"
|
|
46
|
+
Requires-Dist: uvicorn; extra == "full"
|
|
47
|
+
Requires-Dist: rich; extra == "full"
|
|
48
|
+
Requires-Dist: pydantic; extra == "full"
|
|
49
|
+
Provides-Extra: dev
|
|
50
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
51
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
52
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
53
|
+
Requires-Dist: mypy>=1.8; extra == "dev"
|
|
54
|
+
Requires-Dist: build; extra == "dev"
|
|
55
|
+
Requires-Dist: twine; extra == "dev"
|
|
56
|
+
Dynamic: license-file
|
|
57
|
+
|
|
58
|
+
# zelt ⚡
|
|
59
|
+
|
|
60
|
+
[](https://pypi.org/project/zelt/)
|
|
61
|
+
[](https://www.python.org/downloads/)
|
|
62
|
+
[](https://opensource.org/licenses/MIT)
|
|
63
|
+
[](paper/zelt_paper.tex)
|
|
64
|
+
|
|
65
|
+
**Calibrated, risk-controlled early exit for reasoning LLMs.**
|
|
66
|
+
|
|
67
|
+
Stops a reasoning model's chain-of-thought (CoT) once a learned decider is confident the answer is already correct — with a mathematically certified bound on potential accuracy loss ($\alpha \le 2\%$).
|
|
68
|
+
|
|
69
|
+
- **100% Local**: Runs on Apple Silicon MPS, CUDA, or CPU. No OpenAI/GPT API needed.
|
|
70
|
+
- **Pretrained & Calibrated**: Bundles a ready-to-use decider trained on real DeepSeek-R1 trajectories.
|
|
71
|
+
- **Zero Configuration**: Just import `zelt` and call.
|
|
72
|
+
- **Production-Ready**: Live streaming, batching, side-by-side comparison, dataset auditing, cost & carbon calculators, local web UI, Ollama/vLLM adapters, and Prometheus metrics.
|
|
73
|
+
- 📖 **Full Documentation**: See [DOCUMENTATION.md](DOCUMENTATION.md) for complete technical reference.
|
|
74
|
+
- 📄 **Research Paper**: Full LaTeX manuscript with Clopper-Pearson derivations available in [paper/zelt_paper.tex](paper/zelt_paper.tex).
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🚀 Installation & PyPI
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Core package (benchmark, calibration, bundled decider, CPU):
|
|
82
|
+
pip install zelt-ai
|
|
83
|
+
|
|
84
|
+
# With local HuggingFace inference (DeepSeek-R1 on MPS / CUDA):
|
|
85
|
+
pip install "zelt-ai[model]"
|
|
86
|
+
|
|
87
|
+
# Full installation (server + web studio + ML):
|
|
88
|
+
pip install "zelt-ai[full]"
|
|
89
|
+
|
|
90
|
+
# For local development from source:
|
|
91
|
+
pip install -e .
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 💻 Python API Features
|
|
97
|
+
|
|
98
|
+
### 1. One-Liner Quickstart (`ask`)
|
|
99
|
+
```python
|
|
100
|
+
from zelt import ask
|
|
101
|
+
|
|
102
|
+
answer = ask("What is 17 * 23?")
|
|
103
|
+
print(answer) # "391"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 2. Side-by-Side Comparison (`compare`)
|
|
107
|
+
Compare Full unconstrained CoT vs. Zelt Early-Exit side-by-side:
|
|
108
|
+
```python
|
|
109
|
+
import zelt
|
|
110
|
+
|
|
111
|
+
comp = zelt.compare("What is 17 * 23?")
|
|
112
|
+
print(comp.summary())
|
|
113
|
+
```
|
|
114
|
+
**Output:**
|
|
115
|
+
```text
|
|
116
|
+
════════════════════════════════════════════════════════════
|
|
117
|
+
Zelt Side-by-Side Comparison
|
|
118
|
+
────────────────────────────────────────────────────────────
|
|
119
|
+
Question : What is 17 * 23?
|
|
120
|
+
Full CoT Answer : 391 (576 tokens, 2.10s)
|
|
121
|
+
Zelt Answer : 391 (144 tokens, 0.54s)
|
|
122
|
+
Agreement : MATCH (Exact)
|
|
123
|
+
Tokens Saved : 432 (75.0%)
|
|
124
|
+
Effective Speedup: 3.89x faster
|
|
125
|
+
════════════════════════════════════════════════════════════
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 3. Wrap Functions with `@zelt.accelerate`
|
|
129
|
+
Automatically accelerate any reasoning function or query pipeline:
|
|
130
|
+
```python
|
|
131
|
+
import zelt
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@zelt.accelerate
|
|
135
|
+
def reason(prompt: str) -> str:
|
|
136
|
+
return "fallback"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
print(reason("What is 15 * 15?")) # "225" (exits early with saved compute)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 4. Benchmark & Risk Audit (`evaluate`)
|
|
143
|
+
Run formal finite-sample risk evaluation with Clopper-Pearson bounds:
|
|
144
|
+
```python
|
|
145
|
+
import zelt
|
|
146
|
+
|
|
147
|
+
# Evaluates on real test trajectories and computes exact harm UCB
|
|
148
|
+
report = zelt.evaluate(limit=50)
|
|
149
|
+
print(report.summary())
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 5. Live Token Streaming (`stream`)
|
|
153
|
+
Stream reasoning tokens live with probe pulses and instant early exits:
|
|
154
|
+
```python
|
|
155
|
+
from zelt import stream
|
|
156
|
+
|
|
157
|
+
for chunk in stream("A train leaves Chicago travelling at 60 mph..."):
|
|
158
|
+
if chunk.is_probe:
|
|
159
|
+
print(f" [Probe gm={chunk.confidence:.2f}]", end="", flush=True)
|
|
160
|
+
elif chunk.stopped:
|
|
161
|
+
print(f"\n⚡ Stopped early at token {chunk.token_count}! Answer: {chunk.answer}")
|
|
162
|
+
break
|
|
163
|
+
else:
|
|
164
|
+
print(chunk.text, end="", flush=True)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 6. Batch Inference & Cost Tracking (`batch`)
|
|
168
|
+
Process queries in bulk with financial and environmental savings telemetry:
|
|
169
|
+
```python
|
|
170
|
+
from zelt import batch
|
|
171
|
+
|
|
172
|
+
questions = ["What is 17 * 23?", "Solve 3x + 9 = 24.", "What is 15% of 240?"]
|
|
173
|
+
results = batch(questions)
|
|
174
|
+
print(results.summary())
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 7. Model Presets (`list_presets`)
|
|
178
|
+
```python
|
|
179
|
+
import zelt
|
|
180
|
+
|
|
181
|
+
print(zelt.list_presets())
|
|
182
|
+
# Supports: DeepSeek-R1-Distill-Qwen (1.5B, 7B), DeepSeek-R1-Distill-Llama-8B, Qwen2.5-Math-7B
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### 6. Integrating into Large LLM Systems
|
|
186
|
+
|
|
187
|
+
#### Option A: Inside Existing HuggingFace `model.generate(...)`
|
|
188
|
+
Attach Zelt directly to standard HuggingFace models via `StoppingCriteria`:
|
|
189
|
+
```python
|
|
190
|
+
from transformers import AutoModelForCausalLM, AutoTokenizer, StoppingCriteriaList
|
|
191
|
+
from zelt import ZeltStoppingCriteria, StopDecider
|
|
192
|
+
|
|
193
|
+
model = AutoModelForCausalLM.from_pretrained("deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B")
|
|
194
|
+
tokenizer = AutoTokenizer.from_pretrained("deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B")
|
|
195
|
+
|
|
196
|
+
criteria = ZeltStoppingCriteria(tokenizer, decider=StopDecider.load())
|
|
197
|
+
|
|
198
|
+
# Zelt interrupts generation the moment the answer is certified confident!
|
|
199
|
+
outputs = model.generate(
|
|
200
|
+
input_ids, max_new_tokens=2048, stopping_criteria=StoppingCriteriaList([criteria])
|
|
201
|
+
)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### Option B: Inside an API Service / FastAPI Backend
|
|
205
|
+
```python
|
|
206
|
+
from fastapi import FastAPI
|
|
207
|
+
from zelt import reduce_compute_thinking
|
|
208
|
+
|
|
209
|
+
app = FastAPI()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@app.post("/solve")
|
|
213
|
+
async def solve(prompt: str):
|
|
214
|
+
# Replaces unconstrained 2,000-token CoT with risk-controlled early exit
|
|
215
|
+
res = reduce_compute_thinking(prompt, verbose=False)
|
|
216
|
+
return {
|
|
217
|
+
"answer": str(res),
|
|
218
|
+
"tokens_saved": res.tokens_saved,
|
|
219
|
+
"saved_pct": res.saved_pct,
|
|
220
|
+
"stopped_early": res.stopped,
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### Option C: Inside AI Agent Frameworks (LangChain / AutoGen / CrewAI)
|
|
225
|
+
```python
|
|
226
|
+
from zelt import reduce_compute_thinking
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class ReasoningTool:
|
|
230
|
+
"""Agent tool for complex math & logic sub-tasks without burning token budget."""
|
|
231
|
+
|
|
232
|
+
def run(self, sub_question: str) -> str:
|
|
233
|
+
return str(reduce_compute_thinking(sub_question, verbose=False))
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 🖥️ Interactive Web UI Dashboard
|
|
239
|
+
|
|
240
|
+
Launch a local visualizer with a live token stream, confidence gauges, and token comparison bars:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
zelt ui --port 8000
|
|
244
|
+
```
|
|
245
|
+
Open **`http://localhost:8000`** in your browser.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## 📊 Proven Results — Real DeepSeek-R1 on GSM8K (1,319 Real Trajectories)
|
|
250
|
+
|
|
251
|
+
Evaluated on held-out test split (331 questions) from real DeepSeek-R1-Distill-Qwen-1.5B runs:
|
|
252
|
+
|
|
253
|
+
| Method | Threshold ($\tau$) | Accuracy | $\Delta$ Acc | Avg Tokens | Token Reduction | Net (inc. probes) | Stop Rate | Harm Rate |
|
|
254
|
+
| :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
|
|
255
|
+
| **Full CoT (baseline)** | — | **78.25%** | baseline | 750.7 | 0.0% | 0.0% | 0.0% | 0.00% |
|
|
256
|
+
| Fixed Budget | 1,632 | 76.74% | -1.51% | 507.7 | 32.4% | 21.5% | 15.1% | 1.51% |
|
|
257
|
+
| Raw Confidence | 0.79 | 78.25% | +0.00% | 430.6 | 42.6% | 33.4% | 40.2% | 0.00% |
|
|
258
|
+
| **Learned Decider (zelt)** | **0.50** | **78.25%** | **+0.00%** | **465.9** | **37.9%** | **27.9%** | **37.8%** | **0.00%** |
|
|
259
|
+
|
|
260
|
+
- **37.9% compute reduction** (1.61× speedup)
|
|
261
|
+
- **Zero accuracy drop** (78.25% retained)
|
|
262
|
+
- **0.00% empirical harm** on test set (certified $\le 2\%$ at 90% confidence)
|
|
263
|
+
- **AUROC = 0.9976** and **ECE = 0.014** (3× better calibration than raw confidence)
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 🛠️ CLI Reference
|
|
268
|
+
|
|
269
|
+
| Command | Description |
|
|
270
|
+
|:---|:---|
|
|
271
|
+
| `zelt ui` | Launch local interactive web studio at `http://localhost:8000` |
|
|
272
|
+
| `zelt ask -q "..."` | Run early-exit inference on a single question |
|
|
273
|
+
| `zelt stream -q "..."` | Stream tokens live with intermediate probe confidence |
|
|
274
|
+
| `zelt batch -i questions.txt` | Run batch inference on a text file with cost metrics |
|
|
275
|
+
| `zelt benchmark` | Evaluate compute reduction on real bundled DeepSeek-R1 data |
|
|
276
|
+
| `zelt fit --inp <path>` | Train decider + calibrate threshold on custom runs |
|
|
277
|
+
| `zelt live-eval` | Live early-exit generation on held-out test split |
|
|
278
|
+
| `zelt demo -q "..."` | Side-by-side full vs early-exit comparison |
|
|
279
|
+
| `zelt selftest` | GPU-free pipeline check on synthetic data |
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## 🔬 How It Works
|
|
284
|
+
|
|
285
|
+
```text
|
|
286
|
+
Prompt ──> DeepSeek-R1 (Local MPS / CUDA / Ollama)
|
|
287
|
+
│
|
|
288
|
+
├── [Every 48 tokens] ──> Lightweight Probe (greedy decode ~10 tokens)
|
|
289
|
+
│ │
|
|
290
|
+
│ Extract: 18 signals (geometric-mean prob,
|
|
291
|
+
│ entropy, answer stability,
|
|
292
|
+
│ confidence acceleration)
|
|
293
|
+
│ │
|
|
294
|
+
│ Decider: P(correct | features)
|
|
295
|
+
│ │
|
|
296
|
+
│ P(correct) ≥ τ ?
|
|
297
|
+
│ ┌───────┴───────┐
|
|
298
|
+
│ YES NO
|
|
299
|
+
│ │ │
|
|
300
|
+
│ STOP EARLY ⚡ Keep thinking...
|
|
301
|
+
│ (Return probed ans)
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
1. **Periodic Probes**: Every $k$ tokens, a lightweight probe attempts greedy extraction of the intermediate answer.
|
|
305
|
+
2. **Feature Extraction**: Captures 18 signals including confidence geometric mean, sequence entropy, stability across consecutive probes, and confidence acceleration.
|
|
306
|
+
3. **Calibrated Decider**: Uses scikit-learn logistic regression with Clopper-Pearson risk control to find threshold $\tau$ bounding harm rate $\le \alpha$ (default 2%) with $(1-\delta)$ confidence (default 90%).
|
|
307
|
+
4. **Adaptive Early Stop**: Halts CoT generation the moment certainty is proven, saving ~40% tokens without harming answer quality.
|
zelt_ai-0.2.1/README.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# zelt ⚡
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/zelt/)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](paper/zelt_paper.tex)
|
|
7
|
+
|
|
8
|
+
**Calibrated, risk-controlled early exit for reasoning LLMs.**
|
|
9
|
+
|
|
10
|
+
Stops a reasoning model's chain-of-thought (CoT) once a learned decider is confident the answer is already correct — with a mathematically certified bound on potential accuracy loss ($\alpha \le 2\%$).
|
|
11
|
+
|
|
12
|
+
- **100% Local**: Runs on Apple Silicon MPS, CUDA, or CPU. No OpenAI/GPT API needed.
|
|
13
|
+
- **Pretrained & Calibrated**: Bundles a ready-to-use decider trained on real DeepSeek-R1 trajectories.
|
|
14
|
+
- **Zero Configuration**: Just import `zelt` and call.
|
|
15
|
+
- **Production-Ready**: Live streaming, batching, side-by-side comparison, dataset auditing, cost & carbon calculators, local web UI, Ollama/vLLM adapters, and Prometheus metrics.
|
|
16
|
+
- 📖 **Full Documentation**: See [DOCUMENTATION.md](DOCUMENTATION.md) for complete technical reference.
|
|
17
|
+
- 📄 **Research Paper**: Full LaTeX manuscript with Clopper-Pearson derivations available in [paper/zelt_paper.tex](paper/zelt_paper.tex).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 🚀 Installation & PyPI
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Core package (benchmark, calibration, bundled decider, CPU):
|
|
25
|
+
pip install zelt-ai
|
|
26
|
+
|
|
27
|
+
# With local HuggingFace inference (DeepSeek-R1 on MPS / CUDA):
|
|
28
|
+
pip install "zelt-ai[model]"
|
|
29
|
+
|
|
30
|
+
# Full installation (server + web studio + ML):
|
|
31
|
+
pip install "zelt-ai[full]"
|
|
32
|
+
|
|
33
|
+
# For local development from source:
|
|
34
|
+
pip install -e .
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 💻 Python API Features
|
|
40
|
+
|
|
41
|
+
### 1. One-Liner Quickstart (`ask`)
|
|
42
|
+
```python
|
|
43
|
+
from zelt import ask
|
|
44
|
+
|
|
45
|
+
answer = ask("What is 17 * 23?")
|
|
46
|
+
print(answer) # "391"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 2. Side-by-Side Comparison (`compare`)
|
|
50
|
+
Compare Full unconstrained CoT vs. Zelt Early-Exit side-by-side:
|
|
51
|
+
```python
|
|
52
|
+
import zelt
|
|
53
|
+
|
|
54
|
+
comp = zelt.compare("What is 17 * 23?")
|
|
55
|
+
print(comp.summary())
|
|
56
|
+
```
|
|
57
|
+
**Output:**
|
|
58
|
+
```text
|
|
59
|
+
════════════════════════════════════════════════════════════
|
|
60
|
+
Zelt Side-by-Side Comparison
|
|
61
|
+
────────────────────────────────────────────────────────────
|
|
62
|
+
Question : What is 17 * 23?
|
|
63
|
+
Full CoT Answer : 391 (576 tokens, 2.10s)
|
|
64
|
+
Zelt Answer : 391 (144 tokens, 0.54s)
|
|
65
|
+
Agreement : MATCH (Exact)
|
|
66
|
+
Tokens Saved : 432 (75.0%)
|
|
67
|
+
Effective Speedup: 3.89x faster
|
|
68
|
+
════════════════════════════════════════════════════════════
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 3. Wrap Functions with `@zelt.accelerate`
|
|
72
|
+
Automatically accelerate any reasoning function or query pipeline:
|
|
73
|
+
```python
|
|
74
|
+
import zelt
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@zelt.accelerate
|
|
78
|
+
def reason(prompt: str) -> str:
|
|
79
|
+
return "fallback"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
print(reason("What is 15 * 15?")) # "225" (exits early with saved compute)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 4. Benchmark & Risk Audit (`evaluate`)
|
|
86
|
+
Run formal finite-sample risk evaluation with Clopper-Pearson bounds:
|
|
87
|
+
```python
|
|
88
|
+
import zelt
|
|
89
|
+
|
|
90
|
+
# Evaluates on real test trajectories and computes exact harm UCB
|
|
91
|
+
report = zelt.evaluate(limit=50)
|
|
92
|
+
print(report.summary())
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 5. Live Token Streaming (`stream`)
|
|
96
|
+
Stream reasoning tokens live with probe pulses and instant early exits:
|
|
97
|
+
```python
|
|
98
|
+
from zelt import stream
|
|
99
|
+
|
|
100
|
+
for chunk in stream("A train leaves Chicago travelling at 60 mph..."):
|
|
101
|
+
if chunk.is_probe:
|
|
102
|
+
print(f" [Probe gm={chunk.confidence:.2f}]", end="", flush=True)
|
|
103
|
+
elif chunk.stopped:
|
|
104
|
+
print(f"\n⚡ Stopped early at token {chunk.token_count}! Answer: {chunk.answer}")
|
|
105
|
+
break
|
|
106
|
+
else:
|
|
107
|
+
print(chunk.text, end="", flush=True)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 6. Batch Inference & Cost Tracking (`batch`)
|
|
111
|
+
Process queries in bulk with financial and environmental savings telemetry:
|
|
112
|
+
```python
|
|
113
|
+
from zelt import batch
|
|
114
|
+
|
|
115
|
+
questions = ["What is 17 * 23?", "Solve 3x + 9 = 24.", "What is 15% of 240?"]
|
|
116
|
+
results = batch(questions)
|
|
117
|
+
print(results.summary())
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 7. Model Presets (`list_presets`)
|
|
121
|
+
```python
|
|
122
|
+
import zelt
|
|
123
|
+
|
|
124
|
+
print(zelt.list_presets())
|
|
125
|
+
# Supports: DeepSeek-R1-Distill-Qwen (1.5B, 7B), DeepSeek-R1-Distill-Llama-8B, Qwen2.5-Math-7B
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 6. Integrating into Large LLM Systems
|
|
129
|
+
|
|
130
|
+
#### Option A: Inside Existing HuggingFace `model.generate(...)`
|
|
131
|
+
Attach Zelt directly to standard HuggingFace models via `StoppingCriteria`:
|
|
132
|
+
```python
|
|
133
|
+
from transformers import AutoModelForCausalLM, AutoTokenizer, StoppingCriteriaList
|
|
134
|
+
from zelt import ZeltStoppingCriteria, StopDecider
|
|
135
|
+
|
|
136
|
+
model = AutoModelForCausalLM.from_pretrained("deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B")
|
|
137
|
+
tokenizer = AutoTokenizer.from_pretrained("deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B")
|
|
138
|
+
|
|
139
|
+
criteria = ZeltStoppingCriteria(tokenizer, decider=StopDecider.load())
|
|
140
|
+
|
|
141
|
+
# Zelt interrupts generation the moment the answer is certified confident!
|
|
142
|
+
outputs = model.generate(
|
|
143
|
+
input_ids, max_new_tokens=2048, stopping_criteria=StoppingCriteriaList([criteria])
|
|
144
|
+
)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### Option B: Inside an API Service / FastAPI Backend
|
|
148
|
+
```python
|
|
149
|
+
from fastapi import FastAPI
|
|
150
|
+
from zelt import reduce_compute_thinking
|
|
151
|
+
|
|
152
|
+
app = FastAPI()
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@app.post("/solve")
|
|
156
|
+
async def solve(prompt: str):
|
|
157
|
+
# Replaces unconstrained 2,000-token CoT with risk-controlled early exit
|
|
158
|
+
res = reduce_compute_thinking(prompt, verbose=False)
|
|
159
|
+
return {
|
|
160
|
+
"answer": str(res),
|
|
161
|
+
"tokens_saved": res.tokens_saved,
|
|
162
|
+
"saved_pct": res.saved_pct,
|
|
163
|
+
"stopped_early": res.stopped,
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### Option C: Inside AI Agent Frameworks (LangChain / AutoGen / CrewAI)
|
|
168
|
+
```python
|
|
169
|
+
from zelt import reduce_compute_thinking
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class ReasoningTool:
|
|
173
|
+
"""Agent tool for complex math & logic sub-tasks without burning token budget."""
|
|
174
|
+
|
|
175
|
+
def run(self, sub_question: str) -> str:
|
|
176
|
+
return str(reduce_compute_thinking(sub_question, verbose=False))
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 🖥️ Interactive Web UI Dashboard
|
|
182
|
+
|
|
183
|
+
Launch a local visualizer with a live token stream, confidence gauges, and token comparison bars:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
zelt ui --port 8000
|
|
187
|
+
```
|
|
188
|
+
Open **`http://localhost:8000`** in your browser.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## 📊 Proven Results — Real DeepSeek-R1 on GSM8K (1,319 Real Trajectories)
|
|
193
|
+
|
|
194
|
+
Evaluated on held-out test split (331 questions) from real DeepSeek-R1-Distill-Qwen-1.5B runs:
|
|
195
|
+
|
|
196
|
+
| Method | Threshold ($\tau$) | Accuracy | $\Delta$ Acc | Avg Tokens | Token Reduction | Net (inc. probes) | Stop Rate | Harm Rate |
|
|
197
|
+
| :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
|
|
198
|
+
| **Full CoT (baseline)** | — | **78.25%** | baseline | 750.7 | 0.0% | 0.0% | 0.0% | 0.00% |
|
|
199
|
+
| Fixed Budget | 1,632 | 76.74% | -1.51% | 507.7 | 32.4% | 21.5% | 15.1% | 1.51% |
|
|
200
|
+
| Raw Confidence | 0.79 | 78.25% | +0.00% | 430.6 | 42.6% | 33.4% | 40.2% | 0.00% |
|
|
201
|
+
| **Learned Decider (zelt)** | **0.50** | **78.25%** | **+0.00%** | **465.9** | **37.9%** | **27.9%** | **37.8%** | **0.00%** |
|
|
202
|
+
|
|
203
|
+
- **37.9% compute reduction** (1.61× speedup)
|
|
204
|
+
- **Zero accuracy drop** (78.25% retained)
|
|
205
|
+
- **0.00% empirical harm** on test set (certified $\le 2\%$ at 90% confidence)
|
|
206
|
+
- **AUROC = 0.9976** and **ECE = 0.014** (3× better calibration than raw confidence)
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 🛠️ CLI Reference
|
|
211
|
+
|
|
212
|
+
| Command | Description |
|
|
213
|
+
|:---|:---|
|
|
214
|
+
| `zelt ui` | Launch local interactive web studio at `http://localhost:8000` |
|
|
215
|
+
| `zelt ask -q "..."` | Run early-exit inference on a single question |
|
|
216
|
+
| `zelt stream -q "..."` | Stream tokens live with intermediate probe confidence |
|
|
217
|
+
| `zelt batch -i questions.txt` | Run batch inference on a text file with cost metrics |
|
|
218
|
+
| `zelt benchmark` | Evaluate compute reduction on real bundled DeepSeek-R1 data |
|
|
219
|
+
| `zelt fit --inp <path>` | Train decider + calibrate threshold on custom runs |
|
|
220
|
+
| `zelt live-eval` | Live early-exit generation on held-out test split |
|
|
221
|
+
| `zelt demo -q "..."` | Side-by-side full vs early-exit comparison |
|
|
222
|
+
| `zelt selftest` | GPU-free pipeline check on synthetic data |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 🔬 How It Works
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
Prompt ──> DeepSeek-R1 (Local MPS / CUDA / Ollama)
|
|
230
|
+
│
|
|
231
|
+
├── [Every 48 tokens] ──> Lightweight Probe (greedy decode ~10 tokens)
|
|
232
|
+
│ │
|
|
233
|
+
│ Extract: 18 signals (geometric-mean prob,
|
|
234
|
+
│ entropy, answer stability,
|
|
235
|
+
│ confidence acceleration)
|
|
236
|
+
│ │
|
|
237
|
+
│ Decider: P(correct | features)
|
|
238
|
+
│ │
|
|
239
|
+
│ P(correct) ≥ τ ?
|
|
240
|
+
│ ┌───────┴───────┐
|
|
241
|
+
│ YES NO
|
|
242
|
+
│ │ │
|
|
243
|
+
│ STOP EARLY ⚡ Keep thinking...
|
|
244
|
+
│ (Return probed ans)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
1. **Periodic Probes**: Every $k$ tokens, a lightweight probe attempts greedy extraction of the intermediate answer.
|
|
248
|
+
2. **Feature Extraction**: Captures 18 signals including confidence geometric mean, sequence entropy, stability across consecutive probes, and confidence acceleration.
|
|
249
|
+
3. **Calibrated Decider**: Uses scikit-learn logistic regression with Clopper-Pearson risk control to find threshold $\tau$ bounding harm rate $\le \alpha$ (default 2%) with $(1-\delta)$ confidence (default 90%).
|
|
250
|
+
4. **Adaptive Early Stop**: Halts CoT generation the moment certainty is proven, saving ~40% tokens without harming answer quality.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Forward from zelt for backward compatibility."""
|
|
2
|
+
|
|
3
|
+
import zelt
|
|
4
|
+
from zelt import (
|
|
5
|
+
BatchResult,
|
|
6
|
+
CompareResult,
|
|
7
|
+
EarlyStop,
|
|
8
|
+
EarlyStopResult,
|
|
9
|
+
EvaluationResult,
|
|
10
|
+
StopDecider,
|
|
11
|
+
StreamChunk,
|
|
12
|
+
__version__,
|
|
13
|
+
accelerate,
|
|
14
|
+
ask,
|
|
15
|
+
batch,
|
|
16
|
+
calibrate,
|
|
17
|
+
compare,
|
|
18
|
+
evaluate,
|
|
19
|
+
extract_answer,
|
|
20
|
+
featurize,
|
|
21
|
+
fit_and_report,
|
|
22
|
+
from_ollama,
|
|
23
|
+
from_vllm,
|
|
24
|
+
is_correct,
|
|
25
|
+
list_presets,
|
|
26
|
+
make_stop_fn,
|
|
27
|
+
risk_report,
|
|
28
|
+
same_answer,
|
|
29
|
+
stream,
|
|
30
|
+
token_budget,
|
|
31
|
+
)
|
|
32
|
+
from zelt.core import EarlyStopper
|
|
33
|
+
|
|
34
|
+
# Aliases
|
|
35
|
+
Zelt = EarlyStop
|
|
36
|
+
ZeltResult = EarlyStopResult
|
|
37
|
+
reduce_compute_thinking = ask
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"EarlyStop",
|
|
41
|
+
"EarlyStopResult",
|
|
42
|
+
"StreamChunk",
|
|
43
|
+
"BatchResult",
|
|
44
|
+
"CompareResult",
|
|
45
|
+
"EvaluationResult",
|
|
46
|
+
"EarlyStopper",
|
|
47
|
+
"StopDecider",
|
|
48
|
+
"make_stop_fn",
|
|
49
|
+
"featurize",
|
|
50
|
+
"fit_and_report",
|
|
51
|
+
"extract_answer",
|
|
52
|
+
"is_correct",
|
|
53
|
+
"same_answer",
|
|
54
|
+
"ask",
|
|
55
|
+
"stream",
|
|
56
|
+
"batch",
|
|
57
|
+
"compare",
|
|
58
|
+
"evaluate",
|
|
59
|
+
"calibrate",
|
|
60
|
+
"accelerate",
|
|
61
|
+
"list_presets",
|
|
62
|
+
"from_ollama",
|
|
63
|
+
"from_vllm",
|
|
64
|
+
"token_budget",
|
|
65
|
+
"risk_report",
|
|
66
|
+
"Zelt",
|
|
67
|
+
"ZeltResult",
|
|
68
|
+
"reduce_compute_thinking",
|
|
69
|
+
"__version__",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def __getattr__(name: str):
|
|
74
|
+
return getattr(zelt, name)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Adapters for external LLM servers (Ollama, vLLM, OpenAI-compatible APIs).
|
|
3
|
+
Allows running early-exit reasoning when models are hosted on local servers.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from zelt.adapters import OllamaAdapter, VLLMAdapter
|
|
7
|
+
|
|
8
|
+
__all__ = ["OllamaAdapter", "VLLMAdapter"]
|