Skip to content

Add mergekit-check-compat pre-merge compatibility checker - #688

Open
nloughl wants to merge 3 commits into
arcee-ai:mainfrom
nloughl:feat/pre-merge-compat-checker
Open

Add mergekit-check-compat pre-merge compatibility checker#688
nloughl wants to merge 3 commits into
arcee-ai:mainfrom
nloughl:feat/pre-merge-compat-checker

Conversation

@nloughl

@nloughl nloughl commented May 14, 2026

Copy link
Copy Markdown

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.

mergekit-check-compat config.yml
  • Tensor shape params (hidden_size, num_hidden_layers, num_attention_heads, num_key_value_heads, intermediate_size) → ERROR if any differ; merge will fail at the weight level
  • model_type mismatchWARNING; shapes may be compatible but architecture semantics may differ (activation functions, attention variants, norm placement)
  • RoPE theta / rope_scaling divergenceWARNING; positional encoding mismatch degrades coherence, especially at longer sequence lengths
  • Vocabulary size mismatchWARNING with advice to use tokenizer_source: union or resize embeddings; notes FIM token drop if applicable
  • FIM token presence in one model but not others → WARNING
  • Chat template / instruct-model mixingINFO

Verdict line exits with code 1 on any ERROR, 0 otherwise.

Multimodal config support

Multimodal wrapper configs (e.g. Mistral3ForConditionalGeneration, LLaVA-style) store architecture params under a text_config sub-object rather than at the top level. The checker transparently unwraps text_config when top-level arch params are absent, so models like Mistral Medium 3.5 report real values instead of N/A. Also handles rope_theta embedded inside rope_scaling dicts (Ministral3 style).

Example output

Model Compatibility Report
============================================================
                     Llama-2-7b-hf     CodeLlama-7b-hf   
hidden_size          4096              4096              ✓
num_hidden_layers    32                32                ✓
num_attention_heads  32                32                ✓
num_key_value_heads  32                32                ✓
intermediate_size    11008             11008             ✓
model_type           llama             llama             ✓
rope_theta           10000.0           1000000.0         ⚠
rope_scaling         none              none              ✓
vocab_size           32000             32016             ⚠
FIM tokens           No                Yes               ⚠
chat_template        No                No                ✓

Issues
----------------------------------------
[WARNING] RoPE theta mismatch (Llama-2-7b-hf=10000.0,
          CodeLlama-7b-hf=1000000.0). Positional encodings are
          incompatible; merged model will likely have degraded coherence,
          especially for longer outputs.

[WARNING] Vocabulary size mismatch (Llama-2-7b-hf=32000,
          CodeLlama-7b-hf=32016). MergeKit will truncate to the base
          model's vocab. FIM tokens (<PRE>, <MID>, <SUF>, <EOT>) in
          CodeLlama-7b-hf will be dropped. Consider: resize_tok_vocab.py
          or set `tokenizer_source: union` in config.

[WARNING] CodeLlama-7b-hf contains FIM tokens (<PRE>, <MID>, <SUF>,
          <EOT>) but other models do not. FIM tokens may appear in natural
          language completions after merging.

Verdict: MERGE POSSIBLE WITH WARNINGS

Test plan

  • mergekit-check-compat config.yml runs without downloading weights
  • Architecture shape mismatches produce ERROR and exit code 1
  • model_type-only mismatch (same shapes) produces WARNING, not ERROR
  • RoPE, vocab, FIM, and chat-template checks fire correctly
  • Multimodal wrapper configs (Mistral3, LLaVA) populate all rows without N/A

Note

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_config when top-level arch fields are missing, and rope_theta inside rope_scaling is read when needed. The command is registered in pyproject.toml as mergekit-check-compat.

Reviewed by Cursor Bugbot for commit aae614d. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented May 14, 2026

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

Comment thread mergekit/scripts/check_compat.py Outdated
Comment thread mergekit/scripts/check_compat.py Outdated
@nloughl

nloughl commented Jul 7, 2026

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

nloughl added 2 commits July 7, 2026 10:11
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
@nloughl
nloughl force-pushed the feat/pre-merge-compat-checker branch from d557f25 to 27b8d04 Compare July 7, 2026 14:12
Comment thread mergekit/scripts/check_compat.py Outdated
Comment thread mergekit/scripts/check_compat.py
- 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.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ 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.",
)
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit aae614d. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant