reasonkit 0.2.0__py3-none-any.whl

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.
@@ -0,0 +1,336 @@
1
+ Metadata-Version: 2.4
2
+ Name: reasonkit
3
+ Version: 0.2.0
4
+ Summary: Wrap an existing LLM callable with a short reasoning pipeline. No model or API of its own.
5
+ Author-email: Xavier Cartwright <xavier@thecartwrights.id.au>
6
+ License-Expression: GPL-3.0-only
7
+ Project-URL: Homepage, https://github.com/xavcartwheel/reasonkit
8
+ Project-URL: Repository, https://github.com/xavcartwheel/reasonkit
9
+ Keywords: llm,reasoning,prompt,pipeline,critique
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Classifier: Operating System :: OS Independent
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Provides-Extra: examples
24
+ Requires-Dist: openai; extra == "examples"
25
+ Requires-Dist: anthropic; extra == "examples"
26
+ Provides-Extra: test
27
+ Requires-Dist: pytest; extra == "test"
28
+ Dynamic: license-file
29
+
30
+ <div align="center">
31
+ <picture>
32
+ <source media="(prefers-color-scheme: dark)" srcset="./img/logo-dark.png">
33
+ <img src="./img/logo-light.png" alt="ReasonKit">
34
+ </picture>
35
+ </div>
36
+
37
+ <p align="center">
38
+ <strong>Your LLM's first answer is not your best option. One wrapper later, your model checks its work and improves.</strong>
39
+ </p>
40
+
41
+ <p align="center">
42
+ <a href="https://www.python.org"><img src="https://img.shields.io/badge/python-3.9%2B-blue?style=flat-square" alt="Python version"></a>
43
+ <a href="./LICENSE"><img src="https://img.shields.io/badge/license-GPL--3.0-blue?style=flat-square" alt="License"></a>
44
+ </p>
45
+
46
+ ---
47
+
48
+ Single-pass LLM calls sound confident. They ship their first draft without review. They do not catch the assumptions they made or the questions they should have asked.
49
+
50
+ **ReasonKit** wraps your `call_llm(prompt) -> str` and returns a function with the same signature. The wrapped function runs classification, generates alternative approaches, critiques them, merges the best ideas, and deepens the final answer. Every call goes through your model, your credentials, and your rate limits. No second provider. No new API.
51
+
52
+ ```python
53
+ import reasonkit
54
+
55
+ def call_llm(prompt: str) -> str:
56
+ ... # your existing LLM call
57
+
58
+ better_llm = reasonkit.enhance(call_llm)
59
+ answer = better_llm("Should I start a coffee shop?")
60
+ ```
61
+
62
+ The **benchmark** across 2 providers (Cloudflare, LLM7.io) and 6 models shows the results:
63
+
64
+ | Model | RQI raw | RQI ReasonKit | Delta | Catch rate | SC lift |
65
+ |-------|---------|---------------|-------|------------|---------|
66
+ | Llama 3.1 8B | 21 | 24 | +3.0 | 80% | +6.8 |
67
+ | Llama 4 Scout 17B | 23 | 28 | +4.8 | 100% | +8.5 |
68
+ | Qwen QwQ 32B | 23 | 29 | +6.0 | 100% | +8.7 |
69
+ | GPT-OSS 20B | 23 | 30 | +7.4 | 100% | +8.9 |
70
+ | Codestral Latest | 21 | 29 | +8.6 | 100% | +8.6 |
71
+ | MiniMax M2.7 | 21 | 22 | +0.6 | 100% | +9.0 |
72
+ | **Average** | **22** | **27** | **+5.1** | **97%** | **+8.4** |
73
+
74
+ RQI is a 0-40 composite of reasoning, accuracy, questioning, and structure. A fixed judge model scores each answer blindly. Self-correction (SC) is trace-derived and reported separately. Read the full methodology.
75
+
76
+ **Cost warning.** `enhance()` multiplies your token usage by about 3 to 4 times. Every internal call goes through your function. You pay for every one. Use ReasonKit for prompts where quality matters. For high-volume traffic, lower branches and max_cycles to reduce cost.
77
+
78
+ ## Features
79
+
80
+ - **Self-correcting output.** The pipeline critiques its own draft, finds concrete flaws, and fixes them. It catches 80% to 100% of issues a raw call would ship without review — 97% average across 6 models.
81
+ - **Surfaces hidden assumptions.** The critique pass forces the model to name its own assumptions. You see the clarifying questions a single-pass call omits.
82
+ - Drop-in wrapper. enhance() keeps your existing str -> str signature. Async and streaming callables work too.
83
+ - **Zero dependencies.** Standard library only. No third-party packages are installed.
84
+ - Full trace. Opt-in to see every internal call, classification, and revision.
85
+
86
+ ## Install
87
+
88
+ ```bash
89
+ pip install reasonkit
90
+ ```
91
+
92
+ Requires Python 3.9 or later. No third-party packages are installed by default.
93
+
94
+ For development:
95
+
96
+ ```bash
97
+ pip install -e ".[test]"
98
+ ```
99
+
100
+ ## Quick start
101
+
102
+ ```python
103
+ import reasonkit
104
+
105
+ def call_llm(prompt: str) -> str:
106
+ ... # your existing LLM call
107
+
108
+ better_llm = reasonkit.enhance(call_llm)
109
+ answer = better_llm("Should I start a coffee shop?")
110
+ ```
111
+
112
+ Enable the trace for full visibility:
113
+
114
+ ```python
115
+ better_llm = reasonkit.enhance(call_llm, return_trace=True)
116
+ result = better_llm("Should I start a coffee shop?")
117
+ result.answer # str
118
+ result.trace # every internal call
119
+ result.mode # decision, code, or direct
120
+ result.stopped_reason # why the pipeline stopped
121
+ ```
122
+
123
+ Compare raw and wrapped output side by side:
124
+
125
+ ```python
126
+ comparison = reasonkit.compare(call_llm, "Should I start a coffee shop?")
127
+ comparison.baseline_answer # raw call_llm result
128
+ comparison.reasonkit_answer # wrapped enhance result
129
+ ```
130
+
131
+ A decorator form is also supported:
132
+
133
+ ```python
134
+ @reasonkit.enhance
135
+ def call_llm(prompt: str) -> str:
136
+ ...
137
+ ```
138
+
139
+ ## How ReasonKit works
140
+
141
+ Every stage is a differently-worded prompt sent through your own function. ReasonKit never calls a model directly.
142
+
143
+ ```
144
+ User Prompt
145
+ |
146
+ v
147
+ Classify + Surface Assumptions
148
+ |
149
+ +--direct--> Answer --> Refine
150
+ |
151
+ +--decision--> Generate Approaches --> Critique --> Merge
152
+ |
153
+ +--code--> Generate Code --> Verify --> Fix Issues
154
+ |
155
+ v
156
+ Final answer with caveats
157
+ ```
158
+
159
+ Decision mode routes advisory questions through generate, critique, and merge. The model surfaces assumptions, weighs trade-offs, and appends open questions.
160
+
161
+ Code mode generates code, then runs verify and fix loops. Pass a test_hook to use your own tests instead of LLM self-review.
162
+
163
+ Direct mode answers plain questions in one pass with a refinement step.
164
+
165
+ It stops when the issue list is empty, stops shrinking, or hits max_cycles. There is no fabricated confidence score.
166
+
167
+ ## Configuration
168
+
169
+ enhance() accepts these keyword arguments:
170
+
171
+ | Option | Default | Description |
172
+ |--------|---------|-------------|
173
+ | max_cycles | 2 | Max decision or code-loop cycles |
174
+ | branches | 3 | Approaches generated per cycle |
175
+ | return_trace | False | Return EnhanceResult with .answer, .trace, .mode, .stopped_reason |
176
+ | verbose | False | Print cycle progress |
177
+ | test_hook | None | Function (code: str) -> list[str] for code verify pass |
178
+
179
+ ```python
180
+ better_llm = reasonkit.enhance(call_llm, max_cycles=2, branches=3, test_hook=my_tests)
181
+ ```
182
+
183
+ ## API
184
+
185
+ ### reasonkit.enhance(fn, **config)
186
+
187
+ Wrap fn with the reasoning pipeline. fn must accept (prompt: str) -> str. Sync, async, and async generator functions are all supported. The wrapper keeps the same callable shape.
188
+
189
+ When return_trace=True, each call returns an EnhanceResult instead of a plain string.
190
+
191
+ ### class EnhanceResult
192
+
193
+ | Attribute | Type | Description |
194
+ |-----------|------|-------------|
195
+ | .answer | str | The final output |
196
+ | .trace | Trace | Record of every internal call |
197
+ | .mode | str | decision, code, or direct |
198
+ | .stopped_reason | str | no_issues, no_improvement, max_cycles, or similar |
199
+
200
+ ### reasonkit.compare(fn, prompt, **config)
201
+
202
+ Run fn(prompt) directly and enhance(fn)(prompt) side by side. Returns a Comparison with .baseline_answer, .reasonkit_answer, and .trace.
203
+
204
+ ### class Trace
205
+
206
+ Records every call ReasonKit made through the wrapped function.
207
+
208
+ | Method or Attribute | Type | Description |
209
+ |--------------------|------|-------------|
210
+ | .calls | list[CallRecord] | Stage, prompt, and response per call |
211
+ | .call_count | int | Total internal calls |
212
+ | .mode | str | Pipeline mode |
213
+ | .stopped_reason | str | Why the pipeline stopped |
214
+ | .notes | list[str] | Diagnostic notes from the run |
215
+ | .code_versions | list[str] | Each draft or fix produced in code mode |
216
+ | .to_dict() | dict | Serialize the full trace |
217
+
218
+ ### Error types
219
+
220
+ All errors inherit from ReasonKitError.
221
+
222
+ | Exception | Raised when |
223
+ |-----------|-------------|
224
+ | ConfigurationError | Invalid config at enhance() time |
225
+ | ModelCallError | Critical pipeline stage exhausted all retries |
226
+
227
+ ## Cost and call-reduction notes
228
+
229
+ The largest lever on spend is branches multiplied by max_cycles. The defaults (3 x 2) favor quality over frugality. Several mechanisms already reduce call count:
230
+
231
+ - Decision mode skips the merge on a clean first draft. If cycle 1 critique finds zero issues, the pipeline returns the draft plus a clarifying note and stops.
232
+ - Direct mode uses the classifier's output in the first draft. It does not answer blind and then refine. The classify pass produces goal, assumptions, and clarifying questions. ReasonKit feeds these into the first draft call.
233
+ - Code mode reuses your supplied code. If you paste code, generation is skipped. The verify and fix loop works on what you provided.
234
+
235
+ To reduce cost further, lower the settings:
236
+
237
+ ```python
238
+ better_llm = reasonkit.enhance(call_llm, branches=1, max_cycles=1)
239
+ ```
240
+
241
+ branches=1 collapses approach generation to a single draft. max_cycles=1 runs exactly one generate, critique, and merge pass. Wrap only the prompts where the quality lift is worth the extra calls.
242
+
243
+ ## Examples
244
+
245
+ Two examples show enhance() wrapping real providers:
246
+
247
+ - wrap_openai_example.py wraps an OpenAI gpt-4o-mini call.
248
+ - wrap_anthropic_example.py wraps Anthropic Claude in sync and async forms.
249
+
250
+ Provider SDK imports appear only in these examples. They are not package dependencies.
251
+
252
+ ## Benchmark
253
+
254
+ Results use a 5-axis rubric scored by LLM-as-judge. A fixed judge model evaluates each answer blindly. The judge does not know which condition produced the answer. The four text axes (reasoning, accuracy, questioning, structure) are blind-scored. Self-correction is trace-derived.
255
+
256
+ Benchmarked across 14 fixture-runs on 6 models (2 providers):
257
+
258
+ | Model | Condition | RQI | SC |
259
+ |-------|-----------|-----|----|
260
+ | Llama 3.1 8B | Raw | 21 | 0.2 |
261
+ | | ReasonKit | 24 | 7.0 |
262
+ | | Delta | **+3.0** | **+6.8** |
263
+ | Llama 4 Scout 17B | Raw | 23 | 0.5 |
264
+ | | ReasonKit | 28 | 9.0 |
265
+ | | Delta | **+4.8** | **+8.5** |
266
+ | Qwen QwQ 32B | Raw | 23 | 0.3 |
267
+ | | ReasonKit | 29 | 9.0 |
268
+ | | Delta | **+6.0** | **+8.7** |
269
+ | GPT-OSS 20B | Raw | 23 | 0.1 |
270
+ | | ReasonKit | 30 | 9.0 |
271
+ | | Delta | **+7.4** | **+8.9** |
272
+ | Codestral Latest | Raw | 21 | 0.4 |
273
+ | | ReasonKit | 29 | 9.0 |
274
+ | | Delta | **+8.6** | **+8.6** |
275
+ | MiniMax M2.7 | Raw | 21 | 0.0 |
276
+ | | ReasonKit | 22 | 9.0 |
277
+ | | Delta | **+0.6** | **+9.0** |
278
+ | **Average** | Raw | 22 | 0.3 |
279
+ | | ReasonKit | 27 | 8.7 |
280
+ | | **Delta** | **+5.1** | **+8.4** |
281
+
282
+ Catch rate. The fraction of fixtures where ReasonKit caught a concrete flaw the raw call shipped without review: Llama 3.1 8B 80%, Llama 4 Scout 17B 100%, Qwen QwQ 32B 100%, GPT-OSS 20B 100%, Codestral Latest 100%, MiniMax M2.7 100%. Average 97%.
283
+
284
+ | Axis | What it measures | Judge criterion |
285
+ |------|-----------------|-----------------|
286
+ | Reasoning | Multiple angles weighed, trade-offs named | Several distinct considerations, not a single narrow recommendation |
287
+ | Accuracy | Addresses what was asked | Honest about missing input, does not fabricate specifics |
288
+ | Questioning | Surfaces assumptions, asks what would change the answer | Names assumptions clearly, asks targeted questions |
289
+ | Structure | Organized and scannable | Clear headings, logical flow, not a wall of text |
290
+ | Self-Correction | Caught and fixed its own flaw | Trace-derived. Did the pipeline revise its own draft? |
291
+
292
+ Each axis is scored 0 to 10. RQI is the 0 to 40 composite of RE plus AC plus QU plus ST. SC is reported separately. A single-shot raw call structurally cannot earn SC points.
293
+
294
+ Key takeaways:
295
+
296
+ - **Self-correction is the largest difference.** Raw calls get SC equal to 0 by definition. They cannot revise what they already emitted. ReasonKit catches and fixes concrete flaws in 97% of fixtures. Average SC lift is +8.4. This axis is where no single-pass call competes.
297
+ - **Questioning lifts consistently across all models.** The pipeline forces the model to surface its own assumptions and ask clarifying questions. Raw calls rarely do this.
298
+ - **The lift grows with model capability.** Codestral Latest gains +8.6 RQI. MiniMax M2.7 gains +0.6 RQI. The pipeline amplifies stronger models further. It is not a crutch for weak models.
299
+ - **No axis is inflated.** Accuracy on small models shows occasional slight negative deltas. The longer pipeline sometimes loses detail on weaker base models. These numbers are reported as-is.
300
+
301
+ Methodology. The four text axes are scored blind. The judge receives no metadata about which run produced an answer. Per-fixture reports label the two outputs RUN 1 and RUN 2 in randomized order. Execution order is also randomized per fixture to avoid fixed-order provider drift. The judge is nemotron-3-ultra-free (OpenCode), a fixed model independent of the models being benchmarked. Underperformance is stated plainly per axis. No result is adjusted. Full per-fixture output and traces are in benchmarks/stats_output/ and benchmarks/stats_output.llm7io/.
302
+
303
+ ## Claude Code plugin
304
+
305
+ Turn Claude Code into a self-checking reasoner. The plugin wraps the claude CLI as the model behind reasonkit.enhance. You get the full pipeline without an API key.
306
+
307
+ ### Install
308
+
309
+ ```
310
+ /plugin marketplace add xavcartwheel/reasonkit
311
+ /plugin install reasonkit@reasonkit-marketplace
312
+ ```
313
+
314
+ ### Use
315
+
316
+ ```
317
+ /reasonkit Should I start a coffee shop?
318
+ ```
319
+
320
+ Or run the bundled script directly:
321
+
322
+ ```
323
+ python plugins/reasonkit/scripts/reasonkit_run.py "Should I start a coffee shop?"
324
+ ```
325
+
326
+ See plugins/reasonkit/ for the full plugin source.
327
+
328
+ Requires pip install reasonkit and the claude CLI on your PATH.
329
+
330
+ ## Contributing
331
+
332
+ Contributions are welcome. Open an issue to discuss substantial changes first. See CONTRIBUTING.md for setup and conventions. The test suite must pass, and the package must stay dependency-free beyond the standard library.
333
+
334
+ ## License
335
+
336
+ Released under the GNU General Public License v3.0.
@@ -0,0 +1,30 @@
1
+ reasonkit/__init__.py,sha256=Z_Ald_4z7vLLlFwz5iEY9ozeZIytZ3n7H8SngWy6UAA,512
2
+ reasonkit/__main__.py,sha256=g3DYEe4KMMoeGRgdrbucivrRJ1AvjR1Qa2-2350j2NU,126
3
+ reasonkit/_sanitize.py,sha256=BpCJlawduhPjozIk6huUlTysQoMJSa-kxDRr-KlUcB0,6533
4
+ reasonkit/_utils.py,sha256=Y6lvDEwglDf6c91EsZlOxJOJlTi3D8kjct9m-wWJq6E,3953
5
+ reasonkit/branching.py,sha256=bvgUqXY-zafl9_YX_u3Dp6eZR0TAyLDzwMsLnBUDCzI,2679
6
+ reasonkit/classifier.py,sha256=KYsyS9pqKxJ78t51ebEq6Vc4e8EsN_GKa08JwNHGFTw,6735
7
+ reasonkit/codegen.py,sha256=deedDoNoCu8RFd6zW66-xQ-gVjknaPBbDsuumxkJmRQ,6759
8
+ reasonkit/compare.py,sha256=ZdZFQvGwEiuxE6vZjl5zM-23ZBMYomAG8wviU1H6cdU,1819
9
+ reasonkit/core.py,sha256=D79igRdw-nMSh2Ss6p12oyZdvtvo2niM4PM7lQ35Ox0,17333
10
+ reasonkit/critique.py,sha256=w3FuOrMcCOHEBiAs8f1bOaUjPIBLN_ALZYUpy7BKSkg,2943
11
+ reasonkit/errors.py,sha256=ceJc1nmwA--pnT1gED3BLcs_f7Mk3J3LTw0W9Vvj-cQ,649
12
+ reasonkit/merge.py,sha256=zGXrfJ6vfiIp2Kzjhb_FOzn9yvJyoCi_ygCmhLomV_I,4609
13
+ reasonkit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ reasonkit/stop_conditions.py,sha256=2kZcOyjiHzQHcupA01VRebd6lCLcvQRuPnZjq76E5nk,833
15
+ reasonkit/trace.py,sha256=fx-H7eVP3YVXDa2UjnF9s2k0scRJqy6ViVi9J779kEg,1960
16
+ reasonkit/prompts/classify_and_assumptions.txt,sha256=gAoejxu7FK3t6udfGYeHzszqynz8nP9Rv0u7prMMk3k,2195
17
+ reasonkit/prompts/critique_all.txt,sha256=cVNzlIK8f2qKRbguJbjKLokCx_PIGP2HpZGIkirGc2A,2595
18
+ reasonkit/prompts/deepen_concrete.txt,sha256=D22PrsFa2HHiM3etDu0iNFuf9HkQBSHaGWnXQWKjw0k,1364
19
+ reasonkit/prompts/fix_code.txt,sha256=Aalon9owKaJXWcCWV9q7lauBaJkCq-9qxWezyiJ22Q4,255
20
+ reasonkit/prompts/generate_approaches.txt,sha256=S9FDE8tiQYS-YqJWx_60F7B0nDD9qrC6UXrqc7ErPUE,1403
21
+ reasonkit/prompts/generate_code.txt,sha256=K947qqIs6kqfiN6pTlF1mAAiRwBcE7n2R4vkBlf7hq8,686
22
+ reasonkit/prompts/merge.txt,sha256=xe6XdMBtfNJmuBm4fMaknK2TKmYDdwnWoq3HYmAQ8gQ,2269
23
+ reasonkit/prompts/refine_direct.txt,sha256=bhIXxqU5iXiQhmIkw8QP5tUGK-EXDWRO2uKN76IJq00,813
24
+ reasonkit/prompts/refine_merge.txt,sha256=xJB2AeEAl9UqWkc-hsH14l1Cn-E_vWB0pLc8iN78pR0,1504
25
+ reasonkit/prompts/verify_code.txt,sha256=-25w-5DFNgRlGwVIMp14UE6DWeQ5qhk8wmHzHX86tXQ,315
26
+ reasonkit-0.2.0.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
27
+ reasonkit-0.2.0.dist-info/METADATA,sha256=m7j8LtnRKIDb4hA6tbcb4Zjhj5iZwpxTAcvInVslqdo,14579
28
+ reasonkit-0.2.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
29
+ reasonkit-0.2.0.dist-info/top_level.txt,sha256=buz3XREAfEBnxKe-eyEqfh4MkZPH35f5shf7i3LfD54,10
30
+ reasonkit-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+