from typing import Any from nbconvert import HTMLExporter from utils.create_info_files import create_hf_card from utils.notebook_generator import * from utils.components_creator import * finetuning_notebook = "Finetuning_NoteBook" notebook = None css = """ .container { align-items: center; justify-content: center; } .center_text { text-align: center; } .a_custom { border-radius: var(--button-large-radius); padding: var(--button-large-padding); font-weight: var(--button-large-text-weight); font-size: var(--button-large-text-size); border: var(--button-border-width) solid var(--button-primary-border-color); background: var(--button-primary-background-fill); color: var(--button-primary-text-color); justify-content: center; align-items: center; transition: var(--button-transition); box-shadow: var(--button-shadow); text-align: center; cursor: pointer; } .a_custom:hover { border-color: var(--button-primary-border-color-hover); background: var(--button-primary-background-fill-hover); color: var(--button-primary-text-color-hover); } .a_custom a { text-decoration: none; color: white; display: block; } .dashed_row { border: 2px dashed #60a5fa; } """ def centered_column(): return gr.Column(elem_classes=["container"]) def dashed_row(): return gr.Row(elem_classes=["dashed_row"]) def should_login_to_hf_model(model_id: str): return model_id == gemma.name or model_id == llama.name def change_model_selection(model_id): if model_id == gemma.name: gr.Warning(""" Access Gemma: To load Gemma from Hugging Face, you’re required to review and agree to Google’s usage license. """) if model_id == llama.name: gr.Warning(""" Access Llama 2: To load Llama 2 from Hugging Face, you’re required to review and agree to Meta’s usage license. """) for m in models: if m.name == model_id: return gr.Dropdown(choices=m.versions, interactive=True, visible=True, info=f"Select the version of the model {m.name} you wish to use.") return None def check_valid_input(value): if isinstance(value, str): return value and value.strip() if isinstance(value, list): return len(value) > 0 return not None def get_dataset(dataset_path): for d in ft_datasets: if d.path == dataset_path: return d return None def get_value(components: dict[Component, Any], elem_id: str) -> Any: for component, val in components.items(): if component.elem_id == elem_id: return val return None def preview_notebook(): html_exporter = HTMLExporter() global notebook (body, resources) = html_exporter.from_notebook_node(notebook) html_path = f"{finetuning_notebook}.html" with open(html_path, 'w') as f: f.write(body) return f'' def generate_code(components: dict[Component, Any]): global notebook notebook = nbf.v4.new_notebook() create_install_libraries_cells(notebook['cells']) flash_attention_value = get_value(components, FLASH_ATTENTION_ID) if flash_attention_value: create_install_flash_attention(notebook['cells']) dataset_value = get_value(components, DATASET_SELECTION_ID) seed_value = get_value(components, DATASET_SHUFFLING_SEED) if not check_valid_input(dataset_value): gr.Warning("No dataset is selected") else: create_datasets_cells(notebook['cells'], get_dataset(dataset_value), seed_value) model_value = get_value(components, MODEL_SELECTION_ID) should_login = should_login_to_hf_model(model_value) version_value = "" if not check_valid_input(model_value): gr.Warning("No model is selected!") else: version_value = get_value(components, MODEL_VERSION_SELECTION_ID) if not check_valid_input(version_value): gr.Warning("No version of the model is selected") else: if should_login: create_login_hf_cells(notebook['cells'], should_login=True, model_name=model_value) load_in_4bit = get_value(components, LOAD_IN_4_BIT_ID) bnb_4bit_use_double_quant = get_value(components, BNB_4BIT_USE_DOUBLE_QUANT) bnb_4bit_quant_type = get_value(components, BNB_4BIT_QUANT_TYPE) bnb_4bit_compute_dtype = get_value(components, BNB_4BIT_COMPUTE_DTYPE) pad_side = get_value(components, PAD_SIDE_ID) pad_value = get_value(components, PAD_VALUE_ID) create_model_cells(notebook['cells'], model_id=model_value, version=version_value, flash_attention=flash_attention_value, pad_value=pad_value, pad_side=pad_side, load_in_4bit=load_in_4bit, bnb_4bit_use_double_quant=bnb_4bit_use_double_quant, bnb_4bit_quant_type=bnb_4bit_quant_type, bnb_4bit_compute_dtype=bnb_4bit_compute_dtype) r_value = get_value(components, LORA_R_ID) alpha_value = get_value(components, LORA_ALPHA_ID) dropout_value = get_value(components, LORA_DROPOUT_ID) bias_value = get_value(components, LORA_BIAS_ID) create_lora_config_cells(notebook['cells'], r_value, alpha_value, dropout_value, bias_value) epochs = get_value(components, NUM_TRAIN_EPOCHS_ID) max_steps = get_value(components, MAX_STEPS_ID) logging_steps = get_value(components, LOGGING_STEPS_ID) per_device_train_batch_size = get_value(components, PER_DEVICE_TRAIN_BATCH_SIZE) save_strategy = get_value(components, SAVE_STRATEGY_ID) gradient_accumulation_steps = get_value(components, GRADIENT_ACCUMULATION_STEPS_ID) gradient_checkpointing = get_value(components, GRADIENT_CHECKPOINTING_ID) learning_rate = get_value(components, LEARNING_RATE_ID) max_grad_norm = get_value(components, MAX_GRAD_NORM_ID) warmup_ratio = get_value(components, WARMUP_RATIO_ID) lr_scheduler_type = get_value(components, LR_SCHEDULER_TYPE_ID) output_dir = get_value(components, OUTPUT_DIR_ID) report_to = get_value(components, REPORT_TO_ID) if not check_valid_input(output_dir): gr.Warning("No output_dir is given") create_training_args_cells(notebook['cells'], epochs=epochs, max_steps=max_steps, logging_steps=logging_steps, per_device_train_batch_size=per_device_train_batch_size, save_strategy=save_strategy, gradient_accumulation_steps=gradient_accumulation_steps, gradient_checkpointing=gradient_checkpointing, learning_rate=learning_rate, max_grad_norm=max_grad_norm, warmup_ratio=warmup_ratio, lr_scheduler_type=lr_scheduler_type, output_dir=output_dir, report_to=report_to, seed=seed_value) max_seq_length = get_value(components, MAX_SEQ_LENGTH_ID) packing = get_value(components, PACKING_ID) create_sft_trainer_cells(notebook['cells'], max_seq_length, packing) push_to_hub = get_value(components, PUSH_TO_HUB_ID) create_start_training_cells(notebook['cells'], epochs, max_steps, push_to_hub, output_dir) create_free_gpu_cells(notebook['cells']) create_merge_lora_cells(notebook['cells'], output_dir) merge_model_cells(notebook['cells'], output_dir) create_readme = get_value(components, README_ID) if create_readme: create_hf_card(notebook['cells'], name=output_dir, base_model_name=model_value, base_model_version=version_value, dataset_name=dataset_value, output_dir=output_dir, report_to=report_to) if push_to_hub: if not should_login: create_login_hf_cells(notebook['cells'], output_dir=output_dir) push_to_hub_cells(notebook['cells'], output_dir) file_name = f"{finetuning_notebook}.ipynb" with open(file_name, 'w') as f: nbf.write(notebook, f) return gr.Button( visible=True), f'''
💾️ Download {finetuning_notebook}.ipynb
''', "
" with gr.Blocks(css=css, theme=gr.themes.Soft(text_size='lg', font=["monospace"], primary_hue=gr.themes.colors.blue)) as demo: gr.Label("UI-Guided LLM Fine-Tuning Jupyter Notebook Generator 🛠️🧠", show_label=False) gr.Markdown(''' This space generates a **Jupyter Notebook file (.ipynb)** 📔⚙️ that guides you through the entire process of **supervised fine-tuning** of a raw Large Language Model (**LLM**) 🧠 on a chosen dataset in the **Conversational format**. The process is facilitated by an intuitive **User Interface (UI)** 👆💻 **:** ''', elem_classes=["center_text"]) with dashed_row(): with centered_column(): with gr.Accordion("1. No Coding Required", open=False): gr.Markdown("The UI guides you through the entire process, eliminating the need for manual coding.") with gr.Accordion("2. Customizable Parameters", open=False): gr.Markdown( "You can customize the most commonly used parameters for supervised fine-tuning to suit your needs.") with centered_column(): with gr.Accordion("3. Comprehensive Notebook", open=False): gr.Markdown("The generated .ipynb contains all steps, from installing libraries and writing a " "README.md, " "to pushing the final model to the Hugging Face Hub.") with gr.Accordion("4. Preview Before Download", open=False): gr.Markdown("You can preview the generated .ipynb before downloading it to ensure it " "meets " "your requirements.") with centered_column(): with gr.Accordion("5. User-Friendly", open=False): gr.Markdown("The UI is designed to be easy to use and understand, making the fine-tuning process " "accessible " "to everyone.") with gr.Accordion("6. Open-Source", open=False): gr.Markdown( "This space is open source, so you can collaborate to improve it and make it more powerful.") all_components: Set[Component] = set() gr.HTML("

Model 🧠

") with gr.Row(): model_selection = gr.Dropdown( [model.name for model in models], elem_id=MODEL_SELECTION_ID, label="Select a raw LLM", info="Select a raw Large Language Model (LLM) to fine-tune." ) version_selection = gr.Dropdown( choices=[], label="Select a Model Version 🔄", info="", visible=False, elem_id=MODEL_VERSION_SELECTION_ID ) all_components.add(model_selection) all_components.add(version_selection) gr.HTML("

Dataset 📊

") with gr.Row(): all_components.update(add_dataset_components()) gr.HTML("

⚡ Flash Attention ⚡

") with gr.Row(): flash_attention = gr.Checkbox(value=True, label="Enable Flash Attention", interactive=True, elem_id=FLASH_ATTENTION_ID, info="Flash Attention is a technique that reduces the memory and runtime costs " "associated with " "the attention layer in a model. For more details, please refer to the " "Flash Attention " "repository on GitHub.") all_components.add(flash_attention) gr.HTML("

Quantization

") with gr.Row(): with centered_column(): all_components.update(add_quantization_components()) with centered_column(): all_components.update(add_quantization_components1()) gr.HTML("

Tokenizer Configuration

") with gr.Row(): all_components.update(add_pad_tokens()) gr.HTML("

LoRA Configuration

") with gr.Row(): with centered_column(): all_components.update(add_lora_components1()) with centered_column(): all_components.update(add_lora_components()) gr.HTML("

⚙️ Training Arguments ⚙️

") with gr.Row(): with centered_column(): all_components.update(add_training_args_1()) all_components.update(add_training_args_1_bis()) with centered_column(): all_components.update(add_training_args_3()) gr.HTML("

Optimizer Arguments

") with gr.Row(): with centered_column(): optimizer1 = add_optimizer1() all_components.update(optimizer1) with centered_column(): optimizer = add_optimizer() all_components.update(optimizer) gr.HTML("

Outputs

") with gr.Row(): with centered_column(): output_dir_cmp, push_to_hub_cmp = add_outputs() all_components.update({output_dir_cmp, push_to_hub_cmp}) with centered_column(): all_components.update(add_outputs1()) gr.HTML("

SFTTrainer Arguments

") with gr.Row(): sft_args = add_sft_trainer_args() all_components.update(sft_args) with gr.Row(): iframe = gr.HTML(show_label=False, visible=True) with gr.Row(): greet_btn = gr.Button("Generate 🛠️", variant="primary") with gr.Row(): preview_btn = gr.Button(f"👀 Preview {finetuning_notebook}.ipynb", variant="primary", visible=False) download_btn = gr.HTML(show_label=False, visible=True) greet_btn.click(fn=generate_code, inputs=all_components, outputs=[preview_btn, download_btn, iframe]) preview_btn.click(fn=preview_notebook, inputs=None, outputs=iframe) model_selection.change( fn=change_model_selection, inputs=model_selection, outputs=version_selection ) demo.launch(allowed_paths=["/"]) # Upload metrics to the hub.... """ import os from huggingface_hub import Repository # Create a repository object repo = Repository("Menouar/ft-phi-1") # Push the runs directory os.system(f"git -C {repo.local_dir} add output_dir/runs") repo.git_commit("Adding TensorBoard logs") repo.push_to_hub(commit_message="Adding TensorBoard logs") """