dot-inference 2.2.0__tar.gz → 3.0.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 (54) hide show
  1. {dot_inference-2.2.0 → dot_inference-3.0.0}/.pre-commit-config.yaml +3 -3
  2. {dot_inference-2.2.0 → dot_inference-3.0.0}/AUTHORS.md +1 -0
  3. {dot_inference-2.2.0 → dot_inference-3.0.0}/CHANGELOG.md +25 -1
  4. dot_inference-3.0.0/CONTRIBUTING.md +37 -0
  5. dot_inference-3.0.0/LICENSE.md +21 -0
  6. {dot_inference-2.2.0 → dot_inference-3.0.0}/PKG-INFO +8 -12
  7. {dot_inference-2.2.0 → dot_inference-3.0.0}/README.md +6 -10
  8. {dot_inference-2.2.0 → dot_inference-3.0.0}/docs/ARCHITECTURE.md +1 -1
  9. {dot_inference-2.2.0 → dot_inference-3.0.0}/docs/DEVELOPMENT.md +2 -7
  10. {dot_inference-2.2.0 → dot_inference-3.0.0}/docs/VERSIONING.md +3 -3
  11. {dot_inference-2.2.0 → dot_inference-3.0.0}/examples/demo.py +0 -3
  12. {dot_inference-2.2.0 → dot_inference-3.0.0}/examples/demo_streaming.py +0 -3
  13. {dot_inference-2.2.0 → dot_inference-3.0.0}/pyproject.toml +2 -2
  14. {dot_inference-2.2.0 → dot_inference-3.0.0}/scripts/test_all_models.py +0 -3
  15. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/__init__.py +0 -3
  16. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/_client.py +3 -6
  17. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/_cost_tracker.py +0 -3
  18. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/_llm_registry.py +13 -3
  19. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/_local_check.py +0 -3
  20. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/_mistral_compat.py +6 -5
  21. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/_openai_compat.py +5 -5
  22. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/_rate_limit.py +0 -3
  23. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/_retry.py +0 -3
  24. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/_sync.py +0 -3
  25. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/_types.py +0 -3
  26. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/mock.py +0 -3
  27. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/models.yaml +20 -0
  28. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/settings.py +2 -4
  29. dot_inference-3.0.0/tests/__init__.py +0 -0
  30. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_cost_tracker.py +0 -3
  31. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_factories.py +0 -3
  32. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_llm_registry.py +26 -3
  33. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_local_check.py +0 -3
  34. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_mistral_compat.py +2 -5
  35. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_mistral_live.py +0 -3
  36. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_openai_compat.py +52 -7
  37. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_rate_limit.py +0 -3
  38. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_retry.py +0 -3
  39. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_settings.py +5 -3
  40. {dot_inference-2.2.0 → dot_inference-3.0.0}/tests/test_types.py +0 -3
  41. {dot_inference-2.2.0 → dot_inference-3.0.0}/uv.lock +1 -1
  42. dot_inference-2.2.0/CONTRIBUTING.md +0 -87
  43. dot_inference-2.2.0/DCO +0 -34
  44. dot_inference-2.2.0/LICENSE.md +0 -660
  45. dot_inference-2.2.0/tests/__init__.py +0 -2
  46. {dot_inference-2.2.0 → dot_inference-3.0.0}/.env.template +0 -0
  47. {dot_inference-2.2.0 → dot_inference-3.0.0}/.gitignore +0 -0
  48. {dot_inference-2.2.0 → dot_inference-3.0.0}/.gitlab-ci.yml +0 -0
  49. {dot_inference-2.2.0 → dot_inference-3.0.0}/.python-version +0 -0
  50. {dot_inference-2.2.0 → dot_inference-3.0.0}/docs/PUBLISHING.md +0 -0
  51. {dot_inference-2.2.0 → dot_inference-3.0.0}/docs/provider-quirks/openrouter-errors.md +0 -0
  52. {dot_inference-2.2.0 → dot_inference-3.0.0}/docs/provider-quirks/tool-choice.md +0 -0
  53. {dot_inference-2.2.0 → dot_inference-3.0.0}/examples/doc_stream.md +0 -0
  54. {dot_inference-2.2.0 → dot_inference-3.0.0}/src/dot_inference/README.md +0 -0
@@ -1,6 +1,6 @@
1
- # Verbatim legal texts: the AGPL and the DCO both forbid modification,
2
- # so no hook may normalise their whitespace or line endings.
3
- exclude: '^(LICENSE\.md|DCO)$'
1
+ # Verbatim legal text (MIT licence): no hook may normalise its whitespace
2
+ # or line endings.
3
+ exclude: '^LICENSE\.md$'
4
4
 
5
5
  repos:
6
6
  - repo: https://github.com/pre-commit/pre-commit-hooks
@@ -7,6 +7,7 @@ here does not confer any ownership of, or rights in, the project.
7
7
  ## Kannon For Deep Tech
8
8
 
9
9
  - Adrien Marjollet
10
+ - Charles Capon
10
11
  - Clément Olivier
11
12
  - Jean Fechter
12
13
  - Louis Le Tarnec
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.0.0] - 2026-10-15
11
+
12
+ ### Added
13
+
14
+ - Registry: `supports_temperature` (default `true`, can be overridden per
15
+ provider), independent of `supports_reasoning`. OpenAI's `gpt-5*` and
16
+ `gpt-6*` models are marked `false`: their API accepts only the default
17
+ temperature (1).
18
+
19
+ ### Changed
20
+
21
+ - **Breaking** — temperature no longer depends on reasoning: a temperature is
22
+ sent whenever one is set, reasoning model or not (gpt-oss, Claude, Mistral,
23
+ Qwen… honour it), and dropped only for a model whose registry entry says
24
+ `supports_temperature: false`. A per-call `temperature=` is treated the
25
+ same way.
26
+ - **Breaking** — `GenerationSettings.temperature` defaults to `None` instead of
27
+ `0`: unset, no temperature is sent and the provider applies its own default.
28
+ Set `DOTI_GENERATION__TEMPERATURE=0` to keep the previous behaviour for
29
+ non-reasoning models.
30
+ - Licence: from `AGPL-3.0-or-later` to `MIT`. Releases already published
31
+ stay under the AGPL.
32
+
10
33
  ## [2.2.0] - 2026-10-08
11
34
 
12
35
  ### Added
@@ -107,7 +130,8 @@ this release.
107
130
  - `LLMCallable` and `EmbeddingCallable` return a `Coroutine` rather than the
108
131
  looser `Awaitable`, matching what `asyncio.run_coroutine_threadsafe` accepts.
109
132
 
110
- [Unreleased]: https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/compare/v2.2.0...main
133
+ [Unreleased]: https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/compare/v3.0.0...main
134
+ [3.0.0]: https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/tags/v3.0.0
111
135
  [2.2.0]: https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/tags/v2.2.0
112
136
  [2.1.0]: https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/tags/v2.1.0
113
137
  [2.0.3]: https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/tags/v2.0.3
@@ -0,0 +1,37 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest in this project. Contributions are welcome.
4
+
5
+ This project is maintained by **Kannon For Deep Tech** and released under the
6
+ MIT License (`MIT`).
7
+
8
+ ## 1. Licensing of your contribution
9
+
10
+ By contributing to this project, you agree that your contribution is licensed
11
+ under the MIT License, the same terms as the rest of the project. You remain
12
+ the author and copyright holder of your contribution.
13
+
14
+ You confirm that you are entitled to do so: that your contribution is your
15
+ original work or that you hold the necessary rights over it, and that it does
16
+ not infringe any third-party rights. If you are contributing in the course of
17
+ your employment or under a service agreement, you confirm that your employer or
18
+ client has authorised you to contribute under these terms.
19
+
20
+ ## 2. Contractors and employees of Kannon For Deep Tech
21
+
22
+ If you are working for Kannon For Deep Tech as an employee or under a service
23
+ agreement, the assignment of rights set out in your contract governs, and takes
24
+ precedence over this file.
25
+
26
+ ## 3. Submitting a change
27
+
28
+ 1. Open an issue first for anything substantial, so we can agree on the approach.
29
+ 2. Fork, branch, and keep commits focused.
30
+ 3. Add or update tests where relevant.
31
+ 4. If you would like to be credited individually, add yourself to
32
+ [AUTHORS.md](AUTHORS.md) in the same pull request.
33
+ 5. Open a pull request.
34
+
35
+ ## 4. Questions
36
+
37
+ For anything about licensing, contact <louis.letarnec@deepika.ai>.
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2026 Kannon For Deep Tech
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: dot-inference
3
- Version: 2.2.0
3
+ Version: 3.0.0
4
4
  Summary: Unified async Python library for LLM inference and embeddings across multiple providers
5
5
  Project-URL: Homepage, https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference
6
6
  Project-URL: Repository, https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference
7
7
  Project-URL: Issues, https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/issues
8
8
  Author-email: Kannon For Deep Tech <louis.letarnec@deepika.ai>
9
- License-Expression: AGPL-3.0-or-later
9
+ License-Expression: MIT
10
10
  License-File: LICENSE.md
11
11
  Keywords: embeddings,inference,llm,providers
12
12
  Classifier: Development Status :: 3 - Alpha
@@ -29,7 +29,7 @@ Description-Content-Type: text/markdown
29
29
 
30
30
  [![PyPI](https://img.shields.io/pypi/v/dot-inference)](https://pypi.org/project/dot-inference/)
31
31
  ![Python Version](https://img.shields.io/badge/python-3.12%2B-blue)
32
- [![Licence: AGPL v3](https://img.shields.io/badge/licence-AGPL--3.0--or--later-blue)](LICENSE.md)
32
+ [![Licence: MIT](https://img.shields.io/badge/licence-MIT-blue)](LICENSE.md)
33
33
  [![Pipeline](https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/badges/main/pipeline.svg)](https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/pipelines)
34
34
 
35
35
  **One async interface for LLM inference and embeddings, across every provider.**
@@ -313,7 +313,7 @@ package is covered, anything underscore-prefixed is internal and may change in
313
313
  any release. Public names are never removed without a deprecation period.
314
314
 
315
315
  ```toml
316
- dependencies = ["dot-inference>=2.0,<3"]
316
+ dependencies = ["dot-inference>=3.0,<4"]
317
317
  ```
318
318
 
319
319
  See [docs/VERSIONING.md](docs/VERSIONING.md) for the full policy.
@@ -337,16 +337,12 @@ See [docs/VERSIONING.md](docs/VERSIONING.md) for the full policy.
337
337
 
338
338
  ## Contributing
339
339
 
340
- Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the DCO
341
- sign-off requirement, the licensing terms that apply to contributions, and how to
342
- submit a change.
340
+ Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the
341
+ licensing terms that apply to contributions and how to submit a change.
343
342
 
344
343
  ## Licence
345
344
 
346
345
  Copyright (C) 2026 Kannon For Deep Tech (deepika)
347
346
 
348
- This software is distributed under the GNU Affero General Public License,
349
- version 3 or later — see [LICENSE.md](LICENSE.md).
350
-
351
- A commercial licence is available for use in proprietary environments.
352
- Contact: louis.letarnec@deepika.ai
347
+ This software is distributed under the MIT License — see
348
+ [LICENSE.md](LICENSE.md).
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![PyPI](https://img.shields.io/pypi/v/dot-inference)](https://pypi.org/project/dot-inference/)
4
4
  ![Python Version](https://img.shields.io/badge/python-3.12%2B-blue)
5
- [![Licence: AGPL v3](https://img.shields.io/badge/licence-AGPL--3.0--or--later-blue)](LICENSE.md)
5
+ [![Licence: MIT](https://img.shields.io/badge/licence-MIT-blue)](LICENSE.md)
6
6
  [![Pipeline](https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/badges/main/pipeline.svg)](https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/pipelines)
7
7
 
8
8
  **One async interface for LLM inference and embeddings, across every provider.**
@@ -286,7 +286,7 @@ package is covered, anything underscore-prefixed is internal and may change in
286
286
  any release. Public names are never removed without a deprecation period.
287
287
 
288
288
  ```toml
289
- dependencies = ["dot-inference>=2.0,<3"]
289
+ dependencies = ["dot-inference>=3.0,<4"]
290
290
  ```
291
291
 
292
292
  See [docs/VERSIONING.md](docs/VERSIONING.md) for the full policy.
@@ -310,16 +310,12 @@ See [docs/VERSIONING.md](docs/VERSIONING.md) for the full policy.
310
310
 
311
311
  ## Contributing
312
312
 
313
- Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the DCO
314
- sign-off requirement, the licensing terms that apply to contributions, and how to
315
- submit a change.
313
+ Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the
314
+ licensing terms that apply to contributions and how to submit a change.
316
315
 
317
316
  ## Licence
318
317
 
319
318
  Copyright (C) 2026 Kannon For Deep Tech (deepika)
320
319
 
321
- This software is distributed under the GNU Affero General Public License,
322
- version 3 or later — see [LICENSE.md](LICENSE.md).
323
-
324
- A commercial licence is available for use in proprietary environments.
325
- Contact: louis.letarnec@deepika.ai
320
+ This software is distributed under the MIT License — see
321
+ [LICENSE.md](LICENSE.md).
@@ -148,7 +148,7 @@ sequenceDiagram
148
148
  App->>RateLimit: await client.call(messages)
149
149
  RateLimit->>RateLimit: Sliding-window check / wait
150
150
  RateLimit->>Compat: forward call
151
- Compat->>Compat: Build request kwargs (temperature or reasoning_effort)
151
+ Compat->>Compat: Build request kwargs (reasoning_effort if the model reasons, temperature if set and the model accepts it)
152
152
 
153
153
  loop retry up to 4 attempts on transient errors
154
154
  Compat->>API: POST /chat/completions
@@ -1,8 +1,8 @@
1
1
  # Development Guide
2
2
 
3
3
  > Looking to contribute? Start with [CONTRIBUTING.md](../CONTRIBUTING.md) at the
4
- > repository root: it covers the DCO sign-off and the licensing terms your
5
- > contribution falls under. This guide covers the practical side.
4
+ > repository root: it covers the licensing terms your contribution
5
+ > falls under. This guide covers the practical side.
6
6
 
7
7
  ## Requirements
8
8
 
@@ -53,11 +53,6 @@ and re-run in CI, so most of the style is applied for you.
53
53
  - Use meaningful variable and function names
54
54
  - Add docstrings for public functions and classes
55
55
  - Keep functions focused and small
56
- - Add the SPDX headers to any new file:
57
- ```python
58
- # SPDX-FileCopyrightText: Kannon For Deep Tech and contributors
59
- # SPDX-License-Identifier: AGPL-3.0-or-later
60
- ```
61
56
 
62
57
  ## Testing
63
58
 
@@ -1,7 +1,7 @@
1
1
  # Versioning and stability
2
2
 
3
3
  `dot-inference` follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
- This page says what that actually covers, so `>=2.0,<3` means something concrete.
4
+ This page says what that actually covers, so `>=3.0,<4` means something concrete.
5
5
 
6
6
  ## What is public
7
7
 
@@ -94,11 +94,11 @@ manual. Use them to validate a release without committing to it.
94
94
  ### From PyPI — the supported way
95
95
 
96
96
  ```toml
97
- dependencies = ["dot-inference>=2.0,<3"]
97
+ dependencies = ["dot-inference>=3.0,<4"]
98
98
  ```
99
99
 
100
100
  The upper bound is what makes the guarantees above useful: you get every fix and
101
- feature of the 2.x line, and never an unannounced break.
101
+ feature of the 3.x line, and never an unannounced break.
102
102
 
103
103
  ### From git — development only
104
104
 
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """
5
2
  dot-inference demo script
6
3
 
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """
5
2
  dot-inference streaming demo
6
3
 
@@ -1,10 +1,10 @@
1
1
  [project]
2
2
  name = "dot-inference"
3
- version = "2.2.0"
3
+ version = "3.0.0"
4
4
  description = "Unified async Python library for LLM inference and embeddings across multiple providers"
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Kannon For Deep Tech", email = "louis.letarnec@deepika.ai" }]
7
- license = "AGPL-3.0-or-later"
7
+ license = "MIT"
8
8
  license-files = ["LICENSE.md"]
9
9
  keywords = ["llm", "inference", "embeddings", "providers"]
10
10
 
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Ad-hoc live smoke test for every model × provider route in the registry.
5
2
 
6
3
  Makes a minimal real call per (model, provider) where a key is available,
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  from dot_inference._client import (
5
2
  EmbeddingClient,
6
3
  LLMClient,
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Class-based LLM client interface.
5
2
 
6
3
  Provides ``LLMClient`` and ``EmbeddingClient`` — abstract base classes with
@@ -371,10 +368,10 @@ def _warn_compatibility(
371
368
  # separately in LLMClient._resolve_reasoning_effort.
372
369
  _validate_reasoning_effort_for_model(model, reasoning_effort, config.supports_reasoning)
373
370
 
374
- if config.supports_reasoning and temperature:
371
+ if not config.supports_temperature and temperature is not None:
375
372
  logger.warning(
376
- "Model '%s' is a reasoning model — the temperature setting (%.2f) "
377
- "will be ignored in favor of reasoning_effort.",
373
+ "Model '%s' does not accept a temperature — the temperature setting "
374
+ "(%.2f) will not be sent.",
378
375
  model,
379
376
  temperature,
380
377
  )
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Cost and token usage tracker for aggregating across multiple LLM calls."""
5
2
 
6
3
  from __future__ import annotations
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Model registry — loads model configurations from models.yaml.
5
2
 
6
3
  The built-in ``models.yaml`` ships with the package. Users can extend or
@@ -31,6 +28,8 @@ class ProviderModelConfig:
31
28
  # Useful when reasoning works through one provider (e.g. OpenRouter) but
32
29
  # not another (e.g. native SDK doesn't expose the parameter yet).
33
30
  supports_reasoning: bool | None = None
31
+ # Per-provider override for temperature support (None = inherit from model).
32
+ supports_temperature: bool | None = None
34
33
  # OpenRouter-specific features (ignored by other providers)
35
34
  response_healing: bool = False
36
35
  fallback_models: list[str] = field(default_factory=list)
@@ -44,6 +43,11 @@ class ModelConfig:
44
43
  model_id: str
45
44
  supports_strict_json: bool = True
46
45
  supports_reasoning: bool = False
46
+ # Whether the API accepts a ``temperature`` parameter. Independent of
47
+ # ``supports_reasoning``: gpt-oss reasons and honours temperature, while
48
+ # OpenAI's gpt-5 family rejects any value other than the default (1).
49
+ # When False, a configured temperature is dropped from the request.
50
+ supports_temperature: bool = True
47
51
  requires_cache_control: bool = False
48
52
  input_token_cost: float | None = None
49
53
  output_token_cost: float | None = None
@@ -75,6 +79,9 @@ class ModelConfig:
75
79
  supports_reasoning=pmc.supports_reasoning
76
80
  if pmc.supports_reasoning is not None
77
81
  else self.supports_reasoning,
82
+ supports_temperature=pmc.supports_temperature
83
+ if pmc.supports_temperature is not None
84
+ else self.supports_temperature,
78
85
  requires_cache_control=self.requires_cache_control,
79
86
  input_token_cost=pmc.input_token_cost
80
87
  if pmc.input_token_cost is not None
@@ -98,6 +105,7 @@ class ResolvedModelConfig:
98
105
  api_model_name: str
99
106
  supports_strict_json: bool = True
100
107
  supports_reasoning: bool = False
108
+ supports_temperature: bool = True
101
109
  requires_cache_control: bool = False
102
110
  input_token_cost: float | None = None
103
111
  output_token_cost: float | None = None
@@ -130,6 +138,7 @@ def _parse_models_yaml(raw: dict[str, Any]) -> dict[str, ModelConfig]:
130
138
  input_token_cost=_to_float(prov_cfg.get("input_token_cost")),
131
139
  output_token_cost=_to_float(prov_cfg.get("output_token_cost")),
132
140
  supports_reasoning=prov_cfg.get("supports_reasoning"),
141
+ supports_temperature=prov_cfg.get("supports_temperature"),
133
142
  response_healing=features.get("response_healing", False),
134
143
  fallback_models=features.get("fallback_models", []),
135
144
  provider_routing=features.get("provider_routing"),
@@ -139,6 +148,7 @@ def _parse_models_yaml(raw: dict[str, Any]) -> dict[str, ModelConfig]:
139
148
  model_id=model_id,
140
149
  supports_strict_json=cfg.get("supports_strict_json", True),
141
150
  supports_reasoning=cfg.get("supports_reasoning", False),
151
+ supports_temperature=cfg.get("supports_temperature", True),
142
152
  requires_cache_control=cfg.get("requires_cache_control", False),
143
153
  input_token_cost=_to_float(cfg.get("input_token_cost")),
144
154
  output_token_cost=_to_float(cfg.get("output_token_cost")),
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Sanity check for the ``local`` provider endpoint.
5
2
 
6
3
  Single-model OpenAI-compatible servers (SGLang, vLLM in single-model mode)
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Shared Mistral-native client.
5
2
 
6
3
  Provides ``MistralClient`` — a class-based LLM client using the native
@@ -161,9 +158,13 @@ class MistralClient(LLMClient):
161
158
  # Mistral reasoning models (Medium 3.5, Small) take reasoning_effort
162
159
  # natively on the chat-completion request — La Plateforme accepts
163
160
  # "none" (minimal thinking, thinking chunk omitted) and "high"
164
- # (full thinking chunk). Temperature is ignored for these.
161
+ # (full thinking chunk).
165
162
  create_kwargs["reasoning_effort"] = reasoning_effort
166
- elif not is_reasoning and temperature is not None:
163
+ # Temperature is independent of reasoning: sent whenever it is set,
164
+ # unless the registry says the model rejects it (unknown models get it).
165
+ if temperature is not None and (
166
+ self._model_config is None or self._model_config.supports_temperature
167
+ ):
167
168
  create_kwargs["temperature"] = temperature
168
169
 
169
170
  response_model: type[BaseModel] | None = None
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Shared OpenAI-compatible client.
5
2
 
6
3
  Provides ``OpenAICompatClient`` — a class-based LLM client for any
@@ -187,11 +184,14 @@ class OpenAICompatClient(LLMClient):
187
184
  "messages": [m.model_dump(exclude_none=True) for m in messages],
188
185
  }
189
186
 
190
- # Reasoning models use reasoning_effort instead of temperature
191
187
  is_reasoning = self._model_config.supports_reasoning if self._model_config else False
192
188
  if is_reasoning and reasoning_effort is not None:
193
189
  create_kwargs["reasoning_effort"] = reasoning_effort
194
- elif not is_reasoning and temperature is not None:
190
+ # Temperature is independent of reasoning: sent whenever it is set,
191
+ # unless the registry says the model rejects it (unknown models get it).
192
+ if temperature is not None and (
193
+ self._model_config is None or self._model_config.supports_temperature
194
+ ):
195
195
  create_kwargs["temperature"] = temperature
196
196
 
197
197
  response_model: type[BaseModel] | None = None
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Async rate-limiting wrapper for ``LLMCallable``."""
5
2
 
6
3
  from __future__ import annotations
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Decides how long to wait before retrying a transient provider error.
5
2
 
6
3
  Shared by the OpenAI and Mistral clients so both honor ``Retry-After`` the
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Sync helpers — run async code from synchronous contexts.
5
2
 
6
3
  Uses a single persistent background event loop in a daemon thread so that:
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Shared types for dot-llm."""
5
2
 
6
3
  from __future__ import annotations
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Mock clients for testing without API calls."""
5
2
 
6
3
  from __future__ import annotations
@@ -38,6 +38,13 @@
38
38
  # - Can be overridden per provider (see below) when reasoning is
39
39
  # available through one provider but not another.
40
40
  #
41
+ # supports_temperature: true/false (default true)
42
+ # - Whether the API accepts a temperature parameter. Independent of
43
+ # supports_reasoning: gpt-oss reasons and honours temperature, while
44
+ # OpenAI's gpt-5 family accepts only its default (1). When false, a
45
+ # configured temperature is not sent.
46
+ # - Can be overridden per provider (see below).
47
+ #
41
48
  # reasoning_effort_options: list[str] (optional)
42
49
  # - The reasoning_effort values this model actually accepts. Lets a
43
50
  # client offer only the valid choices. Defaults to
@@ -78,6 +85,10 @@
78
85
  # - Useful when the model supports reasoning via one provider (e.g.
79
86
  # OpenRouter) but not another (e.g. native SDK lacks the param).
80
87
  #
88
+ # supports_temperature: true/false (optional)
89
+ # - Per-provider override for temperature support; inherits the
90
+ # model-level value when omitted.
91
+ #
81
92
  # features (optional, provider-specific):
82
93
  # response_healing: true/false
83
94
  # - OpenRouter plugin that post-processes malformed JSON responses.
@@ -95,6 +106,7 @@
95
106
  openai/gpt-5:
96
107
  supports_strict_json: true
97
108
  supports_reasoning: true
109
+ supports_temperature: false # the OpenAI API accepts only its default (1) for this family
98
110
  input_token_cost: 1.25e-6 # $1.25/M
99
111
  output_token_cost: 1.e-5 # $10/M
100
112
  context_window: 400000
@@ -110,6 +122,7 @@ openai/gpt-5:
110
122
  openai/gpt-5.1:
111
123
  supports_strict_json: true
112
124
  supports_reasoning: true
125
+ supports_temperature: false # the OpenAI API accepts only its default (1) for this family
113
126
  input_token_cost: 1.25e-6 # $1.25/M
114
127
  output_token_cost: 1.e-5 # $10/M
115
128
  context_window: 400000
@@ -125,6 +138,7 @@ openai/gpt-5.1:
125
138
  openai/gpt-5.2:
126
139
  supports_strict_json: true
127
140
  supports_reasoning: true
141
+ supports_temperature: false # the OpenAI API accepts only its default (1) for this family
128
142
  input_token_cost: 1.75e-6 # $1.75/M
129
143
  output_token_cost: 1.4e-5 # $14/M
130
144
  context_window: 400000
@@ -140,6 +154,7 @@ openai/gpt-5.2:
140
154
  openai/gpt-5-mini:
141
155
  supports_strict_json: true
142
156
  supports_reasoning: true
157
+ supports_temperature: false # the OpenAI API accepts only its default (1) for this family
143
158
  input_token_cost: 2.5e-7 # $0.25/M
144
159
  output_token_cost: 2.e-6 # $2/M
145
160
  context_window: 400000
@@ -179,6 +194,7 @@ openai/gpt-oss-20b-local:
179
194
  openai/gpt-5.4-nano:
180
195
  supports_strict_json: true
181
196
  supports_reasoning: true
197
+ supports_temperature: false # the OpenAI API accepts only its default (1) for this family
182
198
  input_token_cost: 2e-7 # $0.20/M
183
199
  output_token_cost: 1.25e-6 # $1.25/M
184
200
  context_window: 400000
@@ -194,6 +210,7 @@ openai/gpt-5.4-nano:
194
210
  openai/gpt-5.4-mini:
195
211
  supports_strict_json: true
196
212
  supports_reasoning: true
213
+ supports_temperature: false # the OpenAI API accepts only its default (1) for this family
197
214
  input_token_cost: 7.5e-7 # $0.75/M
198
215
  output_token_cost: 4.5e-6 # $4.50/M
199
216
  context_window: 400000
@@ -209,6 +226,7 @@ openai/gpt-5.4-mini:
209
226
  openai/gpt-5.4:
210
227
  supports_strict_json: true
211
228
  supports_reasoning: true
229
+ supports_temperature: false # the OpenAI API accepts only its default (1) for this family
212
230
  input_token_cost: 2.5e-6 # $2.50/M
213
231
  output_token_cost: 1.5e-5 # $15/M
214
232
  context_window: 1050000
@@ -225,6 +243,7 @@ openai/gpt-5.4:
225
243
  openai/gpt-6-luna:
226
244
  supports_strict_json: true
227
245
  supports_reasoning: true
246
+ supports_temperature: false # the OpenAI API accepts only its default (1) for this family
228
247
  input_token_cost: 1e-7 # $0.10/M
229
248
  output_token_cost: 5e-7 # $0.50/M
230
249
  context_window: 1050000
@@ -242,6 +261,7 @@ openai/gpt-6-luna:
242
261
  openai/gpt-6.1-sol:
243
262
  supports_strict_json: true
244
263
  supports_reasoning: true
264
+ supports_temperature: false # the OpenAI API accepts only its default (1) for this family
245
265
  input_token_cost: 2e-6 # $2/M
246
266
  output_token_cost: 1e-5 # $10/M
247
267
  context_window: 1050000
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Settings for dot-inference configuration via environment variables.
5
2
 
6
3
  All environment variables are prefixed with ``DOTI_`` and use ``__`` as
@@ -85,7 +82,8 @@ class GenerationSettings(BaseModel):
85
82
 
86
83
  mock: bool = False
87
84
  provider: Provider = Provider.OPENROUTER
88
- temperature: float = 0
85
+ # None: no temperature is sent, the provider applies its own default.
86
+ temperature: float | None = None
89
87
  max_tokens: int | None = None
90
88
  reasoning_effort: ReasoningEffort | None = ReasoningEffort.MEDIUM
91
89
  calls_per_minute_limit: int = 0 # no limit by default
File without changes
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Tests for dot_inference._cost_tracker."""
5
2
 
6
3
  import pytest
@@ -1,6 +1,3 @@
1
- # SPDX-FileCopyrightText: Kannon For Deep Tech
2
- # SPDX-License-Identifier: AGPL-3.0-or-later
3
-
4
1
  """Tests for get_llm_client and get_embedding_client factories."""
5
2
 
6
3
  import pytest