.. _i-scaling-compute-gpt: .. role:: raw-html(raw) :format: html Scaling Compute: Training a BabyGPT =================================== In this tutorial, we will examine how we can scale up `EIR` to train a baby version of the GPT model, streaming data from the FineWeb dataset for model training. .. note:: This tutorial assumes you are familiar with the basics of `EIR`. While not required, it's recommended to have gone through the basic tutorials first. .. note:: See :ref:`i-scaling-streaming-data` and :ref:`streaming-data-guide` for more information on streaming data in EIR. A - Overview ------------ This tutorial largely follows the same approach as in :ref:`i-scaling-streaming-data`. Again, we will be using a WebSocket server to stream data, but this time we will be focusing on scaling compute by training a larger model. B - Setting Up -------------- Here's the folder structure we'll be working with: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/commands/tutorial_folder.txt :language: console The global config specifies basic training and below are highlighted a couple related to scaling: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/globals.yaml :language: yaml :caption: globals.yaml :emphasize-lines: 8-10,17-24 Now, the optimization parameters are not directly related to scaling, but follow common practice used to train large language models such as GPT2. However, we do specify that we want to compile the model and train with a ``bf16-mixed`` precision, which is becoming common practice for training large models. Additionally, many options related to e.g. hardware are set to ``auto`` (which is the default), which allows the framework to automatically select the best options for the compute environment being used. Note a lot of this functionality is taking advantage of the excellent done by the folks at `PyTorch `__ and `Fabric `__. You might also notice the ``streaming_setup_samples`` option there, read a bit further down to when we are discussing the ``output.yaml`` for more details. For fusion, we use a simple pass-through configuration since we're only doing sequence generation: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/fusion.yaml :language: yaml :caption: fusion.yaml Compared to the streaming tutorial, we can see here how we are increasing the maximum sequence length used by the model (now 512), as well as a bunch of parameters in the model configuration. .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/output.yaml :language: yaml :caption: output.yaml :emphasize-lines: 10,15-22 You might also notice something new here, we are using the ``tokenizer`` option to point to the file ``fineweb_tokenizer.json``. This is a tokenizer file created with the `tokenizers `__ library, specifically the BPE tokenizer, trained on 0.5m samples from the FineWeb dataset. You can download the tokenizer file from `this link. `__. Now, we can also omit this and allow ``EIR`` to train the optimizer from scratch, this is where the ``streaming_setup_samples`` option comes in. This option controls how many samples are collected from the streaming server to use for setup (e.g., training the tokenizer, estimating means for imputation, etc.). However, training the tokenizer can take a while, so to speed things up a bit, we are using the pre-trained tokenizer. C - Training ------------ Before starting training, we need to ensure our streaming server is running. The server will serve chunks of text from the FineWeb dataset. Once it's running, we can start training: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/commands/STREAMING_SEQUENCE_GENERATION.txt :language: console Now, to train this, you almost certainly need a GPU. For this tutorial, the model was trained for around 2 hours on two H100 GPUs. At iteration 500: .. container:: wrapped-output .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/figures/auto_generated_iter_500.txt :language: console :caption: Auto-generated sequence at iteration 500 .. container:: wrapped-output .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/figures/manual_generated_iter_500.txt :language: console :caption: Manually generated sequence at iteration 500 By iteration 52000, we can see improvement: .. container:: wrapped-output .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/figures/auto_generated_iter_52000.txt :language: console :caption: Auto-generated sequence at iteration 52000 .. container:: wrapped-output .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/figures/manual_generated_iter_52000.txt :language: console :caption: Manually generated sequence at iteration 52000 Here's the training curve showing our progress: .. image:: ../tutorial_files/i_scaling/02_scaling_compute/figures/training_curve_LOSS.png :width: 100% :align: center D - Complete Server Implementation ---------------------------------- Here's the complete implementation of our streaming server, which you can use as a reference for implementing your own: .. literalinclude:: ../../doc_modules/i_scaling/text_streamer.py :language: python :caption: text_streamer.py E - Supervised Fine-Tuning from a Pretrained Model -------------------------------------------------- In this section, we will explore how to perform supervised fine-tuning (SFT) using a pretrained model. This approach allows us to leverage the knowledge already captured in a pretrained model and adapt it to a new specific task. For this example, we'll use the model we trained in the previous section as our pretrained checkpoint and fine-tune it on the Alpaca dataset, which contains instruction-following examples. Training """""""" .. note:: If you look at the code in the ``text_streamer.py`` file, you might notice that the dataset to use is grabbed from a ``DATASET_NAME`` environment variable. To use the Alpaca dataset, start the server with the following command: ``DATASET_NAME=tatsu-lab/alpaca python text_streamer.py``. Before starting the fine-tuning process, we need to set up our command with the path to the pretrained model: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/commands/SFT_FROM_PRETRAINED_EXPERIMENT.txt :language: console :emphasize-lines: 8-9 Note the important parameters in the command above: - We're specifying a new output folder for our fine-tuned model - We're providing the path to our pretrained checkpoint via the ``pretrained_checkpoint`` parameter This time, our training should be much faster since we're starting from a pretrained model. Let's look at the training curve: .. image:: ../tutorial_files/i_scaling/02_scaling_compute/figures/sft_pretrained_training_curve_LOSS.png :width: 100% :align: center Let's examine the output at different stages of training. At iteration 500: .. container:: wrapped-output .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/figures/sft_pretrained_auto_generated_iter_500.txt :language: console :caption: Auto-generated response at iteration 500 The initial outputs might be somewhat incoherent as the model is still learning the instruction format. By iteration 12000, we can see significant improvement: .. container:: wrapped-output .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/figures/sft_pretrained_auto_generated_iter_12000.txt :language: console :caption: Auto-generated response at iteration 12000 Now the model is starting to generate coherent responses that follow the instruction format, demonstrating the effectiveness of supervised fine-tuning. F - Deploying the Model ----------------------- In this section, we'll demonstrate how to deploy our fine-tuned model as a web service and interact with it using HTTP requests. Starting the Web Service """""""""""""""""""""""" To serve the model, we use the ``eirserve`` command: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/commands/SFT_GENERATION_DEPLOY.txt :language: console This command initiates a web service that listens for incoming requests on the default port (8000). Note that we're specifying: - The GPU device for inference - The path to our fine-tuned model Sending Requests """""""""""""""" With the server running, we can now send inference requests to our model. Here are two approaches to interact with the deployed model: Python Example '''''''''''''' Here's a Python function for sending requests to the model: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/request_example/python_request_example_module.py :language: python :caption: python_request_example_module.py When running this code, we get the following response: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/request_example/python_request_example.json :language: json :caption: python_request_example.json .. note:: Notice how in the response, we often end up with multiple instruction-answer pairs. This is because how the data is structured for the model in the streaming server, where multiple samples are aggregated together into a single sequence. Optimally, we might want to change this for the SFT part to only feed one sample at a time, or build some trimming functionality into our response handling. Bash Example '''''''''''' Alternatively, you can use a simple curl command from bash: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/request_example/bash_request_example_module.sh :language: console :caption: bash_request_example_module.sh This produces a similar response: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/request_example/bash_request_example.json :language: json :caption: bash_request_example.json Analyzing Responses """"""""""""""""""" Let's look at some example responses from our model for various instructions: .. literalinclude:: ../tutorial_files/i_scaling/02_scaling_compute/serve_results/predictions.json :language: json :caption: predictions.json As we can see, the model is able to generate appropriate responses for different types of instructions, from generating creative content to providing explanations and advice. G - Conclusion -------------- In this tutorial, we've explored how to scale up ``EIR`` to train a baby version of the GPT model, stream data for training, and perform supervised fine-tuning using a pretrained checkpoint. We've also learned how to deploy the model as a web service and interact with it using HTTP requests. Thank you for reading!