ml-explore / ml-explore/mlx-examples

Fusing adapters with llama3 cause bad performances

Open
#832 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
9k
Forks
1.2k
PR merge metrics
No merged PRs in 30d

Description

Hello,

I'm using the following script to fine tune the llama3 model with a custom dataset of questions & responses using the {'prompt: "", completion:""} format defined here.

#!/usr/bin/env bash

DATA_PATH=data
ADAPTERS_PATH=adapters
MODEL_NAME=meta-llama/Meta-Llama-3-8B
MODEL_PATH=models/mlx
LORA_CONFIG_PATH=lora_config.yaml

NAME="my-assistant"
ITERATIONS=1000

# Parse options
while [[ "$#" -gt 0 ]]; do
    case $1 in
        --name)
            if [[ -z "$2" ]] || [[ "$2" == --* ]]; then
                echo "Error: Model name cannot be empty"
                echo "Usage: fine-tune.sh --iter <number of iterations> --name <output model name>"
                exit 1
            fi
            NAME="$2"
            shift
            ;;
        --iter)
            if [[ "$2" -lt 100 || "$2" -gt 10000 ]]; then
                echo "Error: Iteration value must be an integer between 100 and 10000"
                exit 1
            fi
            ITERATIONS="$2"
            shift
            ;;
        *)
          echo "Unknown option: $1."
          echo "Usage: fine-tune.sh --iter <number of iterations> --name <output model name>"
          exit 1
          ;;
    esac
    shift
done

echo "Fine-tuning with $ITERATIONS iterations"
echo "Output model name: $NAME"
FINE_TUNED_MODEL_PATH=models/$NAME
GGUF_MODEL_PATH=models/$NAME.gguf

set -ex

# Install llama.cpp if needed
if [ ! -d "llama.cpp" ]; then
    git clone git@github.com:ggerganov/llama.cpp.git;
    cd llama.cpp;
    make -j 8;
    cd ..;
else
    echo "Directory llama.cpp found, skipping download and build"
fi

# Download & quantize the HuggingFace model to reduce weights memory footprint
if [ ! -d "$MODEL_PATH" ]; then
    echo "No models found, initiating quantization...";
    python -m mlx_lm.convert \
        --hf-path "$MODEL_NAME" \
        --mlx-path "$MODEL_PATH" \
        -q;
else
  echo "Model found in $MODEL_PATH, skipping quantization"
fi

# Launch fine-tuning
python -m mlx_lm.lora \
    --data "$DATA_PATH" \
    --model "$MODEL_PATH" \
    --train \
    --iters "$ITERATIONS" \
    --config "$LORA_CONFIG_PATH"

# Merge the model and fine-tuned adapter
python -m mlx_lm.fuse \
    --model "$MODEL_PATH" \
    --adapter-path "$ADAPTERS_PATH" \
    --save-path "$FINE_TUNED_MODEL_PATH" \
    --de-quantize

# Generate GGUF file to use the new model with Ollama
python llama.cpp/convert-hf-to-gguf.py "$FINE_TUNED_MODEL_PATH" \
    --outfile "$GGUF_MODEL_PATH" \
    --outtype q8_0 \

ollama create "$NAME" -f Modelfile

I trained the model over 1000 iterations with the following config parameters:

# Number of validation batches, -1 uses the entire validation set.
val_batches: -1

# Adam learning rate.
learning_rate: 1e-5

# Number of training steps between loss reporting.
steps_per_report: 10

# Number of training steps between validations.
steps_per_eval: 50

# Save the model every N iterations.
save_every: 100

# Evaluate on the test set after training
test: true

# Number of test set batches, -1 uses the entire test set.
test_batches: 100

lora_parameters:
  # The layer keys to apply LoRA to.
  # These will be applied for the last lora_layers
  rank: 8
  scale: 20.0
  dropout: 0.0

The Modelfile s below:

FROM ./models/my-assistant.gguf

TEMPLATE """{{ if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}{{ if .Prompt }}<|im_start|>user
{{ .Prompt }}<|im_end|>
{{ end }}<|im_start|>assistant
"""

PARAMETER stop "<|im_end|>"
PARAMETER stop "<|im_start|>"
PARAMETER temperature 0

During the training I get the following message but I don't know what I am supposed to do with mlx_lm options:

No chat template is set for this tokenizer, falling back to a default class-level template. This is very error-prone, because models are often trained with templates different from the class default! Default chat templates are a legacy feature and will be removed in Transformers v4.43, at which point any code depending on them will stop working. We recommend setting a valid chat template before then to ensure that this model continues working without issues.

The final loss on training set (1300 samples) is around 0.16 and over validation set is 0.26. When running the generate command :

python -m mlx_lm.generate --model models/mlx --adapter-path adapters --prompt "<question>" 

I get very good results and nothing to complain about.

However when I use the fused model generated by my script using this documentation, the performances are super bad and answer are using random values when asking for specific amounts the model was trained for. The performances are as bad as if I didn't do any fine tuning.

Did I do something wrong or is the fusing process supposed to be that bad ? I there a way to export the model used by the mlx_lm.generate command to GGUF instead of relying on mlx_lm.fuse ?

Thank you.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the discrepancy using the shown mlx_lm.generate command with adapters and the mlx_lm.fuse command, then inspect the fused model before conversion with llama.cpp/convert-hf-to-gguf.py. Compare generation outputs and model settings, including the chat template warning. Done means the fused and adapter-backed models produce equivalent results for the reported prompts.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash, python
Domain
machine-learning, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.