Class ChatModelShape
The decoder geometry the memory budget is computed from. A preset declares it - the budget has
to refuse before 1.24 GB is mapped, and reading the shape at load time is too late -
and the loader cross-checks the declaration against the provisioned genai_config.json
field by field, so a republished model folder is
ChatModelShapeMismatch rather than a wrong budget.
public sealed record ChatModelShape : IEquatable<ChatModelShape>
- Inheritance
-
ChatModelShape
- Implements
- Inherited Members
Properties
- ContextLength
model.context_length. The hard ceiling onsearch.max_length.
- DecoderFileName
model.decoder.filename.
- HeadSize
model.decoder.head_size.
- KvCacheBytesPerElement
Bytes per KV cache element. Default 2 (fp16).
This is the one field the cross-check cannot validate.
genai_config.jsonstates layers, KV heads and head size but says nothing about the KV dtype, so a disagreement here is undetectable at load and shows up only as a budget that is wrong by a factor of two. 2 is the calibrated default, not a guess: forLlama32_1BInstructInt4it puts the arithmetic within 1.2% of a measured 1280 MiB peak, where 4 would put it 11% over. Spec section 19 item 4 is the nightly measurement that answers it per preset, and MeasuredPeakBytes is what absorbs the error meanwhile.
- KvCacheBytesPerToken
layers x 2 (K and V) x kvHeads x headSize x bytesPerElement.
- MeasuredOn
What device and runtime MeasuredPeakBytes came from. Never a guess.
It is a diagnostics string and nothing else: spec section 9.3's formula reads MeasuredPeakBytes alone and cannot discount a measurement by provenance. So the rule is on the way in, not on the way out - MeasuredPeakBytes is set only from a measurement taken on a device of the class the preset is meant to run on. A server or laptop peak is recorded here with MeasuredPeakBytes left null, which is what
Qwen3_600MInt4does with its published Graviton figure.
- MeasuredPeakBytes
A peak RSS measured on a real device at ContextLength, or null. When present and PreferMeasuredPeak is set, the budget takes
max(arithmetic, measured + ReserveBytes)- spec section 9.3 is the normative formula - and records which term bound in UsedMeasuredPeak. The reserve is added to the measured term because a measured peak is the model's own resident footprint and carries no headroom for the rest of the app. Pure arithmetic underestimates large-vocabulary models badly - Gemma-3-1b computes ~929 MiB and measures 1502 MiB - so a preset without a measurement is running on arithmetic alone and the diagnostics block says so.For both shipped presets this term is inert today, and that is stated rather than implied.
Llama32_1BInstructInt4's measured 1280 MiB plus a 192 MiB reserve is 1472 MiB, below its own arithmetic of 1679 MiB at 4096 tokens, so the arithmetic binds;Qwen3_600MInt4has no device measurement at all. The machinery exists for the case it was built for - a large-vocabulary preset whose arithmetic under-reports, which is exactly Gemma-3-1b - and spec section 19 item 3 is what would make it bind here.
- ModelType
model.type: "llama", "qwen3", "phi3". Diagnostics only.
- NumHiddenLayers
model.decoder.num_hidden_layers.
- NumKeyValueHeads
model.decoder.num_key_value_heads.
- SlidingWindow
model.decoder.sliding_windowwhen the model declares one; null otherwise.
- VocabSize
model.vocab_size.
- WeightsBytes
Resident weight estimate: the sum of the manifest's
GraphandGraphExternalDatafile sizes, and notTotalSizeBytes- a 17 MBtokenizer.jsonis not resident weights, and counting it would over-report by tens of megabytes inside a user-visible refusal message.
Methods
- FromGenAiConfig(string, long)
Reads the geometry out of a
genai_config.jsonbody.
- KvCacheBytes(int)
KV bytes for a context, clamped by SlidingWindow when the model declares one.
- TryFromGenAiConfig(string, long, out ChatModelShape?, out string?)
Reads the geometry out of a
genai_config.jsonbody without throwing.