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