Metadata-Version: 2.4
Name: ctxlen
Version: 2026.10.11.dev1
Summary: max_input and max_output for any litellm model id, with no dependencies and no network
Keywords: llm,litellm,context window,tokens,models.dev
License-Expression: MIT
License-File: LICENSE
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.9
Project-URL: Repository, https://github.com/michaeltheologitis/ctxlen
Description-Content-Type: text/markdown

# ctxlen

How many tokens a model takes in, and how many it can write back, for any model id you would
pass to `litellm.completion`. No dependencies, no network: the numbers ship inside the package.

```shell
uv add ctxlen
```

```pycon
>>> import ctxlen
>>> ctxlen.max_input("gpt-4o"), ctxlen.max_output("gpt-4o")
(128000, 16384)
>>> ctxlen.max_input("openai/gpt-4o")
128000
>>> ctxlen.max_input("GPT-4o")
128000
>>> ctxlen.max_input("text-embedding-3-small"), ctxlen.max_output("text-embedding-3-small")
(8191, None)
>>> print(ctxlen.max_input("not-a-model"))
None

```

That is the whole API: `max_input(model)` and `max_output(model)`, each an `int` or `None`.

## What the numbers mean

The numbers are litellm's, from its `model_prices_and_context_window.json`. Where litellm's
row has no number, ctxlen uses [models.dev](https://models.dev)'s for the same provider's model.
litellm wins every conflict.

The sources store what each provider publishes. For some models that is the input cap (gpt-5:
272,000 tokens of a 400,000-token window); for others it is the whole window, the reply
included (Claude). ctxlen passes the numbers through and does not reconcile them, so leave room
for the reply.

## The ids it takes

Any id litellm takes, resolved the way litellm's `get_model_info` resolves it:

- bare names, such as `gpt-4o` and `claude-sonnet-4-5`;
- provider prefixes, such as `openai/gpt-4o`, `anthropic/claude-sonnet-4-5`,
  `vertex_ai/gemini-2.5-pro`, `bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0` and
  `azure/gpt-4.1`;
- the forms litellm strips back to a known model: a date suffix such as `-2024-08-06`, a `-001`
  version on Vertex and Gemini, a fine-tune such as `ft:gpt-4o-2024-08-06:acme::AbC123`,
  Bedrock regions and routes, and any letter case.

A test in CI runs the same ids through litellm itself and fails if any answer differs.

ctxlen reads the id string only. litellm's `custom_llm_provider=`, `api_base=` and
`register_model` have no counterpart.

## When the answer is None

`None` means no source has a number. ctxlen never guesses.

- The id is unknown, or empty. Nothing is trimmed: `" gpt-4o"` is unknown.
- The id names a deployment, such as `azure/my-prod-gpt4`. Ask by model: `azure/gpt-4.1`.
- The id is an `openrouter/` id. OpenRouter's terms forbid scripted copying, so v1 leaves it out.
- The model is too new for litellm, and models.dev has no entry for that provider either.
  litellm's pattern rule would guess 200,000 tokens for an unknown Claude; ctxlen does not.
- `max_output` of an embedding model, which writes no tokens.
- models.dev's output limit equals the whole window, which is padding rather than a limit, so it
  is dropped.

A `model` that is not a `str` raises `TypeError`.

## How fresh the data is

A job rebuilds the data from litellm and models.dev every 6 hours, and publishes a release when
the data has changed. The version is the date of that snapshot: `2026.10.11.3` is the third
release built from data fetched on 2026-10-11 (UTC).

Your lock file decides what you get: `uv lock --upgrade-package ctxlen`. If a release most days
is too much for Dependabot, group the updates or check weekly:

```yaml
version: 2
updates:
  - package-ecosystem: pip
    directory: /
    schedule:
      interval: weekly
    groups:
      ctxlen:
        patterns: [ctxlen]
```

## Credits

- [litellm](https://github.com/BerriAI/litellm) (BerriAI, MIT): the model map, and the lookup
  ctxlen ports from it.
- [models.dev](https://github.com/anomalyco/models.dev) (MIT): the numbers where litellm has
  none. Its entries for OpenRouter, Vercel and Venice are not used, because their terms forbid
  copying, and neither are Hugging Face's, whose router serves one model on hosts with different
  windows.

Both MIT notices are in [LICENSE](LICENSE), after ctxlen's own.
