Skip to content

Commit 9d43bba

Browse files
authored
Merge pull request #100 from georgian-io/feature/config-path-param
[CLI] Parameter for Config Path
2 parents 5d3fa49 + c5a9952 commit 9d43bba

File tree

2 files changed

+60
-62
lines changed

2 files changed

+60
-62
lines changed

README.md

Lines changed: 46 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# LLM Finetuning Toolkit
1+
# LLM Finetuning Toolkit
22

33
<p align="center">
44
<img src="assets/toolkit-animation.gif" width="900" />
@@ -12,8 +12,6 @@ LLM Finetuning toolkit is a config-based CLI tool for launching a series of LLM
1212
<img src="assets/overview_diagram.png" width="900" />
1313
</p>
1414

15-
16-
1715
## Installation
1816

1917
### Clone Repository
@@ -26,8 +24,8 @@ LLM Finetuning toolkit is a config-based CLI tool for launching a series of LLM
2624
### [Option 1] Docker (recommended)
2725

2826
```shell
29-
docker build -t llm-toolkit
30-
```
27+
docker build -t llm-toolkit
28+
```
3129

3230
#### CPU Only
3331

@@ -63,29 +61,25 @@ See poetry documentation page for poetry [installation instructions](https://pyt
6361
pip install -r requirements.txt
6462
```
6563

66-
6764
## Quick Start
6865

6966
This guide contains 3 stages that will enable you to get the most out of this toolkit!
7067

71-
* __Basic__: Run your first LLM fine-tuning experiment
72-
* __Intermediate__: Run a custom experiment by changing the componenets of the YAML configuration file
73-
* __Advanced__: Launch series of fine-tuning experiments across different prompt templates, LLMs, optimization techniques -- all through **one** YAML configuration file
74-
68+
- **Basic**: Run your first LLM fine-tuning experiment
69+
- **Intermediate**: Run a custom experiment by changing the componenets of the YAML configuration file
70+
- **Advanced**: Launch series of fine-tuning experiments across different prompt templates, LLMs, optimization techniques -- all through **one** YAML configuration file
7571

76-
77-
### Basic
72+
### Basic
7873

7974
```python
8075
python toolkit.py --config ./config.yml
8176
```
8277

8378
This command initiates the fine-tuning process using the settings specified in the default YAML configuration file `config.yaml`.
8479

85-
8680
### Intermediate
8781

88-
The configuration file is the central piece that defines the behavior of the toolkit. It is written in YAML format and consists of several sections that control different aspects of the process, such as data ingestion, model definition, training, inference, and quality assurance. We highlight some of the critical sections.
82+
The configuration file is the central piece that defines the behavior of the toolkit. It is written in YAML format and consists of several sections that control different aspects of the process, such as data ingestion, model definition, training, inference, and quality assurance. We highlight some of the critical sections.
8983

9084
#### Data Ingestion
9185

@@ -99,14 +93,13 @@ data:
9993
### Instruction: {instruction}
10094
### Input: {input}
10195
### Output:
102-
prompt_stub:
103-
{output}
96+
prompt_stub: { output }
10497
test_size: 0.1 # Proportion of test as % of total; if integer then # of samples
10598
train_size: 0.9 # Proportion of train as % of total; if integer then # of samples
10699
train_test_split_seed: 42
107100
```
108101
109-
* While the above example illustrates using a public dataset from Hugging Face, the config file can also ingest your own data.
102+
- While the above example illustrates using a public dataset from Hugging Face, the config file can also ingest your own data.
110103
111104
```yaml
112105
file_type: "json"
@@ -118,13 +111,12 @@ data:
118111
path: "<path to your data file>
119112
```
120113
121-
* The prompt fields help create instructions to fine-tune the LLM on. It reads data from specific columns, mentioned in {} brackets, that are present in your dataset. In the example provided, it is expected for the data file to have column names: `instruction`, `input` and `output`.
122-
123-
* The prompt fields use both `prompt` and `prompt_stub` during fine-tuning. However, during testing, **only** the `prompt` section is used as input to the fine-tuned LLM.
114+
- The prompt fields help create instructions to fine-tune the LLM on. It reads data from specific columns, mentioned in {} brackets, that are present in your dataset. In the example provided, it is expected for the data file to have column names: `instruction`, `input` and `output`.
124115
116+
- The prompt fields use both `prompt` and `prompt_stub` during fine-tuning. However, during testing, **only** the `prompt` section is used as input to the fine-tuned LLM.
125117
126118
#### LLM Definition
127-
119+
128120
```yaml
129121
model:
130122
hf_model_ckpt: "NousResearch/Llama-2-7b-hf"
@@ -149,60 +141,59 @@ lora:
149141
- gate_proj
150142
```
151143
152-
* While the above example showcases using Llama2 7B, in theory, any open-source LLM supported by Hugging Face can be used in this toolkit.
144+
- While the above example showcases using Llama2 7B, in theory, any open-source LLM supported by Hugging Face can be used in this toolkit.
153145
154146
```yaml
155-
hf_model_ckpt: "mistralai/Mistral-7B-v0.1"
147+
hf_model_ckpt: "mistralai/Mistral-7B-v0.1"
156148
```
157149
158150
```yaml
159-
hf_model_ckpt: "tiiuae/falcon-7b"
151+
hf_model_ckpt: "tiiuae/falcon-7b"
160152
```
161153
162-
* The parameters for LoRA, such as the rank `r` and dropout, can be altered.
154+
- The parameters for LoRA, such as the rank `r` and dropout, can be altered.
163155

164156
```yaml
165-
lora:
166-
r: 64
167-
lora_dropout: 0.25
157+
lora:
158+
r: 64
159+
lora_dropout: 0.25
168160
```
169-
161+
170162
#### Quality Assurance
171163

172164
```yaml
173165
qa:
174166
llm_tests:
175-
- length_test
167+
- length_test
176168
- word_overlap_test
177169
```
178170

179-
* To ensure that the fine-tuned LLM behaves as expected, you can add tests that check if the desired behaviour is being attained. Example: for an LLM fine-tuned for a summarization task, we may want to check if the generated summary is indeed smaller in length than the input text. We would also like to learn the overlap between words in the original text and generated summary.
180-
171+
- To ensure that the fine-tuned LLM behaves as expected, you can add tests that check if the desired behaviour is being attained. Example: for an LLM fine-tuned for a summarization task, we may want to check if the generated summary is indeed smaller in length than the input text. We would also like to learn the overlap between words in the original text and generated summary.
181172

182173
#### Artifact Outputs
183174

184175
This config will run finetuning and save the results under directory `./experiment/[unique_hash]`. Each unique configuration will generate a unique hash, so that our tool can automatically pick up where it left off. For example, if you need to exit in the middle of the training, by relaunching the script, the program will automatically load the existing dataset that has been generated under the directory, instead of doing it all over again.
185176

186177
After the script finishes running you will see these distinct artifacts:
178+
187179
```shell
188180
/dataset # generated pkl file in hf datasets format
189181
/model # peft model weights in hf format
190182
/results # csv of prompt, ground truth, and predicted values
191183
/qa # csv of test results: e.g. vector similarity between ground truth and prediction
192184
```
193185

194-
Once all the changes have been incorporated in the YAML file, you can simply use it to run a custom fine-tuning experiment!
186+
Once all the changes have been incorporated in the YAML file, you can simply use it to run a custom fine-tuning experiment!
195187

196188
```python
197-
python toolkit.py --config <path to custom YAML file>
189+
python toolkit.py --config-path <path to custom YAML file>
198190
```
199191

200-
### Advanced
201-
192+
### Advanced
202193

203194
Fine-tuning workflows typically involve running ablation studies across various LLMs, prompt designs and optimization techniques. The configuration file can be altered to support running ablation studies.
204195

205-
* Specify different prompt templates to experiment with while fine-tuning.
196+
- Specify different prompt templates to experiment with while fine-tuning.
206197

207198
```yaml
208199
data:
@@ -212,55 +203,55 @@ data:
212203
- >-
213204
This is the first prompt template to iterate over
214205
### Input: {input}
215-
### Output:
206+
### Output:
216207
- >-
217208
This is the second prompt template
218209
### Instruction: {instruction}
219210
### Input: {input}
220211
### Output:
221-
prompt_stub:
222-
{output}
212+
prompt_stub: { output }
223213
test_size: 0.1 # Proportion of test as % of total; if integer then # of samples
224214
train_size: 0.9 # Proportion of train as % of total; if integer then # of samples
225215
train_test_split_seed: 42
226216
```
227217

228-
229-
* Specify various LLMs that you would like to experiment with.
218+
- Specify various LLMs that you would like to experiment with.
230219

231220
```yaml
232221
model:
233-
hf_model_ckpt: ["NousResearch/Llama-2-7b-hf", mistralai/Mistral-7B-v0.1", "tiiuae/falcon-7b"]
222+
hf_model_ckpt:
223+
[
224+
"NousResearch/Llama-2-7b-hf",
225+
mistralai/Mistral-7B-v0.1",
226+
"tiiuae/falcon-7b",
227+
]
234228
quantize: true
235229
bitsandbytes:
236230
load_in_4bit: true
237231
bnb_4bit_compute_dtype: "bf16"
238232
bnb_4bit_quant_type: "nf4"
239233
```
240234

241-
* Specify different configurations of LoRA that you would like to ablate over.
235+
- Specify different configurations of LoRA that you would like to ablate over.
242236

243237
```yaml
244-
lora:
245-
r: [16, 32, 64]
246-
lora_dropout: [0.25, 0.50]
238+
lora:
239+
r: [16, 32, 64]
240+
lora_dropout: [0.25, 0.50]
247241
```
248242

249243
## Extending
250244

251245
The toolkit provides a modular and extensible architecture that allows developers to customize and enhance its functionality to suit their specific needs. Each component of the toolkit, such as data ingestion, finetuning, inference, and quality assurance testing, is designed to be easily extendable.
252246

253-
254247
## Contributing
255248

256249
If you would like to contribute to this project, we recommend following the "fork-and-pull" Git workflow.
257250

258-
1. **Fork** the repo on GitHub
259-
2. **Clone** the project to your own machine
260-
3. **Commit** changes to your own branch
261-
4. **Push** your work back up to your fork
262-
5. Submit a **Pull request** so that we can review your changes
251+
1. **Fork** the repo on GitHub
252+
2. **Clone** the project to your own machine
253+
3. **Commit** changes to your own branch
254+
4. **Push** your work back up to your fork
255+
5. Submit a **Pull request** so that we can review your changes
263256

264257
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
265-
266-

toolkit.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from transformers import utils as hf_utils
77
from pydantic import ValidationError
88
import torch
9+
import typer
910

1011
from src.pydantic_models.config_model import Config
1112
from src.data.dataset_generator import DatasetGenerator
@@ -19,7 +20,10 @@
1920
torch._logging.set_logs(all=logging.CRITICAL)
2021

2122

22-
def run_one_experiment(config: Config) -> None:
23+
app = typer.Typer()
24+
25+
26+
def run_one_experiment(config: Config, config_path: str) -> None:
2327
dir_helper = DirectoryHelper(config_path, config)
2428

2529
# Loading Data -------------------------------
@@ -70,7 +74,7 @@ def run_one_experiment(config: Config) -> None:
7074
RichUI.inference_found(results_path)
7175

7276
# QA -------------------------------
73-
# console.rule("[bold blue]:thinking_face: Running LLM Unit Tests")
77+
# RichUI.before_qa()
7478
# qa_path = dir_helper.save_paths.qa
7579
# if not exists(qa_path) or not listdir(qa_path):
7680
# # TODO: Instantiate unit test classes
@@ -80,9 +84,8 @@ def run_one_experiment(config: Config) -> None:
8084
# pass
8185

8286

83-
if __name__ == "__main__":
84-
config_path = "./config.yml" # TODO: parameterize this
85-
87+
@app.command()
88+
def run(config_path: str = "./config.yml") -> None:
8689
# Load YAML config
8790
with open(config_path, "r") as file:
8891
config = yaml.safe_load(file)
@@ -92,9 +95,9 @@ def run_one_experiment(config: Config) -> None:
9295
else [config]
9396
)
9497
for config in configs:
98+
# validate data with pydantic
9599
try:
96100
config = Config(**config)
97-
# validate data with pydantic
98101
except ValidationError as e:
99102
print(e.json())
100103

@@ -105,4 +108,8 @@ def run_one_experiment(config: Config) -> None:
105108
config = yaml.safe_load(file)
106109
config = Config(**config)
107110

108-
run_one_experiment(config)
111+
run_one_experiment(config, config_path)
112+
113+
114+
if __name__ == "__main__":
115+
app()

0 commit comments

Comments
 (0)