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.
@@ -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).
@@ -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.
@@ -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).