LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 196 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/9
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningBayesian Inference from EvidenceStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/15
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageStatistical Learning and GeneralizationConformal Prediction and UncertaintyClustering and PCAProbabilistic Generative ModelsCore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingCausal Inference and CounterfactualsPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/25
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernancePrivacy-Preserving Machine LearningData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/9
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned ClassifierCapstone: Reproducible ML Study
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/17
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabJAX for PyTorch ResearchersContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningTraining Run OperationsReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/31
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceAccelerator Architecture Field GuideCorrect GPU Profiling and BenchmarkingGPU Kernel Performance Engineering LabGPU Parallel Primitives LabGPU Compilers and Kernel LanguagesGEMM From Naive CUDA to Tensor CoresLow-Precision GPU ProgrammingGPU Runtime Execution LabAI-Generated Kernel EngineeringModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingGPU Failure OperationsDistributed Inference Data PlaneServing Benchmark EngineeringA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning Agent System Design
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
🔬Project Deep Dives0/17
Deep Dive - vLLMDeep Dive - SkyRLDeep Dive - FlashAttentionDeep Dive - FlashInferDeep Dive - DeepGEMMDeep Dive - NCCLDeep Dive - MegatronDeep Dive - DeepSpeedDeep Dive - RayDeep Dive - MLflowDeep Dive - PyTorchDeep Dive - TransformersDeep Dive - SGLangDeep Dive - slimeDeep Dive - DeepEPDeep Dive - TinkerDeep Dive - Light-PEFT
Back to Topics
LearnAdvanced Training & AdaptationModel Merging and Weight Interpolation
⚡HardFine-Tuning & Training

Model Merging and Weight Interpolation

Learn model merging techniques, from simple weight averaging and task arithmetic to TIES-Merging and DARE, including practical guidance on tokenizer compatibility, mergekit workflows, and evaluation.

31 min read
Learning path
Step 119 of 196 in the full curriculum
Knowledge Distillation for LLMsVector DB Internals: HNSW & IVF

Personalize this lesson

Adapt explanations and teaching visuals to your background and preferred voice.

Distillation trains a smaller student from teacher signal. Model merging starts later: you already have useful fine-tuned checkpoints and want one checkpoint without another gradient-based training run.

Picture your platform team serving three same-base 8B assistants: Code, Math, and Chat. Routing among them costs extra memory and makes rollback messier. The first merge writes successfully and reports an aggregate score of 87.2. Then the slice report arrives: code 92.4, math 82.1 against an 85.0 gate, and chat 87.0. Keeping one model would simplify routing, but this candidate stays blocked. The failed Math slice is the useful starting point: a file on disk proves construction, not retained behavior.

Before choosing a recipe, check whether coordinates still mean the same thing. If token ID 417 means return in one tokenizer but <fim_prefix> in another, averaging row 417 blends unrelated output symbols. Direct tensor interpolation needs compatible shapes and meanings, and embedding matrices plus language-model heads need an explicit tokenizer policy. Mergekit can build a union tokenizer and assign fallback embeddings for missing tokens, but that's an output-space choice that still needs evaluation.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit Same-base checkpoints are the conservative starting point because their parameter coordinates share lineage. Matching shapes alone doesn't make a merge good.

Keep Code, Math, and Chat as our running trio. We'll compare several recipes, from a plain average to sparse, conflict-aware task-vector merging. First ask whether a straight path through weight space is even usable.

When averaging weights is worth testing

If someone told you to average the internal numbers of two trained neural networks, skepticism is correct. The useful question is narrower: do these nearby checkpoints share a low-loss region? Weight averaging is plausible in some fine-tuning settings, but two good endpoints don't certify the points between them.

Fine-tuning moves a checkpoint from a shared starting point through weight space. Linear mode connectivity asks whether the straight path between endpoints crosses a high-loss barrier.[2]Reference 2Linear Mode Connectivity and the Lottery Ticket Hypothesis.https://arxiv.org/abs/1912.05671 Model Soups found useful averages in its evaluated vision and text-classification settings when models shared a pretrained initialization and differed in hyperparameters.[3]Reference 3Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Timehttps://arxiv.org/abs/2203.05482 That supports testing nearby same-lineage candidates. It doesn't show that Code and Math share one basin.

Evaluate points on θ(α)=(1−α)θA+αθB\theta(\alpha) = (1-\alpha)\theta_A + \alpha\theta_Bθ(α)=(1−α)θA​+αθB​ rather than assuming the midpoint is usable. Code and Math can each pass alone and still interfere along the path. Models with unrelated pretraining lineages are even poorer candidates because no common base preserved their parameter coordinates.

Now make the first prediction. If the Code and Math endpoints pass, does α=0.50\alpha=0.50α=0.50 pass too? The screen below treats interpolation measurements as evidence. In a real run, losses and task_scores come from held-out evaluations; these values are a worked Code-to-Math path whose midpoint misses both gates.

screen-measured-interpolation-path.py
1alphas = [0.00, 0.25, 0.50, 0.75, 1.00] 2losses = [0.18, 0.20, 0.61, 0.23, 0.19] 3task_scores = [0.88, 0.86, 0.70, 0.85, 0.89] 4 5max_accepted_loss = 0.30 6min_accepted_score = 0.84 7 8accepted = [ 9 alpha 10 for alpha, loss, score in zip(alphas, losses, task_scores) 11 if loss <= max_accepted_loss and score >= min_accepted_score 12] 13 14print("accepted_alphas:", accepted) 15print("midpoint_passes:", 0.50 in accepted)
Output
1accepted_alphas: [0.0, 0.25, 0.75, 1.0] 2midpoint_passes: False
Two interpolation-loss charts on the same 0 to 1 scale. Nearby same-task soup checkpoints stay low, about 0.18, 0.12, 0.09, 0.12, 0.19. The code-to-math specialist path matches the screening example: 0.18, 0.20, 0.61, 0.23, 0.19, with a high-loss ridge at alpha 0.50.
The right-hand path uses the screen's losses: 0.18, 0.20, 0.61, 0.23, 0.19. Shared lineage earns a path measurement, not a pass at the midpoint.

Same-base lineage: A shared base makes Code and Math worth testing together. It doesn't establish that either behavior survives. Per-task evaluation decides that.

The permutation invariance problem

Why can two networks that solve the same task disagree at nearly every coordinate? Neural networks can exhibit permutation invariance: under corresponding reordering of incoming and outgoing weights, hidden-unit permutations can preserve the function a network computes.[4]Reference 4The Role of Permutation Invariance in Linear Mode Connectivity of Neural Networks.https://arxiv.org/abs/2110.06296 A slot number is an address, not a feature identity, so independently trained networks may be poorly aligned for naive averaging.

Git Re-Basin[5]Reference 5Git Re-Basin: Merging Models modulo Permutation Symmetries.https://arxiv.org/abs/2209.04836 searches for a permutation π\piπ that aligns the hidden units of one model to the other before merging:

θmerged=12(θA+π(θB))\theta_{\text{merged}} = \frac{1}{2}(\theta_A + \pi(\theta_B))θmerged​=21​(θA​+π(θB​))

Use a tiny three-feature example to see the failure. Two checkpoints learn A, B, and C but store them in different slot orders. Here θB\theta_BθB​ stores B, C, A. Git Re-Basin searches for a permutation π\piπ that restores A, B, C before averaging.

Side-by-side hidden-unit tables. Naive averaging pairs slot 1 as feature A with feature B, slot 2 as B with C, and slot 3 as C with A. After permuting theta_B from B-C-A into A-B-C, matching features share a slot before the average.
Slot numbers aren't semantic IDs. Naive averaging mixes A with B in slot 1. After $\pi$, matching features share a slot, so the average combines corresponding units.

Git Re-Basin uses permutation matching and reports merged independently trained MLP, CNN, and ResNet models in its studied settings, including zero-barrier linear mode connectivity for sufficiently wide ResNets on CIFAR-10.[5]Reference 5Git Re-Basin: Merging Models modulo Permutation Symmetries.https://arxiv.org/abs/2209.04836 Alignment fixes one kind of coordinate mismatch. It isn't evidence that an arbitrary pair of large language models can be repaired and merged, so same-base candidates plus downstream evaluation remain our LLM default.

Why does Git Re-Basin apply π\piπ before averaging?

Answer

Two models can represent the same function with neurons in different orders. The permutation aligns corresponding neurons first, so averaging combines matching features instead of unrelated ones.

From simple averages to conflict-aware methods

The first screen asks whether coordinates line up. The next asks what to do when they do: average endpoints, add deltas, filter conflicts, or change interpolation geometry. Choose against source lineage, observed delta conflict, and the evaluations the output must pass.

MethodMechanismProsConsBest For
Model Soups / LinearUniform or weighted averagingSimple baselineInterference between conflicting parametersNearby checkpoints with representative evaluation
Task ArithmeticWeighted task vectorsSeparate coefficients per deltaCoefficients don't guarantee separate capabilities surviveSame-base task-vector experiments
TIES-Merging (Trim, Elect Sign, Merge)Trim and aggregate-sign filteringExplicitly handles conflicting delta signsDensity and scale need tuningConflicting same-base task vectors
DARE (sparsify first)Random dropping and rescaling of task vectorsSparse preprocessing evaluated by its paperNot a complete merge rule on its ownTesting DARE plus a downstream merge
SLERP (Spherical Linear Interpolation)Spherical interpolation in direction spaceHas a norm-preserving geometric interpretationGeometry alone doesn't establish task qualityPairwise interpolation experiment

Model soups (uniform averaging)

Start with the deliberately boring control: average the endpoint weights and see what behavior you lose. This is Model Soups[3]Reference 3Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Timehttps://arxiv.org/abs/2203.05482, applied to multiple fine-tuned models:

θmerged=1N∑i=1Nθi\theta_{\text{merged}} = \frac{1}{N} \sum_{i=1}^{N} \theta_iθmerged​=N1​∑i=1N​θi​

Predict the tiny example before reading the code. If checkpoint A has a weight 2.0 and checkpoint B has 4.0, equal averaging returns 3.0. The dictionaries below stand in for tensor slices, so the arithmetic is visible without loading a checkpoint. A single coordinate still can't tell you whether Code, Math, or Chat behavior survived.

Model Soups evaluates models fine-tuned from a shared initialization over hyperparameter configurations and reports improved accuracy and robustness in its studied settings without the inference cost of an ensemble.[3]Reference 3Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Timehttps://arxiv.org/abs/2203.05482 That evidence motivates a baseline for nearby candidates, not a blanket rule for specialists.

The original paper distinguishes two selection strategies. Uniform soups average all fine-tuned checkpoints with equal weight, which is simple but risky: one bad checkpoint can drag the average down. Greedy soups start from the best individual model and add a candidate only if the resulting average improves a held-out validation metric. In the reported experiments, greedy soups outperform uniform averaging because the selection rule skips candidates that hurt that validation metric.[3]Reference 3Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Timehttps://arxiv.org/abs/2203.05482 That rule is only as useful as the validation slices behind it.

uniform_merge averages matching keys. greedy_keep adds a candidate only when the trial soup score rises. Run it as a control before introducing task-vector filtering.

uniform-vs-greedy-soups.py
1def uniform_merge( 2 models: list[dict[str, list[float]]], 3 weights: list[float] | None = None, 4) -> dict[str, list[float]]: 5 if weights is None: 6 weights = [1.0 / len(models)] * len(models) 7 if abs(sum(weights) - 1.0) >= 1e-6: 8 raise ValueError("Weights must sum to 1") 9 10 merged: dict[str, list[float]] = {} 11 for key in models[0]: 12 merged[key] = [ 13 sum(w * m[key][i] for w, m in zip(weights, models)) 14 for i in range(len(models[0][key])) 15 ] 16 return merged 17 18def greedy_keep(names: list[str], trial_scores: list[float]) -> list[str]: 19 kept: list[str] = [] 20 best = float("-inf") 21 for name, score in zip(names, trial_scores): 22 if score > best: 23 kept.append(name) 24 best = score 25 return kept 26 27code_model = {"w": [2.0, 4.0], "bias": [1.0]} 28math_model = {"w": [4.0, 2.0], "bias": [3.0]} 29merged = uniform_merge([code_model, math_model]) 30kept = greedy_keep(["best", "X", "Y", "Z"], [88.0, 89.0, 87.0, 90.0]) 31 32print("weights_ok:", merged["w"] == [3.0, 3.0]) 33print("bias_ok:", merged["bias"] == [2.0]) 34print("merged w:", merged["w"]) 35print("merged bias:", merged["bias"]) 36print("greedy kept:", kept)
Output
1weights_ok: True 2bias_ok: True 3merged w: [3.0, 3.0] 4merged bias: [2.0] 5greedy kept: ['best', 'X', 'Z']

Averaging is cheap to implement and has no hyperparameters beyond optional weights. On our Code, Math, and Chat trio, a poor aggregate result tells you little about which task caused the loss. Conflicting parameters can cancel when specialists move in opposite directions. To keep those directions visible, the next recipe subtracts the shared base first.

Task arithmetic

The average baseline hides why specialists moved. Task arithmetic[6]Reference 6Editing Models with Task Arithmetichttps://arxiv.org/abs/2212.04089 keeps that reference point: a task vector is the difference between fine-tuned weights and the shared base model.

τi=θi−θ0(task vector for model i)\tau_i = \theta_i - \theta_0 \quad \text{(task vector for model } i \text{)}τi​=θi​−θ0​(task vector for model i)

θmerged=θ0+∑i=1Nλi⋅τi\theta_{\text{merged}} = \theta_0 + \sum_{i=1}^{N} \lambda_i \cdot \tau_iθmerged​=θ0​+∑i=1N​λi​⋅τi​

Here θ0\theta_0θ0​ is the base model, θi\theta_iθi​ are fine-tuned models, τi\tau_iτi​ are per-task deltas, and λi\lambda_iλi​ are merge weights.

A concrete scalar walkthrough

Before you run this on billion-parameter tensors, make one prediction on a single coordinate. Start with a base weight at 2.0. Code pushes it to 2.5, so its task vector is +0.5; Math pushes it to 1.5, so its task vector is -0.5. If Code gets λcode=0.6\lambda_{\text{code}} = 0.6λcode​=0.6 and Math gets λmath=0.4\lambda_{\text{math}} = 0.4λmath​=0.4, does the merged coordinate land above or below the base?

merged weight=2.0+0.6(0.5)+0.4(−0.5)=2.0+0.3−0.2=2.1\text{merged weight} = 2.0 + 0.6(0.5) + 0.4(-0.5) = 2.0 + 0.3 - 0.2 = 2.1merged weight=2.0+0.6(0.5)+0.4(−0.5)=2.0+0.3−0.2=2.1

The result, 2.1, is a net positive nudge at this coordinate. Averaging the absolute fine-tuned weights (2.5 and 1.5) would land at 2.0, cancelling both deltas here. The scalar doesn't predict capability retention. It shows what coefficients do before you inspect billions of such coordinates and then test the model.

Bar chart of one shared weight: base 2.0, code fine-tune 2.5, math fine-tune 1.5, absolute average 2.0, and task arithmetic with lambdas 0.6 and 0.4 landing at 2.1. Opposite specialist deltas cancel under averaging and survive as a directed nudge under task arithmetic.
On this coordinate, averaging the endpoints lands back at the base value 2.0. Task arithmetic with $\lambda_{\text{code}}=0.6$ and $\lambda_{\text{math}}=0.4$ keeps a directed nudge at 2.1.

Why did absolute averaging cancel the two specialist deltas in the scalar example?

Answer

The code-generation fine-tune moved this coordinate up by +0.5 and the math-reasoning fine-tune moved it down by -0.5. Averaging final weights lands this coordinate back at the base value, cancelling both deltas here. Task evaluation determines the broader behavioral effect.

A second coefficient pair exposes a tuning detail. Suppose Code nudges the coordinate to 2.4 (task vector +0.4) and Math nudges it to 1.8 (task vector -0.2). Setting λcode=0.7\lambda_{\text{code}} = 0.7λcode​=0.7 and λmath=0.5\lambda_{\text{math}} = 0.5λmath​=0.5 gives 2.0 + 0.28 - 0.10 = 2.18. The coefficients need not form a convex average; they scale deltas. Capability retention still comes from evaluation.

task_arithmetic_merge subtracts the base to get task vectors, scales them, and adds them back:

a-concrete-scalar-walkthrough.py
1def task_arithmetic_merge( 2 base_model: dict[str, list[float]], 3 fine_tuned_models: list[dict[str, list[float]]], 4 scaling_coefficients: list[float], 5) -> dict[str, list[float]]: 6 merged = {key: value[:] for key, value in base_model.items()} 7 for model, coeff in zip(fine_tuned_models, scaling_coefficients): 8 for key in merged: 9 merged[key] = [ 10 merged_value + coeff * (tuned - base) 11 for merged_value, tuned, base in zip( 12 merged[key], model[key], base_model[key] 13 ) 14 ] 15 return merged 16 17shared_base = {"w": [2.0]} 18code_ft = {"w": [2.5]} 19math_ft = {"w": [1.5]} 20merged = task_arithmetic_merge( 21 base_model=shared_base, 22 fine_tuned_models=[code_ft, math_ft], 23 scaling_coefficients=[0.6, 0.4], 24) 25 26print("base:", shared_base["w"][0]) 27print("matches_expected:", all(abs(v - expected) < 1e-6 for v, expected in zip(merged["w"], [2.1]))) 28print("merged:", round(merged["w"][0], 2))
Output
1base: 2.0 2matches_expected: True 3merged: 2.1

Scaling coefficients control how much of each task vector enters the candidate checkpoint. They don't resolve a coordinate where Code and Math ask for opposite directions. That conflict is the reason to move from task arithmetic to TIES.

TIES-Merging (trim, elect sign, merge)

Task arithmetic exposes conflict but doesn't resolve it. One specialist can increase a coordinate by 0.5 while another decreases it by 0.5. TIES-Merging[7]Reference 7TIES-Merging: Resolving Interference When Merging Modelshttps://arxiv.org/abs/2306.01708 turns that conflict into a three-step filter: trim small deltas, elect a sign from total signed movement, then average only values aligned with that sign.

The paper's PEFT analysis found that keeping the top 20% of magnitudes often matched keeping all values on its studied tasks.[7]Reference 7TIES-Merging: Resolving Interference When Merging Modelshttps://arxiv.org/abs/2306.01708 Treat that result as evidence for its settings. Trim is a noise filter, not a guaranteed compressor for a new LLM merge.

Use the three specialist rows in the figure as a prediction exercise. At p2, the two negative entries total -0.90, while the positive entry is +1.10. Which sign wins? Positive signed mass wins, and only the aligned +1.10 survives the disjoint merge. The resulting task vector still gets added back to the base, often with a global scale λ\lambdaλ.

TIES on four coordinates from code, math, and chat task vectors. After trim, p2 values are -0.50, +1.10, -0.40 with signed sum +0.20, so the elected sign is positive and the merged delta is +1.10. At p4 the signed sum is +0.90 and the aligned average is +0.75.
At p2, two negative deltas lose because signed mass is $+0.20$. TIES then keeps only $+1.10$. At p4 the aligned average of $+0.80$ and $+0.70$ is $+0.75$.

Step 1: Trim

Trim keeps the largest-magnitude fraction of each task vector. With four values and density=0.5, predict which two survive, then check the code: they are the two biggest absolute updates.

step-1-trim.py
1def trim(task_vector: list[float], density: float = 0.2) -> list[float]: 2 k = max(1, round(len(task_vector) * density)) 3 keep = set( 4 sorted(range(len(task_vector)), key=lambda i: abs(task_vector[i]), reverse=True)[:k] 5 ) 6 return [value if i in keep else 0.0 for i, value in enumerate(task_vector)] 7 8task_vector = [0.1, -0.5, 0.02, 0.8] 9trimmed = trim(task_vector, density=0.5) 10 11print("matches_expected:", trimmed == [0.0, -0.5, 0.0, 0.8]) 12print("trimmed:", trimmed)
Output
1matches_expected: True 2trimmed: [0.0, -0.5, 0.0, 0.8]

Step 2: Elect sign

When multiple task vectors update one parameter, TIES-Merging resolves conflicting directions with γmp=sgn(∑tτ^tp)\gamma_m^p = \mathrm{sgn}(\sum_t \hat{\tau}_t^p)γmp​=sgn(∑t​τ^tp​).[7]Reference 7TIES-Merging: Resolving Interference When Merging Modelshttps://arxiv.org/abs/2306.01708 Sum the trimmed signed deltas and take the resulting sign. This isn't a majority vote: one large update can outweigh two smaller opposing updates.

step-2-elect-sign.py
1def sign(value: float) -> float: 2 if value > 0: 3 return 1.0 4 if value < 0: 5 return -1.0 6 return 0.0 7 8def elect_sign(trimmed_vectors: list[list[float]]) -> list[float]: 9 width = len(trimmed_vectors[0]) 10 aggregate = [sum(vector[i] for vector in trimmed_vectors) for i in range(width)] 11 return [sign(total) for total in aggregate] 12 13trimmed_vectors = [ 14 [0.0, -0.5, 0.0, 0.8], 15 [0.0, 1.1, 0.0, -0.6], 16 [0.0, -0.4, 0.0, 0.7], 17] 18elected = elect_sign(trimmed_vectors) 19print("two_negative_votes_at_p2:", True) 20print("positive_mass_wins_at_p2:", elected[1] == 1.0) 21print("matches_expected:", elected == [0.0, 1.0, 0.0, 1.0]) 22print("elected signs:", elected)
Output
1two_negative_votes_at_p2: True 2positive_mass_wins_at_p2: True 3matches_expected: True 4elected signs: [0.0, 1.0, 0.0, 1.0]

Step 3: Disjoint merge

Now average only non-zero updates that agree with the elected sign. Trimmed zeros stay out of the mean, so a discarded proposal can't dilute the surviving direction:

step-3-disjoint-merge.py
1def sign(value: float) -> float: 2 if value > 0: 3 return 1.0 4 if value < 0: 5 return -1.0 6 return 0.0 7 8def disjoint_merge( 9 trimmed_vectors: list[list[float]], 10 elected_signs: list[float], 11) -> list[float]: 12 width = len(trimmed_vectors[0]) 13 merged = [0.0] * width 14 counts = [0.0] * width 15 for vector in trimmed_vectors: 16 for i, value in enumerate(vector): 17 agrees = ( 18 value != 0.0 19 and elected_signs[i] != 0.0 20 and sign(value) == elected_signs[i] 21 ) 22 if agrees: 23 merged[i] += value 24 counts[i] += 1.0 25 return [ 26 total / count if count > 0 else 0.0 27 for total, count in zip(merged, counts) 28 ] 29 30trimmed_vectors = [ 31 [0.0, -0.5, 0.0, 0.8], 32 [0.0, 1.1, 0.0, -0.6], 33 [0.0, -0.4, 0.0, 0.7], 34] 35elected_signs = [0.0, 1.0, 0.0, 1.0] 36merged = disjoint_merge(trimmed_vectors, elected_signs) 37 38print("matches_expected:", merged == [0.0, 1.1, 0.0, 0.75]) 39print("merged task vector:", merged)
Output
1matches_expected: True 2merged task vector: [0.0, 1.1, 0.0, 0.75]

TIES-Merging outperforms compared baselines in the paper's evaluated vision and T5 task-vector settings, and its analysis identifies sign interference.[7]Reference 7TIES-Merging: Resolving Interference When Merging Modelshttps://arxiv.org/abs/2306.01708 For our LLM trio, use it as a candidate when delta signs conflict. Keep plain task arithmetic in the comparison so any gain has a visible baseline.

DARE (drop and rescale)[8]Reference 8Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunchhttps://arxiv.org/abs/2311.03099

TIES chooses a direction among surviving updates. DARE asks a different question first: how many update entries need to survive at all? It randomly drops entries from each task vector and rescales the survivors before a downstream merge. Rescaling preserves an entry's expected delta under the random mask; it doesn't prove that the model preserves a capability.

The paper studies redundancy in supervised fine-tuning (SFT) deltas and reports that its evaluated models can often tolerate dropping 90% of delta entries, and in some cases 99%, before merging. Its size ablation reports that WizardMath-70B remains effective at a 99% drop rate while the evaluated 7B and 13B variants fail there.[8]Reference 8Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunchhttps://arxiv.org/abs/2311.03099 Treat that as evidence for the paper's SFT models, not as our trio's default density. DARE is a sparsification step, not a complete merge recipe: sparse task vectors still need a merger such as averaging or TIES.

DARE's analysis separates SFT deltas, which it observes are typically within roughly 0.002, from continued-pretraining deltas that approach 0.03; its drop-and-rescale approach becomes ineffective on the latter.[8]Reference 8Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunchhttps://arxiv.org/abs/2311.03099 One candidate pipeline is DARE-TIES: DARE sparsifies each delta, then TIES resolves directional conflicts among survivors. Mergekit exposes that composition as dare_ties.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit

τiDARE=τi⊙m1−p\tau_i^{\text{DARE}} = \frac{\tau_i \odot m}{1 - p}τiDARE​=1−pτi​⊙m​

where mmm is a random binary mask with drop rate ppp and the 1/(1−p)1/(1-p)1/(1−p) factor preserves each entry's expectation under masking.[8]Reference 8Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunchhttps://arxiv.org/abs/2311.03099

Why does DARE divide by 1−p1-p1−p after dropping weights?

Answer

Only a fraction 1−p1-p1−p of task-vector entries survive. Dividing by 1−p1-p1−p keeps each randomly masked delta entry unbiased in expectation; retained task quality still requires evaluation.

dare_sparsify applies a keep-mask and the 1/(1−p)1/(1-p)1/(1−p) rescale. DARE chooses its mask randomly; this example fixes the mask so you can check the arithmetic. With p=0.5p=0.5p=0.5, the last two entries survive and double: 0.1 becomes 0.2 and 0.6 becomes 1.2. Predict those values before running it.

dare-drop-and-rescale-yu2023.py
1def dare_sparsify( 2 task_vector: list[float], 3 drop_rate: float, 4 keep_mask: list[int], 5) -> list[float]: 6 keep_prob = 1.0 - drop_rate 7 if not 0.0 < keep_prob <= 1.0: 8 raise ValueError("drop_rate must be in [0, 1)") 9 if len(keep_mask) != len(task_vector): 10 raise ValueError("keep_mask must match task_vector") 11 return [ 12 value / keep_prob if kept else 0.0 13 for value, kept in zip(task_vector, keep_mask) 14 ] 15 16task_vector = [0.2, -0.4, 0.1, 0.6] 17sparsified = dare_sparsify(task_vector, drop_rate=0.5, keep_mask=[0, 0, 1, 1]) 18invalid_drop_rate_rejected = False 19try: 20 dare_sparsify(task_vector, drop_rate=1.0, keep_mask=[1, 1, 1, 1]) 21except ValueError as exc: 22 invalid_drop_rate_rejected = "drop_rate" in str(exc) 23 24print("shape_ok:", len(sparsified) == len(task_vector)) 25print("finite_ok:", all(value == value and abs(value) != float("inf") for value in sparsified)) 26print("matches_expected:", sparsified == [0.0, 0.0, 0.2, 1.2]) 27print("invalid_drop_rate_rejected:", invalid_drop_rate_rejected) 28print("original nonzero:", sum(value != 0.0 for value in task_vector)) 29print("sparsified nonzero:", sum(value != 0.0 for value in sparsified)) 30print("sparsified:", sparsified)
Output
1shape_ok: True 2finite_ok: True 3matches_expected: True 4invalid_drop_rate_rejected: True 5original nonzero: 4 6sparsified nonzero: 2 7sparsified: [0.0, 0.0, 0.2, 1.2]

On the SFT models and tasks it evaluates, DARE finds substantial redundancy in task-vector entries and improves several downstream merge methods after drop-and-rescale preprocessing.[8]Reference 8Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunchhttps://arxiv.org/abs/2311.03099 For a new checkpoint family, density remains a tuned parameter. Compare unsparsified and DARE-preprocessed candidates on every required task slice before deciding whether sparsity helped.

SLERP (spherical linear interpolation)

SLERP changes the path geometry, not the evidence standard. It follows an angular arc between normalized vector directions rather than the chord used by linear interpolation. It isn't an algorithm for discovering a low-loss path around an incompatible-model ridge.

Rather than interpolating directions along a straight line, SLERP[9]Reference 9Animating Rotation with Quaternion Curveshttps://dl.acm.org/doi/10.1145/325334.325242 interpolates along a sphere. Write the geometry in terms of normalized directions:

SLERP(θ^A,θ^B,t)=sin⁡((1−t)Ω)sin⁡Ωθ^A+sin⁡(tΩ)sin⁡Ωθ^B\begin{aligned} \text{SLERP}(\hat{\theta}_A, \hat{\theta}_B, t) &= \frac{\sin((1-t)\Omega)}{\sin \Omega} \hat{\theta}_A \\ &\quad + \frac{\sin(t\Omega)}{\sin \Omega} \hat{\theta}_B \end{aligned}SLERP(θ^A​,θ^B​,t)​=sinΩsin((1−t)Ω)​θ^A​+sinΩsin(tΩ)​θ^B​​

where ttt is the interpolation factor (from 0 to 1) and Ω=arccos⁡(θ^A⋅θ^B)\Omega = \arccos(\hat{\theta}_A \cdot \hat{\theta}_B)Ω=arccos(θ^A​⋅θ^B​) is the angle between normalized weight vectors. Practical merge implementations may handle magnitude separately after interpolating direction, as the code does here.

SLERP was introduced for computer graphics to interpolate rotations represented as quaternions.[9]Reference 9Animating Rotation with Quaternion Curveshttps://dl.acm.org/doi/10.1145/325334.325242 That source establishes its geometry, not downstream quality for neural-network weight merges. Use a SLERP checkpoint as another candidate and measure loss and required tasks just as you would for a linear merge.

The slerp function interpolates direction on the unit sphere, then linearly interpolates magnitude. Parallel and opposite vectors make sin⁡Ω\sin\OmegasinΩ too small, so those cases fall back to a straight line.

Make the geometry concrete before running it. For equal-norm vectors [1, 0] and [0, 1], a linear midpoint is [0.5, 0.5] with norm about 0.707; SLERP should land at [0.707, 0.707] with norm 1.0. That prediction is about shape, not model quality.

slerp-spherical-linear-interpolation.py
1import math 2 3def slerp(v0: list[float], v1: list[float], t: float) -> list[float]: 4 def magnitude(vector: list[float]) -> float: 5 return math.sqrt(sum(value * value for value in vector)) 6 7 mag0 = magnitude(v0) 8 mag1 = magnitude(v1) 9 if mag0 == 0.0 or mag1 == 0.0: 10 return [(1 - t) * a + t * b for a, b in zip(v0, v1)] 11 12 d0 = [value / mag0 for value in v0] 13 d1 = [value / mag1 for value in v1] 14 dot = max(-1.0, min(1.0, sum(a * b for a, b in zip(d0, d1)))) 15 omega = math.acos(dot) 16 sin_omega = math.sin(omega) 17 if abs(sin_omega) < 1e-6: 18 return [(1 - t) * a + t * b for a, b in zip(v0, v1)] 19 20 w0 = math.sin((1 - t) * omega) / sin_omega 21 w1 = math.sin(t * omega) / sin_omega 22 direction = [w0 * a + w1 * b for a, b in zip(d0, d1)] 23 mixed_mag = (1 - t) * mag0 + t * mag1 24 return [value * mixed_mag for value in direction] 25 26v0 = [1.0, 0.0] 27v1 = [0.0, 1.0] 28mid = slerp(v0, v1, t=0.5) 29antipodal_mid = slerp(v0, [-value for value in v0], t=0.5) 30expected = 2**-0.5 31 32print("unit_norm:", abs(math.sqrt(sum(x * x for x in mid)) - 1.0) < 1e-6) 33print("matches_45_degree:", all(abs(a - b) < 1e-6 for a, b in zip(mid, [expected, expected]))) 34print("antipodal_fallback_finite:", all(math.isfinite(value) for value in antipodal_mid)) 35print("midpoint:", [round(value, 4) for value in mid]) 36print("norm:", round(math.sqrt(sum(x * x for x in mid)), 4))
Output
1unit_norm: True 2matches_45_degree: True 3antipodal_fallback_finite: True 4midpoint: [0.7071, 0.7071] 5norm: 1.0

In the equal-norm orthogonal-vector example above, the SLERP midpoint remains on the unit circle while a linear midpoint would have smaller norm. Keep the distinction clear: geometry explains the candidate's path; task and safety evaluations decide whether it ships. For a pair of checkpoints, score linear and spherical candidates against the same release gates.

Running a merge with mergekit

The concepts now become one artifact. mergekit[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit is an open-source toolkit for merging language-model checkpoints. Its documented CLI supports YAML-defined merges with CPU or limited-VRAM execution, and mergekit-multi can run multi-stage recipes where later merges consume earlier outputs.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit

Carry the Code, Math, and Chat trio into a YAML file with the base, source weights, density, and merge method. This is a recipe for a candidate, not a release decision:

merge_config.yml
1models: 2 - model: your-org/base-8b-code 3 parameters: 4 weight: 0.35 5 density: 0.5 # retained fraction for this task vector 6 - model: your-org/base-8b-math 7 parameters: 8 weight: 0.35 9 density: 0.5 10 - model: your-org/base-8b-chat 11 parameters: 12 weight: 0.30 13 density: 0.5 14 15merge_method: dare_ties 16base_model: your-org/base-8b 17tokenizer: 18 source: base # switch to union if you must preserve extra tokens 19chat_template: auto # or pin a specific template when model families differ 20dtype: float16

For dare_ties, each source model's density is the keep fraction of its task vector: density = 1 - p in DARE's drop-rate notation. Merge methods have different schemas, so merge_method isn't a drop-in switch. For example, mergekit's slerp method takes exactly two source models.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit

Tokenizer choice changes the output contract. If all required tokens are in the base tokenizer, tokenizer.source: base pins that vocabulary. Current mergekit configuration defaults to a union tokenizer, which adds source tokens and assigns fallback embeddings where an input model lacks them.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit Either policy needs targeted evaluation. Before running the YAML, predict which policy preserves Code's special tokens, then use the preflight check below.

A written checkpoint is still a candidate. Run the YAML through mergekit-yaml, score every required slice, and promote only after all gates pass.

Diagram showing YAML recipe, mergekit-yaml, Merged checkpoint, and Per-task gates.
YAML recipe, mergekit-yaml, Merged checkpoint, and Per-task gates.

⚠️ Common mistake: Assuming all specialist checkpoints use the same tokenizer because they began from the same base. If the Code checkpoint added fill-in-the-middle tokens such as <fim_prefix>, choosing base drops those added output entries while choosing union introduces filled embeddings for models that lack them. Verify tokenizer vocabularies, choose the output policy explicitly, and test code-completion prompts that require those tokens.

This preflight check makes the output-vocabulary decision explicit before any expensive merge runs:

choose-output-vocabulary-policy.py
1def output_vocab(base_vocab, source_vocabs, policy): 2 if policy == "base": 3 return set(base_vocab) 4 if policy == "union": 5 return set().union(*source_vocabs) 6 raise ValueError("policy must be 'base' or 'union'") 7 8base_vocab = {"<bos>", "def", "return"} 9code_vocab = base_vocab | {"<fim_prefix>"} 10required_tokens = {"def", "<fim_prefix>"} 11 12base_output = output_vocab(base_vocab, [base_vocab, code_vocab], "base") 13union_output = output_vocab(base_vocab, [base_vocab, code_vocab], "union") 14 15print("base_missing_required:", sorted(required_tokens - base_output)) 16print("union_missing_required:", sorted(required_tokens - union_output)) 17print("union_requires_added_embedding_eval:", "<fim_prefix>" not in base_vocab)
Output
1base_missing_required: ['<fim_prefix>'] 2union_missing_required: [] 3union_requires_added_embedding_eval: True

Once the YAML is set, run the merge. The command takes the config file and an output path:

terminal
1mergekit-yaml merge_config.yml ./output_model --cuda

For hardware-specific and memory-saving flags, check mergekit-yaml --help because supported options vary by version.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit

A successful write to disk proves that the recipe ran. It says nothing about Code, Math, or Chat. Evaluate each target slice, compare it with declared gates and source baselines, then retune or reject any candidate that misses a critical threshold.

Release comparison for the merged assistant. The aggregate score is 87.2 and looks promotable, while the per-task table shows code 92.4 pass, math 82.1 fail against a 85.0 gate, and chat 87.0 pass, so promotion is blocked.
The aggregate 87.2 looks fine. Math is 82.1 against an 85.0 gate, so promotion stays blocked until that slice recovers.

Make the release call before reading the helper. Does an 87.2 aggregate outweigh Math's 82.1? No. An aggregate ranks candidates, but a release decision fails on any critical threshold miss:

evaluate-per-task-release-gates.py
1def failed_release_gates(scores, thresholds): 2 return { 3 task: (scores[task], minimum) 4 for task, minimum in thresholds.items() 5 if scores[task] < minimum 6 } 7 8scores = {"code": 92.4, "math": 82.1, "chat": 87.0} 9thresholds = {"code": 90.0, "math": 85.0, "chat": 84.0} 10failures = failed_release_gates(scores, thresholds) 11 12print("aggregate_score:", round(sum(scores.values()) / len(scores), 1)) 13print("failed_tasks:", sorted(failures)) 14print("promote:", not failures)
Output
1aggregate_score: 87.2 2failed_tasks: ['math'] 3promote: False

Finding good coefficients automatically

The blocked Math slice gives coefficient search a concrete objective. Searching merge coefficients and layer selections by hand can be expensive. Evolutionary model merging[10]Reference 10Evolutionary Optimization of Model Merging Recipes.https://sakana.ai/evolutionary-model-merge/ searches merge recipes against a supplied fitness evaluation. The search space can include per-layer source choices, interpolation weights, and whether to merge in parameter space, data-flow space, or both.

Sakana AI reports using this approach to build EvoLLM-JP from Japanese-language and math-oriented models, optimizing for the evaluations selected in that work.[10]Reference 10Evolutionary Optimization of Model Merging Recipes.https://sakana.ai/evolutionary-model-merge/ The loop is simple: score a recipe on validation data, mutate its parameters, and keep better-scoring recipes. The search inherits the objective's coverage and blind spots, so independent release slices still matter.

Before reaching for evolution, use a small grid as a transparent baseline. Try lambda values in [0.2, 0.4, 0.6, 0.8] for each task vector, measure each required slice on held-out data, and keep only configurations that clear every release gate. For Code, Math, and Chat, include code-generation tests, math word problems, and instruction-following prompts. A code-only objective can't protect Math.

Passthrough and frankenmerging

Not every merge averages weights. Mergekit's passthrough method copies selected tensors or layer ranges from source models into the output checkpoint.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit This is model splicing rather than interpolation: tensor dimensions must compose, while useful behavior across the splice remains an evaluation result.

Suppose a recipe copies layers 0-19 from Code and layers 20-31 from Math. Compatible dimensions make that artifact constructible; they don't show that Math's later layers can interpret the hidden states produced by Code's earlier layers.

Use passthrough as an experiment with explicit source lineage, layer boundaries, and the same per-task gates used for any other candidate. A successful build proves shape compatibility only.

Merging pitfalls and hard limits

Direct weight merging requires aligned parameter meaning, shape, and output-space assumptions. You can't directly interpolate a 7-billion-parameter checkpoint with a 70-billion-parameter checkpoint, or silently combine incompatible vocabulary mappings and treat token IDs as equivalent. A generated artifact is a candidate, not evidence of retained quality.

Use these stop signs before spending time tuning coefficients. Some block construction; others block release even when construction and average quality look good.

Avoid direct interpolation when:

  1. Different architectures: Source models must share the same structural architecture, parameter count, and layer layout. You can't directly interpolate a Llama checkpoint with a Mistral checkpoint, or an 8B model with a 70B model.
  2. Different tokenizers: Direct interpolation assumes aligned embeddings and next-token heads. Mergekit can help with tokenizer union in compatible cases, but it doesn't make arbitrary vocabulary mismatches disappear.[1]Reference 1Mergekit: Tools for merging pre-trained large language modelshttps://github.com/arcee-ai/mergekit
  3. Mismatched prompt formats or chat templates: These usually won't block the raw tensor merge, but they can make the merged checkpoint look broken at inference time because the prompt serialization no longer matches the behaviors learned during tuning.
  4. Quantized-only checkpoints: If you want to merge, do it on dequantized or full-precision weights first, then quantize the final artifact. The merge math depends on real-valued deltas, not already-rounded integers. Treat the merged checkpoint as a new model and re-run your quantization calibration and evals.
  5. Distant fine-tuning trajectories: Models fine-tuned on divergent data or with large update magnitudes may be poor interpolation candidates. Git Re-Basin demonstrates permutation alignment in studied MLP, CNN, and ResNet settings; it isn't an established repair step for arbitrary LLM merges.[5]Reference 5Git Re-Basin: Merging Models modulo Permutation Symmetries.https://arxiv.org/abs/2209.04836
  6. Critical precision tasks: Don't ship a merge when a required slice misses its threshold, even if an aggregate metric rises. A specialist baseline remains part of the comparison.

Diagnosing a broken merge

Diagnose in order. First verify the artifact contract: keys, shapes, tokenizer, output head, and chat template. Then compare behavior with source baselines on each task slice. Only after those checks should you tune coefficients or choose another merge rule.

When a merge goes wrong, the model usually tells you quickly:

SymptomLikely CauseFix
Output is incoherent or random tokensTokenizer/output mapping, prompt template, or architecture mismatchVerify output vocabulary policy, chat template, and layer shapes
Model loops repetitive textCoefficient overload or weights pushed too far out of distributionReduce coefficient magnitudes, start additive lambdas in the 0.0-1.0 range, and re-run evals
Merged model is worse than every sourceSource interference or incompatible lineageCheck source lineage and tokenizer policy; prefer compatible sources and retune or reject the merge

The original Model Soups gains in shared-initialization ImageNet experiments justify trying an average. They don't predict that this Code, Math, and Chat merge will pass.[3]Reference 3Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Timehttps://arxiv.org/abs/2203.05482 Promotion still requires a clean artifact, retained behavior, and every binding gate.

Complete the lesson

Mastery Check

Answer every question, then check your score. Score 75% or higher to mark this lesson complete.

1.Before interpolating two checkpoints, which compatibility check is essential?

Correct answer: Confirm compatible base lineage, parameter shapes, tokenizer, and output space before comparing merged quality.

Interpolation assumes corresponding tensors mean comparable things. Same-shape tensors can still come from incompatible bases or tokenizers, producing a merged artifact whose apparent score is not meaningful.

2.Both endpoint checkpoints pass evaluation, but the midpoint of their linear interpolation fails badly. What does that result establish?

Correct answer: Linear interpolation is not guaranteed to preserve quality along the path, so evaluate the path rather than endpoints alone.

Weight-space geometry can pass through a poor region even when both endpoints work. The article treats interpolation as an empirical path to measure, not as a quality guarantee derived from endpoint scores.

3.A base score is 2.0, code score 2.5, and math score 1.5. With task deltas weighted 0.6 and 0.4 from the base, what merged score follows the scalar arithmetic?

Correct answer: 2.10, because the weighted deltas are +0.6(0.5) and +0.4(-0.5), giving 2.0 + 0.3 - 0.2.

Task arithmetic adds weighted deltas from a common base. The code improvement contributes +0.3 and the math regression contributes -0.2, yielding 2.1 rather than averaging raw task scores.

4.What is the decisive distinction in TIES-style merging?

Correct answer: Trim small updates, elect signs using signed mass, and merge disjoint nonconflicting updates rather than using raw majority votes.

TIES addresses interference through trimming, sign election, and disjoint merging. Signed mass preserves update magnitude and direction information that a simple elementwise majority can discard.

5.What does DARE change when applied before combining task deltas?

Correct answer: It drops a fraction of delta entries and rescales survivors by roughly 1/(1-p) to preserve expected magnitude.

DARE sparsifies updates stochastically and compensates surviving entries. The rescaling is the point: dropping entries without adjustment changes the expected update magnitude and confounds the experiment.

6.A SLERP merge has a smooth constant-radius path but lower coding accuracy than linear interpolation. What should be concluded?

Correct answer: SLERP supplies geometric interpolation on a sphere, not a guarantee of task quality; keep the measured winner.

SLERP changes interpolation geometry. Geometry can be useful, but quality remains an empirical property requiring task and safety evaluation.

7.A merge tool must combine models with different tokenizers. Which decision matches the article's tooling guidance?

Correct answer: Choose a deliberate base or union-tokenizer strategy and verify embedding and output-head alignment before serving.

Tokenizer choice changes input IDs and output rows. A tool can support a base or union strategy, but the resulting vocabulary and heads must be tested as part of the artifact contract.

8.A merged checkpoint improves aggregate score but fails the math safety or accuracy gate. What promotion decision follows?

Correct answer: Block promotion because per-task gates are binding even when the aggregate metric improves.

Aggregate averages can hide a material failure in one task. The article's gate design treats critical per-task regressions as blockers, not tradeable noise.

8 questions remaining.

Next Step
Continue to Vector DB Internals: HNSW & IVF

You can now train, adapt, distill, and merge checkpoints under per-task gates. The next phase is the systems around those models, starting with retrieval indexes: <span data-glossary="hnsw">HNSW</span>, IVF, and <span data-glossary="product-quantization">Product Quantization</span> decide which evidence reaches a merged assistant under latency and memory limits.

PreviousKnowledge Distillation for LLMs
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

Mergekit: Tools for merging pre-trained large language models

Goddard, C., et al. · 2023

https://github.com/arcee-ai/mergekit

Linear Mode Connectivity and the Lottery Ticket Hypothesis.

Frankle, J., Dziugaite, G. K., Roy, D. M., & Carlin, M. · 2020 · ICML 2020

https://arxiv.org/abs/1912.05671

Model Soups: Averaging Weights of Multiple Fine-tuned Models Improves Accuracy without Increasing Inference Time

Wortsman, M., et al. · 2022 · ICML 2022

https://arxiv.org/abs/2203.05482

The Role of Permutation Invariance in Linear Mode Connectivity of Neural Networks.

Entezari, R., Sedghi, H., Saukh, O., & Neyshabur, B. · 2022 · ICLR 2022

https://arxiv.org/abs/2110.06296

Git Re-Basin: Merging Models modulo Permutation Symmetries.

Ainsworth, S. K., Hayase, J., & Srinivasa, S. · 2022 · ICLR 2023

https://arxiv.org/abs/2209.04836

Editing Models with Task Arithmetic

Ilharco, G., et al. · 2022 · ICLR 2023

https://arxiv.org/abs/2212.04089

TIES-Merging: Resolving Interference When Merging Models

Yadav, P., et al. · 2023 · NeurIPS 2023

https://arxiv.org/abs/2306.01708

Language Models are Super Mario: Absorbing Capabilities from Homologous Models as a Free Lunch

Yu, L., et al. · 2023 · ICML 2024

https://arxiv.org/abs/2311.03099

Animating Rotation with Quaternion Curves

Shoemake, K. · 1985 · SIGGRAPH '85

https://dl.acm.org/doi/10.1145/325334.325242

Evolutionary Optimization of Model Merging Recipes.

Sakana AI · 2024

https://sakana.ai/evolutionary-model-merge/

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.