Add mergekit-check-compat pre-merge compatibility checker - #688
Conversation
|
All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
Adds a new CLI tool that loads model configs and tokenizers (no weights, no GPU required) and reports structured errors/warnings before a merge begins, so incompatibilities are caught early rather than mid-merge or in corrupt outputs. Checks performed: - Tensor shape params (hidden_size, num_layers, num_heads, intermediate_size) → ERROR if any differ; merge will fail at weight level - model_type mismatch → WARNING; shapes may match but semantics may not - RoPE theta and rope_scaling divergence → WARNING - Vocabulary size mismatch with FIM token drop advice → WARNING - FIM token presence in one model but not others → WARNING - Chat template / instruct-model mixing → INFO Handles multimodal wrapper configs (e.g. Mistral3, LLaVA) by transparently unwrapping text_config when top-level arch params are absent. Also handles rope_theta embedded inside rope_scaling dicts (Ministral3 style).
…atus symbol - _get_rope_theta: remove unreachable-code structure; check rope_scaling dict first (Ministral3 style) then fall back via getattr to avoid returning a class-level default as if it were a real config value - _format_table: use ✗ for shape-param mismatches (ERROR level) and ⚠ for all others; introduce _SHAPE_PARAMS frozenset shared between check_architecture and _format_table so the sets can't drift
d557f25 to
27b8d04
Compare
- None values no longer silently pass mismatch checks: shape param and RoPE theta comparisons now fire when one model has a value and another has None (missing field), rather than treating None as a match. _format_table also includes N/A as a distinct value for the status symbol, so a mixed None/non-None row shows ⚠/✗ instead of ✓. - check_vocab now accepts tokenizer_source and suppresses the truncation WARNING (emits INFO instead) when tokenizer_source is "union", since no truncation occurs in that mode. main() derives the effective source from either the legacy tokenizer_source field or the newer tokenizer.source field and passes it through.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit aae614d. Configure here.
| "functions, attention variants, or normalization — merged weights may " | ||
| "be semantically incoherent even if tensor shapes match.", | ||
| ) | ||
| ) |
There was a problem hiding this comment.
Missing model_type partial mismatch
Medium Severity
model_type compatibility only flags cases where two or more distinct non-null types appear. When one model reports a type and another is missing (None/N/A), no WARNING is added, unlike tensor shape checks. The table may still show a warning marker without a matching Issues entry.
Reviewed by Cursor Bugbot for commit aae614d. Configure here.


Summary
Adds
mergekit-check-compat, a new CLI that validates model compatibility before a merge runs — loading only configs and tokenizers, no weights, no GPU required.hidden_size,num_hidden_layers,num_attention_heads,num_key_value_heads,intermediate_size) →ERRORif any differ; merge will fail at the weight levelmodel_typemismatch →WARNING; shapes may be compatible but architecture semantics may differ (activation functions, attention variants, norm placement)WARNING; positional encoding mismatch degrades coherence, especially at longer sequence lengthsWARNINGwith advice to usetokenizer_source: unionor resize embeddings; notes FIM token drop if applicableWARNINGINFOVerdict line exits with code
1on any ERROR,0otherwise.Multimodal config support
Multimodal wrapper configs (e.g.
Mistral3ForConditionalGeneration, LLaVA-style) store architecture params under atext_configsub-object rather than at the top level. The checker transparently unwrapstext_configwhen top-level arch params are absent, so models like Mistral Medium 3.5 report real values instead ofN/A. Also handlesrope_thetaembedded insiderope_scalingdicts (Ministral3 style).Example output
Test plan
mergekit-check-compat config.ymlruns without downloading weightsERRORand exit code1model_type-only mismatch (same shapes) producesWARNING, notERRORN/ANote
Low Risk
New read-only diagnostic script and console entry point; no changes to merge execution or model loading paths used during actual merges.
Overview
Adds
mergekit-check-compat, a CLI that reads a merge YAML config and validates referenced models before any weight merge—only configs and tokenizers are loaded.It prints a side-by-side compatibility table and severity-tagged issues for tensor shape params (ERROR on mismatch), model_type, RoPE theta / rope_scaling, vocab size (with awareness of
tokenizer_source: union), FIM tokens, and chat templates. A final verdict exits with code 1 only when ERROR-level issues are present.Multimodal configs are handled by unwrapping
text_configwhen top-level arch fields are missing, andrope_thetainsiderope_scalingis read when needed. The command is registered inpyproject.tomlasmergekit-check-compat.Reviewed by Cursor Bugbot for commit aae614d. Bugbot is set up for automated code reviews on this repo. Configure here.