ctxlen 2026.10.11.dev1__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.
@@ -0,0 +1,76 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Michael Theologitis
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.
22
+
23
+ ---
24
+
25
+ src/ctxlen/_data.json holds data from litellm's model_prices_and_context_window.json,
26
+ and src/ctxlen/_resolve.py ports litellm's lookup of a model id. Both are used under
27
+ litellm's MIT license:
28
+
29
+ MIT License
30
+
31
+ Copyright (c) 2023 Berri AI
32
+
33
+ Permission is hereby granted, free of charge, to any person obtaining a copy
34
+ of this software and associated documentation files (the "Software"), to deal
35
+ in the Software without restriction, including without limitation the rights
36
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37
+ copies of the Software, and to permit persons to whom the Software is
38
+ furnished to do so, subject to the following conditions:
39
+
40
+ The above copyright notice and this permission notice shall be included in all
41
+ copies or substantial portions of the Software.
42
+
43
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
49
+ SOFTWARE.
50
+
51
+ ---
52
+
53
+ src/ctxlen/_data.json also holds data from models.dev's api.json, used under
54
+ models.dev's MIT license:
55
+
56
+ MIT License
57
+
58
+ Copyright (c) 2025 models.dev
59
+
60
+ Permission is hereby granted, free of charge, to any person obtaining a copy
61
+ of this software and associated documentation files (the "Software"), to deal
62
+ in the Software without restriction, including without limitation the rights
63
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
64
+ copies of the Software, and to permit persons to whom the Software is
65
+ furnished to do so, subject to the following conditions:
66
+
67
+ The above copyright notice and this permission notice shall be included in all
68
+ copies or substantial portions of the Software.
69
+
70
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
73
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
76
+ SOFTWARE.
@@ -0,0 +1,113 @@
1
+ Metadata-Version: 2.4
2
+ Name: ctxlen
3
+ Version: 2026.10.11.dev1
4
+ Summary: max_input and max_output for any litellm model id, with no dependencies and no network
5
+ Keywords: llm,litellm,context window,tokens,models.dev
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Typing :: Typed
10
+ Requires-Python: >=3.9
11
+ Project-URL: Repository, https://github.com/michaeltheologitis/ctxlen
12
+ Description-Content-Type: text/markdown
13
+
14
+ # ctxlen
15
+
16
+ How many tokens a model takes in, and how many it can write back, for any model id you would
17
+ pass to `litellm.completion`. No dependencies, no network: the numbers ship inside the package.
18
+
19
+ ```shell
20
+ uv add ctxlen
21
+ ```
22
+
23
+ ```pycon
24
+ >>> import ctxlen
25
+ >>> ctxlen.max_input("gpt-4o"), ctxlen.max_output("gpt-4o")
26
+ (128000, 16384)
27
+ >>> ctxlen.max_input("openai/gpt-4o")
28
+ 128000
29
+ >>> ctxlen.max_input("GPT-4o")
30
+ 128000
31
+ >>> ctxlen.max_input("text-embedding-3-small"), ctxlen.max_output("text-embedding-3-small")
32
+ (8191, None)
33
+ >>> print(ctxlen.max_input("not-a-model"))
34
+ None
35
+
36
+ ```
37
+
38
+ That is the whole API: `max_input(model)` and `max_output(model)`, each an `int` or `None`.
39
+
40
+ ## What the numbers mean
41
+
42
+ The numbers are litellm's, from its `model_prices_and_context_window.json`. Where litellm's
43
+ row has no number, ctxlen uses [models.dev](https://models.dev)'s for the same provider's model.
44
+ litellm wins every conflict.
45
+
46
+ The sources store what each provider publishes. For some models that is the input cap (gpt-5:
47
+ 272,000 tokens of a 400,000-token window); for others it is the whole window, the reply
48
+ included (Claude). ctxlen passes the numbers through and does not reconcile them, so leave room
49
+ for the reply.
50
+
51
+ ## The ids it takes
52
+
53
+ Any id litellm takes, resolved the way litellm's `get_model_info` resolves it:
54
+
55
+ - bare names, such as `gpt-4o` and `claude-sonnet-4-5`;
56
+ - provider prefixes, such as `openai/gpt-4o`, `anthropic/claude-sonnet-4-5`,
57
+ `vertex_ai/gemini-2.5-pro`, `bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0` and
58
+ `azure/gpt-4.1`;
59
+ - the forms litellm strips back to a known model: a date suffix such as `-2024-08-06`, a `-001`
60
+ version on Vertex and Gemini, a fine-tune such as `ft:gpt-4o-2024-08-06:acme::AbC123`,
61
+ Bedrock regions and routes, and any letter case.
62
+
63
+ A test in CI runs the same ids through litellm itself and fails if any answer differs.
64
+
65
+ ctxlen reads the id string only. litellm's `custom_llm_provider=`, `api_base=` and
66
+ `register_model` have no counterpart.
67
+
68
+ ## When the answer is None
69
+
70
+ `None` means no source has a number. ctxlen never guesses.
71
+
72
+ - The id is unknown, or empty. Nothing is trimmed: `" gpt-4o"` is unknown.
73
+ - The id names a deployment, such as `azure/my-prod-gpt4`. Ask by model: `azure/gpt-4.1`.
74
+ - The id is an `openrouter/` id. OpenRouter's terms forbid scripted copying, so v1 leaves it out.
75
+ - The model is too new for litellm, and models.dev has no entry for that provider either.
76
+ litellm's pattern rule would guess 200,000 tokens for an unknown Claude; ctxlen does not.
77
+ - `max_output` of an embedding model, which writes no tokens.
78
+ - models.dev's output limit equals the whole window, which is padding rather than a limit, so it
79
+ is dropped.
80
+
81
+ A `model` that is not a `str` raises `TypeError`.
82
+
83
+ ## How fresh the data is
84
+
85
+ A job rebuilds the data from litellm and models.dev every 6 hours, and publishes a release when
86
+ the data has changed. The version is the date of that snapshot: `2026.10.11.3` is the third
87
+ release built from data fetched on 2026-10-11 (UTC).
88
+
89
+ Your lock file decides what you get: `uv lock --upgrade-package ctxlen`. If a release most days
90
+ is too much for Dependabot, group the updates or check weekly:
91
+
92
+ ```yaml
93
+ version: 2
94
+ updates:
95
+ - package-ecosystem: pip
96
+ directory: /
97
+ schedule:
98
+ interval: weekly
99
+ groups:
100
+ ctxlen:
101
+ patterns: [ctxlen]
102
+ ```
103
+
104
+ ## Credits
105
+
106
+ - [litellm](https://github.com/BerriAI/litellm) (BerriAI, MIT): the model map, and the lookup
107
+ ctxlen ports from it.
108
+ - [models.dev](https://github.com/anomalyco/models.dev) (MIT): the numbers where litellm has
109
+ none. Its entries for OpenRouter, Vercel and Venice are not used, because their terms forbid
110
+ copying, and neither are Hugging Face's, whose router serves one model on hosts with different
111
+ windows.
112
+
113
+ Both MIT notices are in [LICENSE](LICENSE), after ctxlen's own.
@@ -0,0 +1,100 @@
1
+ # ctxlen
2
+
3
+ How many tokens a model takes in, and how many it can write back, for any model id you would
4
+ pass to `litellm.completion`. No dependencies, no network: the numbers ship inside the package.
5
+
6
+ ```shell
7
+ uv add ctxlen
8
+ ```
9
+
10
+ ```pycon
11
+ >>> import ctxlen
12
+ >>> ctxlen.max_input("gpt-4o"), ctxlen.max_output("gpt-4o")
13
+ (128000, 16384)
14
+ >>> ctxlen.max_input("openai/gpt-4o")
15
+ 128000
16
+ >>> ctxlen.max_input("GPT-4o")
17
+ 128000
18
+ >>> ctxlen.max_input("text-embedding-3-small"), ctxlen.max_output("text-embedding-3-small")
19
+ (8191, None)
20
+ >>> print(ctxlen.max_input("not-a-model"))
21
+ None
22
+
23
+ ```
24
+
25
+ That is the whole API: `max_input(model)` and `max_output(model)`, each an `int` or `None`.
26
+
27
+ ## What the numbers mean
28
+
29
+ The numbers are litellm's, from its `model_prices_and_context_window.json`. Where litellm's
30
+ row has no number, ctxlen uses [models.dev](https://models.dev)'s for the same provider's model.
31
+ litellm wins every conflict.
32
+
33
+ The sources store what each provider publishes. For some models that is the input cap (gpt-5:
34
+ 272,000 tokens of a 400,000-token window); for others it is the whole window, the reply
35
+ included (Claude). ctxlen passes the numbers through and does not reconcile them, so leave room
36
+ for the reply.
37
+
38
+ ## The ids it takes
39
+
40
+ Any id litellm takes, resolved the way litellm's `get_model_info` resolves it:
41
+
42
+ - bare names, such as `gpt-4o` and `claude-sonnet-4-5`;
43
+ - provider prefixes, such as `openai/gpt-4o`, `anthropic/claude-sonnet-4-5`,
44
+ `vertex_ai/gemini-2.5-pro`, `bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0` and
45
+ `azure/gpt-4.1`;
46
+ - the forms litellm strips back to a known model: a date suffix such as `-2024-08-06`, a `-001`
47
+ version on Vertex and Gemini, a fine-tune such as `ft:gpt-4o-2024-08-06:acme::AbC123`,
48
+ Bedrock regions and routes, and any letter case.
49
+
50
+ A test in CI runs the same ids through litellm itself and fails if any answer differs.
51
+
52
+ ctxlen reads the id string only. litellm's `custom_llm_provider=`, `api_base=` and
53
+ `register_model` have no counterpart.
54
+
55
+ ## When the answer is None
56
+
57
+ `None` means no source has a number. ctxlen never guesses.
58
+
59
+ - The id is unknown, or empty. Nothing is trimmed: `" gpt-4o"` is unknown.
60
+ - The id names a deployment, such as `azure/my-prod-gpt4`. Ask by model: `azure/gpt-4.1`.
61
+ - The id is an `openrouter/` id. OpenRouter's terms forbid scripted copying, so v1 leaves it out.
62
+ - The model is too new for litellm, and models.dev has no entry for that provider either.
63
+ litellm's pattern rule would guess 200,000 tokens for an unknown Claude; ctxlen does not.
64
+ - `max_output` of an embedding model, which writes no tokens.
65
+ - models.dev's output limit equals the whole window, which is padding rather than a limit, so it
66
+ is dropped.
67
+
68
+ A `model` that is not a `str` raises `TypeError`.
69
+
70
+ ## How fresh the data is
71
+
72
+ A job rebuilds the data from litellm and models.dev every 6 hours, and publishes a release when
73
+ the data has changed. The version is the date of that snapshot: `2026.10.11.3` is the third
74
+ release built from data fetched on 2026-10-11 (UTC).
75
+
76
+ Your lock file decides what you get: `uv lock --upgrade-package ctxlen`. If a release most days
77
+ is too much for Dependabot, group the updates or check weekly:
78
+
79
+ ```yaml
80
+ version: 2
81
+ updates:
82
+ - package-ecosystem: pip
83
+ directory: /
84
+ schedule:
85
+ interval: weekly
86
+ groups:
87
+ ctxlen:
88
+ patterns: [ctxlen]
89
+ ```
90
+
91
+ ## Credits
92
+
93
+ - [litellm](https://github.com/BerriAI/litellm) (BerriAI, MIT): the model map, and the lookup
94
+ ctxlen ports from it.
95
+ - [models.dev](https://github.com/anomalyco/models.dev) (MIT): the numbers where litellm has
96
+ none. Its entries for OpenRouter, Vercel and Venice are not used, because their terms forbid
97
+ copying, and neither are Hugging Face's, whose router serves one model on hosts with different
98
+ windows.
99
+
100
+ Both MIT notices are in [LICENSE](LICENSE), after ctxlen's own.
@@ -0,0 +1,36 @@
1
+ [project]
2
+ name = "ctxlen"
3
+ version = "2026.10.11.dev1"
4
+ description = "max_input and max_output for any litellm model id, with no dependencies and no network"
5
+ requires-python = ">=3.9"
6
+ dependencies = []
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ readme = "README.md"
10
+ keywords = [
11
+ "llm",
12
+ "litellm",
13
+ "context window",
14
+ "tokens",
15
+ "models.dev",
16
+ ]
17
+ classifiers = [
18
+ "Programming Language :: Python :: 3",
19
+ "Typing :: Typed",
20
+ ]
21
+
22
+ [project.urls]
23
+ Repository = "https://github.com/michaeltheologitis/ctxlen"
24
+
25
+ [build-system]
26
+ requires = ["uv_build>=0.11.32,<0.12"]
27
+ build-backend = "uv_build"
28
+
29
+ [dependency-groups]
30
+ dev = ["pytest>=8"]
31
+
32
+ [tool.pytest.ini_options]
33
+ testpaths = ["tests"]
34
+ pythonpath = ["."]
35
+ markers = ["live: real PyPI and GitHub; run with -m live"]
36
+ addopts = "-m 'not live'"
@@ -0,0 +1,30 @@
1
+ [project]
2
+ name = "ctxlen"
3
+ version = "2026.10.11.dev1"
4
+ description = "max_input and max_output for any litellm model id, with no dependencies and no network"
5
+ requires-python = ">=3.9"
6
+ dependencies = []
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ readme = "README.md"
10
+ keywords = ["llm", "litellm", "context window", "tokens", "models.dev"]
11
+ classifiers = [
12
+ "Programming Language :: Python :: 3",
13
+ "Typing :: Typed",
14
+ ]
15
+
16
+ [project.urls]
17
+ Repository = "https://github.com/michaeltheologitis/ctxlen"
18
+
19
+ [build-system]
20
+ requires = ["uv_build>=0.11.32,<0.12"]
21
+ build-backend = "uv_build"
22
+
23
+ [dependency-groups]
24
+ dev = ["pytest>=8"]
25
+
26
+ [tool.pytest.ini_options]
27
+ testpaths = ["tests"]
28
+ pythonpath = ["."]
29
+ markers = ["live: real PyPI and GitHub; run with -m live"]
30
+ addopts = "-m 'not live'"
@@ -0,0 +1,35 @@
1
+ """max_input and max_output for any litellm model id, from bundled data, with no network."""
2
+
3
+ import typing as _typing
4
+
5
+ from ctxlen import _resolve
6
+
7
+ __all__ = ["max_input", "max_output"]
8
+
9
+
10
+ def max_input(model: str) -> _typing.Optional[int]: # noqa: FA100 (help() shows Optional[int] on 3.9)
11
+ """The most input tokens `model` accepts, or None if no source knows it.
12
+
13
+ `model` is any id you would pass to litellm.completion ("gpt-4o",
14
+ "anthropic/claude-sonnet-4-5", "bedrock/us.anthropic..."), resolved as
15
+ litellm resolves it. The number is litellm's; where litellm has none,
16
+ models.dev's for the same provider's model.
17
+
18
+ The sources store what each provider publishes: for some models the input
19
+ cap (gpt-5: 272,000 of a 400,000 window), for others the whole window,
20
+ the reply included (Claude). ctxlen does not reconcile them: leave room
21
+ for the reply.
22
+ """
23
+ return _resolve.limits(model, "max_input")[0]
24
+
25
+
26
+ def max_output(model: str) -> _typing.Optional[int]: # noqa: FA100
27
+ """The most tokens `model` can generate in one reply, or None if no source knows it.
28
+
29
+ `model` is any id you would pass to litellm.completion ("gpt-4o",
30
+ "anthropic/claude-sonnet-4-5", "bedrock/us.anthropic..."), resolved as
31
+ litellm resolves it. The number is litellm's max_output_tokens for that
32
+ model; where litellm has none, models.dev's for the same provider's model.
33
+ An embedding model has no output limit, so it gives None.
34
+ """
35
+ return _resolve.limits(model, "max_output")[1]