whatmodel 0.0.1__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.
- whatmodel-0.0.1/.gitignore +220 -0
- whatmodel-0.0.1/CHANGELOG.md +24 -0
- whatmodel-0.0.1/CONTRIBUTING.md +110 -0
- whatmodel-0.0.1/LICENSE +21 -0
- whatmodel-0.0.1/PKG-INFO +270 -0
- whatmodel-0.0.1/README.md +238 -0
- whatmodel-0.0.1/pyproject.toml +87 -0
- whatmodel-0.0.1/tests/conftest.py +28 -0
- whatmodel-0.0.1/tests/test_cli.py +314 -0
- whatmodel-0.0.1/tests/test_dictionary.py +351 -0
- whatmodel-0.0.1/tests/test_lookup.py +425 -0
- whatmodel-0.0.1/tests/test_parser.py +425 -0
- whatmodel-0.0.1/whatmodel/__init__.py +33 -0
- whatmodel-0.0.1/whatmodel/cli.py +197 -0
- whatmodel-0.0.1/whatmodel/dictionary.py +524 -0
- whatmodel-0.0.1/whatmodel/lookup.py +517 -0
- whatmodel-0.0.1/whatmodel/parser.py +468 -0
- whatmodel-0.0.1/whatmodel/py.typed +0 -0
- whatmodel-0.0.1/whatmodel/render.py +304 -0
- whatmodel-0.0.1/whatmodel/tokens.yaml +1101 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
*.lcov
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
.pybuilder/
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
|
|
82
|
+
# IPython
|
|
83
|
+
profile_default/
|
|
84
|
+
ipython_config.py
|
|
85
|
+
|
|
86
|
+
# pyenv
|
|
87
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
88
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
89
|
+
# .python-version
|
|
90
|
+
|
|
91
|
+
# pipenv
|
|
92
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
93
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
94
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
95
|
+
# install all needed dependencies.
|
|
96
|
+
# Pipfile.lock
|
|
97
|
+
|
|
98
|
+
# uv
|
|
99
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
100
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
101
|
+
# commonly ignored for libraries.
|
|
102
|
+
# uv.lock
|
|
103
|
+
|
|
104
|
+
# poetry
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
106
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
107
|
+
# commonly ignored for libraries.
|
|
108
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
109
|
+
# poetry.lock
|
|
110
|
+
# poetry.toml
|
|
111
|
+
|
|
112
|
+
# pdm
|
|
113
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
114
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
115
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
116
|
+
# pdm.lock
|
|
117
|
+
# pdm.toml
|
|
118
|
+
.pdm-python
|
|
119
|
+
.pdm-build/
|
|
120
|
+
|
|
121
|
+
# pixi
|
|
122
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
123
|
+
# pixi.lock
|
|
124
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
125
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
126
|
+
.pixi/*
|
|
127
|
+
!.pixi/config.toml
|
|
128
|
+
|
|
129
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
130
|
+
__pypackages__/
|
|
131
|
+
|
|
132
|
+
# Celery stuff
|
|
133
|
+
celerybeat-schedule*
|
|
134
|
+
celerybeat.pid
|
|
135
|
+
|
|
136
|
+
# Redis
|
|
137
|
+
*.rdb
|
|
138
|
+
*.aof
|
|
139
|
+
*.pid
|
|
140
|
+
|
|
141
|
+
# RabbitMQ
|
|
142
|
+
mnesia/
|
|
143
|
+
rabbitmq/
|
|
144
|
+
rabbitmq-data/
|
|
145
|
+
|
|
146
|
+
# ActiveMQ
|
|
147
|
+
activemq-data/
|
|
148
|
+
|
|
149
|
+
# SageMath parsed files
|
|
150
|
+
*.sage.py
|
|
151
|
+
|
|
152
|
+
# Environments
|
|
153
|
+
.env
|
|
154
|
+
.envrc
|
|
155
|
+
.venv
|
|
156
|
+
env/
|
|
157
|
+
venv/
|
|
158
|
+
ENV/
|
|
159
|
+
env.bak/
|
|
160
|
+
venv.bak/
|
|
161
|
+
|
|
162
|
+
# Spyder project settings
|
|
163
|
+
.spyderproject
|
|
164
|
+
.spyproject
|
|
165
|
+
|
|
166
|
+
# Rope project settings
|
|
167
|
+
.ropeproject
|
|
168
|
+
|
|
169
|
+
# mkdocs/Zensical documentation
|
|
170
|
+
/site
|
|
171
|
+
|
|
172
|
+
# mypy
|
|
173
|
+
.mypy_cache/
|
|
174
|
+
.dmypy.json
|
|
175
|
+
dmypy.json
|
|
176
|
+
|
|
177
|
+
# Pyre type checker
|
|
178
|
+
.pyre/
|
|
179
|
+
|
|
180
|
+
# pytype static type analyzer
|
|
181
|
+
.pytype/
|
|
182
|
+
|
|
183
|
+
# Cython debug symbols
|
|
184
|
+
cython_debug/
|
|
185
|
+
|
|
186
|
+
# PyCharm
|
|
187
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
188
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
189
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
190
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
191
|
+
# .idea/
|
|
192
|
+
|
|
193
|
+
# Abstra
|
|
194
|
+
# Abstra is an AI-powered process automation framework.
|
|
195
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
196
|
+
# Learn more at https://abstra.io/docs
|
|
197
|
+
.abstra/
|
|
198
|
+
|
|
199
|
+
# Visual Studio Code
|
|
200
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore that
|
|
201
|
+
# can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
202
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer, you
|
|
203
|
+
# could uncomment the following to ignore the entire vscode folder
|
|
204
|
+
# .vscode/
|
|
205
|
+
# Temporary file for partial code execution
|
|
206
|
+
tempCodeRunnerFile.py
|
|
207
|
+
|
|
208
|
+
# Ruff stuff:
|
|
209
|
+
.ruff_cache/
|
|
210
|
+
|
|
211
|
+
# PyPI configuration file
|
|
212
|
+
.pypirc
|
|
213
|
+
|
|
214
|
+
# Marimo
|
|
215
|
+
marimo/_static/
|
|
216
|
+
marimo/_lsp/
|
|
217
|
+
__marimo__/
|
|
218
|
+
|
|
219
|
+
# Streamlit
|
|
220
|
+
.streamlit/secrets.toml
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `whatmodel <name>...` explains Ollama names, Hugging Face repos and GGUF file names in plain English.
|
|
13
|
+
- Layer 1 reads the name offline: family and version, publisher, size, effective size, active parameters, tier, tuning, quantization, format, context, build stamps and hosting.
|
|
14
|
+
- Unknown tokens are reported as unknown, and ambiguous tokens and name formats show every reading.
|
|
15
|
+
- Layer 2 looks up quantization, context length, parameter count, architecture, tool, vision and thinking support, license and file size from the local Ollama API and the Hugging Face Hub API.
|
|
16
|
+
- `whatmodel list` explains every model installed in local Ollama.
|
|
17
|
+
- `whatmodel tokens` prints the token dictionary.
|
|
18
|
+
- Flags `--json`, `--offline`, `--ollama-url`, `--verbose` and `--version`.
|
|
19
|
+
- Library API: `parse()` and `explain()`.
|
|
20
|
+
- Token dictionary in `whatmodel/tokens.yaml`, the only place token meanings live.
|
|
21
|
+
- CI on Python 3.10 to 3.13 across Linux, macOS and Windows.
|
|
22
|
+
- Release workflow that publishes to PyPI with Trusted Publishing when a GitHub Release is published.
|
|
23
|
+
|
|
24
|
+
[Unreleased]: https://github.com/ShekharBhardwaj/whatmodel/commits/main
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
The most useful contribution is a new token. Every meaning whatmodel knows lives in [`whatmodel/tokens.yaml`](whatmodel/tokens.yaml), and adding one needs no Python.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/ShekharBhardwaj/whatmodel
|
|
9
|
+
cd whatmodel
|
|
10
|
+
uv sync
|
|
11
|
+
uv run pytest
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Add a token in three steps
|
|
15
|
+
|
|
16
|
+
1. Run the name that confused you and note what is reported as `Unknown`:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
uv run whatmodel olmo-2:7b --offline
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
2. Add an entry to `whatmodel/tokens.yaml`, next to the other entries of its category:
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
- pattern: olmo
|
|
26
|
+
category: family
|
|
27
|
+
label: OLMo
|
|
28
|
+
maker: Allen Institute for AI
|
|
29
|
+
explanation: The open language model family from the Allen Institute for AI.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
3. Run the checks and look at the result:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
uv run pytest
|
|
36
|
+
uv run whatmodel olmo-2:7b --offline
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Label the pull request `tokens` so it lands under "New tokens" in the release notes.
|
|
40
|
+
|
|
41
|
+
## Entry fields
|
|
42
|
+
|
|
43
|
+
| Field | Required | Meaning |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `pattern` | yes | A literal, or a list of literals that mean the same thing. With `regex: true`, a regular expression. |
|
|
46
|
+
| `category` | yes | One of the ids under `categories` at the top of the file. |
|
|
47
|
+
| `label` | yes | The short phrase shown in the output. Keep it under 60 characters. |
|
|
48
|
+
| `explanation` | yes | One plain-English sentence, ending in a full stop. |
|
|
49
|
+
| `regex` | no | `true` when `pattern` is a regular expression. |
|
|
50
|
+
| `examples` | for regex entries | Tokens the pattern must match. The tests check them, and `whatmodel tokens` prints them instead of the raw regex. |
|
|
51
|
+
| `value` | no | The normalized value for JSON and the library, such as `4B` for `4b`. Defaults to the literal as written, or to the matched token for a regex. |
|
|
52
|
+
| `after` | no | Match only directly after a token of the named category. |
|
|
53
|
+
| `maker` | no | Family entries only: who makes the family. Shown as `Gemma 4 (Google)`. |
|
|
54
|
+
| `implies` | no | A fact in another category that this token settles, such as `{architecture: moe}`. |
|
|
55
|
+
|
|
56
|
+
`label`, `explanation` and `value` may use `{text}` (the matched token, lowercased) and any named regex group. Add `!u` to uppercase one: `{text!u}`.
|
|
57
|
+
|
|
58
|
+
## How matching works
|
|
59
|
+
|
|
60
|
+
- Case is ignored. `Q4_K_M` and `q4_k_m` are the same token.
|
|
61
|
+
- `-`, `_` and `.` are all separators, and they are interchangeable. A dot between two digits is a decimal point, so `3.5` stays whole.
|
|
62
|
+
- A pattern must match a whole token. `mini` does not match inside `minicpm`.
|
|
63
|
+
- Multi-part patterns match across separators. Write literals the way they usually appear (`gpt-oss`). In a regex, write `_` wherever the name has a separator (`q4_k_m`).
|
|
64
|
+
- When a name can be split more than one way, the split with the fewest unknown parts wins, then the one with the fewest tokens. That is why `mistral-small` beats `mistral` followed by `small`.
|
|
65
|
+
- A known family glued to a version, as in `qwen3.5`, is split into the two. This only happens when the family is in the dictionary.
|
|
66
|
+
|
|
67
|
+
## Regex entries
|
|
68
|
+
|
|
69
|
+
Use a regex when a token carries a number:
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
- pattern: '(?P<n>\d+(?:\.\d+)?)b'
|
|
73
|
+
regex: true
|
|
74
|
+
category: size
|
|
75
|
+
value: '{n}B'
|
|
76
|
+
label: '{n}B parameters'
|
|
77
|
+
explanation: About {n} billion parameters (learned weights), where more usually means more capable but slower and hungrier for memory.
|
|
78
|
+
examples: [4b, 12B, 1.5b]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Put the pattern in single quotes so YAML leaves the backslashes alone. Quote examples that look like numbers (`'2507'`).
|
|
82
|
+
|
|
83
|
+
## Rules for entries
|
|
84
|
+
|
|
85
|
+
These keep the output trustworthy. The test suite enforces most of them.
|
|
86
|
+
|
|
87
|
+
- **Say only what the token always means.** If a token means different things in different names, either leave it out or add both meanings (see below).
|
|
88
|
+
- **Never make whatmodel guess.** If two entries match the same token, it is reported as ambiguous with both readings. That is the right outcome for a token such as `base` (a model without chat tuning, or the standard size). It is the wrong outcome if it happens by accident, so the tests fail on any overlap that is not listed in `INTENDED_AMBIGUOUS` in `tests/test_dictionary.py`.
|
|
89
|
+
- **One sentence per explanation**, in plain English. Explain jargon instead of repeating it.
|
|
90
|
+
- **Use `after` for tokens that only make sense in context.** A bare number is a version only right after a family, so that entry has `after: family`.
|
|
91
|
+
- **Use `implies` when a token settles something in another category.** `A3B` implies `architecture: moe`. A hosted-only family implies `hosting: cloud`. The implied token must be an entry in that category.
|
|
92
|
+
- **Facts must be checkable.** For a family, name the maker. For a publisher who converts other teams' models, say so.
|
|
93
|
+
|
|
94
|
+
## Adding a category
|
|
95
|
+
|
|
96
|
+
Add it under `categories` with a `heading` and a one-sentence `description`. Categories that share a heading share an output row, and their order in the file is the display order. A category may also have a `default`, shown when no token in the name belongs to it.
|
|
97
|
+
|
|
98
|
+
## Changing code
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
uv run ruff check
|
|
102
|
+
uv run ruff format
|
|
103
|
+
uv run pytest
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- Token meanings never go in Python. If a change needs a new word of explanation, it belongs in `tokens.yaml`.
|
|
107
|
+
- Tests must not use the network. `tests/conftest.py` blocks every socket, including localhost, so lookup tests use `httpx.MockTransport`.
|
|
108
|
+
- Type hints are required everywhere; ruff checks this.
|
|
109
|
+
|
|
110
|
+
Releases are described in [RELEASING.md](RELEASING.md).
|
whatmodel-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shekhar
|
|
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.
|
whatmodel-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: whatmodel
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Explain LLM model names in plain English.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ShekharBhardwaj/whatmodel
|
|
6
|
+
Project-URL: Repository, https://github.com/ShekharBhardwaj/whatmodel
|
|
7
|
+
Project-URL: Issues, https://github.com/ShekharBhardwaj/whatmodel/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/ShekharBhardwaj/whatmodel/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Shekhar
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: cli,gguf,huggingface,llm,lm-studio,model-names,ollama
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
24
|
+
Classifier: Topic :: Utilities
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Requires-Dist: httpx>=0.27
|
|
28
|
+
Requires-Dist: pyyaml>=6.0
|
|
29
|
+
Requires-Dist: rich>=13.7
|
|
30
|
+
Requires-Dist: typer>=0.12
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# whatmodel
|
|
34
|
+
|
|
35
|
+
Explain LLM model names in plain English: give it `gemma4:e2b-it-qat` and it tells you what each part means, plus the facts the name leaves out.
|
|
36
|
+
|
|
37
|
+
It reads names from Ollama, Hugging Face and GGUF files. There are no LLM calls: every explanation comes from a plain data file and from model metadata.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
uv tool install whatmodel
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or run it once without installing:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uvx whatmodel qwen3.5:4b
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`pip install whatmodel` works too. Python 3.10 or newer.
|
|
52
|
+
|
|
53
|
+
## Examples
|
|
54
|
+
|
|
55
|
+
The outputs below are pasted from real runs.
|
|
56
|
+
|
|
57
|
+
### An Ollama name
|
|
58
|
+
|
|
59
|
+
```console
|
|
60
|
+
$ whatmodel gemma4:e2b-it-qat
|
|
61
|
+
|
|
62
|
+
gemma4:e2b-it-qat
|
|
63
|
+
┌──────────────┬────────────────────────────────────┬──────────────┐
|
|
64
|
+
│ Field │ Value │ Source │
|
|
65
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
66
|
+
│ Family │ Gemma 4 (Google) │ name │
|
|
67
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
68
|
+
│ Size │ effective 2B parameters │ name │
|
|
69
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
70
|
+
│ Tuning │ instruction tuned (ready for chat) │ name │
|
|
71
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
72
|
+
│ Compression │ quantization-aware trained │ name │
|
|
73
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
74
|
+
│ Runs │ locally │ name │
|
|
75
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
76
|
+
│ Parameters │ 4.6B │ local Ollama │
|
|
77
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
78
|
+
│ Compression │ 4-bit (Q4_0) │ local Ollama │
|
|
79
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
80
|
+
│ Architecture │ dense │ local Ollama │
|
|
81
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
82
|
+
│ Context │ 128k tokens │ local Ollama │
|
|
83
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
84
|
+
│ Tools │ yes │ local Ollama │
|
|
85
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
86
|
+
│ Vision │ yes │ local Ollama │
|
|
87
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
88
|
+
│ Thinking │ yes │ local Ollama │
|
|
89
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
90
|
+
│ License │ Apache License, Version 2.0 │ local Ollama │
|
|
91
|
+
├──────────────┼────────────────────────────────────┼──────────────┤
|
|
92
|
+
│ File size │ 4.3 GB │ local Ollama │
|
|
93
|
+
└──────────────┴────────────────────────────────────┴──────────────┘
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The Source column says where each row came from: `name` rows are read from the name alone, and the rest are looked up, here from the Ollama running on the same machine.
|
|
97
|
+
|
|
98
|
+
### A Hugging Face repo
|
|
99
|
+
|
|
100
|
+
```console
|
|
101
|
+
$ whatmodel bartowski/Qwen_Qwen3-30B-A3B-GGUF
|
|
102
|
+
|
|
103
|
+
bartowski/Qwen_Qwen3-30B-A3B-GGUF
|
|
104
|
+
┌──────────────┬────────────────────────────────────────────┬──────────────┐
|
|
105
|
+
│ Field │ Value │ Source │
|
|
106
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
107
|
+
│ Publisher │ bartowski (community GGUF conversions) │ name │
|
|
108
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
109
|
+
│ Family │ Qwen 3 (Alibaba) │ name │
|
|
110
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
111
|
+
│ Size │ 30B parameters, 3B active per token │ name │
|
|
112
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
113
|
+
│ Architecture │ mixture of experts │ name │
|
|
114
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
115
|
+
│ Format │ GGUF (for llama.cpp, Ollama and LM Studio) │ name │
|
|
116
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
117
|
+
│ Runs │ locally │ name │
|
|
118
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
119
|
+
│ Parameters │ 30.5B │ Hugging Face │
|
|
120
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
121
|
+
│ Context │ 32k tokens │ Hugging Face │
|
|
122
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
123
|
+
│ Tools │ yes (judged from the chat template) │ Hugging Face │
|
|
124
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
125
|
+
│ License │ apache-2.0 │ Hugging Face │
|
|
126
|
+
├──────────────┼────────────────────────────────────────────┼──────────────┤
|
|
127
|
+
│ File size │ 8.1 GB to 39.7 GB, 28 GGUF files │ Hugging Face │
|
|
128
|
+
└──────────────┴────────────────────────────────────────────┴──────────────┘
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### A GGUF file name
|
|
132
|
+
|
|
133
|
+
```console
|
|
134
|
+
$ whatmodel Llama-3-8B-Instruct.Q4_K_M.gguf
|
|
135
|
+
|
|
136
|
+
Llama-3-8B-Instruct.Q4_K_M.gguf
|
|
137
|
+
┌─────────────┬────────────────────────────────────────────┬────────┐
|
|
138
|
+
│ Field │ Value │ Source │
|
|
139
|
+
├─────────────┼────────────────────────────────────────────┼────────┤
|
|
140
|
+
│ Family │ Llama 3 (Meta) │ name │
|
|
141
|
+
├─────────────┼────────────────────────────────────────────┼────────┤
|
|
142
|
+
│ Size │ 8B parameters │ name │
|
|
143
|
+
├─────────────┼────────────────────────────────────────────┼────────┤
|
|
144
|
+
│ Tuning │ instruction tuned (ready for chat) │ name │
|
|
145
|
+
├─────────────┼────────────────────────────────────────────┼────────┤
|
|
146
|
+
│ Compression │ 4-bit (Q4_K_M, the balanced variant) │ name │
|
|
147
|
+
├─────────────┼────────────────────────────────────────────┼────────┤
|
|
148
|
+
│ Format │ GGUF (for llama.cpp, Ollama and LM Studio) │ name │
|
|
149
|
+
├─────────────┼────────────────────────────────────────────┼────────┤
|
|
150
|
+
│ Runs │ locally │ name │
|
|
151
|
+
└─────────────┴────────────────────────────────────────────┴────────┘
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
A file name has nothing to look up, so every row comes from the name.
|
|
155
|
+
|
|
156
|
+
## Usage
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
whatmodel <name> explain one name
|
|
160
|
+
whatmodel <name> <name>... explain several
|
|
161
|
+
whatmodel list explain every model installed in local Ollama
|
|
162
|
+
whatmodel tokens print the token dictionary
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
| Flag | What it does |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `--json` | Print JSON. One name gives an object, several names give a list. |
|
|
168
|
+
| `--offline` | Read the name only and make no network requests. |
|
|
169
|
+
| `--ollama-url URL` | Where Ollama listens. Defaults to `http://localhost:11434`, or `OLLAMA_HOST` if set. |
|
|
170
|
+
| `--verbose`, `-v` | Add a column with a one-sentence explanation of each row. |
|
|
171
|
+
| `--version` | Print the version. |
|
|
172
|
+
|
|
173
|
+
Accepted name formats:
|
|
174
|
+
|
|
175
|
+
- Ollama: `[host/][namespace/]model[:tag]`, for example `qwen3.5:4b` or `hf.co/bartowski/Qwen_Qwen3-30B-A3B-GGUF:Q4_K_M`
|
|
176
|
+
- Hugging Face: `org/repo`, or a pasted `https://huggingface.co/org/repo` link
|
|
177
|
+
- File names: `Llama-3-8B-Instruct.Q4_K_M.gguf`, with or without a folder in front
|
|
178
|
+
|
|
179
|
+
A model that happens to be called `list` or `tokens` can be explained with `whatmodel explain list`.
|
|
180
|
+
|
|
181
|
+
### Unknown and ambiguous tokens
|
|
182
|
+
|
|
183
|
+
whatmodel never guesses. A token that is not in its dictionary is reported as unknown. A token with two possible meanings is shown with both:
|
|
184
|
+
|
|
185
|
+
```console
|
|
186
|
+
$ whatmodel qwen-max-0725 --offline
|
|
187
|
+
|
|
188
|
+
qwen-max-0725
|
|
189
|
+
┌───────────┬───────────────────────────────────────┬────────┐
|
|
190
|
+
│ Field │ Value │ Source │
|
|
191
|
+
├───────────┼───────────────────────────────────────┼────────┤
|
|
192
|
+
│ Family │ Qwen (Alibaba) │ name │
|
|
193
|
+
├───────────┼───────────────────────────────────────┼────────┤
|
|
194
|
+
│ Tier │ max tier (the most capable option) │ name │
|
|
195
|
+
├───────────┼───────────────────────────────────────┼────────┤
|
|
196
|
+
│ Build │ latest (the default build) │ name │
|
|
197
|
+
├───────────┼───────────────────────────────────────┼────────┤
|
|
198
|
+
│ Runs │ locally │ name │
|
|
199
|
+
├───────────┼───────────────────────────────────────┼────────┤
|
|
200
|
+
│ Ambiguous │ 0725: dated 07-25 (month-day) [build] │ name │
|
|
201
|
+
│ │ or released 2025-07 [build] │ │
|
|
202
|
+
└───────────┴───────────────────────────────────────┴────────┘
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
The same applies to a name such as `org/model` with no tag, which fits both a Hugging Face repo and an Ollama model. Both readings are named unless a lookup settles which one it is.
|
|
206
|
+
|
|
207
|
+
### Where the facts come from
|
|
208
|
+
|
|
209
|
+
The lookup step tries two sources in order and merges them:
|
|
210
|
+
|
|
211
|
+
1. The local Ollama API (`/api/show` and `/api/tags`), for models you have installed.
|
|
212
|
+
2. The Hugging Face Hub API, for names that contain `org/repo`.
|
|
213
|
+
|
|
214
|
+
Timeouts are short. A source that is offline, slow, or does not know the model is skipped, and the name is still explained. In JSON every item carries a `source` of `name`, `ollama` or `huggingface`, and `lookups` reports what happened with each source.
|
|
215
|
+
|
|
216
|
+
## Library
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from whatmodel import parse, explain
|
|
220
|
+
|
|
221
|
+
parsed = parse("qwen3.5:4b") # the name only, no network
|
|
222
|
+
parsed.family, parsed.version, parsed.size # ('qwen', '3.5', '4B')
|
|
223
|
+
parsed.unknown # tokens the dictionary does not know
|
|
224
|
+
|
|
225
|
+
info = explain("qwen3.5:4b") # the name plus lookups
|
|
226
|
+
info.facts # looked-up facts, each with its source
|
|
227
|
+
info.to_dict() # the same data --json prints
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
`explain(name, offline=True)` makes no requests at all.
|
|
231
|
+
|
|
232
|
+
## What the name cannot tell you
|
|
233
|
+
|
|
234
|
+
A model name is a label chosen by whoever published it. Even a fully understood name leaves these open, which is what the lookup step is for:
|
|
235
|
+
|
|
236
|
+
- **The exact compression.** `qat` says how a model was trained, not how many bits it uses. A bare tag such as `:4b` says nothing about compression at all.
|
|
237
|
+
- **What `latest` points to.** It is a moving pointer. The size and compression behind it can change.
|
|
238
|
+
- **The real parameter count.** `4b` is a rounded label. The model above is called `e2b` and has 4.6 billion parameters.
|
|
239
|
+
- **Context length.** Rarely in the name, and the usable value also depends on how the model is run.
|
|
240
|
+
- **Capabilities.** Tool calling, vision and thinking are usually not in the name.
|
|
241
|
+
- **The license.** Never in the name.
|
|
242
|
+
- **Who trained it.** The publisher in `org/repo` is often a third party who converted the model.
|
|
243
|
+
- **File size and memory needs.** These depend on compression and format. whatmodel reports file size when a source has it and does not estimate whether a model fits your hardware.
|
|
244
|
+
|
|
245
|
+
And some things no lookup settles: a name does not tell you how good a model is.
|
|
246
|
+
|
|
247
|
+
## Adding a token
|
|
248
|
+
|
|
249
|
+
Every meaning whatmodel knows lives in one file, [`whatmodel/tokens.yaml`](whatmodel/tokens.yaml). No Python is needed to teach it a new token:
|
|
250
|
+
|
|
251
|
+
```yaml
|
|
252
|
+
- pattern: olmo
|
|
253
|
+
category: family
|
|
254
|
+
label: OLMo
|
|
255
|
+
maker: Allen Institute for AI
|
|
256
|
+
explanation: The open language model family from the Allen Institute for AI.
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Then check it:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
uv run pytest
|
|
263
|
+
uv run whatmodel olmo-2:7b --offline
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) covers patterns, regex entries and the rules entries must follow.
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT. See [LICENSE](LICENSE).
|