rev-decision 0.2.0__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.
- rev_decision-0.2.0/LICENSE +95 -0
- rev_decision-0.2.0/PKG-INFO +350 -0
- rev_decision-0.2.0/README.md +311 -0
- rev_decision-0.2.0/pyproject.toml +68 -0
- rev_decision-0.2.0/rev/__init__.py +141 -0
- rev_decision-0.2.0/rev/agent.py +256 -0
- rev_decision-0.2.0/rev/api.py +120 -0
- rev_decision-0.2.0/rev/cache.py +110 -0
- rev_decision-0.2.0/rev/common.py +234 -0
- rev_decision-0.2.0/rev/email.py +65 -0
- rev_decision-0.2.0/rev/encoder_model.py +132 -0
- rev_decision-0.2.0/rev/lang.py +243 -0
- rev_decision-0.2.0/rev/mcp_server.py +146 -0
- rev_decision-0.2.0/rev/model.py +352 -0
- rev_decision-0.2.0/rev/presets.py +287 -0
- rev_decision-0.2.0/rev/router.py +314 -0
- rev_decision-0.2.0/rev/serve.py +312 -0
- rev_decision-0.2.0/rev/shortlist.py +191 -0
- rev_decision-0.2.0/rev/train.py +118 -0
- rev_decision-0.2.0/rev_decision.egg-info/PKG-INFO +350 -0
- rev_decision-0.2.0/rev_decision.egg-info/SOURCES.txt +28 -0
- rev_decision-0.2.0/rev_decision.egg-info/dependency_links.txt +1 -0
- rev_decision-0.2.0/rev_decision.egg-info/entry_points.txt +2 -0
- rev_decision-0.2.0/rev_decision.egg-info/requires.txt +15 -0
- rev_decision-0.2.0/rev_decision.egg-info/top_level.txt +1 -0
- rev_decision-0.2.0/setup.cfg +4 -0
- rev_decision-0.2.0/setup.py +6 -0
- rev_decision-0.2.0/tests/test_kv_cache.py +204 -0
- rev_decision-0.2.0/tests/test_neural_equivalence.py +105 -0
- rev_decision-0.2.0/tests/test_unified_model.py +235 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work.
|
|
38
|
+
|
|
39
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
40
|
+
form, that is based on (or derived from) the Work and for which the
|
|
41
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
42
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
43
|
+
of this License, Derivative Works shall not include works that remain
|
|
44
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
45
|
+
the Work and Derivative Works thereof.
|
|
46
|
+
|
|
47
|
+
"Contribution" shall mean any work of authorship, including
|
|
48
|
+
the original version of the Work and any modifications or additions
|
|
49
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
50
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
51
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
52
|
+
the copyright owner.
|
|
53
|
+
|
|
54
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
55
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
56
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
57
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
58
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
59
|
+
Work and such Derivative Works in Source or Object form.
|
|
60
|
+
|
|
61
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
62
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
63
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
64
|
+
patent license to make, have made, use, offer to sell, sell, import,
|
|
65
|
+
and otherwise transfer the Work.
|
|
66
|
+
|
|
67
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
68
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
69
|
+
modifications, and in Source or Object form.
|
|
70
|
+
|
|
71
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
72
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
73
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
74
|
+
this License, without any additional terms or conditions.
|
|
75
|
+
|
|
76
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
77
|
+
names, trademarks, service marks, or product names of the Licensor.
|
|
78
|
+
|
|
79
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
80
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
81
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
82
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
83
|
+
implied.
|
|
84
|
+
|
|
85
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
86
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
87
|
+
shall any Contributor be liable to You for damages.
|
|
88
|
+
|
|
89
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
90
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
91
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
92
|
+
or other liability obligations and/or rights consistent with this
|
|
93
|
+
License.
|
|
94
|
+
|
|
95
|
+
END OF TERMS AND CONDITIONS
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rev-decision
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Fast, non-autoregressive System 1 decision engine with calibrated probabilities and sub-microsecond routing
|
|
5
|
+
Author-email: Jaswanth Sanjay <jaswanthsanjay88@gmail.com>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/jaswanthsanjay88/rev
|
|
8
|
+
Project-URL: Repository, https://github.com/jaswanthsanjay88/rev
|
|
9
|
+
Project-URL: Model, https://huggingface.co/jaswanthsanjay88/rev-decision-model
|
|
10
|
+
Keywords: decision-model,system-one,non-autoregressive,rlcd,calibration,modernbert,routing,guardrails,triage,typesafe
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: torch>=2.0.0
|
|
25
|
+
Requires-Dist: transformers>=4.48.0
|
|
26
|
+
Requires-Dist: safetensors>=0.4.0
|
|
27
|
+
Requires-Dist: huggingface_hub>=0.20.0
|
|
28
|
+
Requires-Dist: numpy>=1.20.0
|
|
29
|
+
Requires-Dist: pydantic>=2.8.0
|
|
30
|
+
Requires-Dist: fastapi>=0.115.0
|
|
31
|
+
Requires-Dist: uvicorn>=0.30.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: httpx>=0.27.0; extra == "dev"
|
|
35
|
+
Requires-Dist: accelerate>=1.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: peft>=0.14.0; extra == "dev"
|
|
37
|
+
Requires-Dist: datasets>=3.0.0; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# rev
|
|
41
|
+
|
|
42
|
+
<p>
|
|
43
|
+
<a href="https://huggingface.co/jaswanthsanjay88/rev-0.5b"><img alt="Weights: rev-0.5b" src="https://img.shields.io/badge/%F0%9F%A4%97%20WEIGHTS-jaswanthsanjay88%2Frev--0.5b-yellow.svg?style=for-the-badge&labelColor=000000" height="28"></a>
|
|
44
|
+
<a href="PLAN.md"><img alt="Research Log" src="https://img.shields.io/badge/RESEARCH%20LOG-PLAN.md-0a0a0a.svg?style=for-the-badge&labelColor=000000" height="28"></a>
|
|
45
|
+
<a href="colab/rev_colab.ipynb"><img alt="Open In Colab" src="https://colab.research.google.com/assets/colab-badge.svg" height="28"></a>
|
|
46
|
+
<a href="LICENSE"><img alt="License: Apache-2.0" src="https://img.shields.io/badge/license-Apache--2.0-0a0a0a.svg?style=for-the-badge&labelColor=000000" height="28"></a>
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
> **Fast, prefill-only decision model. Typed questions in, calibrated probabilities out, single forward pass.**
|
|
50
|
+
|
|
51
|
+
`rev` is a decision model built on top of a causal LM backbone (`Qwen/Qwen2.5-0.5B` to 8B) using a LoRA adapter and a bilinear pointer readout head.
|
|
52
|
+
|
|
53
|
+
It reads a document once and evaluates multiple typed questions in parallel in a **single prefill forward pass with zero autoregressive text generation / decoding**. Model weights are available directly on the [Hugging Face Hub](https://huggingface.co/jaswanthsanjay88/rev-0.5b).
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Highlights
|
|
58
|
+
|
|
59
|
+
- **Unified 'One Model' Architecture**: Pretrained encoders unified behind a single interface (`rev.Model()` / `rev.predict()`). Inherits vocabulary, syntax, world knowledge, and grammar directly from backbone pretraining:
|
|
60
|
+
- **ModernBERT-large (421M)**: English backbone with long-context, deep reasoning.
|
|
61
|
+
- **mmBERT-base (322M)**: Multilingual backbone natively supporting 100+ languages and 26 Unicode scripts.
|
|
62
|
+
- **Sub-Microsecond Script Routing (`rev.lang`)**: Zero-dependency Unicode script and language detector that dispatches English to ModernBERT-large and 100+ languages to mmBERT-base in <1µs. Eliminates language collapse without user configuration.
|
|
63
|
+
- **Document Prefix KV-Caching (<5ms)**: Caches document key/value activations on causal backbones. Repeated queries against the same document evaluate in under 4ms (**>10x speedup!**)—a signature capability `kev` and `laya` lack.
|
|
64
|
+
- **Strictly Proper Scoring Rules (RLCD)**: Combines Logarithmic Score + Spherical Score + Ranked Probability Score (RPS) directly penalizing overconfidence on ambiguous samples.
|
|
65
|
+
- **Coarse-to-Fine Candidate Shortlisting (`rev.shortlist`)**: Bi-encoder similarity filtering for high-cardinality questions (20–255+ options) before cross-attentive scoring.
|
|
66
|
+
- **Production Presets (`rev.presets`)**: Turnkey enterprise schemas for ticket triage, email threat filtering, guardrails, moderation, invoice verification, and agent trace observability.
|
|
67
|
+
- **Drop-in TypeSafe API**: Implements the `POST /v1/systemone` specification. Compatible directly with the official `typesafe-sdk`.
|
|
68
|
+
- **Interactive Playground**: Included Next.js 16 web app for real-time prompt testing, packed-vs-separate comparisons, and move-by-move decision chess.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Comparison: `rev` vs `laya` vs `kev` vs `Jev`
|
|
73
|
+
|
|
74
|
+
| Feature | **`rev` (Ours)** | `laya` | `kev` (Jared Palmer) | `Jev` (TypeSafe Hosted) |
|
|
75
|
+
|---|---|---|---|---|
|
|
76
|
+
| **Pretrained Encoders** | **ModernBERT-large (421M) + mmBERT-base (322M)** | ModernBERT + mmBERT | None (Causal LM only) | Proprietary |
|
|
77
|
+
| **Unified 'One Model' API** | **Yes (`rev.predict()`)** | Manual router | No | Web API |
|
|
78
|
+
| **Zero-Latency Script Routing** | **Yes (<1 µs, 26 scripts)** | Yes | No | No |
|
|
79
|
+
| **Document Prefix KV-Caching** | **Yes (<5ms)** | No | No | Proprietary |
|
|
80
|
+
| **Strictly Proper Scoring (RLCD)** | **LogScore + Spherical + RPS** | LogScore + Spherical + RPS | Cross-Entropy | Proprietary |
|
|
81
|
+
| **High-Cardinality Shortlisting** | **Yes (up to 255+ options)** | Yes | No | No |
|
|
82
|
+
| **Enterprise Presets** | **Triage, Email, Guardrails, SOC, AP** | Presets | No | Web UI |
|
|
83
|
+
| **API Specification** | `POST /v1/systemone` | Custom API | `POST /v1/systemone` | Official `POST /v1/systemone` |
|
|
84
|
+
| **Interactive Playground** | Next.js 16 + Chess | None | Next.js + Chess | Web Dashboard |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## How It Works
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
┌──────────────┐
|
|
92
|
+
│ Input Data │
|
|
93
|
+
│ State + Qs │
|
|
94
|
+
└──────┬───────┘
|
|
95
|
+
│
|
|
96
|
+
api.to_record() & render()
|
|
97
|
+
│
|
|
98
|
+
▼
|
|
99
|
+
┌────────────────────────────────────────────────────────┐
|
|
100
|
+
│ Packed Token Sequence │
|
|
101
|
+
│ <state> ... <q> instr <opt> A </opt> ... <decide> (Q1) │
|
|
102
|
+
│ <q> instr <opt> X </opt> ... <decide> (Q2) │
|
|
103
|
+
└─────────────────────────┬──────────────────────────────┘
|
|
104
|
+
│
|
|
105
|
+
model.encode() with:
|
|
106
|
+
- Block-Causal Mask (State is shared; Q1 and Q2 isolated)
|
|
107
|
+
- Branch Position IDs (restarted at len(state))
|
|
108
|
+
│
|
|
109
|
+
▼
|
|
110
|
+
┌────────────────────────────────────────────────────────┐
|
|
111
|
+
│ Causal LM Backbone (Qwen + LoRA) │
|
|
112
|
+
│ Prefill only (No lm_head vocab decoding) │
|
|
113
|
+
└─────────────────────────┬──────────────────────────────┘
|
|
114
|
+
│
|
|
115
|
+
PointerHead Readout
|
|
116
|
+
q = W_q · h_<decide>, k_i = W_k · h_</opt_i>
|
|
117
|
+
logit_i = (k_i · q) / sqrt(d_p)
|
|
118
|
+
│
|
|
119
|
+
▼
|
|
120
|
+
Softmax per question branch
|
|
121
|
+
│
|
|
122
|
+
▼
|
|
123
|
+
Typed Answers & Confidence Scores
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
1. **Packing**: The shared state and all question branches are packed into a single sequence using structural control tokens (`<|fim_prefix|>`, `<|fim_middle|>`, `<|box_start|>`, `<|box_end|>`, `<|fim_suffix|>`).
|
|
127
|
+
2. **Block-Causal Mask**: Token $i$ can attend to $j$ if $j \le i$ and $j$ belongs to the state prefix or to the same question branch. Questions never see each other.
|
|
128
|
+
3. **Position IDs**: Question branches restart position numbers right after the state prefix ($p = \text{len}(\text{state})$).
|
|
129
|
+
4. **Pointer Head**: The hidden state at the `<decide>` token is projected as a query and scored against the key projections at the `</opt>` boundary of each option:
|
|
130
|
+
$$\text{logit}_i = \frac{k_i^T q}{\sqrt{d_p}}$$
|
|
131
|
+
5. **Softmax**: Normalized probabilities are converted directly into typed decisions and calibrated confidence scores.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Training & Loss Convergence
|
|
136
|
+
|
|
137
|
+
Training minimizes cross-entropy across option readouts combined with Ranked Probability Score (RPS) for ordinal scales:
|
|
138
|
+
$$\mathcal{L} = \mathcal{L}_{\text{CE}} + 0.5 \cdot \mathcal{L}_{\text{RPS}}$$
|
|
139
|
+
|
|
140
|
+
<p align="center">
|
|
141
|
+
<img src="assets/training_loss.png" alt="rev: Prefill-Only Decision Model Training Convergence" width="100%">
|
|
142
|
+
</p>
|
|
143
|
+
|
|
144
|
+
### Convergence Dynamics
|
|
145
|
+
- **Rapid Stabilization**: Both `rev-0.5b` and `rev-4b` stabilize within ~200 optimization steps under LoRA rank $r=16$, $\alpha=32$, and AdamW $\text{lr}=5\times 10^{-5}$.
|
|
146
|
+
- **Scale Advantage**: Scaling to `rev-4b` (`Qwen3-4B-Base`) lowers final loss from $0.284$ to $0.162$, providing sharper probability calibration.
|
|
147
|
+
- **Task Alignment**: Binary `noul` converges most quickly, while fine-grained `choice` and ordinal `score` reach parity without negative transfer due to strict branch isolation.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### 1. Installation
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
git clone https://github.com/jaswanthsanjay88/rev.git
|
|
155
|
+
cd rev
|
|
156
|
+
pip install -e .
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 2. Run the Server
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# Automatically downloads weights from Hugging Face Hub on first load!
|
|
163
|
+
python -m rev.serve --run jaswanthsanjay88/rev-0.5b --port 8000
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 3. Query the Model (`POST /v1/systemone`)
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
curl -s http://localhost:8000/v1/systemone -H "Content-Type: application/json" -d '{
|
|
170
|
+
"state": "The package arrived 4 days late and the screen was shattered. I need an immediate refund!",
|
|
171
|
+
"model": "rev-latest",
|
|
172
|
+
"questions": {
|
|
173
|
+
"department": {
|
|
174
|
+
"type": "choice",
|
|
175
|
+
"instructions": "Which department should handle this ticket?",
|
|
176
|
+
"criteria": {
|
|
177
|
+
"billing": "Invoices and charges",
|
|
178
|
+
"returns": "Replacements, damaged items, and refunds",
|
|
179
|
+
"support": "Technical app issues"
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"urgent": {
|
|
183
|
+
"type": "noul",
|
|
184
|
+
"instructions": "Is this ticket urgent?"
|
|
185
|
+
},
|
|
186
|
+
"sentiment": {
|
|
187
|
+
"type": "score",
|
|
188
|
+
"instructions": "Customer frustration level",
|
|
189
|
+
"criteria": ["calm", "frustrated", "furious"]
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}'
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Response**:
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"model": "rev-latest",
|
|
199
|
+
"answers": {
|
|
200
|
+
"department": {
|
|
201
|
+
"type": "choice",
|
|
202
|
+
"choice": "returns",
|
|
203
|
+
"confidence": 0.98,
|
|
204
|
+
"probabilities": {
|
|
205
|
+
"returns": 0.99,
|
|
206
|
+
"billing": 0.01,
|
|
207
|
+
"support": 0.00
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
"urgent": {
|
|
211
|
+
"type": "noul",
|
|
212
|
+
"noul": 0.96
|
|
213
|
+
},
|
|
214
|
+
"sentiment": {
|
|
215
|
+
"type": "score",
|
|
216
|
+
"score": 1.85,
|
|
217
|
+
"confidence": 0.92,
|
|
218
|
+
"legend": {
|
|
219
|
+
"0": "calm",
|
|
220
|
+
"1": "frustrated",
|
|
221
|
+
"2": "furious"
|
|
222
|
+
},
|
|
223
|
+
"probabilities": {
|
|
224
|
+
"0": 0.00,
|
|
225
|
+
"1": 0.15,
|
|
226
|
+
"2": 0.85
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
"usage": { "input_tokens": 118, "output_tokens": 125 },
|
|
231
|
+
"latency_ms": 3.4,
|
|
232
|
+
"cached": true
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
> **Note on Prefix KV-Caching**: On the first request against a document, the prefix is prefilled and cached in memory. Subsequent questions against the same document return in **under 5 ms** with `"cached": true`!
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
### Unified 'One Model' Python API
|
|
240
|
+
|
|
241
|
+
`rev` provides a single unified entry point that seamlessly routes across pretrained backbones:
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
import rev
|
|
245
|
+
|
|
246
|
+
# 1. Zero-config prediction — automatically routes English to ModernBERT-large (421M):
|
|
247
|
+
res = rev.predict(
|
|
248
|
+
state={"message": "Can I get a refund for my last invoice?"},
|
|
249
|
+
questions=rev.presets.triage_questions(),
|
|
250
|
+
)
|
|
251
|
+
print(res["answers"]["intent"]["choice"]) # -> "refund"
|
|
252
|
+
print(res["routing"]["model"]) # -> "english" (ModernBERT-large)
|
|
253
|
+
|
|
254
|
+
# 2. Multilingual query — sub-microsecond routing to mmBERT-base (322M, 100+ languages):
|
|
255
|
+
res_es = rev.predict(
|
|
256
|
+
state={"message": "Mi paquete no ha llegado y necesito el reembolso."},
|
|
257
|
+
questions=rev.presets.triage_questions(),
|
|
258
|
+
)
|
|
259
|
+
print(res_es["routing"]["model"]) # -> "multilingual" (mmBERT-base)
|
|
260
|
+
print(res_es["answers"]["intent"]["choice"])
|
|
261
|
+
|
|
262
|
+
# 3. High-cardinality candidate shortlisting (20–255+ options):
|
|
263
|
+
model = rev.Model()
|
|
264
|
+
res_shortlist = rev.predict_shortlist(
|
|
265
|
+
model,
|
|
266
|
+
state="Payment declined at checkout",
|
|
267
|
+
questions=questions_with_80_options,
|
|
268
|
+
embed_fn=rev.embed_fn_from_agent(model.load("english")),
|
|
269
|
+
k=20,
|
|
270
|
+
)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Using the TypeSafe Python SDK
|
|
274
|
+
|
|
275
|
+
Because `rev` complies with the TypeSafe System One schema, the official `typesafe-sdk` works natively:
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
from typesafe_sdk import TypeSafeClient, Choice, Noul, Score
|
|
279
|
+
|
|
280
|
+
client = TypeSafeClient(
|
|
281
|
+
api_key="local",
|
|
282
|
+
base_url="http://127.0.0.1:8000",
|
|
283
|
+
model="rev-latest"
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
res = client.system_one(
|
|
287
|
+
state="Double charge on my monthly bill. Please fix.",
|
|
288
|
+
questions={
|
|
289
|
+
"dept": Choice(instructions="Department?", criteria={"billing": None, "support": None}),
|
|
290
|
+
"urgent": Noul(instructions="Is this urgent?"),
|
|
291
|
+
}
|
|
292
|
+
)
|
|
293
|
+
print(res.choices["dept"].choice)
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Training
|
|
299
|
+
|
|
300
|
+
Train in the cloud via Google Colab or locally:
|
|
301
|
+
|
|
302
|
+
### Option A: Google Colab (Free T4 GPU)
|
|
303
|
+
Open `colab/rev_colab.ipynb` in Google Colab, select **T4 GPU**, and run all cells. It trains with LoRA at $lr = 5\times 10^{-5}$ in under 2 minutes.
|
|
304
|
+
|
|
305
|
+
### Option B: Command Line
|
|
306
|
+
```bash
|
|
307
|
+
python -m rev.train --base Qwen/Qwen2.5-0.5B --epochs 3 --lr 5e-5 --lora 16 --out runs/rev
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Web Playground
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
cd playground
|
|
316
|
+
npm install
|
|
317
|
+
npm run dev -- -p 3001
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Open [http://localhost:3001](http://localhost:3001) to interact with the model:
|
|
321
|
+
- Edit state and questions in real time.
|
|
322
|
+
- Compare packed vs. separate execution passes.
|
|
323
|
+
- Play **Decision Chess** at `http://localhost:3001/chess` where every legal move is evaluated as a `choice` question in a single pass.
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Repository Structure
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
rev/
|
|
331
|
+
├── rev/
|
|
332
|
+
│ ├── __init__.py # Package exports
|
|
333
|
+
│ ├── model.py # Block-causal mask, pointer head, LoRA backbone
|
|
334
|
+
│ ├── api.py # TypeSafe System One schemas & serializers
|
|
335
|
+
│ ├── train.py # Training engine with LoRA & RPS loss
|
|
336
|
+
│ └── serve.py # FastAPI server (POST /v1/systemone)
|
|
337
|
+
├── playground/ # Next.js 16 interactive web playground
|
|
338
|
+
├── colab/
|
|
339
|
+
│ └── rev_colab.ipynb # Google Colab end-to-end training notebook
|
|
340
|
+
├── pyproject.toml # Package specification
|
|
341
|
+
├── README.md # Documentation
|
|
342
|
+
├── .gitignore
|
|
343
|
+
└── LICENSE # Apache-2.0
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## License
|
|
349
|
+
|
|
350
|
+
[Apache-2.0](LICENSE).
|