# WhichLLM Model Normalization: Complete List of Suffixes Stripped from Model IDs

> Discover the 13 model suffixes WhichLLM strips for normalization including quantisation markers precision flags and variant tags to group related models.

- Repository: [andy/whichllm](https://github.com/Andyyyy64/whichllm)
- Tags: api-reference
- Published: 2026-06-09

---

**WhichLLM strips 13 regex-defined suffixes—including quantisation markers, precision flags, and variant tags—via the `_normalize_name` helper in [`src/whichllm/models/grouper.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/models/grouper.py) to group related models under a single family identifier.**

When working with the WhichLLM repository, model normalization is the critical first step that collapses variant-specific names into logical families. The private helper `_normalize_name` iterates over a hard-coded list of regular-expression suffixes, removing any that match the end of a model ID. This process ensures that quantised, instruction-tuned, or dated releases do not fragment the same base model across multiple groups.

## The `_normalize_name` Helper in [`src/whichllm/models/grouper.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/models/grouper.py)

The core of WhichLLM model normalization lives in [`src/whichllm/models/grouper.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/models/grouper.py). Inside this file, `_normalize_name` performs a regex-based stripping pass over incoming model identifiers.

Each suffix pattern is anchored to the end of the string with `$`, so only trailing components are removed. The function runs the substitution loop up to three times, catching suffixes that stack on top of one another.

### How the Suffix-Stripping Loop Works

The loop inside `_normalize_name` applies the following logic:

1. Compile the suffix regex list defined in the same module.
2. For each model ID, scan the list and delete the first matching suffix found at the end.
3. Repeat up to three iterations to dismantle stacked variants such as `model-gguf-fp16`.
4. Return the cleaned identifier for downstream grouping.

After suffix removal, additional normalization steps collapse embedded version fragments and standardise size tokens. For example, `mistral-small-3.2-24b` may be simplified to `mistral-small-24b` depending on the full ruleset in place.

### Full List of Removed Suffixes

The `_normalize_name` helper recognizes and removes these suffix patterns:

- `-gguf$` — GGUF format indicator (e.g., `llama-2-7b-gguf`)
- `-gptq$` — GPTQ quantisation (e.g., `mixtral-8x7b-gptq`)
- `-awq$` — AWQ quantisation (e.g., `phi-1.5-awq`)
- `-instruct$` — Instruction-tuned variant (e.g., `mistral-7b-instruct`)
- `-chat$` — Chat-oriented variant (e.g., `gemma-2b-chat`)
- `-it$` — Instruction shorthand (e.g., `deepseek-coder-it`)
- `-hf$` — HuggingFace-compatible fork (e.g., `stablelm-7b-hf`)
- `-fp8$` — 8-bit floating-point (e.g., `gemma-2b-fp8`)
- `-fp16$` — 16-bit floating-point (e.g., `gemma-2b-fp16`)
- `-bf16$` — BFloat16 precision (e.g., `gemma-2b-bf16`)
- `-nvfp4$` — NVIDIA 4-bit FP format (e.g., `gemma-2b-nvfp4`)
- `-\d+bit$` — Generic "X-bit" quantisation (e.g., `opt-125m-4bit`)
- `-\d{4}$` — Four-digit date or version tag (e.g., `qwen3-4b-2507`)

## Why WhichLLM Strips Model ID Suffixes

The purpose of WhichLLM model normalization is to treat different quantised or fine-tuned releases as members of the same logical family. Without this cleaning step, a benchmark dataset would treat `llama-2-7b-gguf` and `llama-2-7b-fp16` as unrelated entries.

By stripping these suffixes in [`src/whichllm/models/grouper.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/models/grouper.py), the higher-level `group_models` function can aggregate `ModelInfo` objects under a shared `family_id`. This behavior is essential for accurate grouping, benchmarking, and CLI display output.

## Code Examples: Normalizing and Grouping Models

You can call `_normalize_name` directly to preview the cleaning step:

```python
from whichllm.models.grouper import _normalize_name

# Raw model IDs from common repositories

raw_ids = [
    "llama-2-7b-gguf",
    "mixtral-8x7b-gptq",
    "gemma-2b-fp16",
    "qwen3-4b-2507",
    "deepseek-coder-instruct"
]

norm_names = [_normalize_name(mid) for mid in raw_ids]
print(norm_names)

# ['llama-2-7b', 'mixtral-8x7b', 'gemma-2b', 'qwen3-4b', 'deepseek-coder']

```

For production use, the public `group_models` API consumes `ModelInfo` objects and returns `ModelFamily` instances:

```python
from whichllm.models.grouper import group_models
from whichllm.models.types import ModelInfo

models = [
    ModelInfo(id="llama-2-7b-gguf", base_model=None),
    ModelInfo(id="llama-2-7b-fp16", base_model=None),
    ModelInfo(id="llama-2-7b", base_model=None)
]

families = group_models(models)
print(families[0].family_id)   # → "llama-2-7b"

```

## How Stacked Suffixes Are Handled

Some model IDs carry multiple variant markers simultaneously, such as `model-name-gguf-fp16`. The `_normalize_name` loop is intentionally capped at three passes to handle these stacked suffixes without over-processing.

Because the regex list is evaluated sequentially during each pass, the function removes the outermost suffix first, then continues inward. This design prevents fragmented families even when upstream repositories append multiple format or precision indicators.

## Related Files in the Normalization Pipeline

Several modules cooperate to deliver the final grouped output:

- **[`src/whichllm/models/grouper.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/models/grouper.py)** — Defines `_normalize_name` and the suffix list, and exposes `group_models`.
- **[`src/whichllm/models/types.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/models/types.py)** — Declares `ModelInfo` and `ModelFamily` data structures consumed by the grouper.
- **[`src/whichllm/cli.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/cli.py)** — Entry point that invokes `group_models` to present cleaned families to the user.

## Summary

- WhichLLM removes **13 regex-defined suffixes** during model normalization, covering quantisation, precision, variants, dates, and generic bit-width markers.
- The logic resides in **`_normalize_name`** inside [`src/whichllm/models/grouper.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/models/grouper.py).
- A **three-pass loop** dismantles stacked suffixes like `model-gguf-fp16`.
- Cleaned IDs feed directly into `group_models`, which aggregates `ModelInfo` records into unified `ModelFamily` objects.
- Supporting types live in [`src/whichllm/models/types.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/models/types.py), while the CLI orchestration happens in [`src/whichllm/cli.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/cli.py).

## Frequently Asked Questions

### What is the exact list of suffixes WhichLLM removes?

WhichLLM removes suffixes matching `-gguf$`, `-gptq$`, `-awq$`, `-instruct$`, `-chat$`, `-it$`, `-hf$`, `-fp8$`, `-fp16$`, `-bf16$`, `-nvfp4$`, `-\d+bit$`, and `-\d{4}$`. These patterns cover GGUF and GPTQ quantisation, chat or instruct variants, common precision flags, generic bit-width labels, and four-digit date or version tags.

### How does WhichLLM handle multiple suffixes on one model ID?

The `_normalize_name` helper runs its suffix-stripping loop up to three times. This multi-pass design removes stacked suffixes sequentially, so an identifier like `model-gguf-fp16` is fully cleaned to `model` before grouping occurs.

### Where is the model normalization logic implemented?

The normalization logic is implemented in [`src/whichllm/models/grouper.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/models/grouper.py). This file contains both the private `_normalize_name` function and the public `group_models` API that relies on it.

### Can I use WhichLLM's normalization function directly in my own code?

Yes. You can import `_normalize_name` from `whichllm.models.grouper` and apply it to raw model identifier strings. For full family aggregation, import `group_models` and pass it a list of `ModelInfo` objects as defined in [`src/whichllm/models/types.py`](https://github.com/Andyyyy64/whichllm/blob/main/src/whichllm/models/types.py).