logitgate 0.3.1__tar.gz → 0.4.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.
Files changed (62) hide show
  1. {logitgate-0.3.1/src/logitgate.egg-info → logitgate-0.4.0}/PKG-INFO +16 -10
  2. {logitgate-0.3.1 → logitgate-0.4.0}/README.md +15 -9
  3. {logitgate-0.3.1 → logitgate-0.4.0}/pyproject.toml +1 -1
  4. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/__init__.py +10 -2
  5. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/backends/base.py +238 -73
  6. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/backends/dory_recurrent.py +4 -1
  7. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/backends/llamacpp.py +106 -46
  8. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/backends/ollama.py +24 -6
  9. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/backends/openai_compat.py +43 -19
  10. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/backends/pytorch_native.py +20 -14
  11. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/backends/recurrent.py +107 -69
  12. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/benchmark.py +56 -36
  13. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/calibration/__init__.py +2 -0
  14. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/calibration/conformal.py +73 -27
  15. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/cascade.py +81 -14
  16. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/cli.py +179 -108
  17. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/config.py +76 -54
  18. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/debiasing/inversion.py +4 -1
  19. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/debiasing/permutation.py +205 -71
  20. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/debiasing/softmax.py +69 -19
  21. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/gates/__init__.py +9 -2
  22. logitgate-0.4.0/src/logitgate/gates/ast_gate.py +882 -0
  23. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/gates/base.py +51 -6
  24. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/gates/judge_gate.py +154 -43
  25. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/gates/logit_gate.py +231 -83
  26. logitgate-0.4.0/src/logitgate/integrations/deepeval.py +453 -0
  27. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/integrations/langgraph.py +41 -8
  28. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/integrations/pytest_plugin.py +52 -8
  29. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/models.py +5 -0
  30. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/snapshot.py +308 -65
  31. {logitgate-0.3.1 → logitgate-0.4.0/src/logitgate.egg-info}/PKG-INFO +16 -10
  32. logitgate-0.4.0/tests/test_ast_gate.py +310 -0
  33. {logitgate-0.3.1 → logitgate-0.4.0}/tests/test_cascade_routing.py +26 -0
  34. {logitgate-0.3.1 → logitgate-0.4.0}/tests/test_debiasing_math.py +77 -0
  35. {logitgate-0.3.1 → logitgate-0.4.0}/tests/test_dx_and_tooling.py +230 -0
  36. logitgate-0.4.0/tests/test_integrations.py +196 -0
  37. {logitgate-0.3.1 → logitgate-0.4.0}/tests/test_logit_gate.py +89 -6
  38. {logitgate-0.3.1 → logitgate-0.4.0}/tests/test_multi_rubric_gate.py +1 -0
  39. {logitgate-0.3.1 → logitgate-0.4.0}/tests/test_usability_and_validation.py +17 -2
  40. logitgate-0.3.1/src/logitgate/gates/ast_gate.py +0 -473
  41. logitgate-0.3.1/src/logitgate/integrations/deepeval.py +0 -212
  42. logitgate-0.3.1/tests/test_ast_gate.py +0 -168
  43. logitgate-0.3.1/tests/test_integrations.py +0 -78
  44. {logitgate-0.3.1 → logitgate-0.4.0}/LICENSE +0 -0
  45. {logitgate-0.3.1 → logitgate-0.4.0}/setup.cfg +0 -0
  46. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/backends/__init__.py +0 -0
  47. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/backends/dory_pytorch.py +0 -0
  48. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/debiasing/__init__.py +0 -0
  49. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/exceptions.py +0 -0
  50. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/hardware/__init__.py +0 -0
  51. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/hardware/memory_guard.py +0 -0
  52. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/integrations/__init__.py +0 -0
  53. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate/py.typed +0 -0
  54. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate.egg-info/SOURCES.txt +0 -0
  55. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate.egg-info/dependency_links.txt +0 -0
  56. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate.egg-info/entry_points.txt +0 -0
  57. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate.egg-info/requires.txt +0 -0
  58. {logitgate-0.3.1 → logitgate-0.4.0}/src/logitgate.egg-info/top_level.txt +0 -0
  59. {logitgate-0.3.1 → logitgate-0.4.0}/tests/test_backends_and_cli.py +0 -0
  60. {logitgate-0.3.1 → logitgate-0.4.0}/tests/test_calibration.py +0 -0
  61. {logitgate-0.3.1 → logitgate-0.4.0}/tests/test_cascade.py +0 -0
  62. {logitgate-0.3.1 → logitgate-0.4.0}/tests/test_conformal_guarantees.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: logitgate
3
- Version: 0.3.1
3
+ Version: 0.4.0
4
4
  Summary: Fast, calibrated first-token logit evaluation and 3-layer cascaded routing for LLMs.
5
5
  Author-email: Jason Bradley <jasonbdly@gmail.com>
6
6
  License: Apache-2.0
@@ -206,6 +206,12 @@ When checking multiple criteria against a single output, combining them into one
206
206
  ```python
207
207
  from logitgate import MultiRubricGate
208
208
 
209
+ candidate_code = """
210
+ def get_user_by_id(cursor, user_id: int) -> tuple | None:
211
+ cursor.execute("SELECT id, email FROM users WHERE id = ?", (user_id,))
212
+ return cursor.fetchone()
213
+ """
214
+
209
215
  rubrics = [
210
216
  "Does the function use parameterized SQL placeholders instead of f-strings?",
211
217
  "Does the function include parameter and return type annotations?",
@@ -227,11 +233,11 @@ for rubric, v in zip(rubrics, gate.evaluate_each(candidate_code)):
227
233
 
228
234
  | Gate | Layer | Latency (GPU) | Tokens Generated | Purpose & Behavior |
229
235
  | :--- | :---: | :---: | :---: | :--- |
230
- | **`ASTGate`** | Layer 0 | **< 0.1 ms** | 0 | Sub-millisecond deterministic checks: Python syntax, forbidden imports, regex, acyclic DAGs, custom callables. |
236
+ | **`ASTGate`** | Layer 0 | **< 0.1 ms** | 0 | Sub-millisecond deterministic adapter: BYO parsers/validators (`ASTGate(PydanticModel, normalize=True)`), Python AST, JSON schema, regex, DAGs. |
231
237
  | **`ContractGate`** | Layer 0 | **< 0.1 ms** | 0 | General-domain contract validation: Pydantic models, JSON Schemas, length bounds, required sections. |
232
238
  | **`LogitGate`** | Layer 1 | **~36-113 ms** | 0 | Calibrated binary classification from first-token logits using symmetric log-odds debiasing ($\bar{L} = \frac{L_1 + L_2}{2T}$). |
233
239
  | **`MultiRubricGate`** | Layer 1 | **~50-140 ms** | 0 | Atomic multi-rubric verification sharing the candidate KV-cache prefix with weakest-link (`min(P)`) aggregation. |
234
- | **`ChoiceGate`** | Layer 1 | **~40-140 ms** | 0 | Discrete K-way routing and classification across options with cyclic permutation debiasing. |
240
+ | **`ChoiceGate`** | Layer 1 | **~40-140 ms** | 0 | Discrete K-way routing and classification across options with symmetric order-reversal debiasing. |
235
241
  | **`ScoreGate`** | Layer 1 | **~50-165 ms** | 0 | Continuous probability-weighted rubric scoring ($\mathbb{E}[S] = \sum s \cdot P(s)$) with 2-pass scale-reversal debiasing. |
236
242
  | **`JudgeGate`** | Layer 2 | **1.5-5.0 s** | 60-300 | Generative step-by-step reasoning judge with reason-then-verdict parsing and a self-healing 1-token logit fallback. |
237
243
  | **`Cascade`** | 0 $\to$ 2 | **~40-120 ms\*** | 0\* | Chained pipeline (`gate_a >> gate_b`). Clear passes and failures at Layer 0/1 skip Layer 2. |
@@ -245,7 +251,7 @@ for rubric, v in zip(rubrics, gate.evaluate_each(candidate_code)):
245
251
  | Approach | What it does | How LogitGate relates |
246
252
  | :--- | :--- | :--- |
247
253
  | **Structured Outputs (`{"pass": bool}`)** | Forces a 1-token boolean or enum via grammar mask. | Naive 1-token decoding suffers from affirmative/position priors and collapses `P=0.51` and `P=0.99` into `True` with no uncertainty routing. `LogitGate` debiases in log-odds space and routes `0.20 < P < 0.85` to Layer 2. |
248
- | **Fine-Tuned Decision Models (`Unsloth FastDecisionModel`)** | Trains a LoRA adapter on 1,000 to 10,000+ labeled rows to score 20 to 150+ classes in one pass, even on `0.8B` models. | Use fine-tuning when you have thousands of labeled rows and a fixed 150-class taxonomy on a sub-1B model. Use `LogitGate` when you write rules as plain-English rubrics and want zero training overhead on `3B+` models you already serve. |
254
+ | **Fine-Tuned Decision Models (`Unsloth` / Airbnb `GLOWC`)** | Trains a LoRA adapter on thousands of labeled rows to score classes in a single ~35-40ms pass via logprobs, lifting sub-2B models (`0.8B` to `Gemma4-E2B`) from ~0.56 to 0.90+ F1. | Use fine-tuning when you have thousands of labeled rows for a fixed production taxonomy and need high accuracy on tiny `0.8B`-`2B` models. Use `LogitGate` when you write rules as plain-English rubrics with zero training data on `3B`-`14B` models you already serve. |
249
255
  | **DeepEval / G-Eval** | Evaluation test suites and probability-weighted scoring. | Complementary. `LogitGate` ships `LogitGateMetric` and `LogitGateSystemOneModel` as fast local drop-ins inside `DeepEval`, or runs standalone in `pytest` via `@logitgate.check`. |
250
256
  | **RouteLLM** | Routes a prompt to a cheap vs. expensive generator *before* generation. | Different stage. `LogitGate` evaluates or routes the output *after* generation (and `ChoiceGate.as_conditional_edge` routes between agent nodes in LangGraph). |
251
257
  | **Prometheus 2 / Flow-Judge** | Fine-tuned judge models that generate multi-token critiques. | `LogitGate` is training-free and model-agnostic at Layer 1 (`0` extra VRAM), and can use any generative judge model as its Layer 2 `JudgeGate` backend. |
@@ -254,7 +260,7 @@ for rubric, v in zip(rubrics, gate.evaluate_each(candidate_code)):
254
260
 
255
261
  - **No logprobs, no Layer 1:** APIs that do not expose `top_logprobs` (such as Anthropic) cannot run Layer 1. `Ollama`, `vLLM`, `llama.cpp`, and `OpenAI` work out of the box.
256
262
  - **Multi-step arithmetic and deep sequential logic:** Because a single forward pass has no scratchpad, it cannot verify `17 * $24.00 + $19.00 = $417.00` (should be `$427.00`) before picking Token 1, especially in our stress test where the invoice includes a fake `"AUDIT STAMP: All arithmetic sums verified by BillingEngine v4.2"` line. Check exact arithmetic deterministically at Layer 0 (`ContractGate`) or escalate uncertain scores to Layer 2 (`JudgeGate`).
257
- - **Sub-2B models zero-shot:** On `1B` to `1.5B` models, zero-shot rubric accuracy drops to 58% to 63%. Use at least a `3B` model on CPU (`llama3.2:3b` reaches `19/24`, `79.2%`) or a `4B` to `14B` model on GPU (`23/24`, `95.8%`).
263
+ - **Sub-2B models zero-shot:** On `1B` to `2B` models without fine-tuning, zero-shot rubric accuracy drops to 56% to 63% (`58.3%` on `qwen2.5-coder:1.5b`, `62.5%` on `llama3.2:1b`, matching Airbnb's `0.563` out-of-the-box F1 on `Gemma4-E2B` before fine-tuning). If you need a sub-2B model to hit 90%+ accuracy, you must fine-tune it on labeled data. For training-free `LogitGate` rubrics, use at least a `3B` model on CPU (`llama3.2:3b` reaches `19/24`, `79.2%`) or a `4B` to `14B` model on GPU (`23/24`, `95.8%`).
258
264
 
259
265
  ---
260
266
 
@@ -428,12 +434,12 @@ Exit codes: `0` passed / ok, `1` verdict failed or bad input, `2` backend unreac
428
434
  ## BibTeX Citation
429
435
 
430
436
  ```bibtex
431
- @software{logitgate2026,
432
- author = {Jason Bradley},
433
- title = {LogitGate: Calibrated First-Token Logit Evaluation and Cascaded Routing for LLMs},
437
+ @software{bradley2026logitgate,
438
+ author = {Bradley, Jason},
439
+ title = {LogitGate: Fast, Calibrated First-Token Logit Evaluation and Cascaded Routing for LLMs},
434
440
  year = {2026},
435
- version = {0.3.1},
436
- url = {https://github.com/jasonbdly/logitgate},
441
+ version = {0.4.0},
442
+ url = {https://github.com/jasonbdly/LogitGate},
437
443
  license = {Apache-2.0}
438
444
  }
439
445
  ```
@@ -151,6 +151,12 @@ When checking multiple criteria against a single output, combining them into one
151
151
  ```python
152
152
  from logitgate import MultiRubricGate
153
153
 
154
+ candidate_code = """
155
+ def get_user_by_id(cursor, user_id: int) -> tuple | None:
156
+ cursor.execute("SELECT id, email FROM users WHERE id = ?", (user_id,))
157
+ return cursor.fetchone()
158
+ """
159
+
154
160
  rubrics = [
155
161
  "Does the function use parameterized SQL placeholders instead of f-strings?",
156
162
  "Does the function include parameter and return type annotations?",
@@ -172,11 +178,11 @@ for rubric, v in zip(rubrics, gate.evaluate_each(candidate_code)):
172
178
 
173
179
  | Gate | Layer | Latency (GPU) | Tokens Generated | Purpose & Behavior |
174
180
  | :--- | :---: | :---: | :---: | :--- |
175
- | **`ASTGate`** | Layer 0 | **< 0.1 ms** | 0 | Sub-millisecond deterministic checks: Python syntax, forbidden imports, regex, acyclic DAGs, custom callables. |
181
+ | **`ASTGate`** | Layer 0 | **< 0.1 ms** | 0 | Sub-millisecond deterministic adapter: BYO parsers/validators (`ASTGate(PydanticModel, normalize=True)`), Python AST, JSON schema, regex, DAGs. |
176
182
  | **`ContractGate`** | Layer 0 | **< 0.1 ms** | 0 | General-domain contract validation: Pydantic models, JSON Schemas, length bounds, required sections. |
177
183
  | **`LogitGate`** | Layer 1 | **~36-113 ms** | 0 | Calibrated binary classification from first-token logits using symmetric log-odds debiasing ($\bar{L} = \frac{L_1 + L_2}{2T}$). |
178
184
  | **`MultiRubricGate`** | Layer 1 | **~50-140 ms** | 0 | Atomic multi-rubric verification sharing the candidate KV-cache prefix with weakest-link (`min(P)`) aggregation. |
179
- | **`ChoiceGate`** | Layer 1 | **~40-140 ms** | 0 | Discrete K-way routing and classification across options with cyclic permutation debiasing. |
185
+ | **`ChoiceGate`** | Layer 1 | **~40-140 ms** | 0 | Discrete K-way routing and classification across options with symmetric order-reversal debiasing. |
180
186
  | **`ScoreGate`** | Layer 1 | **~50-165 ms** | 0 | Continuous probability-weighted rubric scoring ($\mathbb{E}[S] = \sum s \cdot P(s)$) with 2-pass scale-reversal debiasing. |
181
187
  | **`JudgeGate`** | Layer 2 | **1.5-5.0 s** | 60-300 | Generative step-by-step reasoning judge with reason-then-verdict parsing and a self-healing 1-token logit fallback. |
182
188
  | **`Cascade`** | 0 $\to$ 2 | **~40-120 ms\*** | 0\* | Chained pipeline (`gate_a >> gate_b`). Clear passes and failures at Layer 0/1 skip Layer 2. |
@@ -190,7 +196,7 @@ for rubric, v in zip(rubrics, gate.evaluate_each(candidate_code)):
190
196
  | Approach | What it does | How LogitGate relates |
191
197
  | :--- | :--- | :--- |
192
198
  | **Structured Outputs (`{"pass": bool}`)** | Forces a 1-token boolean or enum via grammar mask. | Naive 1-token decoding suffers from affirmative/position priors and collapses `P=0.51` and `P=0.99` into `True` with no uncertainty routing. `LogitGate` debiases in log-odds space and routes `0.20 < P < 0.85` to Layer 2. |
193
- | **Fine-Tuned Decision Models (`Unsloth FastDecisionModel`)** | Trains a LoRA adapter on 1,000 to 10,000+ labeled rows to score 20 to 150+ classes in one pass, even on `0.8B` models. | Use fine-tuning when you have thousands of labeled rows and a fixed 150-class taxonomy on a sub-1B model. Use `LogitGate` when you write rules as plain-English rubrics and want zero training overhead on `3B+` models you already serve. |
199
+ | **Fine-Tuned Decision Models (`Unsloth` / Airbnb `GLOWC`)** | Trains a LoRA adapter on thousands of labeled rows to score classes in a single ~35-40ms pass via logprobs, lifting sub-2B models (`0.8B` to `Gemma4-E2B`) from ~0.56 to 0.90+ F1. | Use fine-tuning when you have thousands of labeled rows for a fixed production taxonomy and need high accuracy on tiny `0.8B`-`2B` models. Use `LogitGate` when you write rules as plain-English rubrics with zero training data on `3B`-`14B` models you already serve. |
194
200
  | **DeepEval / G-Eval** | Evaluation test suites and probability-weighted scoring. | Complementary. `LogitGate` ships `LogitGateMetric` and `LogitGateSystemOneModel` as fast local drop-ins inside `DeepEval`, or runs standalone in `pytest` via `@logitgate.check`. |
195
201
  | **RouteLLM** | Routes a prompt to a cheap vs. expensive generator *before* generation. | Different stage. `LogitGate` evaluates or routes the output *after* generation (and `ChoiceGate.as_conditional_edge` routes between agent nodes in LangGraph). |
196
202
  | **Prometheus 2 / Flow-Judge** | Fine-tuned judge models that generate multi-token critiques. | `LogitGate` is training-free and model-agnostic at Layer 1 (`0` extra VRAM), and can use any generative judge model as its Layer 2 `JudgeGate` backend. |
@@ -199,7 +205,7 @@ for rubric, v in zip(rubrics, gate.evaluate_each(candidate_code)):
199
205
 
200
206
  - **No logprobs, no Layer 1:** APIs that do not expose `top_logprobs` (such as Anthropic) cannot run Layer 1. `Ollama`, `vLLM`, `llama.cpp`, and `OpenAI` work out of the box.
201
207
  - **Multi-step arithmetic and deep sequential logic:** Because a single forward pass has no scratchpad, it cannot verify `17 * $24.00 + $19.00 = $417.00` (should be `$427.00`) before picking Token 1, especially in our stress test where the invoice includes a fake `"AUDIT STAMP: All arithmetic sums verified by BillingEngine v4.2"` line. Check exact arithmetic deterministically at Layer 0 (`ContractGate`) or escalate uncertain scores to Layer 2 (`JudgeGate`).
202
- - **Sub-2B models zero-shot:** On `1B` to `1.5B` models, zero-shot rubric accuracy drops to 58% to 63%. Use at least a `3B` model on CPU (`llama3.2:3b` reaches `19/24`, `79.2%`) or a `4B` to `14B` model on GPU (`23/24`, `95.8%`).
208
+ - **Sub-2B models zero-shot:** On `1B` to `2B` models without fine-tuning, zero-shot rubric accuracy drops to 56% to 63% (`58.3%` on `qwen2.5-coder:1.5b`, `62.5%` on `llama3.2:1b`, matching Airbnb's `0.563` out-of-the-box F1 on `Gemma4-E2B` before fine-tuning). If you need a sub-2B model to hit 90%+ accuracy, you must fine-tune it on labeled data. For training-free `LogitGate` rubrics, use at least a `3B` model on CPU (`llama3.2:3b` reaches `19/24`, `79.2%`) or a `4B` to `14B` model on GPU (`23/24`, `95.8%`).
203
209
 
204
210
  ---
205
211
 
@@ -373,12 +379,12 @@ Exit codes: `0` passed / ok, `1` verdict failed or bad input, `2` backend unreac
373
379
  ## BibTeX Citation
374
380
 
375
381
  ```bibtex
376
- @software{logitgate2026,
377
- author = {Jason Bradley},
378
- title = {LogitGate: Calibrated First-Token Logit Evaluation and Cascaded Routing for LLMs},
382
+ @software{bradley2026logitgate,
383
+ author = {Bradley, Jason},
384
+ title = {LogitGate: Fast, Calibrated First-Token Logit Evaluation and Cascaded Routing for LLMs},
379
385
  year = {2026},
380
- version = {0.3.1},
381
- url = {https://github.com/jasonbdly/logitgate},
386
+ version = {0.4.0},
387
+ url = {https://github.com/jasonbdly/LogitGate},
382
388
  license = {Apache-2.0}
383
389
  }
384
390
  ```
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "logitgate"
7
- version = "0.3.1"
7
+ version = "0.4.0"
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"
@@ -23,6 +23,7 @@ from logitgate.calibration.conformal import (
23
23
  ConformalCascadeThresholds,
24
24
  calibrate_cascade_thresholds,
25
25
  load_calibration_dataset,
26
+ min_samples_per_class,
26
27
  )
27
28
  from logitgate.cascade import Cascade
28
29
  from logitgate.config import (
@@ -69,7 +70,12 @@ from logitgate.exceptions import (
69
70
  LogitGateError,
70
71
  StubBackendWarning,
71
72
  )
72
- from logitgate.gates.ast_gate import ASTFailureCode, ASTGate, ContractGate
73
+ from logitgate.gates.ast_gate import (
74
+ ASTFailureCode,
75
+ ASTGate,
76
+ ContractGate,
77
+ normalize_candidate,
78
+ )
73
79
  from logitgate.gates.base import BaseGate, EscalationPolicy
74
80
  from logitgate.gates.judge_gate import JudgeGate
75
81
  from logitgate.gates.logit_gate import ChoiceGate, LogitGate, MultiRubricGate, ScoreGate
@@ -115,7 +121,7 @@ def __getattr__(name: str) -> Any:
115
121
  def __dir__() -> list[str]:
116
122
  return sorted({*globals(), *_LAZY_INTEGRATIONS})
117
123
 
118
- __version__ = "0.3.1"
124
+ __version__ = "0.4.0"
119
125
 
120
126
  __all__ = [
121
127
  "KNOWN_MODEL_TEMPERATURES",
@@ -187,6 +193,8 @@ __all__ = [
187
193
  "infer_backend_spec",
188
194
  "load_calibration_dataset",
189
195
  "marginalize_pole_logprob",
196
+ "min_samples_per_class",
197
+ "normalize_candidate",
190
198
  "reset_config",
191
199
  "resolve_generative_backend",
192
200
  "resolve_logit_backend",