Safe By Design AI

Findings

Things worth knowing before you read a Granite configuration as though it were a description of the model. None of this is a defect in any model — every one of them works. They are places where the metadata says something other than what a careful reader would take it to mean, and each one is a trap somebody has to walk into once.

Every count below is recomputed from the published configurations and their digests each time this page is generated.

1. The class name does not always describe the stack

7 models declare GraniteMoeHybridForCausalLM and then list every layer as attention. There is no state-space layer in them. The hybrid class is the configuration family they were cut from, not a statement about what is in the model.

modellayersstack as listed
granite-4.0-1b4040 attention
granite-4.0-1b-base4040 attention
granite-4.0-350m2828 attention
granite-4.0-350m-base2828 attention
granite-4.0-micro4040 attention
granite-4.0-micro-base4040 attention
granite-guardian-4.0-3b-toxicity-ja4040 attention

The published layer_types table is the reliable fact. Grouping on the class name puts pure-attention models in the family whose whole point is that it is not one. Each of the first six shares its class and its nominal size with a hybrid twin, but not its geometry: granite-4.0-1b is 40 x 2048 where granite-4.0-h-1b is 40 x 1536, granite-4.0-350m is 28 x 1024 where granite-4.0-h-350m is 32 x 768, and granite-4.0-micro is 40 x 2560 where granite-4.0-h-micro is 40 x 2048. The class name does not separate them; the layer table does, and it is the field to read. The pairs are set out in generations.md.

2. Keys left behind by the template

11 models carry mamba_* geometry keys — state dimensions, convolution widths — with no state-space layer to use them. 17 declare num_local_experts: 0, an expert count on a model that has no experts.

Read literally, a reader is told a model is a mixture of experts with zero of them. Read as what it is — a field the template carried and this checkpoint does not use — it is harmless. A tool that branches on presence rather than on value gets this wrong.

3. One fact, several spellings

Granite spans several upstream codebases and each brought its own vocabulary for the same number.

factspellingmodels
depthnum_hidden_layers118
depthn_layer9
depthnum_layers5
depthencoder_num_layers1
widthhidden_size117
widthd_model8
widthn_embd7
widthembedding_feature_dim1
contextmax_position_embeddings117
contextn_positions7

Reading only the common spelling silently loses every model of the older code lineage. Depth is not always num_hidden_layers.

4. The geometry is not always in the same place

wheremodels
at the top level116
nowhere — no configuration published33
under text_config15
published, but no depth field6
under encoder_config2

A model with a language half nests under text_config. One without — an encoder that emits tokens directly — nests under encoder_config and has no text config at all. Looking in one place finds most models and misses a family.

5. Multi-query attention is declared by a flag

7 models set multi_query: true and publish no num_key_value_heads. Every query head shares one key/value head. A reader that infers grouping only from a head count records these as having no grouping at all, which is the exact opposite of the truth.

modelheadskey/value heads
granite-20b-code-base-8k481 (by flag)
granite-20b-code-base-r1.1481 (by flag)
granite-20b-code-instruct-8k481 (by flag)
granite-20b-code-instruct-r1.1481 (by flag)
granite-20b-functioncalling481 (by flag)
granite-34b-code-base-8k481 (by flag)
granite-34b-code-instruct-8k481 (by flag)

6. Many checkpoints are indistinguishable by configuration

16 groups of models publish a byte-identical config.json — the same sha256 in evidence/claims.json, so a reader can confirm each group from the digests alone. A base and an instruction-tuned model, a code base and its instruct variant, a revision and its predecessor, even two consecutive releases, are one architecture; the weights differ and nothing in the configuration does.

models sharing one configuration
GneissWeb.7B_ablation_model_on_350B_FineWeb.Edu.seed1, GneissWeb.7B_ablation_model_on_350B_FineWeb.Edu.seed2, GneissWeb.7B_ablation_model_on_350B_FineWeb.Edu.seed3, GneissWeb.7B_ablation_model_on_350B_FineWeb.seed1, GneissWeb.7B_ablation_model_on_350B_FineWeb.seed2, GneissWeb.7B_ablation_model_on_350B_FineWeb.seed3, GneissWeb.7B_ablation_model_on_350B_GneissWeb.seed1, GneissWeb.7B_ablation_model_on_350B_GneissWeb.seed2, GneissWeb.7B_ablation_model_on_350B_GneissWeb.seed3
granite-20b-code-base-8k, granite-20b-code-base-r1.1
granite-20b-code-instruct-8k, granite-20b-code-instruct-r1.1
granite-3.1-2b-instruct, granite-3.2-2b-instruct
granite-3b-code-base-2k, granite-3b-code-instruct-2k
granite-4.0-1b, granite-4.0-1b-base
granite-4.0-350m, granite-4.0-350m-base
granite-4.0-h-1b, granite-4.0-h-1b-base
granite-4.0-h-350m, granite-4.0-h-350m-base
granite-4.0-h-micro, granite-4.0-h-micro-base
granite-4.0-h-tiny, granite-4.0-h-tiny-base
granite-4.0-micro, granite-4.0-micro-base
granite-4.1-3b, granite-4.1-3b-base
granite-4.1-8b, granite-4.1-8b-base
granite-8b-code-base-4k, granite-8b-code-instruct-4k
granite-speech-5.0-470m-turboctc, granite-speech-5.0-470m-turboctc-nc

These are the groups that match byte for byte, provenance fields included. Setting aside fields that record how a file was written rather than what the model is — _name_or_path, transformers_version, torch_dtype — can only merge more: safety classifiers and adapter libraries that repeat their base's geometry are candidates. This bundle carries digests, not whole configurations, so it does not list those further groups rather than list them unchecked.

This is why nothing in this reference tries to pick "the" model for an architecture, and why the role column in models.md is derived from the name — it is the only place that distinction is recorded.

7. Context lengths are not all round numbers

tokensmodelsnote
131,07261= 128 x 1024
8,19224
4,09617
5147= 512 + 2 (RoBERTa-style position offset); every one is a RoBERTa or XLM-RoBERTa model
32,7686
128,0004= 125 x 1024, and universally called 128k
2,0482
5122
16,3841

Both values get called "128k". They differ by 3,072 tokens. This reference prints the number the configuration holds and leaves the naming alone.

8. Not every model publishes a configuration, and not every configuration has a depth

33 of 172 models have no config.json at all: adapters that ship only adapter weights, earth-observation releases with their own formats, and dataset-ablation artifacts. They are real published models and they cannot be described by the method used here, which is why they appear in models.md with dashes rather than being dropped.

A further 6 publish a configuration that simply has no layer count — the speculative-decoding heads, whose size is how many tokens they propose (n_predict) rather than how many layers they stack. A published configuration without a depth field is not a missing one, and counting the two together overstates how much of this catalogue is undocumented.