logitgate 0.2.0__tar.gz → 0.2.2__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.
- logitgate-0.2.2/PKG-INFO +357 -0
- logitgate-0.2.2/README.md +302 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/pyproject.toml +1 -1
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/__init__.py +13 -1
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/backends/base.py +38 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/backends/ollama.py +5 -3
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/backends/openai_compat.py +7 -3
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/cascade.py +279 -94
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/debiasing/permutation.py +2 -2
- logitgate-0.2.2/src/logitgate/exceptions.py +29 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/gates/ast_gate.py +20 -4
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/gates/judge_gate.py +30 -28
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/gates/logit_gate.py +51 -17
- logitgate-0.2.2/src/logitgate.egg-info/PKG-INFO +357 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate.egg-info/SOURCES.txt +1 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/tests/test_cascade.py +50 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/tests/test_usability_and_validation.py +95 -0
- logitgate-0.2.0/PKG-INFO +0 -1236
- logitgate-0.2.0/README.md +0 -1181
- logitgate-0.2.0/src/logitgate.egg-info/PKG-INFO +0 -1236
- {logitgate-0.2.0 → logitgate-0.2.2}/LICENSE +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/setup.cfg +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/backends/__init__.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/backends/dory_pytorch.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/backends/llamacpp.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/backends/recurrent.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/cli.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/config.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/debiasing/__init__.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/debiasing/inversion.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/debiasing/softmax.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/gates/__init__.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/gates/base.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/integrations/__init__.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/integrations/deepeval.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/integrations/langgraph.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/integrations/pytest_plugin.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/models.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/py.typed +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate/snapshot.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate.egg-info/dependency_links.txt +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate.egg-info/entry_points.txt +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate.egg-info/requires.txt +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/src/logitgate.egg-info/top_level.txt +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/tests/test_ast_gate.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/tests/test_backends_and_cli.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/tests/test_debiasing_math.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/tests/test_integrations.py +0 -0
- {logitgate-0.2.0 → logitgate-0.2.2}/tests/test_logit_gate.py +0 -0
logitgate-0.2.2/PKG-INFO
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: logitgate
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Fast, calibrated first-token logit evaluation and 3-layer cascaded routing for LLMs.
|
|
5
|
+
Author-email: Jason Bradley <jasonbdly@gmail.com>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/jasonbdly/LogitGate
|
|
8
|
+
Project-URL: Repository, https://github.com/jasonbdly/LogitGate
|
|
9
|
+
Project-URL: Mirror, https://gitlab.com/jasonbdly/logitgate
|
|
10
|
+
Keywords: llm,evaluation,logprobs,logits,calibration,cascaded-routing
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Requires-Dist: httpx>=0.23.0
|
|
27
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
28
|
+
Provides-Extra: openai
|
|
29
|
+
Requires-Dist: openai>=1.0.0; extra == "openai"
|
|
30
|
+
Provides-Extra: deepeval
|
|
31
|
+
Requires-Dist: deepeval>=1.0.0; extra == "deepeval"
|
|
32
|
+
Provides-Extra: langgraph
|
|
33
|
+
Requires-Dist: langgraph>=0.0.1; extra == "langgraph"
|
|
34
|
+
Provides-Extra: llamacpp
|
|
35
|
+
Requires-Dist: llama-cpp-python>=0.2.0; extra == "llamacpp"
|
|
36
|
+
Provides-Extra: recurrent
|
|
37
|
+
Requires-Dist: torch>=2.0.0; extra == "recurrent"
|
|
38
|
+
Requires-Dist: transformers>=4.40.0; extra == "recurrent"
|
|
39
|
+
Provides-Extra: pytest
|
|
40
|
+
Requires-Dist: pytest>=8.0.0; extra == "pytest"
|
|
41
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == "pytest"
|
|
42
|
+
Provides-Extra: test
|
|
43
|
+
Requires-Dist: pytest>=8.0.0; extra == "test"
|
|
44
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == "test"
|
|
45
|
+
Provides-Extra: all
|
|
46
|
+
Requires-Dist: openai>=1.0.0; extra == "all"
|
|
47
|
+
Requires-Dist: deepeval>=1.0.0; extra == "all"
|
|
48
|
+
Requires-Dist: langgraph>=0.0.1; extra == "all"
|
|
49
|
+
Requires-Dist: llama-cpp-python>=0.2.0; extra == "all"
|
|
50
|
+
Requires-Dist: torch>=2.0.0; extra == "all"
|
|
51
|
+
Requires-Dist: transformers>=4.40.0; extra == "all"
|
|
52
|
+
Requires-Dist: pytest>=8.0.0; extra == "all"
|
|
53
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == "all"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# LogitGate (`logitgate`)
|
|
57
|
+
|
|
58
|
+
[](https://pypi.org/project/logitgate/)
|
|
59
|
+
[](LICENSE)
|
|
60
|
+
[](https://www.python.org/downloads/)
|
|
61
|
+
[](src/logitgate/py.typed)
|
|
62
|
+
[](pyproject.toml)
|
|
63
|
+
[](https://github.com/astral-sh/ruff)
|
|
64
|
+
[](https://gitlab.com/jasonbdly/logitgate/-/pipelines)
|
|
65
|
+
|
|
66
|
+
**Fast, calibrated first-token logit evaluation and 3-layer cascaded routing for LLMs.**
|
|
67
|
+
|
|
68
|
+
LogitGate replaces slow, multi-token LLM-as-a-judge critiques (5–20s) with calibrated first-token logit gates (**36–110 ms**) and a 3-layer cascaded routing pipeline (`ASTGate >> LogitGate >> JudgeGate`), saving 90%–98% of evaluation tokens and wall-clock time while canceling token prior and positional biases.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## How It Works in 60 Seconds
|
|
73
|
+
|
|
74
|
+
When evaluating whether an LLM output satisfies a rubric, traditional frameworks prompt a model to generate a 200–500 word critique before outputting `PASS` or `FAIL`. This takes **5 to 20 seconds**, consumes hundreds of tokens, and suffers from recency and positional biases.
|
|
75
|
+
|
|
76
|
+
`LogitGate` uses a **3-layer cascaded pipeline**:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
Candidate Artifact
|
|
80
|
+
│
|
|
81
|
+
▼
|
|
82
|
+
┌──────────────────────────────────────┐
|
|
83
|
+
│ Layer 0: ASTGate / ContractGate ├──► [FAIL: syntax/schema, <0.1ms]
|
|
84
|
+
└──────────────────┬───────────────────┘
|
|
85
|
+
│ Passed
|
|
86
|
+
▼
|
|
87
|
+
┌──────────────────────────────────────┐
|
|
88
|
+
│ Layer 1: LogitGate ├──► [PASS: P >= 0.85, ~40–110ms]
|
|
89
|
+
└──────────────────┬───────────────────┤
|
|
90
|
+
│ Ambiguous └──► [FAIL: P <= 0.20, ~40–110ms]
|
|
91
|
+
│ (0.20 < P < 0.85)
|
|
92
|
+
▼
|
|
93
|
+
┌──────────────────────────────────────┐
|
|
94
|
+
│ Layer 2: JudgeGate ├──► [Actionable Diagnostic Report]
|
|
95
|
+
└──────────────────────────────────────┘
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
1. **Layer 0 (`ASTGate` / `ContractGate`)**: Deterministic checks in **<0.1 ms** on CPU (Python AST syntax, JSON/Pydantic schemas, regex patterns, acyclic DAG topology). Failures reject immediately with zero LLM overhead.
|
|
99
|
+
2. **Layer 1 (`LogitGate` / `ChoiceGate` / `ScoreGate`)**: Reads **first-token log-probabilities (`max_tokens=1`)** in **~36–41 ms on GPU** (~170 ms on CPU). To eliminate pretraining label bias, it averages forward and reverse passes in log-odds space ($\bar{L} = \frac{L_1 + L_2}{2T}$).
|
|
100
|
+
3. **Layer 2 (`JudgeGate`)**: Only when Layer 1 confidence is genuinely ambiguous (between 20% and 85%) or requires failure diagnostics does the pipeline escalate to generating a full text critique.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Installation
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Core package (zero dependencies except pydantic & httpx)
|
|
108
|
+
pip install logitgate
|
|
109
|
+
|
|
110
|
+
# With optional framework integrations:
|
|
111
|
+
pip install "logitgate[openai]" # OpenAI, vLLM, and compatible endpoints
|
|
112
|
+
pip install "logitgate[llamacpp]" # In-process llama.cpp (zero background daemon)
|
|
113
|
+
pip install "logitgate[langgraph]" # LangGraph conditional edge routing
|
|
114
|
+
pip install "logitgate[deepeval]" # DeepEval System-1 metrics
|
|
115
|
+
pip install "logitgate[recurrent]" # Elastic recurrent looping (NVIDIA Dory-4B)
|
|
116
|
+
pip install "logitgate[all]" # All integrations
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 30-Second Quickstart
|
|
122
|
+
|
|
123
|
+
### 1. Single Atomic Rubric (3-Layer Cascaded Fast Path)
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from logitgate import ASTGate, LogitGate, JudgeGate
|
|
127
|
+
|
|
128
|
+
# Compose the 3-layer pipeline using the >> operator
|
|
129
|
+
cascade = (
|
|
130
|
+
# Layer 0: Ensure valid Python syntax without LLM calls (<0.1ms)
|
|
131
|
+
ASTGate(syntax=True)
|
|
132
|
+
# Layer 1: First-token debiased logit gate (~40-90ms, 0 CoT tokens)
|
|
133
|
+
>> LogitGate(
|
|
134
|
+
rubric="Does the function calculate Fibonacci numbers using recursion?",
|
|
135
|
+
pass_threshold=0.85,
|
|
136
|
+
fail_threshold=0.20,
|
|
137
|
+
)
|
|
138
|
+
# Layer 2: Escalated diagnostic judge (only fires if Layer 1 is ambiguous or failing)
|
|
139
|
+
>> JudgeGate(trigger="on_ambiguous_only")
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
candidate_code = """
|
|
143
|
+
def fibonacci(n: int) -> int:
|
|
144
|
+
if n <= 0:
|
|
145
|
+
return 0
|
|
146
|
+
elif n == 1:
|
|
147
|
+
return 1
|
|
148
|
+
return fibonacci(n - 1) + fibonacci(n - 2)
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
verdict = cascade.evaluate(candidate_code)
|
|
152
|
+
|
|
153
|
+
print(f"Passed: {verdict.passed}") # True
|
|
154
|
+
print(f"Confidence: {verdict.probability:.4f}") # e.g., 0.9982
|
|
155
|
+
print(f"Triggered Layer: {verdict.triggered_layer}") # LogitGate (bypassed Layer 2!)
|
|
156
|
+
print(f"Latency: {verdict.total_latency_ms:.1f}ms") # ~86ms
|
|
157
|
+
print(f"Tokens Generated: {verdict.total_tokens_generated}") # 0 tokens!
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 2. Multi-Rubric Batching (Prefix-Preserved KV-Cache Reuse)
|
|
161
|
+
|
|
162
|
+
When verifying multiple criteria against a candidate artifact, **do not combine them into a single monolithic compound rubric** (which dilutes logit signals and conflates orthogonal requirements). Instead, evaluate isolated atomic rubrics in a single batch using `evaluate_batch`.
|
|
163
|
+
|
|
164
|
+
The candidate code is anchored at Token 0, sharing 95–99% of prefix tokens in KV cache across all checks:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from logitgate import LogitGate
|
|
168
|
+
|
|
169
|
+
# Best Practice: Keep rubrics atomic — evaluate multiple criteria via evaluate_batch
|
|
170
|
+
rubrics = [
|
|
171
|
+
"Does the function calculate Fibonacci numbers recursively?",
|
|
172
|
+
"Does the function explicitly handle non-positive inputs (n <= 0)?",
|
|
173
|
+
"Does the function include parameter and return type annotations?",
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
gate = LogitGate("Base rubric")
|
|
177
|
+
|
|
178
|
+
# Evaluates all 3 rubrics in a single batch reusing the shared KV-cache prefix
|
|
179
|
+
verdicts = gate.evaluate_batch(candidate_code, rubrics)
|
|
180
|
+
|
|
181
|
+
for rubric, v in zip(rubrics, verdicts):
|
|
182
|
+
status = "PASS" if v.passed else "FAIL"
|
|
183
|
+
print(f"[{status}] P={v.probability:.4f} | {rubric}")
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Core Gates Quick Reference
|
|
189
|
+
|
|
190
|
+
| Gate | Layer | Latency | Tokens Generated | Purpose & Behavior |
|
|
191
|
+
| :--- | :---: | :---: | :---: | :--- |
|
|
192
|
+
| **`ASTGate`** | Layer 0 | **< 0.1 ms** | 0 | Sub-millisecond deterministic checks: Python syntax, forbidden imports, regex, acyclic DAGs, custom callables. |
|
|
193
|
+
| **`ContractGate`** | Layer 0 | **< 0.1 ms** | 0 | General-domain contract validation: Pydantic models, JSON Schemas, length bounds, required sections. |
|
|
194
|
+
| **`LogitGate`** | Layer 1 | **~40–110 ms** | 0 | Calibrated binary classification from first-token logits using symmetric log-odds debiasing ($\bar{L} = \frac{L_1 + L_2}{2T}$). |
|
|
195
|
+
| **`ChoiceGate`** | Layer 1 | **~40–120 ms** | 0 | Discrete K-ary routing and intent classification across arbitrary string options with permutation averaging. |
|
|
196
|
+
| **`ScoreGate`** | Layer 1 | **~50–160 ms** | 0 | Continuous probability-weighted rubric scoring (𝔼[S] = Σ s · P(s)) with inverted scale debiasing. |
|
|
197
|
+
| **`JudgeGate`** | Layer 2 | **1.5–5.0 s** | 60–300 | Generative System-2 reasoning judge with reason-then-verdict parsing and self-healing 1-token logit probes. |
|
|
198
|
+
| **`Cascade`** | 0 $\to$ 2 | **~40–120 ms\*** | 0\* | Chained pipeline (`gate_a >> gate_b`). Fast passes short-circuit Layer 2 entirely. |
|
|
199
|
+
|
|
200
|
+
*\*Typical latency on non-ambiguous inputs.*
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Benchmark Highlights
|
|
205
|
+
|
|
206
|
+
Across a 24-item multi-domain suite (RAG groundedness, customer support policy, SQL safety, and Python security), `LogitGate` resolves **95.8%–100.0% of cases at Layers 0 and 1**, avoiding multi-token generation:
|
|
207
|
+
|
|
208
|
+
| Evaluation Approach | Typical Latency | Generated Tokens | Extra GPU VRAM | Bias Cancellation | Speedup |
|
|
209
|
+
| :--- | :---: | :---: | :---: | :---: | :---: |
|
|
210
|
+
| **Generative LLM Judge** *(G-Eval, MT-Bench)* | 1,500ms – 8,000ms | 100 – 600 CoT tokens | 0 GB (Shared) | ❌ None | 1.0x |
|
|
211
|
+
| **Fine-Tuned Judge Models** *(Prometheus 2, Selene)* | 800ms – 3,500ms | 80 – 300 CoT tokens | 14 GB – 48 GB (Dedicated) | ❌ Susceptible to bias | 2.5x |
|
|
212
|
+
| **`LogitGate` 3-Layer Cascade** | **36ms – 113ms** | **0 CoT tokens** | **0 GB (Reuses generator)** | **✅ Symmetric Log-Odds** | **10x – 17x** |
|
|
213
|
+
|
|
214
|
+
### CPU-Only CI/CD Champion: `llama3.2:3b` in Q4_K_M
|
|
215
|
+
- **In-Process `llama.cpp`**: Cold-starts in **3.2 seconds** inside your Python process (zero external background daemon), allocating only **2.36 GB RAM**.
|
|
216
|
+
- **Performance**: Evaluates 2-pass symmetric debiased gating in **815 ms** on CPU with **$\rho = 0.8487$** continuous scoring correlation.
|
|
217
|
+
- **Thread Scaling Law**: CPU execution saturates at **2 threads** (112 ms forward pass) due to memory bandwidth limits.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## In-Depth Documentation Index
|
|
222
|
+
|
|
223
|
+
For complete research data, mathematical derivations, and production recipes, explore our modular documentation:
|
|
224
|
+
|
|
225
|
+
- 📊 **[Empirical Benchmarks & Falsification Studies](docs/benchmarks.md)**:
|
|
226
|
+
- 24-item multi-domain cascade efficiency & token savings
|
|
227
|
+
- Fair pure-CPU CI/CD runner benchmarks (10-item CI suite)
|
|
228
|
+
- Compact models on CPU (1B–3B vs 4B baseline)
|
|
229
|
+
- In-process `llama.cpp` vs Ollama daemon & thread scaling sweeps
|
|
230
|
+
- Hardened 32-item adversarial benchmark suite ($N=5$)
|
|
231
|
+
- Falsification boundaries: reasoning depth, context length (16k), and context window squeezing
|
|
232
|
+
- Elastic recurrent layer-looping (NVIDIA Dory-4B, RTX 5090 vs RTX 4070)
|
|
233
|
+
- 🏗️ **[3-Layer Architecture & Deployment Topologies](docs/architecture.md)**:
|
|
234
|
+
- Execution mechanics, lookahead policy, and monotonic failure preservation
|
|
235
|
+
- System requirements across 0-GPU, Consumer GPU, and Enterprise hardware
|
|
236
|
+
- 3 deployment topologies to prevent KV-cache eviction and thrashing
|
|
237
|
+
- 📐 **[Mathematical Foundations & Symmetric Debiasing](docs/math_and_debiasing.md)**:
|
|
238
|
+
- Analytical proof of prior token bias cancellation in log-odds space
|
|
239
|
+
- Probability averaging vs. log-odds space contrast
|
|
240
|
+
- Prefix-preserving attention inversion & missing-token bounded floor
|
|
241
|
+
- Temperature calibration ($T$) and Brier score minimization
|
|
242
|
+
- 💡 **[Production Use Cases & Best Practices](docs/use_cases.md)**:
|
|
243
|
+
- CI/CD final merge gates vs local inner loop
|
|
244
|
+
- Reproducing CI failures locally via `VerdictSnapshot` and `logitgate explain`
|
|
245
|
+
- RAG hallucination guardrails & LangGraph agent intent routing
|
|
246
|
+
- Candidate-prefix isolated batching (`evaluate_batch`) vs monolithic prompt anti-patterns
|
|
247
|
+
- 🔌 **[Framework Integrations](docs/integrations.md)**:
|
|
248
|
+
- Pytest `@check` test decorator
|
|
249
|
+
- DeepEval `LogitGateSystemOneModel` and `LogitGateMetric`
|
|
250
|
+
- LangGraph conditional edge routing (`as_conditional_edge`)
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Common Recipes
|
|
255
|
+
|
|
256
|
+
### Multi-Rubric Batch Evaluation (`evaluate_batch`)
|
|
257
|
+
Evaluates multiple rubrics against a single candidate artifact while anchoring the candidate at Token 0 to share 95–99% of prefix tokens in KV-cache:
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
from logitgate import LogitGate
|
|
261
|
+
|
|
262
|
+
gate = LogitGate("Base rubric")
|
|
263
|
+
|
|
264
|
+
rubrics = [
|
|
265
|
+
"Does the code include full type annotations?",
|
|
266
|
+
"Does the code avoid mutable default arguments?",
|
|
267
|
+
"Does the code implement proper error handling?",
|
|
268
|
+
]
|
|
269
|
+
|
|
270
|
+
candidate_code = "def fetch(url: str, timeout: int = 10) -> str: pass"
|
|
271
|
+
verdicts = gate.evaluate_batch(candidate_code, rubrics)
|
|
272
|
+
|
|
273
|
+
for rubric, v in zip(rubrics, verdicts):
|
|
274
|
+
print(f"[{'PASS' if v.passed else 'FAIL'}] P={v.probability:.2f} | {rubric}")
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Discrete Multi-Way Routing (`ChoiceGate`)
|
|
278
|
+
Routes requests across $K$ options in ~40–90 ms without generating JSON:
|
|
279
|
+
|
|
280
|
+
```python
|
|
281
|
+
from logitgate import ChoiceGate
|
|
282
|
+
|
|
283
|
+
router = ChoiceGate(
|
|
284
|
+
question="Route this incoming user request to the appropriate specialist:",
|
|
285
|
+
options={
|
|
286
|
+
"A": "Database and SQL query optimizations",
|
|
287
|
+
"B": "Authentication and user permissions",
|
|
288
|
+
"C": "Billing, invoices, and payment processing",
|
|
289
|
+
},
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
verdict = router.evaluate("My credit card was charged twice for invoice #902.")
|
|
293
|
+
print(f"Selected route: {verdict.choice}") # 'C'
|
|
294
|
+
print(f"Probabilities: {verdict.choice_probabilities}")
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Continuous Rubric Scoring (`ScoreGate`)
|
|
298
|
+
Calculates a smooth expected score (𝔼[S] ∈ [1.0, 5.0]) using first-token softmax weights:
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
from logitgate import ScoreGate
|
|
302
|
+
|
|
303
|
+
scorer = ScoreGate(
|
|
304
|
+
rubric="Rate the architectural code quality from 1 (disastrous) to 5 (flawless):",
|
|
305
|
+
scale=(1, 5),
|
|
306
|
+
symmetric_debiasing=True, # Evaluates 1->5 and 5->1 to eliminate scale anchoring
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
verdict = scorer.evaluate("def add(a, b): return a + b")
|
|
310
|
+
print(f"Expected Score: {verdict.score:.2f} / 5.00")
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Command-Line Interface (CLI)
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# Evaluate candidate text directly
|
|
319
|
+
logitgate eval --rubric "Must not contain shell commands" --candidate "echo 'hello'"
|
|
320
|
+
|
|
321
|
+
# Evaluate candidate from a file with Layer 0 AST check and JSON output
|
|
322
|
+
logitgate eval --rubric "Must be valid Python" --file script.py --ast-syntax --json
|
|
323
|
+
|
|
324
|
+
# Pipe candidate directly via standard input
|
|
325
|
+
cat schema.json | logitgate eval --rubric "Must be valid JSON schema"
|
|
326
|
+
|
|
327
|
+
# Replay and explain a frozen failure snapshot from CI
|
|
328
|
+
logitgate explain .logitgate/failures/latest.json
|
|
329
|
+
|
|
330
|
+
# Auto-calibrate model temperature on micro-dataset
|
|
331
|
+
logitgate calibrate --backend "ollama://localhost:11434" --model "qwen2.5:14b"
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## BibTeX Citation
|
|
337
|
+
|
|
338
|
+
If you use LogitGate in your research or production systems, please cite it as follows:
|
|
339
|
+
|
|
340
|
+
```bibtex
|
|
341
|
+
@software{logitgate2026,
|
|
342
|
+
author = {Jason Bradley},
|
|
343
|
+
title = {LogitGate: Calibrated First-Token Logit Evaluation and Cascaded Routing for LLMs},
|
|
344
|
+
year = {2026},
|
|
345
|
+
version = {0.2.2},
|
|
346
|
+
url = {https://github.com/jasonbdly/LogitGate},
|
|
347
|
+
license = {Apache-2.0}
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Contributing & License
|
|
354
|
+
|
|
355
|
+
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for local development setup and testing procedures.
|
|
356
|
+
|
|
357
|
+
LogitGate is licensed under the [Apache License 2.0](LICENSE).
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# LogitGate (`logitgate`)
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/logitgate/)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
[](src/logitgate/py.typed)
|
|
7
|
+
[](pyproject.toml)
|
|
8
|
+
[](https://github.com/astral-sh/ruff)
|
|
9
|
+
[](https://gitlab.com/jasonbdly/logitgate/-/pipelines)
|
|
10
|
+
|
|
11
|
+
**Fast, calibrated first-token logit evaluation and 3-layer cascaded routing for LLMs.**
|
|
12
|
+
|
|
13
|
+
LogitGate replaces slow, multi-token LLM-as-a-judge critiques (5–20s) with calibrated first-token logit gates (**36–110 ms**) and a 3-layer cascaded routing pipeline (`ASTGate >> LogitGate >> JudgeGate`), saving 90%–98% of evaluation tokens and wall-clock time while canceling token prior and positional biases.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## How It Works in 60 Seconds
|
|
18
|
+
|
|
19
|
+
When evaluating whether an LLM output satisfies a rubric, traditional frameworks prompt a model to generate a 200–500 word critique before outputting `PASS` or `FAIL`. This takes **5 to 20 seconds**, consumes hundreds of tokens, and suffers from recency and positional biases.
|
|
20
|
+
|
|
21
|
+
`LogitGate` uses a **3-layer cascaded pipeline**:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Candidate Artifact
|
|
25
|
+
│
|
|
26
|
+
▼
|
|
27
|
+
┌──────────────────────────────────────┐
|
|
28
|
+
│ Layer 0: ASTGate / ContractGate ├──► [FAIL: syntax/schema, <0.1ms]
|
|
29
|
+
└──────────────────┬───────────────────┘
|
|
30
|
+
│ Passed
|
|
31
|
+
▼
|
|
32
|
+
┌──────────────────────────────────────┐
|
|
33
|
+
│ Layer 1: LogitGate ├──► [PASS: P >= 0.85, ~40–110ms]
|
|
34
|
+
└──────────────────┬───────────────────┤
|
|
35
|
+
│ Ambiguous └──► [FAIL: P <= 0.20, ~40–110ms]
|
|
36
|
+
│ (0.20 < P < 0.85)
|
|
37
|
+
▼
|
|
38
|
+
┌──────────────────────────────────────┐
|
|
39
|
+
│ Layer 2: JudgeGate ├──► [Actionable Diagnostic Report]
|
|
40
|
+
└──────────────────────────────────────┘
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
1. **Layer 0 (`ASTGate` / `ContractGate`)**: Deterministic checks in **<0.1 ms** on CPU (Python AST syntax, JSON/Pydantic schemas, regex patterns, acyclic DAG topology). Failures reject immediately with zero LLM overhead.
|
|
44
|
+
2. **Layer 1 (`LogitGate` / `ChoiceGate` / `ScoreGate`)**: Reads **first-token log-probabilities (`max_tokens=1`)** in **~36–41 ms on GPU** (~170 ms on CPU). To eliminate pretraining label bias, it averages forward and reverse passes in log-odds space ($\bar{L} = \frac{L_1 + L_2}{2T}$).
|
|
45
|
+
3. **Layer 2 (`JudgeGate`)**: Only when Layer 1 confidence is genuinely ambiguous (between 20% and 85%) or requires failure diagnostics does the pipeline escalate to generating a full text critique.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Core package (zero dependencies except pydantic & httpx)
|
|
53
|
+
pip install logitgate
|
|
54
|
+
|
|
55
|
+
# With optional framework integrations:
|
|
56
|
+
pip install "logitgate[openai]" # OpenAI, vLLM, and compatible endpoints
|
|
57
|
+
pip install "logitgate[llamacpp]" # In-process llama.cpp (zero background daemon)
|
|
58
|
+
pip install "logitgate[langgraph]" # LangGraph conditional edge routing
|
|
59
|
+
pip install "logitgate[deepeval]" # DeepEval System-1 metrics
|
|
60
|
+
pip install "logitgate[recurrent]" # Elastic recurrent looping (NVIDIA Dory-4B)
|
|
61
|
+
pip install "logitgate[all]" # All integrations
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 30-Second Quickstart
|
|
67
|
+
|
|
68
|
+
### 1. Single Atomic Rubric (3-Layer Cascaded Fast Path)
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from logitgate import ASTGate, LogitGate, JudgeGate
|
|
72
|
+
|
|
73
|
+
# Compose the 3-layer pipeline using the >> operator
|
|
74
|
+
cascade = (
|
|
75
|
+
# Layer 0: Ensure valid Python syntax without LLM calls (<0.1ms)
|
|
76
|
+
ASTGate(syntax=True)
|
|
77
|
+
# Layer 1: First-token debiased logit gate (~40-90ms, 0 CoT tokens)
|
|
78
|
+
>> LogitGate(
|
|
79
|
+
rubric="Does the function calculate Fibonacci numbers using recursion?",
|
|
80
|
+
pass_threshold=0.85,
|
|
81
|
+
fail_threshold=0.20,
|
|
82
|
+
)
|
|
83
|
+
# Layer 2: Escalated diagnostic judge (only fires if Layer 1 is ambiguous or failing)
|
|
84
|
+
>> JudgeGate(trigger="on_ambiguous_only")
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
candidate_code = """
|
|
88
|
+
def fibonacci(n: int) -> int:
|
|
89
|
+
if n <= 0:
|
|
90
|
+
return 0
|
|
91
|
+
elif n == 1:
|
|
92
|
+
return 1
|
|
93
|
+
return fibonacci(n - 1) + fibonacci(n - 2)
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
verdict = cascade.evaluate(candidate_code)
|
|
97
|
+
|
|
98
|
+
print(f"Passed: {verdict.passed}") # True
|
|
99
|
+
print(f"Confidence: {verdict.probability:.4f}") # e.g., 0.9982
|
|
100
|
+
print(f"Triggered Layer: {verdict.triggered_layer}") # LogitGate (bypassed Layer 2!)
|
|
101
|
+
print(f"Latency: {verdict.total_latency_ms:.1f}ms") # ~86ms
|
|
102
|
+
print(f"Tokens Generated: {verdict.total_tokens_generated}") # 0 tokens!
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 2. Multi-Rubric Batching (Prefix-Preserved KV-Cache Reuse)
|
|
106
|
+
|
|
107
|
+
When verifying multiple criteria against a candidate artifact, **do not combine them into a single monolithic compound rubric** (which dilutes logit signals and conflates orthogonal requirements). Instead, evaluate isolated atomic rubrics in a single batch using `evaluate_batch`.
|
|
108
|
+
|
|
109
|
+
The candidate code is anchored at Token 0, sharing 95–99% of prefix tokens in KV cache across all checks:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from logitgate import LogitGate
|
|
113
|
+
|
|
114
|
+
# Best Practice: Keep rubrics atomic — evaluate multiple criteria via evaluate_batch
|
|
115
|
+
rubrics = [
|
|
116
|
+
"Does the function calculate Fibonacci numbers recursively?",
|
|
117
|
+
"Does the function explicitly handle non-positive inputs (n <= 0)?",
|
|
118
|
+
"Does the function include parameter and return type annotations?",
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
gate = LogitGate("Base rubric")
|
|
122
|
+
|
|
123
|
+
# Evaluates all 3 rubrics in a single batch reusing the shared KV-cache prefix
|
|
124
|
+
verdicts = gate.evaluate_batch(candidate_code, rubrics)
|
|
125
|
+
|
|
126
|
+
for rubric, v in zip(rubrics, verdicts):
|
|
127
|
+
status = "PASS" if v.passed else "FAIL"
|
|
128
|
+
print(f"[{status}] P={v.probability:.4f} | {rubric}")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Core Gates Quick Reference
|
|
134
|
+
|
|
135
|
+
| Gate | Layer | Latency | Tokens Generated | Purpose & Behavior |
|
|
136
|
+
| :--- | :---: | :---: | :---: | :--- |
|
|
137
|
+
| **`ASTGate`** | Layer 0 | **< 0.1 ms** | 0 | Sub-millisecond deterministic checks: Python syntax, forbidden imports, regex, acyclic DAGs, custom callables. |
|
|
138
|
+
| **`ContractGate`** | Layer 0 | **< 0.1 ms** | 0 | General-domain contract validation: Pydantic models, JSON Schemas, length bounds, required sections. |
|
|
139
|
+
| **`LogitGate`** | Layer 1 | **~40–110 ms** | 0 | Calibrated binary classification from first-token logits using symmetric log-odds debiasing ($\bar{L} = \frac{L_1 + L_2}{2T}$). |
|
|
140
|
+
| **`ChoiceGate`** | Layer 1 | **~40–120 ms** | 0 | Discrete K-ary routing and intent classification across arbitrary string options with permutation averaging. |
|
|
141
|
+
| **`ScoreGate`** | Layer 1 | **~50–160 ms** | 0 | Continuous probability-weighted rubric scoring (𝔼[S] = Σ s · P(s)) with inverted scale debiasing. |
|
|
142
|
+
| **`JudgeGate`** | Layer 2 | **1.5–5.0 s** | 60–300 | Generative System-2 reasoning judge with reason-then-verdict parsing and self-healing 1-token logit probes. |
|
|
143
|
+
| **`Cascade`** | 0 $\to$ 2 | **~40–120 ms\*** | 0\* | Chained pipeline (`gate_a >> gate_b`). Fast passes short-circuit Layer 2 entirely. |
|
|
144
|
+
|
|
145
|
+
*\*Typical latency on non-ambiguous inputs.*
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Benchmark Highlights
|
|
150
|
+
|
|
151
|
+
Across a 24-item multi-domain suite (RAG groundedness, customer support policy, SQL safety, and Python security), `LogitGate` resolves **95.8%–100.0% of cases at Layers 0 and 1**, avoiding multi-token generation:
|
|
152
|
+
|
|
153
|
+
| Evaluation Approach | Typical Latency | Generated Tokens | Extra GPU VRAM | Bias Cancellation | Speedup |
|
|
154
|
+
| :--- | :---: | :---: | :---: | :---: | :---: |
|
|
155
|
+
| **Generative LLM Judge** *(G-Eval, MT-Bench)* | 1,500ms – 8,000ms | 100 – 600 CoT tokens | 0 GB (Shared) | ❌ None | 1.0x |
|
|
156
|
+
| **Fine-Tuned Judge Models** *(Prometheus 2, Selene)* | 800ms – 3,500ms | 80 – 300 CoT tokens | 14 GB – 48 GB (Dedicated) | ❌ Susceptible to bias | 2.5x |
|
|
157
|
+
| **`LogitGate` 3-Layer Cascade** | **36ms – 113ms** | **0 CoT tokens** | **0 GB (Reuses generator)** | **✅ Symmetric Log-Odds** | **10x – 17x** |
|
|
158
|
+
|
|
159
|
+
### CPU-Only CI/CD Champion: `llama3.2:3b` in Q4_K_M
|
|
160
|
+
- **In-Process `llama.cpp`**: Cold-starts in **3.2 seconds** inside your Python process (zero external background daemon), allocating only **2.36 GB RAM**.
|
|
161
|
+
- **Performance**: Evaluates 2-pass symmetric debiased gating in **815 ms** on CPU with **$\rho = 0.8487$** continuous scoring correlation.
|
|
162
|
+
- **Thread Scaling Law**: CPU execution saturates at **2 threads** (112 ms forward pass) due to memory bandwidth limits.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## In-Depth Documentation Index
|
|
167
|
+
|
|
168
|
+
For complete research data, mathematical derivations, and production recipes, explore our modular documentation:
|
|
169
|
+
|
|
170
|
+
- 📊 **[Empirical Benchmarks & Falsification Studies](docs/benchmarks.md)**:
|
|
171
|
+
- 24-item multi-domain cascade efficiency & token savings
|
|
172
|
+
- Fair pure-CPU CI/CD runner benchmarks (10-item CI suite)
|
|
173
|
+
- Compact models on CPU (1B–3B vs 4B baseline)
|
|
174
|
+
- In-process `llama.cpp` vs Ollama daemon & thread scaling sweeps
|
|
175
|
+
- Hardened 32-item adversarial benchmark suite ($N=5$)
|
|
176
|
+
- Falsification boundaries: reasoning depth, context length (16k), and context window squeezing
|
|
177
|
+
- Elastic recurrent layer-looping (NVIDIA Dory-4B, RTX 5090 vs RTX 4070)
|
|
178
|
+
- 🏗️ **[3-Layer Architecture & Deployment Topologies](docs/architecture.md)**:
|
|
179
|
+
- Execution mechanics, lookahead policy, and monotonic failure preservation
|
|
180
|
+
- System requirements across 0-GPU, Consumer GPU, and Enterprise hardware
|
|
181
|
+
- 3 deployment topologies to prevent KV-cache eviction and thrashing
|
|
182
|
+
- 📐 **[Mathematical Foundations & Symmetric Debiasing](docs/math_and_debiasing.md)**:
|
|
183
|
+
- Analytical proof of prior token bias cancellation in log-odds space
|
|
184
|
+
- Probability averaging vs. log-odds space contrast
|
|
185
|
+
- Prefix-preserving attention inversion & missing-token bounded floor
|
|
186
|
+
- Temperature calibration ($T$) and Brier score minimization
|
|
187
|
+
- 💡 **[Production Use Cases & Best Practices](docs/use_cases.md)**:
|
|
188
|
+
- CI/CD final merge gates vs local inner loop
|
|
189
|
+
- Reproducing CI failures locally via `VerdictSnapshot` and `logitgate explain`
|
|
190
|
+
- RAG hallucination guardrails & LangGraph agent intent routing
|
|
191
|
+
- Candidate-prefix isolated batching (`evaluate_batch`) vs monolithic prompt anti-patterns
|
|
192
|
+
- 🔌 **[Framework Integrations](docs/integrations.md)**:
|
|
193
|
+
- Pytest `@check` test decorator
|
|
194
|
+
- DeepEval `LogitGateSystemOneModel` and `LogitGateMetric`
|
|
195
|
+
- LangGraph conditional edge routing (`as_conditional_edge`)
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Common Recipes
|
|
200
|
+
|
|
201
|
+
### Multi-Rubric Batch Evaluation (`evaluate_batch`)
|
|
202
|
+
Evaluates multiple rubrics against a single candidate artifact while anchoring the candidate at Token 0 to share 95–99% of prefix tokens in KV-cache:
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
from logitgate import LogitGate
|
|
206
|
+
|
|
207
|
+
gate = LogitGate("Base rubric")
|
|
208
|
+
|
|
209
|
+
rubrics = [
|
|
210
|
+
"Does the code include full type annotations?",
|
|
211
|
+
"Does the code avoid mutable default arguments?",
|
|
212
|
+
"Does the code implement proper error handling?",
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
candidate_code = "def fetch(url: str, timeout: int = 10) -> str: pass"
|
|
216
|
+
verdicts = gate.evaluate_batch(candidate_code, rubrics)
|
|
217
|
+
|
|
218
|
+
for rubric, v in zip(rubrics, verdicts):
|
|
219
|
+
print(f"[{'PASS' if v.passed else 'FAIL'}] P={v.probability:.2f} | {rubric}")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Discrete Multi-Way Routing (`ChoiceGate`)
|
|
223
|
+
Routes requests across $K$ options in ~40–90 ms without generating JSON:
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
from logitgate import ChoiceGate
|
|
227
|
+
|
|
228
|
+
router = ChoiceGate(
|
|
229
|
+
question="Route this incoming user request to the appropriate specialist:",
|
|
230
|
+
options={
|
|
231
|
+
"A": "Database and SQL query optimizations",
|
|
232
|
+
"B": "Authentication and user permissions",
|
|
233
|
+
"C": "Billing, invoices, and payment processing",
|
|
234
|
+
},
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
verdict = router.evaluate("My credit card was charged twice for invoice #902.")
|
|
238
|
+
print(f"Selected route: {verdict.choice}") # 'C'
|
|
239
|
+
print(f"Probabilities: {verdict.choice_probabilities}")
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Continuous Rubric Scoring (`ScoreGate`)
|
|
243
|
+
Calculates a smooth expected score (𝔼[S] ∈ [1.0, 5.0]) using first-token softmax weights:
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
from logitgate import ScoreGate
|
|
247
|
+
|
|
248
|
+
scorer = ScoreGate(
|
|
249
|
+
rubric="Rate the architectural code quality from 1 (disastrous) to 5 (flawless):",
|
|
250
|
+
scale=(1, 5),
|
|
251
|
+
symmetric_debiasing=True, # Evaluates 1->5 and 5->1 to eliminate scale anchoring
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
verdict = scorer.evaluate("def add(a, b): return a + b")
|
|
255
|
+
print(f"Expected Score: {verdict.score:.2f} / 5.00")
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Command-Line Interface (CLI)
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
# Evaluate candidate text directly
|
|
264
|
+
logitgate eval --rubric "Must not contain shell commands" --candidate "echo 'hello'"
|
|
265
|
+
|
|
266
|
+
# Evaluate candidate from a file with Layer 0 AST check and JSON output
|
|
267
|
+
logitgate eval --rubric "Must be valid Python" --file script.py --ast-syntax --json
|
|
268
|
+
|
|
269
|
+
# Pipe candidate directly via standard input
|
|
270
|
+
cat schema.json | logitgate eval --rubric "Must be valid JSON schema"
|
|
271
|
+
|
|
272
|
+
# Replay and explain a frozen failure snapshot from CI
|
|
273
|
+
logitgate explain .logitgate/failures/latest.json
|
|
274
|
+
|
|
275
|
+
# Auto-calibrate model temperature on micro-dataset
|
|
276
|
+
logitgate calibrate --backend "ollama://localhost:11434" --model "qwen2.5:14b"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## BibTeX Citation
|
|
282
|
+
|
|
283
|
+
If you use LogitGate in your research or production systems, please cite it as follows:
|
|
284
|
+
|
|
285
|
+
```bibtex
|
|
286
|
+
@software{logitgate2026,
|
|
287
|
+
author = {Jason Bradley},
|
|
288
|
+
title = {LogitGate: Calibrated First-Token Logit Evaluation and Cascaded Routing for LLMs},
|
|
289
|
+
year = {2026},
|
|
290
|
+
version = {0.2.2},
|
|
291
|
+
url = {https://github.com/jasonbdly/LogitGate},
|
|
292
|
+
license = {Apache-2.0}
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Contributing & License
|
|
299
|
+
|
|
300
|
+
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for local development setup and testing procedures.
|
|
301
|
+
|
|
302
|
+
LogitGate is licensed under the [Apache License 2.0](LICENSE).
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "logitgate"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "Fast, calibrated first-token logit evaluation and 3-layer cascaded routing for LLMs."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|