thinkless 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- thinkless-0.2.0/.gitignore +33 -0
- thinkless-0.2.0/CHANGELOG.md +73 -0
- thinkless-0.2.0/LICENSE +202 -0
- thinkless-0.2.0/PKG-INFO +357 -0
- thinkless-0.2.0/README.md +271 -0
- thinkless-0.2.0/pyproject.toml +136 -0
- thinkless-0.2.0/src/thinkless/__init__.py +63 -0
- thinkless-0.2.0/src/thinkless/__main__.py +3 -0
- thinkless-0.2.0/src/thinkless/_hub.py +84 -0
- thinkless-0.2.0/src/thinkless/_json.py +33 -0
- thinkless-0.2.0/src/thinkless/_version.py +1 -0
- thinkless-0.2.0/src/thinkless/bench/__init__.py +22 -0
- thinkless-0.2.0/src/thinkless/bench/intents.py +406 -0
- thinkless-0.2.0/src/thinkless/bench/intents_report.py +87 -0
- thinkless-0.2.0/src/thinkless/bench/metrics.py +115 -0
- thinkless-0.2.0/src/thinkless/bench/report.py +123 -0
- thinkless-0.2.0/src/thinkless/bench/support.py +342 -0
- thinkless-0.2.0/src/thinkless/cli/__init__.py +1 -0
- thinkless-0.2.0/src/thinkless/cli/main.py +595 -0
- thinkless-0.2.0/src/thinkless/confidence.py +62 -0
- thinkless-0.2.0/src/thinkless/data/pricing.toml +56 -0
- thinkless-0.2.0/src/thinkless/data/viewer.html +411 -0
- thinkless-0.2.0/src/thinkless/decision.py +185 -0
- thinkless-0.2.0/src/thinkless/demo/__init__.py +1 -0
- thinkless-0.2.0/src/thinkless/demo/support/__init__.py +19 -0
- thinkless-0.2.0/src/thinkless/demo/support/agent.py +379 -0
- thinkless-0.2.0/src/thinkless/demo/support/data/calibration.jsonl +48 -0
- thinkless-0.2.0/src/thinkless/demo/support/data/scenarios.jsonl +53 -0
- thinkless-0.2.0/src/thinkless/demo/support/data/world.json +78 -0
- thinkless-0.2.0/src/thinkless/demo/support/questions.py +118 -0
- thinkless-0.2.0/src/thinkless/demo/support/stack.py +93 -0
- thinkless-0.2.0/src/thinkless/demo/support/world.py +165 -0
- thinkless-0.2.0/src/thinkless/engine.py +605 -0
- thinkless-0.2.0/src/thinkless/errors.py +13 -0
- thinkless-0.2.0/src/thinkless/llm/__init__.py +47 -0
- thinkless-0.2.0/src/thinkless/llm/anthropic.py +126 -0
- thinkless-0.2.0/src/thinkless/llm/base.py +82 -0
- thinkless-0.2.0/src/thinkless/llm/factory.py +91 -0
- thinkless-0.2.0/src/thinkless/llm/local.py +168 -0
- thinkless-0.2.0/src/thinkless/llm/openai_compat.py +165 -0
- thinkless-0.2.0/src/thinkless/llm/openrouter.py +78 -0
- thinkless-0.2.0/src/thinkless/llm/scripted.py +75 -0
- thinkless-0.2.0/src/thinkless/logs.py +68 -0
- thinkless-0.2.0/src/thinkless/pricing.py +100 -0
- thinkless-0.2.0/src/thinkless/providers/__init__.py +43 -0
- thinkless-0.2.0/src/thinkless/providers/base.py +108 -0
- thinkless-0.2.0/src/thinkless/providers/gliner.py +194 -0
- thinkless-0.2.0/src/thinkless/providers/hf.py +161 -0
- thinkless-0.2.0/src/thinkless/providers/laya.py +121 -0
- thinkless-0.2.0/src/thinkless/providers/llm.py +305 -0
- thinkless-0.2.0/src/thinkless/providers/rules.py +181 -0
- thinkless-0.2.0/src/thinkless/providers/systemone.py +147 -0
- thinkless-0.2.0/src/thinkless/providers/wire.py +108 -0
- thinkless-0.2.0/src/thinkless/py.typed +0 -0
- thinkless-0.2.0/src/thinkless/questions.py +246 -0
- thinkless-0.2.0/src/thinkless/settings.py +93 -0
- thinkless-0.2.0/src/thinkless/tracing/__init__.py +23 -0
- thinkless-0.2.0/src/thinkless/tracing/console.py +169 -0
- thinkless-0.2.0/src/thinkless/tracing/otel.py +139 -0
- thinkless-0.2.0/src/thinkless/tracing/sinks.py +142 -0
- thinkless-0.2.0/src/thinkless/tracing/span.py +98 -0
- thinkless-0.2.0/src/thinkless/tracing/summary.py +143 -0
- thinkless-0.2.0/src/thinkless/tracing/tracer.py +159 -0
- thinkless-0.2.0/src/thinkless/tracing/viewer.py +87 -0
- thinkless-0.2.0/tests/__init__.py +0 -0
- thinkless-0.2.0/tests/conftest.py +81 -0
- thinkless-0.2.0/tests/local/__init__.py +0 -0
- thinkless-0.2.0/tests/local/test_local_models.py +122 -0
- thinkless-0.2.0/tests/network/__init__.py +0 -0
- thinkless-0.2.0/tests/network/test_openrouter_live.py +49 -0
- thinkless-0.2.0/tests/unit/__init__.py +0 -0
- thinkless-0.2.0/tests/unit/test_bench.py +96 -0
- thinkless-0.2.0/tests/unit/test_cli_and_viewer.py +128 -0
- thinkless-0.2.0/tests/unit/test_confidence.py +44 -0
- thinkless-0.2.0/tests/unit/test_engine.py +375 -0
- thinkless-0.2.0/tests/unit/test_hf_classifier.py +70 -0
- thinkless-0.2.0/tests/unit/test_llm_decider.py +107 -0
- thinkless-0.2.0/tests/unit/test_openrouter.py +228 -0
- thinkless-0.2.0/tests/unit/test_pricing_and_llm.py +119 -0
- thinkless-0.2.0/tests/unit/test_questions.py +75 -0
- thinkless-0.2.0/tests/unit/test_rules.py +77 -0
- thinkless-0.2.0/tests/unit/test_support_demo.py +172 -0
- thinkless-0.2.0/tests/unit/test_systemone.py +126 -0
- thinkless-0.2.0/tests/unit/test_systemone_sdk_compat.py +79 -0
- thinkless-0.2.0/tests/unit/test_tracing.py +91 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
|
|
11
|
+
# Tooling
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
.mypy_cache/
|
|
15
|
+
.coverage
|
|
16
|
+
coverage.xml
|
|
17
|
+
htmlcov/
|
|
18
|
+
site/
|
|
19
|
+
|
|
20
|
+
# ThinkLess runtime output (traces, viewer exports, scratch benchmark runs)
|
|
21
|
+
.thinkless/
|
|
22
|
+
|
|
23
|
+
# Editors and OS
|
|
24
|
+
.idea/
|
|
25
|
+
.vscode/
|
|
26
|
+
*.swp
|
|
27
|
+
.DS_Store
|
|
28
|
+
Thumbs.db
|
|
29
|
+
|
|
30
|
+
# Secrets
|
|
31
|
+
.env
|
|
32
|
+
.env.*
|
|
33
|
+
!.env.example
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses
|
|
5
|
+
[semantic versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
## 0.2.0 - 2026-09-25
|
|
10
|
+
|
|
11
|
+
First release on PyPI.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `OpenRouterLLM` and the `openrouter:<slug>` spec: one key for models from
|
|
16
|
+
Anthropic, OpenAI, Google, Qwen, DeepSeek and others.
|
|
17
|
+
- Billed cost: `Completion.cost_usd` and `ProviderResult.cost_usd` carry the
|
|
18
|
+
cost a backend reports (OpenRouter does); the engine prefers it over the
|
|
19
|
+
price table and records `cost_source` on spans. Benchmark reports add a
|
|
20
|
+
billed cost row, and the intent benchmark reports cost per 1k per provider
|
|
21
|
+
and per cascade threshold.
|
|
22
|
+
- `--reasoning` for every CLI command that builds an LLM, and
|
|
23
|
+
`from_spec(..., reasoning=...)`, mapped to OpenRouter's `reasoning`,
|
|
24
|
+
Anthropic's `effort` and local thinking switches.
|
|
25
|
+
- `HFClassifier`: any Hugging Face text-classification model as a provider for
|
|
26
|
+
the questions it was trained for.
|
|
27
|
+
- `load_env()`, and the CLI reads `./.env` without overriding set variables.
|
|
28
|
+
- Escalation context: when a question escalates to the LLM decider, the
|
|
29
|
+
engine includes the decisions already settled in the same batch. It removed
|
|
30
|
+
false injection flags on requests for a human that appeared when an LLM saw
|
|
31
|
+
the injection question alone. On by default (`Engine(escalation_context=...)`).
|
|
32
|
+
- The System One wire format is tested against TypeSafe's official SDK models.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- `LLMDecider` detects replies cut off at the token limit, logs why, and
|
|
37
|
+
retries once with a larger budget instead of abstaining silently.
|
|
38
|
+
- The OpenAI-compatible client retries once without `response_format` when an
|
|
39
|
+
endpoint rejects JSON mode.
|
|
40
|
+
- A redaction test that failed about one run in fifty when a random span id
|
|
41
|
+
contained its marker.
|
|
42
|
+
|
|
43
|
+
## 0.1.0 - 2026-09-25
|
|
44
|
+
|
|
45
|
+
First public release.
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- Typed questions: `Choice`, `Score`, `YesNo` and `Extract`, following the
|
|
50
|
+
System One wire format.
|
|
51
|
+
- `Engine` with a confidence cascade across providers, batched provider calls,
|
|
52
|
+
`accepted`, `uncertain` and `abstained` statuses, per-question and
|
|
53
|
+
per-provider thresholds (`"question@provider"`), question-level provider
|
|
54
|
+
allowlists, and async variants of every call.
|
|
55
|
+
- Normalized confidence, `(k * p_max - 1) / (k - 1)`, applied uniformly across
|
|
56
|
+
providers.
|
|
57
|
+
- Decision providers: `Rules`, `GLiNER` (GLiNER 2.5), `Laya`, `SystemOne`
|
|
58
|
+
(TypeSafe Jev and compatible servers such as Kev and OpenJev) and
|
|
59
|
+
`LLMDecider`.
|
|
60
|
+
- LLM backends: `TransformersLLM`, `OpenAICompatibleLLM` (OpenAI, Ollama, vLLM
|
|
61
|
+
and others) and `AnthropicLLM` with server-side refusal fallbacks.
|
|
62
|
+
- Tracing: spans for runs, steps, decisions, provider attempts, generations,
|
|
63
|
+
tools and rules; JSONL, memory, console and OpenTelemetry sinks; run
|
|
64
|
+
summaries with decisions by plane, escalations, tokens, cost and time by
|
|
65
|
+
plane; content capture switch; a self-contained HTML viewer.
|
|
66
|
+
- A price table with sources, overridable with `THINKLESS_PRICING`.
|
|
67
|
+
- The support demo: an agent, a mock store, 53 labeled tickets and a separate
|
|
68
|
+
48-row calibration set.
|
|
69
|
+
- Benchmarks: the support benchmark across `llm`, `hybrid` and `models` modes,
|
|
70
|
+
and intent benchmarks on Banking77, CLINC150 and Emotion with a simulated
|
|
71
|
+
cascade.
|
|
72
|
+
- `thinkless` CLI: `doctor`, `demo`, `bench support`, `bench intents`,
|
|
73
|
+
`calibrate`, `trace ls`, `trace show` and `trace view`.
|
thinkless-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright 2026 Praveen Kumar
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
|
202
|
+
|
thinkless-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: thinkless
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: The decision plane for AI agents. Rules and small calibrated models make the routine decisions, the LLM is reserved for the steps that need thought, and every step is traced.
|
|
5
|
+
Project-URL: Homepage, https://github.com/inboxpraveen/ThinkLess
|
|
6
|
+
Project-URL: Documentation, https://github.com/inboxpraveen/ThinkLess/tree/main/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/inboxpraveen/ThinkLess
|
|
8
|
+
Project-URL: Issues, https://github.com/inboxpraveen/ThinkLess/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/inboxpraveen/ThinkLess/blob/main/CHANGELOG.md
|
|
10
|
+
Author: Praveen Kumar
|
|
11
|
+
License-Expression: Apache-2.0
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: agents,classification,decision-models,gliner,jev,laya,llm,observability,routing,system-one,tracing
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Requires-Dist: httpx<1,>=0.27
|
|
29
|
+
Requires-Dist: pydantic<3,>=2.6
|
|
30
|
+
Requires-Dist: rich>=13.7
|
|
31
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
32
|
+
Requires-Dist: typer>=0.12
|
|
33
|
+
Provides-Extra: all
|
|
34
|
+
Requires-Dist: accelerate>=1.0; extra == 'all'
|
|
35
|
+
Requires-Dist: anthropic>=1.0; extra == 'all'
|
|
36
|
+
Requires-Dist: datasets>=3.0; extra == 'all'
|
|
37
|
+
Requires-Dist: gliner2[local]<3,>=2.0; extra == 'all'
|
|
38
|
+
Requires-Dist: laya<0.4,>=0.3.20; extra == 'all'
|
|
39
|
+
Requires-Dist: openai>=2.0; extra == 'all'
|
|
40
|
+
Requires-Dist: opentelemetry-api>=1.25; extra == 'all'
|
|
41
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.25; extra == 'all'
|
|
42
|
+
Requires-Dist: opentelemetry-sdk>=1.25; extra == 'all'
|
|
43
|
+
Requires-Dist: protobuf>=4.25; extra == 'all'
|
|
44
|
+
Requires-Dist: sentencepiece>=0.2; extra == 'all'
|
|
45
|
+
Requires-Dist: torch>=2.1; extra == 'all'
|
|
46
|
+
Requires-Dist: transformers<5,>=4.48; extra == 'all'
|
|
47
|
+
Provides-Extra: anthropic
|
|
48
|
+
Requires-Dist: anthropic>=1.0; extra == 'anthropic'
|
|
49
|
+
Provides-Extra: bench
|
|
50
|
+
Requires-Dist: datasets>=3.0; extra == 'bench'
|
|
51
|
+
Provides-Extra: dev
|
|
52
|
+
Requires-Dist: mkdocs-material>=9.5; extra == 'dev'
|
|
53
|
+
Requires-Dist: mkdocstrings[python]>=0.26; extra == 'dev'
|
|
54
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
55
|
+
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
56
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
57
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
58
|
+
Requires-Dist: typesafe-sdk>=0.7; extra == 'dev'
|
|
59
|
+
Provides-Extra: gliner
|
|
60
|
+
Requires-Dist: gliner2[local]<3,>=2.0; extra == 'gliner'
|
|
61
|
+
Requires-Dist: protobuf>=4.25; extra == 'gliner'
|
|
62
|
+
Requires-Dist: sentencepiece>=0.2; extra == 'gliner'
|
|
63
|
+
Requires-Dist: transformers<5,>=4.48; extra == 'gliner'
|
|
64
|
+
Provides-Extra: laya
|
|
65
|
+
Requires-Dist: laya<0.4,>=0.3.20; extra == 'laya'
|
|
66
|
+
Requires-Dist: transformers<5,>=4.48; extra == 'laya'
|
|
67
|
+
Provides-Extra: local
|
|
68
|
+
Requires-Dist: accelerate>=1.0; extra == 'local'
|
|
69
|
+
Requires-Dist: gliner2[local]<3,>=2.0; extra == 'local'
|
|
70
|
+
Requires-Dist: laya<0.4,>=0.3.20; extra == 'local'
|
|
71
|
+
Requires-Dist: protobuf>=4.25; extra == 'local'
|
|
72
|
+
Requires-Dist: sentencepiece>=0.2; extra == 'local'
|
|
73
|
+
Requires-Dist: torch>=2.1; extra == 'local'
|
|
74
|
+
Requires-Dist: transformers<5,>=4.48; extra == 'local'
|
|
75
|
+
Provides-Extra: local-llm
|
|
76
|
+
Requires-Dist: accelerate>=1.0; extra == 'local-llm'
|
|
77
|
+
Requires-Dist: torch>=2.1; extra == 'local-llm'
|
|
78
|
+
Requires-Dist: transformers<5,>=4.48; extra == 'local-llm'
|
|
79
|
+
Provides-Extra: openai
|
|
80
|
+
Requires-Dist: openai>=2.0; extra == 'openai'
|
|
81
|
+
Provides-Extra: otel
|
|
82
|
+
Requires-Dist: opentelemetry-api>=1.25; extra == 'otel'
|
|
83
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.25; extra == 'otel'
|
|
84
|
+
Requires-Dist: opentelemetry-sdk>=1.25; extra == 'otel'
|
|
85
|
+
Description-Content-Type: text/markdown
|
|
86
|
+
|
|
87
|
+
<h1 align="center">ThinkLess</h1>
|
|
88
|
+
|
|
89
|
+
<p align="center"><b>Stop using an LLM for every decision.</b></p>
|
|
90
|
+
|
|
91
|
+
<p align="center">
|
|
92
|
+
<a href="https://pypi.org/project/thinkless/"><img alt="PyPI" src="https://img.shields.io/pypi/v/thinkless.svg"></a>
|
|
93
|
+
<a href="https://github.com/inboxpraveen/ThinkLess/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/inboxpraveen/ThinkLess/actions/workflows/ci.yml/badge.svg"></a>
|
|
94
|
+
<a href="https://github.com/inboxpraveen/ThinkLess/blob/main/LICENSE"><img alt="License: Apache 2.0" src="https://img.shields.io/badge/license-Apache%202.0-blue.svg"></a>
|
|
95
|
+
<img alt="Python 3.10+" src="https://img.shields.io/badge/python-3.10%2B-blue.svg">
|
|
96
|
+
<a href="https://github.com/inboxpraveen/ThinkLess/blob/main/docs/benchmarks.md"><img alt="Benchmarks" src="https://img.shields.io/badge/benchmarks-reproducible-brightgreen.svg"></a>
|
|
97
|
+
</p>
|
|
98
|
+
|
|
99
|
+
ThinkLess is an open-source decision plane for AI agents. The routine
|
|
100
|
+
judgments an agent makes (what the user wants, whether they asked for a
|
|
101
|
+
person, which order they mean, whether a message is trying to manipulate the
|
|
102
|
+
system) are answered by rules and small calibrated models in milliseconds. The
|
|
103
|
+
LLM is kept for the steps that need it: writing, planning, and the decisions
|
|
104
|
+
the small models are not sure about. Every step is traced with the plane that
|
|
105
|
+
handled it, its confidence, latency, tokens and cost.
|
|
106
|
+
|
|
107
|
+
It is model-neutral. Rules, [GLiNER 2.5](https://github.com/fastino-ai/GLiNER2),
|
|
108
|
+
[Laya](https://github.com/NandhaKishorM/laya), TypeSafe's
|
|
109
|
+
[Jev](https://typesafe.ai) (and any server speaking its System One API, such as
|
|
110
|
+
Kev and OpenJev), any Hugging Face classifier, and any LLM (local through
|
|
111
|
+
Transformers, Ollama or vLLM, or hosted through OpenRouter, Anthropic or
|
|
112
|
+
OpenAI) plug into the same cascade. The whole stack also runs offline on a
|
|
113
|
+
laptop GPU, with no API key.
|
|
114
|
+
|
|
115
|
+
<p align="center">
|
|
116
|
+
<img src="https://raw.githubusercontent.com/inboxpraveen/ThinkLess/main/docs/assets/trace-viewer.png" alt="The ThinkLess trace viewer comparing three decision planes on the support benchmark, with one ticket's waterfall: six decisions answered by rules, GLiNER and Laya in 126 ms, then a single LLM call for the reply" width="100%">
|
|
117
|
+
</p>
|
|
118
|
+
|
|
119
|
+
## Why
|
|
120
|
+
|
|
121
|
+
A typical agent sends every branch of its workflow to one generative model:
|
|
122
|
+
classify the request, extract the arguments, pick the tool, check the result,
|
|
123
|
+
check the reply, then write the reply. Most of those are bounded questions with
|
|
124
|
+
a handful of possible answers. A generative model answers them slowly, at full
|
|
125
|
+
token cost, and without telling you how sure it is.
|
|
126
|
+
|
|
127
|
+
ThinkLess treats each of them as a typed question. It asks the cheapest
|
|
128
|
+
provider first and escalates only when the answer's confidence is below a
|
|
129
|
+
threshold you set per question and per provider, from data. Your code reads a
|
|
130
|
+
typed decision and never needs to know which model produced it.
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
intent = engine.decide(ticket, INTENT) # rules, then GLiNER, then Laya, then the LLM
|
|
134
|
+
if intent.is_("refund_duplicate_charge"): # only true when the answer is confident
|
|
135
|
+
...
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Results
|
|
139
|
+
|
|
140
|
+
Same agent, same 53 labeled support tickets, two decision planes: `llm` sends
|
|
141
|
+
every decision to the LLM, `hybrid` asks rules, GLiNER and Laya first. Hosted
|
|
142
|
+
models ran through OpenRouter, and the dollar figures are what OpenRouter
|
|
143
|
+
billed ([full results](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/benchmarks.md)):
|
|
144
|
+
|
|
145
|
+
| Fallback LLM | Success, `llm` | Success, `hybrid` | Billed per 1k tickets, `llm` | Billed per 1k tickets, `hybrid` | Decision time |
|
|
146
|
+
|---|---:|---:|---:|---:|---:|
|
|
147
|
+
| Qwen 3.7 Flash | 92.5% | **98.1%** | $0.034 | **$0.019** | 1.27 s to **0.58 s** |
|
|
148
|
+
| Gemini 2.5 Flash Lite | 98.1% | **98.1%** | $0.104 | **$0.059** | 1.17 s to **0.76 s** |
|
|
149
|
+
| GPT-5.6 Luna | 98.1% | **100%** | $0.235 | **$0.141** | 2.50 s to **1.18 s** |
|
|
150
|
+
| Claude Haiku 4.5 | 98.1% | **98.1%** | $1.338 | **$0.788** | 2.21 s to **1.34 s** |
|
|
151
|
+
| Qwen3-1.7B, local | 86.8% | **94.3%** | free | free | 1.84 s to **0.43 s** |
|
|
152
|
+
|
|
153
|
+
- **Hybrid matched or beat the LLM-only design on every model, at 40 to 44
|
|
154
|
+
percent lower billed cost** and 35 to 55 percent less time spent on
|
|
155
|
+
decisions. 87 percent of hybrid decisions never reached the LLM.
|
|
156
|
+
- **Small models are the most reliable extractors.** Rules and GLiNER found
|
|
157
|
+
every order number on every run. The larger hosted LLMs did too; Qwen 3.7
|
|
158
|
+
Flash and the local 1.7B model missed ones written without the word
|
|
159
|
+
"order".
|
|
160
|
+
- **On Banking77 (77 intents, 500 examples) the cascade matched or beat its
|
|
161
|
+
LLM at a quarter of the cost.** GLiNER alone 71.8 percent; Qwen 3.7 Flash
|
|
162
|
+
alone 73.8 percent, cascade 74.8 percent; Claude Haiku 4.5 alone 76.2
|
|
163
|
+
percent, cascade 76.2 percent. Each time a quarter of the calls reached the
|
|
164
|
+
LLM.
|
|
165
|
+
- **Nothing was tuned on the test tickets.** Thresholds and every fix were
|
|
166
|
+
validated on a separate calibration set first. The baseline is the
|
|
167
|
+
strongest form of the LLM design: all six triage questions in one prompt.
|
|
168
|
+
- The support set is 53 synthetic tickets: evidence of the mechanism and its
|
|
169
|
+
failure modes, not a leaderboard. The [benchmarks page](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/benchmarks.md)
|
|
170
|
+
lists the weak areas found and what was done about each.
|
|
171
|
+
|
|
172
|
+
## Quick start
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
pip install "thinkless[local]" # GLiNER, Laya and a local LLM
|
|
176
|
+
thinkless doctor # check the environment
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from thinkless import Choice, Engine, Extract, JSONLSink, Tracer, YesNo
|
|
181
|
+
from thinkless.llm import TransformersLLM
|
|
182
|
+
from thinkless.providers import GLiNER, Laya, LLMDecider, Rules
|
|
183
|
+
|
|
184
|
+
rules = Rules()
|
|
185
|
+
rules.match("wants_human", r"\b(real person|a human|an agent|operator)\b", True, field="message")
|
|
186
|
+
rules.extract("order", field="message", order_id=r"#\s?(\d{4,5})\b")
|
|
187
|
+
|
|
188
|
+
llm = TransformersLLM("Qwen/Qwen3-1.7B")
|
|
189
|
+
engine = Engine(
|
|
190
|
+
[rules, GLiNER(), Laya(), LLMDecider(llm)], # cheapest first
|
|
191
|
+
llm=llm,
|
|
192
|
+
threshold=0.8,
|
|
193
|
+
tracer=Tracer([JSONLSink(".thinkless/traces")]),
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
with engine.run("ticket") as run:
|
|
197
|
+
decisions = engine.decide_many(
|
|
198
|
+
{"message": "I was charged twice for order #4471. Refund it or I'm cancelling."},
|
|
199
|
+
[
|
|
200
|
+
Choice("What does the customer want?", name="intent",
|
|
201
|
+
options={"refund": "wants money back", "order_status": "asks where an order is",
|
|
202
|
+
"cancel": "wants to cancel", "other": "anything else"}),
|
|
203
|
+
YesNo("Is the customer asking for a person?", name="wants_human"),
|
|
204
|
+
Extract(name="order", fields={"order_id": "the order number"}),
|
|
205
|
+
],
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
for name, d in decisions.items():
|
|
209
|
+
print(f"{name:12} {d.value!s:24} {d.status.value:9} via {d.provider}")
|
|
210
|
+
print(run.summary().decisions_by_plane) # which plane answered what
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Prefer a hosted model? Put `OPENROUTER_API_KEY=...` in `.env` and swap one
|
|
214
|
+
line; OpenRouter reaches Qwen, Gemini, GPT and Claude models with one key:
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from thinkless.llm import OpenRouterLLM
|
|
218
|
+
|
|
219
|
+
llm = OpenRouterLLM("qwen/qwen3.7-flash", reasoning={"enabled": False})
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Then open the trace:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
thinkless trace view
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
No GPU? `pip install thinkless` and run
|
|
229
|
+
[`examples/01_rules_only.py`](https://github.com/inboxpraveen/ThinkLess/blob/main/examples/01_rules_only.py): the API, the cascade
|
|
230
|
+
and the traces with no model downloads.
|
|
231
|
+
|
|
232
|
+
## Try the demo agent
|
|
233
|
+
|
|
234
|
+
A complete customer support agent ships with the package: a mock store with
|
|
235
|
+
orders, payments and a help center, 53 labeled tickets, and every hard case we
|
|
236
|
+
could think of (order numbers written in ways a regex misses, a customer
|
|
237
|
+
asking about someone else's order, prompt injections, requests for a human,
|
|
238
|
+
Spanish and German tickets).
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
thinkless demo --ticket T-016 # one ticket, printed as a trace tree
|
|
242
|
+
thinkless demo --ticket T-051 --mode hybrid --mode llm # compare decision planes
|
|
243
|
+
thinkless bench support # every ticket in every mode
|
|
244
|
+
thinkless bench support --llm openrouter:qwen/qwen3.7-flash --reasoning off
|
|
245
|
+
thinkless bench intents --dataset banking77
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## How it works
|
|
249
|
+
|
|
250
|
+
**Typed questions.** `Choice`, `Score`, `YesNo` and `Extract` declare what you
|
|
251
|
+
want to know and which answers are allowed. They follow the System One wire
|
|
252
|
+
format, so the same question works on every provider.
|
|
253
|
+
[Questions](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/concepts/questions.md)
|
|
254
|
+
|
|
255
|
+
**A confidence cascade.** Providers are tried cheapest first. Each gets one
|
|
256
|
+
call with every open question it supports; answers that clear their threshold
|
|
257
|
+
close, the rest move on. Unresolved questions come back `uncertain` with the
|
|
258
|
+
best answer seen, and `decision.is_()` never matches an uncertain answer.
|
|
259
|
+
[The cascade](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/concepts/cascade.md)
|
|
260
|
+
|
|
261
|
+
**One meaning of confidence.** Providers disagree about what "confidence"
|
|
262
|
+
means (Laya and TypeSafe compute it differently), so a threshold of 0.8 would
|
|
263
|
+
mean different things per backend. ThinkLess derives a single normalized
|
|
264
|
+
confidence from each provider's probabilities.
|
|
265
|
+
[Confidence](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/concepts/confidence.md)
|
|
266
|
+
|
|
267
|
+
**Thresholds from data.** `thinkless calibrate` sweeps thresholds on labeled
|
|
268
|
+
examples and recommends the lowest one that meets your accuracy target, per
|
|
269
|
+
question and per provider (`thresholds={"intent@gliner": 0.9}`).
|
|
270
|
+
[Calibration](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/guides/calibration.md)
|
|
271
|
+
|
|
272
|
+
**Traces for everything.** Decisions, provider attempts, generations, tool
|
|
273
|
+
calls and rule checks are spans with W3C-compatible ids. Write JSONL audit
|
|
274
|
+
files, export to any OpenTelemetry backend with GenAI semantic conventions, or
|
|
275
|
+
open the self-contained HTML viewer. Content capture can be switched off
|
|
276
|
+
without losing structure, timings or confidences.
|
|
277
|
+
[Tracing](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/concepts/tracing.md)
|
|
278
|
+
|
|
279
|
+
## Providers and backends
|
|
280
|
+
|
|
281
|
+
| Decision providers | Answers | Runs |
|
|
282
|
+
|---|---|---|
|
|
283
|
+
| `Rules` | every kind | in-process, under 1 ms |
|
|
284
|
+
| `GLiNER` (GLiNER 2.5) | choice, extract | local, 16 to 38 ms on a laptop GPU, about 85 ms on CPU |
|
|
285
|
+
| `Laya` | choice, score, yes/no | local, about 30 ms per batch on a laptop GPU |
|
|
286
|
+
| `SystemOne` (Jev, Kev, OpenJev) | choice, score, yes/no | hosted or self-hosted HTTP |
|
|
287
|
+
| `HFClassifier` | choice, yes/no, for the questions it was trained on | any Hugging Face text classifier, local |
|
|
288
|
+
| `LLMDecider` | every kind | any LLM backend below |
|
|
289
|
+
|
|
290
|
+
| LLM backends | Covers |
|
|
291
|
+
|---|---|
|
|
292
|
+
| `TransformersLLM` | any Hugging Face chat model, in-process |
|
|
293
|
+
| `OpenRouterLLM` | hundreds of hosted models with one key, billed cost recorded per call |
|
|
294
|
+
| `OpenAICompatibleLLM` | OpenAI, Ollama, vLLM, LM Studio, llama.cpp, Groq |
|
|
295
|
+
| `AnthropicLLM` | Claude, with server-side refusal fallbacks |
|
|
296
|
+
|
|
297
|
+
Writing your own provider is one class. [Providers](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/guides/providers.md),
|
|
298
|
+
[LLM backends](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/guides/llm-backends.md)
|
|
299
|
+
|
|
300
|
+
## Documentation
|
|
301
|
+
|
|
302
|
+
- [Getting started](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/getting-started.md)
|
|
303
|
+
- Concepts: [the four planes](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/concepts/planes.md),
|
|
304
|
+
[questions](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/concepts/questions.md),
|
|
305
|
+
[confidence](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/concepts/confidence.md),
|
|
306
|
+
[the cascade](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/concepts/cascade.md),
|
|
307
|
+
[tracing](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/concepts/tracing.md)
|
|
308
|
+
- Guides: [the support agent](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/guides/support-agent.md),
|
|
309
|
+
[calibration](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/guides/calibration.md),
|
|
310
|
+
[providers](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/guides/providers.md),
|
|
311
|
+
[LLM backends](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/guides/llm-backends.md),
|
|
312
|
+
[production](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/guides/production.md),
|
|
313
|
+
[troubleshooting](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/guides/troubleshooting.md)
|
|
314
|
+
- [Benchmarks](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/benchmarks.md), [CLI reference](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/reference/cli.md),
|
|
315
|
+
[Python API](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/reference/api.md), [roadmap](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/roadmap.md)
|
|
316
|
+
|
|
317
|
+
## Status
|
|
318
|
+
|
|
319
|
+
ThinkLess is at 0.1: the core API (questions, the engine, decisions and
|
|
320
|
+
traces) is meant to stay stable, and providers and benchmarks will grow.
|
|
321
|
+
Next up are shadow mode, calibration from traces, calibrated LLM confidence
|
|
322
|
+
from log probabilities, and live Jev runs. See the [roadmap](https://github.com/inboxpraveen/ThinkLess/blob/main/docs/roadmap.md).
|
|
323
|
+
|
|
324
|
+
## Contributing
|
|
325
|
+
|
|
326
|
+
Issues, providers, benchmark runs on other hardware and models, and new demo
|
|
327
|
+
scenarios are all welcome. Start with [CONTRIBUTING.md](https://github.com/inboxpraveen/ThinkLess/blob/main/CONTRIBUTING.md). The
|
|
328
|
+
bar for changes that affect accuracy, latency or cost is evidence: a before
|
|
329
|
+
and after from `thinkless bench` or `thinkless calibrate`.
|
|
330
|
+
|
|
331
|
+
## Sponsoring
|
|
332
|
+
|
|
333
|
+
If ThinkLess saves your team time or money, consider
|
|
334
|
+
[sponsoring its development](https://github.com/sponsors/inboxpraveen).
|
|
335
|
+
Sponsorship funds frontier-model benchmark runs, more providers and more
|
|
336
|
+
demos.
|
|
337
|
+
|
|
338
|
+
## Citing
|
|
339
|
+
|
|
340
|
+
See [CITATION.cff](https://github.com/inboxpraveen/ThinkLess/blob/main/CITATION.cff).
|
|
341
|
+
|
|
342
|
+
## Acknowledgements
|
|
343
|
+
|
|
344
|
+
ThinkLess builds on the work of the teams behind
|
|
345
|
+
[Jev and the System One API](https://typesafe.ai) (TypeSafe AI),
|
|
346
|
+
[GLiNER2](https://github.com/fastino-ai/GLiNER2) (Fastino),
|
|
347
|
+
[Laya](https://github.com/NandhaKishorM/laya) (Convai Innovations),
|
|
348
|
+
[Qwen](https://github.com/QwenLM) and
|
|
349
|
+
[Banking77](https://github.com/PolyAI-LDN/task-specific-datasets) (PolyAI).
|
|
350
|
+
|
|
351
|
+
ThinkLess is not affiliated with the NeurIPS 2025 paper
|
|
352
|
+
[Thinkless: LLM Learns When to Think](https://github.com/VainF/Thinkless),
|
|
353
|
+
which studies adaptive reasoning inside a single model.
|
|
354
|
+
|
|
355
|
+
## License
|
|
356
|
+
|
|
357
|
+
[Apache License 2.0](https://github.com/inboxpraveen/ThinkLess/blob/main/LICENSE).
|