Views
No views yet
mistral-finetune is a light-weight codebase that enables memory-efficient and performant finetuning of Mistral's models.
It is based on LoRA, a training paradigm where most weights are frozen and only 1-2% additional weights in the form of low-rank matrix perturbations are trained.Note
- The goal of this repository is to provide a simple, guided entrypoint to finetune Mistral models. As such, it is fairly opinionated (especially around data formatting) and does not aim at being exhaustive across multiple model architecture or hardware types. For more generic approaches, you can check out some other great projects like torchtune.
cd $HOME && git clone https://github.com/mistralai/mistral-finetune.gitcd mistral-finetune
pip install -r requirements.txt| Model | Link | Checksum |
|---|---|---|
| 7B Base V3 | 7B Base | 0663b293810d7571dad25dae2f2a5806 |
| 7B Instruct v3 | 7B Instruct v3 | 80b71fcb6416085bcb4efad86dfb4d52 |
| 8x7B Base V1 | 8x7B Base | (HF link) |
| 8x7B Instruct V1 | 8x7B Instruct | 8e2d3930145dc43d3084396f49d38a3f |
| 8x22 Instruct V3 | 8x22 Instruct | 471a02a6902706a2f1e44a693813855b |
| 8x22B Base V3 | 8x22B Base | a2fa75117174f87d1197e3a4eb50371a |
1mkdir -p ~/${HOME}/mistral_models
2cd ${HOME} && wget https://models.mistralcdn.com/mistral-7b-v0-3/mistral-7B-v0.3.tar
3tar -xf mistral-7B-v0.3.tar -C mistral_modelsmodel_id_or_path.$HOME/mistral_models/7B:model_id_or_path: "/Users/johndoe/mistral_models/7B"mistral-finetune has strict
requirements for how the training data has to be formatted."text" key. E.g:1{"text": "Text contained in document n°1"}
2{"text": "Text contained in document n°2"}"messages" key in the form of a list. Each list item is a dictionary containing the "content" and "role" keys. "role" is a string being one of "user", "assistant" or "system_prompt". The loss will only be computed if "role" == "assistant". E.g.:1{
2 "messages": [
3 {
4 "role": "user",
5 "content": "User interaction n°1 contained in document n°1"
6 },
7 {
8 "role": "assistant",
9 "content": "Bot interaction n°1 contained in document n°1"
10 },
11 {
12 "role": "user",
13 "content": "User interaction n°2 contained in document n°1"
14 },
15 {
16 "role": "assistant",
17 "content": "Bot interaction n°2 contained in document n°1"
18 }
19 ]
20}
21{
22 "messages": [
23 {
24 "role": "user",
25 "content": "User interaction n°1 contained in document n°2"
26 },
27 {
28 "role": "assistant",
29 "content": "Bot interaction n°1 contained in document n°2"
30 },
31 {
32 "role": "user",
33 "content": "User interaction n°2 contained in document n°2"
34 },
35 {
36 "role": "assistant",
37 "content": "Bot interaction n°2 contained in document n°2",
38 "weight": 0, # don't train on n°2
39 },
40 {
41 "role": "user",
42 "content": "User interaction n°3 contained in document n°2"
43 },
44 {
45 "role": "assistant",
46 "content": "Bot interaction n°3 contained in document n°2"
47 }
48 ]
49}"messages" key in the form of a list. Each list item is a dictionary containing the "role" and "content" or "tool_calls" keys. "role" is a string being one of "user", "assistant", "system_prompt", or "tool". The loss will only be computed if "role" == "assistant"."id" of "tool_calls" and the "tool_call_id" are randomly generated strings of exactly 9 chars. We recommend to generate this automatically
in a data preparation script as is done here.1{
2 "messages": [
3 {
4 "role": "system",
5 "content": "You are an helpful assistant who has access to the following functions to help the user, you can use the functions if needed"
6 },
7 {
8 "role": "user",
9 "content": "Can you help me generate an anagram of the word \"listen\"?"
10 },
11 {
12 "role": "assistant",
13 "tool_calls": [
14 {
15 "id": "TX92Jm8Zi",
16 "type": "function",
17 "function": {
18 "name": "generate_anagram",
19 "arguments": "{\"word\": \"listen\"}"
20 }
21 }
22 ]
23 },
24 {
25 "role": "tool",
26 "content": "{\"anagram\": \"silent\"}",
27 "tool_call_id": "TX92Jm8Zi"
28 },
29 {
30 "role": "assistant",
31 "content": "The anagram of the word \"listen\" is \"silent\"."
32 },
33 {
34 "role": "user",
35 "content": "That's amazing! Can you generate an anagram for the word \"race\"?"
36 },
37 {
38 "role": "assistant",
39 "tool_calls": [
40 {
41 "id": "3XhQnxLsT",
42 "type": "function",
43 "function": {
44 "name": "generate_anagram",
45 "arguments": "{\"word\": \"race\"}"
46 }
47 }
48 ]
49 }
50 ],
51 "tools": [
52 {
53 "type": "function",
54 "function": {
55 "name": "generate_anagram",
56 "description": "Generate an anagram of a given word",
57 "parameters": {
58 "type": "object",
59 "properties": {
60 "word": {
61 "type": "string",
62 "description": "The word to generate an anagram of"
63 }
64 },
65 "required": [
66 "word"
67 ]
68 }
69 }
70 }
71 ]
72}cd $HOME && mkdir -p data && cd $HOME/datapip install pandas pyarrow).1import pandas as pd
2
3df = pd.read_parquet('https://huggingface.co/datasets/HuggingFaceH4/ultrachat_200k/resolve/main/data/test_gen-00000-of-00001-3d4cd8309148a71f.parquet')1df_train=df.sample(frac=0.95,random_state=200)
2df_eval=df.drop(df_train.index)1df_train.to_json("ultrachat_chunk_train.jsonl", orient="records", lines=True)
2df_eval.to_json("ultrachat_chunk_eval.jsonl", orient="records", lines=True)$HOME/data/ultrachat_chunk_train.jsonl as well as a dataset mixing weight for training and $HOME/data/ultrachat_chunk_eval.jsonl for eval, e.g.data:
instruct_data: "/Users/johndoe/data/ultrachat_chunk_train.jsonl"
eval_instruct_data: "/Users/johndoe/data/ultrachat_chunk_eval.jsonl"cd $HOME/mistral-finetune
python -m utils.validate_data --train_yaml example/7B.yamlThe data in line 1412 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formated.Expected last role to be one of: [assistant] but got user
The data in line 1413 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formated.Expected last role to be one of: [assistant] but got user
The data in line 1414 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formated.Expected last role to be one of: [assistant] but got user
The data in line 1415 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formated.Expected last role to be one of: [assistant] but got usercd $HOME/mistral-finetune
python -m utils.reformat_data $HOME/data/ultrachat_chunk_train.jsonl
python -m utils.reformat_data $HOME/data/ultrachat_chunk_eval.jsonlcd $HOME/mistral-finetune
python -m utils.validate_data --train_yaml example/7B.yamlTrain States
--------------------
{
"expected": {
"eta": "00:52:44",
"data_tokens": 25169147,
"train_tokens": 131072000,
"epochs": "5.21",
"max_steps": 500,
"data_tokens_per_dataset": {
"/Users/johndoe/data/ultrachat_chunk_train.jsonl": "25169147.0"
},
"train_tokens_per_dataset": {
"/Users/johndoe/data/ultrachat_chunk_train.jsonl": "131072000.0"
},
"epochs_per_dataset": {
"/Users/johndoe/data/ultrachat_chunk_train.jsonl": "5.2"
}
},
}max_steps set to 500 would lead to iterating through the dataset roughly 5 times which is reasonable, but might
be a bit too much. A recommended setting is shown below which would only take 30min on a 8xH100 cluster.cd $HOME && mkdir -p data && cd $HOME/datapip install pandas pyarrow).1import pandas as pd
2
3df = pd.read_parquet('https://huggingface.co/datasets/Locutusque/function-calling-chatml/resolve/main/data/train-00000-of-00001-f0b56c6983b4a78f.parquet')1df_train=df.sample(frac=0.95,random_state=200)
2df_eval=df.drop(df_train.index)1df_train.to_json("glaive_train.jsonl", orient="records", lines=True)
2df_eval.to_json("glaive_eval.jsonl", orient="records", lines=True)"from" should be renamed to "user" and superfluous "\n" characters should be removed.
For this dataset you can make use of ./utils/reformat_data_glaive.py:cd $HOME/mistral-finetune
python -m utils.reformat_data_glaive $HOME/data/glaive_train.jsonl
python -m utils.reformat_data_glaive $HOME/data/glaive_eval.jsonldata.instruct_data and data.eval_instruct_data to
$HOME/data/glaive_train.jsonl and $HOME/data/glaive_eval.jsonl in example/7B.yaml respectively.--create_corrected. For this, make sure to add
--create_corrected as follows:cd $HOME/mistral-finetune
python -m utils.validate_data --train_yaml example/7B.yaml --create_corrected$HOME/data/glaive_train.jsonl.corrected and $HOME/data/glaive_eval.jsonl.corrected. Make sure to use these two dataset in example/7B.yaml and run the command again. Now the dataset should be correctly formatted!run_dir to your experiment folder and optionally set wandb_project to a Weights & Biases project for logging`, e.g.:max_steps: 300
run_dir: "/Users/johndoe/ultra_chat_test"
wandb.project: ultra_chatwandb--nproc-per-node to the number of available GPUs.cd $HOME/mistral-finetune
torchrun --nproc-per-node 8 --master_port $RANDOM -m train example/7B.yamlmistral-finetune/examples/7B defines reasonable parameters for learning rate, weight decay, etc... but you are advised to
customize these settings for your use case.model_id_or_path defines the model to start training from. This can be a path to a pre-trained model or a local model directory.run_dir defines the directory where training checkpoints and metrics are stored.seq_len defines the sequence length for training. This is the maximum length of input sequences the model will process. Samples are packed to reach a length of seq_len for maximum training efficiency.batch_size defines the number of training examples used per GPU. Note: The overall effective batch_size (in tokens) across all GPUs equals num_gpus x batch_size x seq_len.max_steps defines the maximum number of training steps. This is the total number of iterations the training process will run. It can be adjusted based on the specific needs of your training scenario. Total number of tokens seen during training is max_steps x num_gpus x batch_size x seq_len.optim.lr defines the learning rate. This is the initial learning rate for the optimizer.optim.weight_decay defines weight decay. Weight decay is a regularization technique used to prevent overfitting by penalizing large weights. We recommend leaving it at 0.1.optim.pct_start defines the percentage of the total training steps used for the learning rate warm-up phase before it starts to decrease. It corresponds to pct_start of PyTorch's OneCycleLR.lora.rank defines the size of the LoRA (Low-Rank Adaptation) adapters. We recommend 64 or less, which adjusts the rank of the low-rank decomposition used in LoRA.seed defines the random seed for initialization and data shuffling/sampling. Setting a seed ensures reproducibility of results.log_freq defines the logging frequency. This specifies how often (in steps) to log training metrics.data.instruct_data is the path to the instruction data used for training. This field has to be filled with one or multiple data sources in the format as explained above. Each data source should either be a path to jsonl file of a path to a directory containing jsonl files followed by a weighting to define the importance of this dataset: <path/to/data_source>:<weight>. E.g.: data.instruct_data: "/path/to/data1.jsonl:5.,/path/to/data2.jsonl:1.,/path/to/dir_of_jsonls:1."data.data is an optional path to additional pretraining data in the format as explained above. Note that this field can be left blank.data.eval_instruct_data is an optional path to evaluation instruction data to run cross-validation at every eval_freq steps. Cross-validation metrics are displayed as loss and perplexity.eval_freq defines how often (in steps) to evaluate the model. This specifies the interval at which the model is evaluated on the validation set.no_eval is a flag to enable or disable intermediate evaluation. Setting it to False enables periodic evaluation during training.ckpt_freq defines how often (in steps) to save checkpoints. This specifies the interval at which the model's state is saved.ckpt_only_lora defines whether to only save the trained LoRA checkpoints or whether the trained LoRA should directly be merged into the base model and saved. Note: When setting ckpt_only_lora=False make sure that you have enough CPU and GPU memory to save the full model on a single process (this is usually only possible for the 7B model).wandb.key is used to pass your Weights & Biases (wandb) API key for logging. This allows you to log training metrics to the wandb dashboard.wandb.project defines the wandb project name. This is where the training run will be logged in the wandb interface.mistral_inference correctly installed:pip install mistral_inferencelora.safetensors is saved under $HOME/ultra_chat_test/checkpoints/checkpoint_000300/consolidated/lora.safetensors, you can chat with the model using mistral_inference, e.g.:mistral-chat /mnt/slow/runs/patrick/mistral-finetune/7B/ --max_tokens 256 --temperature 1.0 --instruct --lora_path $HOME/ultra_chat_test/checkpoints/checkpoint_000300/consolidated/lora.safetensorspython -m utils.extend_model_vocab --original_model_ckpt /folder/to/old/model --extended_model_ckpt /folder/to/extended/model/folder/to/extended/model.
- What's the best practice of fine-tuning MoEs?
- How can I determine the number of tokens used during the model training process?
- What should I do if I encounter a CUDA out-of-memory error?
seq_len x batch_size. Try setting batch_size to 1 and reduce seq_len. You can define the batch_size and seq_len in the .yaml file.