Spaces:
Sleeping
Sleeping
Omar Solano
commited on
Commit
β’
37cbdf5
1
Parent(s):
afc6d39
add gpt-4o-mini
Browse files- scripts/create_db.ipynb +527 -0
- scripts/custom_retriever.py +65 -0
- scripts/gradio-ui.py +112 -38
- scripts/tutor_prompts.py +22 -12
scripts/create_db.ipynb
CHANGED
@@ -268,6 +268,517 @@
|
|
268 |
" document_dict = pickle.load(f)"
|
269 |
]
|
270 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
{
|
272 |
"cell_type": "code",
|
273 |
"execution_count": 4,
|
@@ -347,6 +858,22 @@
|
|
347 |
")"
|
348 |
]
|
349 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
350 |
{
|
351 |
"cell_type": "code",
|
352 |
"execution_count": null,
|
|
|
268 |
" document_dict = pickle.load(f)"
|
269 |
]
|
270 |
},
|
271 |
+
{
|
272 |
+
"cell_type": "code",
|
273 |
+
"execution_count": 6,
|
274 |
+
"metadata": {},
|
275 |
+
"outputs": [
|
276 |
+
{
|
277 |
+
"name": "stdout",
|
278 |
+
"output_type": "stream",
|
279 |
+
"text": [
|
280 |
+
"The LLM sees this: \n",
|
281 |
+
" url: https://huggingface.co/docs/transformers/deepspeed\n",
|
282 |
+
"\n",
|
283 |
+
"DeepSpeed is a PyTorch optimization library that makes distributed training memory-efficient and fast. At itβs core is the Zero Redundancy Optimizer (ZeRO) which enables training large models at scale. ZeRO works in several stages:\n",
|
284 |
+
"ZeRO-1, optimizer state partioning across GPUs ZeRO-2, gradient partitioning across GPUs ZeRO-3, parameteter partitioning across GPUs\n",
|
285 |
+
"In GPU-limited environments, ZeRO also enables offloading optimizer memory and computation from the GPU to the CPU to fit and train really large models on a single GPU. DeepSpeed is integrated with the Transformers Trainer class for all ZeRO stages and offloading. All you need to do is provide a config file or you can use a provided template. For inference, Transformers support ZeRO-3 and offloading since it allows loading huge models.\n",
|
286 |
+
"This guide will walk you through how to deploy DeepSpeed training, the features you can enable, how to setup the config files for different ZeRO stages, offloading, inference, and using DeepSpeed without the Trainer .\n",
|
287 |
+
"\n",
|
288 |
+
"DeepSpeed is available to install from PyPI or Transformers (for more detailed installation options, take a look at the DeepSpeed installation details or the GitHub README ).\n",
|
289 |
+
"If youβre having difficulties installing DeepSpeed, check the DeepSpeed CUDA installation guide. While DeepSpeed has a pip installable PyPI package, it is highly recommended to install it from source to best match your hardware and to support certain features, like 1-bit Adam, which arenβt available in the PyPI distribution.\n",
|
290 |
+
"PyPI Transformers\n",
|
291 |
+
"Copied pip install deepspeed\n",
|
292 |
+
"\n",
|
293 |
+
"Before you begin, it is a good idea to check whether you have enough GPU and CPU memory to fit your model. DeepSpeed provides a tool for estimating the required CPU/GPU memory. For example, to estimate the memory requirements for the bigscience/T0_3B model on a single GPU:\n",
|
294 |
+
"Copied $ python -c 'from transformers import AutoModel; \\\n",
|
295 |
+
"from deepspeed.runtime.zero.stage3 import estimate_zero3_model_states_mem_needs_all_live; \\\n",
|
296 |
+
"model = AutoModel.from_pretrained(\"bigscience/T0_3B\"); \\\n",
|
297 |
+
"estimate_zero3_model_states_mem_needs_all_live(model, num_gpus_per_node=1, num_nodes=1)' [...]\n",
|
298 |
+
"Estimated memory needed for params, optim states and gradients for a:\n",
|
299 |
+
"HW: Setup with 1 node, 1 GPU per node.\n",
|
300 |
+
"SW: Model with 2783M total params, 65M largest layer params.\n",
|
301 |
+
" per CPU | per GPU | Options\n",
|
302 |
+
" 70.00GB | 0.25GB | offload_param=cpu , offload_optimizer=cpu , zero_init=1\n",
|
303 |
+
" 70.00GB | 0.25GB | offload_param=cpu , offload_optimizer=cpu , zero_init=0\n",
|
304 |
+
" 62.23GB | 5.43GB | offload_param=none, offload_optimizer=cpu , zero_init=1\n",
|
305 |
+
" 62.23GB | 5.43GB | offload_param=none, offload_optimizer=cpu , zero_init=0\n",
|
306 |
+
" 0.37GB | 46.91GB | offload_param=none, offload_optimizer=none, zero_init=1\n",
|
307 |
+
" 15.56GB | 46.91GB | offload_param=none, offload_optimizer=none, zero_init=0\n",
|
308 |
+
"This means you either need a single 80GB GPU without CPU offload or a 8GB GPU and a ~60GB CPU to offload to (these are just the memory requirements for the parameters, optimizer states and gradients, and youβll need a bit more for the CUDA kernels and activations). You should also consider the tradeoff between cost and speed because itβll be cheaper to rent or buy a smaller GPU but itβll take longer to train your model.\n",
|
309 |
+
"If you have enough GPU memory make sure you disable CPU/NVMe offload to make everything faster.\n",
|
310 |
+
"\n",
|
311 |
+
"After youβve installed DeepSpeed and have a better idea of your memory requirements, the next step is selecting a ZeRO stage to use. In order of fastest and most memory-efficient:\n",
|
312 |
+
"| Fastest | Memory efficient |\n",
|
313 |
+
"|------------------|--------------------|\n",
|
314 |
+
"| ZeRO-1 | ZeRO-3 + offload |\n",
|
315 |
+
"| ZeRO-2 | ZeRO-3 |\n",
|
316 |
+
"| ZeRO-2 + offload | ZeRO-2 + offload |\n",
|
317 |
+
"| ZeRO-3 | ZeRO-2 |\n",
|
318 |
+
"| ZeRO-3 + offload | ZeRO-1 |\n",
|
319 |
+
"To find what works best for you, start with the fastest approach and if you run out of memory, try the next stage which is slower but more memory efficient. Feel free to work in whichever direction you prefer (starting with the most memory efficient or fastest) to discover the appropriate balance between speed and memory usage.\n",
|
320 |
+
"A general process you can use is (start with batch size of 1):\n",
|
321 |
+
"enable gradient checkpointing try ZeRO-2 try ZeRO-2 and offload the optimizer try ZeRO-3 try ZeRO-3 and offload parameters to the CPU try ZeRO-3 and offload parameters and the optimizer to the CPU try lowering various default values like a narrower search beam if youβre using the generate() method try mixed half-precision (fp16 on older GPU architectures and bf16 on Ampere) over full-precision weights add more hardware if possible or enable Infinity to offload parameters and the optimizer to a NVMe once youβre not running out of memory, measure effective throughput and then try to increase the batch size as large as you can to maximize GPU efficiency lastly, try to optimize your training setup by disabling some offload features or use a faster ZeRO stage and increasing/decreasing the batch size to find the best tradeoff between speed and memory usage\n",
|
322 |
+
"\n",
|
323 |
+
"DeepSpeed works with the Trainer class by way of a config file containing all the parameters for configuring how you want setup your training run. When you execute your training script, DeepSpeed logs the configuration it received from Trainer to the console so you can see exactly what configuration was used.\n",
|
324 |
+
"Find a complete list of DeepSpeed configuration options on the DeepSpeed Configuration JSON reference. You can also find more practical examples of various DeepSpeed configuration examples on the DeepSpeedExamples repository or the main DeepSpeed repository. To quickly find specific examples, you can: Copied git clone https://github.com/microsoft/DeepSpeedExamples cd DeepSpeedExamples\n",
|
325 |
+
"find . -name '*json' # find examples with the Lamb optimizer grep -i Lamb $(find . -name '*json' )\n",
|
326 |
+
"The DeepSpeed configuration file is passed as a path to a JSON file if youβre training from the command line interface or as a nested dict object if youβre using the Trainer in a notebook setting.\n",
|
327 |
+
"path to file nested dict\n",
|
328 |
+
"Copied TrainingArguments(..., deepspeed= \"path/to/deepspeed_config.json\" )\n",
|
329 |
+
"\n",
|
330 |
+
"There are three types of configuration parameters:\n",
|
331 |
+
"Some of the configuration parameters are shared by Trainer and DeepSpeed, and it can be difficult to identify errors when there are conflicting definitions. To make it easier, these shared configuration parameters are configured from the Trainer command line arguments. Some configuration parameters that are automatically derived from the model configuration so you donβt need to manually adjust these values. The Trainer uses a configuration value auto to determine set the most correct or efficient value. You could set your own configuration parameters explicitly, but you must take care to ensure the Trainer arguments and DeepSpeed configuration parameters agree. Mismatches may cause the training to fail in very difficult to detect ways! Some configuration parameters specific to DeepSpeed only which need to be manually set based on your training needs.\n",
|
332 |
+
"You could also modify the DeepSpeed configuration and edit TrainingArguments from it:\n",
|
333 |
+
"Create or load a DeepSpeed configuration to used as the main configuration Create a TrainingArguments object based on these DeepSpeed configuration values\n",
|
334 |
+
"Some values, such as scheduler.params.total_num_steps are calculated by the Trainer during training.\n",
|
335 |
+
"\n",
|
336 |
+
"There are three configurations, each corresponding to a different ZeRO stage. Stage 1 is not as interesting for scalability, and this guide focuses on stages 2 and 3. The zero_optimization configuration contains all the options for what to enable and how to configure them. For a more detailed explanation of each parameter, take a look at the DeepSpeed Configuration JSON reference.\n",
|
337 |
+
"DeepSpeed doesnβt validate parameter names and any typos fallback on the parameter's default setting. You can watch the DeepSpeed engine startup log messages to see what values it is going to use.\n",
|
338 |
+
"The following configurations must be setup with DeepSpeed because the Trainer doesnβt provide equivalent command line arguments.\n",
|
339 |
+
"ZeRO-1 ZeRO-2 ZeRO-3\n",
|
340 |
+
"ZeRO-1 shards the optimizer states across GPUs, and you can expect a tiny speed up. The ZeRO-1 config can be setup like this: Copied { \"zero_optimization\": { \"stage\": 1 }\n",
|
341 |
+
"}\n",
|
342 |
+
"\n",
|
343 |
+
"ZeRO-Infinity allows offloading model states to the CPU and/or NVMe to save even more memory. Smart partitioning and tiling algorithms allow each GPU to send and receive very small amounts of data during offloading such that a modern NVMe can fit an even larger total memory pool than is available to your training process. ZeRO-Infinity requires ZeRO-3.\n",
|
344 |
+
"Depending on the CPU and/or NVMe memory available, you can offload both the optimizer states and parameters , just one of them, or none. You should also make sure the nvme_path is pointing to an NVMe device, because while it still works with a normal hard drive or solid state drive, itβll be significantly slower. With a modern NVMe, you can expect peak transfer speeds of ~3.5GB/s for read and ~3GB/s for write operations. Lastly, run a benchmark on your training setup to determine the optimal aio configuration.\n",
|
345 |
+
"The example ZeRO-3/Infinity configuration file below sets most of the parameter values to auto , but you could also manually add these values.\n",
|
346 |
+
"Copied { \"fp16\": { \"enabled\": \"auto\" , \"loss_scale\": 0 , \"loss_scale_window\": 1000 , \"initial_scale_power\": 16 , \"hysteresis\": 2 , \"min_loss_scale\": 1 }, \"optimizer\": { \"type\": \"AdamW\" , \"params\": { \"lr\": \"auto\" , \"betas\": \"auto\" , \"eps\": \"auto\" , \"weight_decay\": \"auto\" }\n",
|
347 |
+
" }, \"scheduler\": { \"type\": \"WarmupLR\" , \"params\": { \"warmup_min_lr\": \"auto\" , \"warmup_max_lr\": \"auto\" , \"warmup_num_steps\": \"auto\" }\n",
|
348 |
+
" }, \"zero_optimization\": { \"stage\": 3 , \"offload_optimizer\": { \"device\": \"nvme\" , \"nvme_path\": \"/local_nvme\" , \"pin_memory\": true , \"buffer_count\": 4 , \"fast_init\": false }, \"offload_param\": { \"device\": \"nvme\" , \"nvme_path\": \"/local_nvme\" , \"pin_memory\": true , \"buffer_count\": 5 , \"buffer_size\": 1e8 , \"max_in_cpu\": 1e9 }, \"aio\": { \"block_size\": 262144 , \"queue_depth\": 32 , \"thread_count\": 1 , \"single_submit\": false , \"overlap_events\": true }, \"overlap_comm\": true , \"contiguous_gradients\": true , \"sub_group_size\": 1e9 , \"reduce_bucket_size\": \"auto\" , \"stage3_prefetch_bucket_size\": \"auto\" , \"stage3_param_persistence_threshold\": \"auto\" , \"stage3_max_live_parameters\": 1e9 , \"stage3_max_reuse_distance\": 1e9 , \"stage3_gather_16bit_weights_on_model_save\": true }, \"gradient_accumulation_steps\": \"auto\" , \"gradient_clipping\": \"auto\" , \"steps_per_print\": 2000 , \"train_batch_size\": \"auto\" , \"train_micro_batch_size_per_gpu\": \"auto\" , \"wall_clock_breakdown\": false }\n",
|
349 |
+
"\n",
|
350 |
+
"There are a number of important parameters to specify in the DeepSpeed configuration file which are briefly described in this section.\n",
|
351 |
+
"\n",
|
352 |
+
"Activation and gradient checkpointing trades speed for more GPU memory which allows you to overcome scenarios where your GPU is out of memory or to increase your batch size for better performance. To enable this feature:\n",
|
353 |
+
"For a Hugging Face model, set model.gradient_checkpointing_enable() or --gradient_checkpointing in the Trainer . For a non-Hugging Face model, use the DeepSpeed Activation Checkpointing API . You could also replace the Transformers modeling code and replace torch.utils.checkpoint with the DeepSpeed API. This approach is more flexible because you can offload the forward activations to the CPU memory instead of recalculating them.\n",
|
354 |
+
"\n",
|
355 |
+
"DeepSpeed and Transformers optimizer and scheduler can be mixed and matched as long as you donβt enable offload_optimizer . When offload_optimizer is enabled, you could use a non-DeepSpeed optimizer (except for LAMB) as long as it has both a CPU and GPU implementation.\n",
|
356 |
+
"The optimizer and scheduler parameters for the config file can be set from the command line to avoid hard to find errors. For example, if the learning rate is set to a different value in another place you can override it from the command line. Aside from the optimizer and scheduler parameters, youβll need to ensure your Trainer command line arguments match the DeepSpeed configuration.\n",
|
357 |
+
"optimizer scheduler\n",
|
358 |
+
"DeepSpeed offers several optimizers (Adam, AdamW, OneBitAdam, and LAMB) but you can also import other optimizers from PyTorch. If you donβt configure the optimizer in the config, the Trainer automatically selects AdamW and either uses the supplied values or the default values for the following parameters from the command line: lr , adam_beta1 , adam_beta2 , adam_epsilon , weight_decay . You can set the parameters to \"auto\" or manually input your own desired values. Copied { \"optimizer\": { \"type\": \"AdamW\" , \"params\": { \"lr\": \"auto\" , \"betas\": \"auto\" , \"eps\": \"auto\" , \"weight_decay\": \"auto\" }\n",
|
359 |
+
" }\n",
|
360 |
+
"} You can also use an unsupported optimizer by adding the following to the top level configuration. Copied { \"zero_allow_untested_optimizer\": true } From DeepSpeed==0.8.3 on, if you want to use offload, youβll also need to the following to the top level configuration because offload works best with DeepSpeedβs CPU Adam optimizer. Copied { \"zero_force_ds_cpu_optimizer\": false }\n",
|
361 |
+
"\n",
|
362 |
+
"Deepspeed supports fp32, fp16, and bf16 mixed precision.\n",
|
363 |
+
"fp32 fp16 bf16\n",
|
364 |
+
"If your model doesnβt work well with mixed precision, for example if it wasnβt pretrained in mixed precision, you may encounter overflow or underflow issues which can cause NaN loss. For these cases, you should use full fp32 precision by explicitly disabling the default fp16 mode. Copied { \"fp16\": { \"enabled\": false }\n",
|
365 |
+
"} For Ampere GPUs and PyTorch > 1.7, it automatically switches to the more efficient tf32 format for some operations but the results are still in fp32. You can control it from the Trainer by setting --tf32 to enable it, and --tf32 0 or --no_tf32 to disable it.\n",
|
366 |
+
"\n",
|
367 |
+
"The batch size can be auto-configured or explicitly set. If you choose to use the \"auto\" option, Trainer sets train_micro_batch_size_per_gpu to the value of args. per_device_train_batch_size and train_batch_size to args.world_size * args.per_device_train_batch_size * args.gradient_accumulation_steps .\n",
|
368 |
+
"Copied { \"train_micro_batch_size_per_gpu\": \"auto\" , \"train_batch_size\": \"auto\" }\n",
|
369 |
+
"\n",
|
370 |
+
"Gradient accumulation can be auto-configured or explicitly set. If you choose to use the \"auto\" option, Trainer sets it to the value of args.gradient_accumulation_steps .\n",
|
371 |
+
"Copied { \"gradient_accumulation_steps\": \"auto\" }\n",
|
372 |
+
"\n",
|
373 |
+
"Gradient clipping can be auto-configured or explicitly set. If you choose to use the \"auto\" option, Trainer sets it to the value of args.max_grad_norm .\n",
|
374 |
+
"Copied { \"gradient_clipping\": \"auto\" }\n",
|
375 |
+
"\n",
|
376 |
+
"For communication collectives like reduction, gathering and scattering operations, a separate data type is used.\n",
|
377 |
+
"All gather and scatter operations are performed in the same data type the data is in. For example, if youβre training with bf16, the data is also gathered in bf16 because gathering is a non-lossy operation.\n",
|
378 |
+
"Reduce operations are lossy, for example when gradients are averaged across multiple GPUs. When the communication is done in fp16 or bf16, it is more likely to be lossy because adding multiple numbers in low precision isnβt exact. This is especially the case with bf16 which has a lower precision than fp16. For this reason, fp16 is the default for reduction operations because the loss is minimal when averaging gradients.\n",
|
379 |
+
"You can choose the communication data type by setting the communication_data_type parameter in the config file. For example, choosing fp32 adds a small amount of overhead but ensures the reduction operation is accumulated in fp32 and when it is ready, it is downcasted to whichever half-precision dtype youβre training in.\n",
|
380 |
+
"Copied { \"communication_data_type\": \"fp32\" }\n",
|
381 |
+
"\n",
|
382 |
+
"DeepSpeed can be deployed by different launchers such as torchrun , the deepspeed launcher, or Accelerate . To deploy, add --deepspeed ds_config.json to the Trainer command line. Itβs recommended to use DeepSpeedβs add_config_arguments utility to add any necessary command line arguments to your code.\n",
|
383 |
+
"This guide will show you how to deploy DeepSpeed with the deepspeed launcher for different training setups. You can check out this post for more practical usage examples.\n",
|
384 |
+
"multi-GPU single-GPU\n",
|
385 |
+
"To deploy DeepSpeed on multiple GPUs, add the --num_gpus parameter. If you want to use all available GPUs, you donβt need to add --num_gpus . The example below uses 2 GPUs. Copied deepspeed --num_gpus=2 examples/pytorch/translation/run_translation.py \\\n",
|
386 |
+
"--deepspeed tests/deepspeed/ds_config_zero3.json \\\n",
|
387 |
+
"--model_name_or_path google-t5/t5-small --per_device_train_batch_size 1 \\\n",
|
388 |
+
"--output_dir output_dir --overwrite_output_dir --fp16 \\\n",
|
389 |
+
"--do_train --max_train_samples 500 --num_train_epochs 1 \\\n",
|
390 |
+
"--dataset_name wmt16 --dataset_config \"ro-en\" \\\n",
|
391 |
+
"--source_lang en --target_lang ro\n",
|
392 |
+
"\n",
|
393 |
+
"A node is one or more GPUs for running a workload. A more powerful setup is a multi-node setup which can be launched with the deepspeed launcher. For this guide, letβs assume there are two nodes with 8 GPUs each. The first node can be accessed ssh hostname1 and the second node with ssh hostname2 . Both nodes must be able to communicate with each other locally over ssh without a password.\n",
|
394 |
+
"By default, DeepSpeed expects your multi-node environment to use a shared storage. If this is not the case and each node can only see the local filesystem, you need to adjust the config file to include a checkpoint to allow loading without access to a shared filesystem:\n",
|
395 |
+
"Copied { \"checkpoint\": { \"use_node_local_storage\": true }\n",
|
396 |
+
"}\n",
|
397 |
+
"You could also use the Trainer βs --save_on_each_node argument to automatically add the above checkpoint to your config.\n",
|
398 |
+
"torchrun deepspeed\n",
|
399 |
+
"For torchrun , you have to ssh to each node and run the following command on both of them. The launcher waits until both nodes are synchronized before launching the training. Copied torchrun --nproc_per_node=8 --nnode=2 --node_rank=0 --master_addr=hostname1 \\\n",
|
400 |
+
"--master_port=9901 your_program.py <normal cl args> --deepspeed ds_config.json\n",
|
401 |
+
"\n",
|
402 |
+
"In a SLURM environment, youβll need to adapt your SLURM script to your specific SLURM environment. An example SLURM script may look like:\n",
|
403 |
+
"Copied #SBATCH --job-name=test-nodes # name #SBATCH --nodes=2 # nodes #SBATCH --ntasks-per-node=1 # crucial - only 1 task per dist per node! #SBATCH --cpus-per-task=10 # number of cores per tasks #SBATCH --gres=gpu:8 # number of gpus #SBATCH --time 20:00:00 # maximum execution time (HH:MM:SS) #SBATCH --output=%x-%j.out # output file name export GPUS_PER_NODE=8 export MASTER_ADDR=$(scontrol show hostnames $SLURM_JOB_NODELIST | head -n 1) export MASTER_PORT=9901\n",
|
404 |
+
"\n",
|
405 |
+
"srun --jobid $SLURM_JOBID bash -c 'python -m torch.distributed.run \\\n",
|
406 |
+
" --nproc_per_node $GPUS_PER_NODE --nnodes $SLURM_NNODES --node_rank $SLURM_PROCID \\\n",
|
407 |
+
" --master_addr $MASTER_ADDR --master_port $MASTER_PORT \\\n",
|
408 |
+
"your_program.py <normal cl args> --deepspeed ds_config.json'\n",
|
409 |
+
"Then you can schedule your multi-node deployment with the following command which launches training simultaneously on all nodes.\n",
|
410 |
+
"Copied sbatch launch.slurm\n",
|
411 |
+
"\n",
|
412 |
+
"The deepspeed launcher doesnβt support deployment from a notebook so youβll need to emulate the distributed environment. However, this only works for 1 GPU. If you want to use more than 1 GPU, you must use a multi-process environment for DeepSpeed to work. This means you have to use the deepspeed launcher which canβt be emulated as shown here.\n",
|
413 |
+
"Copied # DeepSpeed requires a distributed environment even when only one process is used. # This emulates a launcher in the notebook import os\n",
|
414 |
+
"\n",
|
415 |
+
"os.environ[ \"MASTER_ADDR\" ] = \"localhost\" os.environ[ \"MASTER_PORT\" ] = \"9994\" # modify if RuntimeError: Address already in use os.environ[ \"RANK\" ] = \"0\" os.environ[ \"LOCAL_RANK\" ] = \"0\" os.environ[ \"WORLD_SIZE\" ] = \"1\" # Now proceed as normal, plus pass the DeepSpeed config file training_args = TrainingArguments(..., deepspeed= \"ds_config_zero3.json\" )\n",
|
416 |
+
"trainer = Trainer(...)\n",
|
417 |
+
"trainer.train()\n",
|
418 |
+
"If you want to create the config file on the fly in the notebook in the current directory, you could have a dedicated cell.\n",
|
419 |
+
"Copied %%bash\n",
|
420 |
+
"cat << 'EOT' > ds_config_zero3.json\n",
|
421 |
+
"{ \"fp16\" : { \"enabled\" : \"auto\" , \"loss_scale\" : 0 , \"loss_scale_window\" : 1000 , \"initial_scale_power\" : 16 , \"hysteresis\" : 2 , \"min_loss_scale\" : 1 }, \"optimizer\" : { \"type\" : \"AdamW\" , \"params\" : { \"lr\" : \"auto\" , \"betas\" : \"auto\" , \"eps\" : \"auto\" , \"weight_decay\" : \"auto\" }\n",
|
422 |
+
" }, \"scheduler\" : { \"type\" : \"WarmupLR\" , \"params\" : { \"warmup_min_lr\" : \"auto\" , \"warmup_max_lr\" : \"auto\" , \"warmup_num_steps\" : \"auto\" }\n",
|
423 |
+
" }, \"zero_optimization\" : { \"stage\" : 3 , \"offload_optimizer\" : { \"device\" : \"cpu\" , \"pin_memory\" : true\n",
|
424 |
+
" }, \"offload_param\" : { \"device\" : \"cpu\" , \"pin_memory\" : true\n",
|
425 |
+
" }, \"overlap_comm\" : true, \"contiguous_gradients\" : true, \"sub_group_size\" : 1e9 , \"reduce_bucket_size\" : \"auto\" , \"stage3_prefetch_bucket_size\" : \"auto\" , \"stage3_param_persistence_threshold\" : \"auto\" , \"stage3_max_live_parameters\" : 1e9 , \"stage3_max_reuse_distance\" : 1e9 , \"stage3_gather_16bit_weights_on_model_save\" : true\n",
|
426 |
+
" }, \"gradient_accumulation_steps\" : \"auto\" , \"gradient_clipping\" : \"auto\" , \"steps_per_print\" : 2000 , \"train_batch_size\" : \"auto\" , \"train_micro_batch_size_per_gpu\" : \"auto\" , \"wall_clock_breakdown\" : false\n",
|
427 |
+
"}\n",
|
428 |
+
"EOT\n",
|
429 |
+
"If the training script is in a file and not in a notebook cell, you can launch deepspeed normally from the shell in a notebook cell. For example, to launch run_translation.py :\n",
|
430 |
+
"Copied !git clone https://github.com/huggingface/transformers\n",
|
431 |
+
"!cd transformers; deepspeed examples/pytorch/translation/run_translation.py ...\n",
|
432 |
+
"You could also use %%bash magic and write multi-line code to run the shell program, but you wonβt be able to view the logs until training is complete. With %%bash magic, you donβt need to emulate a distributed environment.\n",
|
433 |
+
"Copied %%bash\n",
|
434 |
+
"\n",
|
435 |
+
"git clone https://github.com/huggingface/transformers\n",
|
436 |
+
"cd transformers\n",
|
437 |
+
"deepspeed examples/pytorch/translation/run_translation.py ...\n",
|
438 |
+
"\n",
|
439 |
+
"DeepSpeed stores the main full precision fp32 weights in custom checkpoint optimizer files (the glob pattern looks like global_step*/*optim_states.pt ) and are saved under the normal checkpoint.\n",
|
440 |
+
"fp16 fp32\n",
|
441 |
+
"A model trained with ZeRO-2 saves the pytorch_model.bin weights in fp16. To save the model weights in fp16 for a model trained with ZeRO-3, you need to set \"stage3_gather_16bit_weights_on_model_save\": true because the model weights are partitioned across multiple GPUs. Otherwise, the Trainer wonβt save the weights in fp16 and it wonβt create a pytorch_model.bin file. This is because DeepSpeedβs state_dict contains a placeholder instead of the real weights and you wonβt be able to load them. Copied { \"zero_optimization\": { \"stage3_gather_16bit_weights_on_model_save\": true }\n",
|
442 |
+
"}\n",
|
443 |
+
"\n",
|
444 |
+
"ZeRO Inference places the model weights in CPU or NVMe memory to avoid burdening the GPU which makes it possible to run inference with huge models on a GPU. Inference doesnβt require any large additional amounts of memory for the optimizer states and gradients so you can fit much larger batches and/or sequence lengths on the same hardware.\n",
|
445 |
+
"ZeRO Inference shares the same configuration file as ZeRO-3 , and ZeRO-2 and ZeRO-1 configs wonβt work because they donβt provide any benefits for inference.\n",
|
446 |
+
"To run ZeRO Inference, pass your usual training arguments to the TrainingArguments class and add the --do_eval argument.\n",
|
447 |
+
"Copied deepspeed --num_gpus=2 your_program.py <normal cl args> --do_eval --deepspeed ds_config.json\n",
|
448 |
+
"\n",
|
449 |
+
"DeepSpeed also works with Transformers without the Trainer class. This is handled by the HfDeepSpeedConfig which only takes care of gathering ZeRO-3 parameters and splitting a model across multiple GPUs when you call from_pretrained() .\n",
|
450 |
+
"If you want everything automatically taken care of for you, try using DeepSpeed with the Trainer ! Youβll need to follow the DeepSpeed documentation , and manually configure the parameter values in the config file (you canβt use the \"auto\" value).\n",
|
451 |
+
"To efficiently deploy ZeRO-3, you must instantiate the HfDeepSpeedConfig object before the model and keep that object alive:\n",
|
452 |
+
"pretrained model non-pretrained model\n",
|
453 |
+
"Copied from transformers.integrations import HfDeepSpeedConfig from transformers import AutoModel import deepspeed\n",
|
454 |
+
"\n",
|
455 |
+
"ds_config = {...} # deepspeed config object or path to the file # must run before instantiating the model to detect zero 3 dschf = HfDeepSpeedConfig(ds_config) # keep this object alive model = AutoModel.from_pretrained( \"openai-community/gpt2\" )\n",
|
456 |
+
"engine = deepspeed.initialize(model=model, config_params=ds_config, ...)\n",
|
457 |
+
"\n",
|
458 |
+
"To run ZeRO Inference without the Trainer in cases where you canβt fit a model onto a single GPU, try using additional GPUs or/and offloading to CPU memory. The important nuance to understand here is that the way ZeRO is designed, you can process different inputs on different GPUs in parallel.\n",
|
459 |
+
"Make sure to:\n",
|
460 |
+
"disable CPU offload if you have enough GPU memory (since it slows things down). enable bf16 if you have an Ampere or newer GPU to make things faster. If you donβt have one of these GPUs, you may enable fp16 as long as you donβt use a model pretrained in bf16 (T5 models) because it may lead to an overflow error.\n",
|
461 |
+
"Take a look at the following script to get a better idea of how to run ZeRO Inference without the Trainer on a model that wonβt fit on a single GPU.\n",
|
462 |
+
"Copied #!/usr/bin/env python # This script demonstrates how to use Deepspeed ZeRO in an inference mode when one can't fit a model # into a single GPU # # 1. Use 1 GPU with CPU offload # 2. Or use multiple GPUs instead # # First you need to install deepspeed: pip install deepspeed # # Here we use a 3B \"bigscience/T0_3B\" model which needs about 15GB GPU RAM - so 1 largish or 2 # small GPUs can handle it. or 1 small GPU and a lot of CPU memory. # # To use a larger model like \"bigscience/T0\" which needs about 50GB, unless you have an 80GB GPU - # you will need 2-4 gpus. And then you can adapt the script to handle more gpus if you want to # process multiple inputs at once. # # The provided deepspeed config also activates CPU memory offloading, so chances are that if you # have a lot of available CPU memory and you don't mind a slowdown you should be able to load a # model that doesn't normally fit into a single GPU. If you have enough GPU memory the program will # run faster if you don't want offload to CPU - so disable that section then. # # To deploy on 1 gpu: # # deepspeed --num_gpus 1 t0.py # or: # python -m torch.distributed.run --nproc_per_node=1 t0.py # # To deploy on 2 gpus: # # deepspeed --num_gpus 2 t0.py # or: # python -m torch.distributed.run --nproc_per_node=2 t0.py from transformers import AutoTokenizer, AutoConfig, AutoModelForSeq2SeqLM from transformers.integrations import HfDeepSpeedConfig import deepspeed import os import torch\n",
|
463 |
+
"\n",
|
464 |
+
"os.environ[ \"TOKENIZERS_PARALLELISM\" ] = \"false\" # To avoid warnings about parallelism in tokenizers # distributed setup local_rank = int (os.getenv( \"LOCAL_RANK\" , \"0\" ))\n",
|
465 |
+
"world_size = int (os.getenv( \"WORLD_SIZE\" , \"1\" ))\n",
|
466 |
+
"torch.cuda.set_device(local_rank)\n",
|
467 |
+
"deepspeed.init_distributed()\n",
|
468 |
+
"\n",
|
469 |
+
"model_name = \"bigscience/T0_3B\" config = AutoConfig.from_pretrained(model_name)\n",
|
470 |
+
"model_hidden_size = config.d_model # batch size has to be divisible by world_size, but can be bigger than world_size train_batch_size = 1 * world_size # ds_config notes # # - enable bf16 if you use Ampere or higher GPU - this will run in mixed precision and will be # faster. # # - for older GPUs you can enable fp16, but it'll only work for non-bf16 pretrained models - e.g. # all official t5 models are bf16-pretrained # # - set offload_param.device to \"none\" or completely remove the `offload_param` section if you don't # - want CPU offload # # - if using `offload_param` you can manually finetune stage3_param_persistence_threshold to control # - which params should remain on gpus - the larger the value the smaller the offload size # # For in-depth info on Deepspeed config see # https://huggingface.co/docs/transformers/main/main_classes/deepspeed # keeping the same format as json for consistency, except it uses lower case for true/false # fmt: off ds_config = { \"fp16\" : { \"enabled\" : False }, \"bf16\" : { \"enabled\" : False }, \"zero_optimization\" : { \"stage\" : 3 , \"offload_param\" : { \"device\" : \"cpu\" , \"pin_memory\" : True }, \"overlap_comm\" : True , \"contiguous_gradients\" : True , \"reduce_bucket_size\" : model_hidden_size * model_hidden_size, \"stage3_prefetch_bucket_size\" : 0.9 * model_hidden_size * model_hidden_size, \"stage3_param_persistence_threshold\" : 10 * model_hidden_size\n",
|
471 |
+
" }, \"steps_per_print\" : 2000 , \"train_batch_size\" : train_batch_size, \"train_micro_batch_size_per_gpu\" : 1 , \"wall_clock_breakdown\" : False } # fmt: on # next line instructs transformers to partition the model directly over multiple gpus using # deepspeed.zero.Init when model's `from_pretrained` method is called. # # **it has to be run before loading the model AutoModelForSeq2SeqLM.from_pretrained(model_name)** # # otherwise the model will first be loaded normally and only partitioned at forward time which is # less efficient and when there is little CPU RAM may fail dschf = HfDeepSpeedConfig(ds_config) # keep this object alive # now a model can be loaded. model = AutoModelForSeq2SeqLM.from_pretrained(model_name) # initialise Deepspeed ZeRO and store only the engine object ds_engine = deepspeed.initialize(model=model, config_params=ds_config)[ 0 ]\n",
|
472 |
+
"ds_engine.module. eval () # inference # Deepspeed ZeRO can process unrelated inputs on each GPU. So for 2 gpus you process 2 inputs at once. # If you use more GPUs adjust for more. # And of course if you have just one input to process you then need to pass the same string to both gpus # If you use only one GPU, then you will have only rank 0. rank = torch.distributed.get_rank() if rank == 0 :\n",
|
473 |
+
" text_in = \"Is this review positive or negative? Review: this is the best cast iron skillet you will ever buy\" elif rank == 1 :\n",
|
474 |
+
" text_in = \"Is this review positive or negative? Review: this is the worst restaurant ever\" tokenizer = AutoTokenizer.from_pretrained(model_name)\n",
|
475 |
+
"inputs = tokenizer.encode(text_in, return_tensors= \"pt\" ).to(device=local_rank) with torch.no_grad():\n",
|
476 |
+
" outputs = ds_engine.module.generate(inputs, synced_gpus= True )\n",
|
477 |
+
"text_out = tokenizer.decode(outputs[ 0 ], skip_special_tokens= True ) print ( f\"rank {rank} :\\n in= {text_in} \\n out= {text_out} \" )\n",
|
478 |
+
"Save the script as t0.py and launch it:\n",
|
479 |
+
"Copied $ deepspeed --num_gpus 2 t0.py\n",
|
480 |
+
"rank0: in =Is this review positive or negative? Review: this is the best cast iron skillet you will ever buy\n",
|
481 |
+
" out=Positive\n",
|
482 |
+
"rank1: in =Is this review positive or negative? Review: this is the worst restaurant ever\n",
|
483 |
+
" out=negative\n",
|
484 |
+
"This is a very basic example and youβll want to adapt it to your use case.\n",
|
485 |
+
"\n",
|
486 |
+
"Using multiple GPUs with ZeRO-3 for generation requires synchronizing the GPUs by setting synced_gpus=True in the generate() method. Otherwise, if one GPU is finished generating before another one, the whole system hangs because the remaining GPUs havenβt received the weight shard from the GPU that finished first.\n",
|
487 |
+
"For Transformers>=4.28, if synced_gpus is automatically set to True if multiple GPUs are detected during generation.\n",
|
488 |
+
"\n",
|
489 |
+
"When you encounter an issue, you should consider whether DeepSpeed is the cause of the problem because often it isnβt (unless itβs super obviously and you can see DeepSpeed modules in the exception)! The first step should be to retry your setup without DeepSpeed, and if the problem persists, then you can report the issue. If the issue is a core DeepSpeed problem and unrelated to the Transformers integration, open an Issue on the DeepSpeed repository .\n",
|
490 |
+
"For issues related to the Transformers integration, please provide the following information:\n",
|
491 |
+
"the full DeepSpeed config file the command line arguments of the Trainer , or TrainingArguments arguments if youβre scripting the Trainer setup yourself (donβt dump the TrainingArguments which has dozens of irrelevant entries) the outputs of:\n",
|
492 |
+
"Copied python -c 'import torch; print(f\"torch: {torch.__version__}\")' python -c 'import transformers; print(f\"transformers: {transformers.__version__}\")' python -c 'import deepspeed; print(f\"deepspeed: {deepspeed.__version__}\")'\n",
|
493 |
+
"a link to a Google Colab notebook to reproduce the issue if impossible, a standard and non-custom dataset we can use and also try to use an existing example to reproduce the issue with\n",
|
494 |
+
"The following sections provide a guide for resolving two of the most common issues.\n",
|
495 |
+
"\n",
|
496 |
+
"When the DeepSpeed process is killed during launch without a traceback, that usually means the program tried to allocate more CPU memory than your system has or your process tried to allocate more CPU memory than allowed leading the OS kernel to terminate the process. In this case, check whether your configuration file has either offload_optimizer , offload_param or both configured to offload to the CPU.\n",
|
497 |
+
"If you have NVMe and ZeRO-3 setup, experiment with offloading to the NVMe ( estimate the memory requirements for your model).\n",
|
498 |
+
"\n",
|
499 |
+
"NaN loss often occurs when a model is pretrained in bf16 and then you try to use it with fp16 (especially relevant for TPU trained models). To resolve this, use fp32 or bf16 if your hardware supports it (TPU, Ampere GPUs or newer).\n",
|
500 |
+
"The other issue may be related to using fp16. For example, if this is your fp16 configuration:\n",
|
501 |
+
"Copied { \"fp16\": { \"enabled\": \"auto\" , \"loss_scale\": 0 , \"loss_scale_window\": 1000 , \"initial_scale_power\": 16 , \"hysteresis\": 2 , \"min_loss_scale\": 1 }\n",
|
502 |
+
"}\n",
|
503 |
+
"You might see the following OVERFLOW! messages in the logs:\n",
|
504 |
+
"Copied 0%| | 0/189 [00:00<?, ?it/s]\n",
|
505 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 262144, reducing to 262144\n",
|
506 |
+
" 1%|β | 1/189 [00:00<01:26, 2.17it/s]\n",
|
507 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 262144, reducing to 131072.0\n",
|
508 |
+
" 1%|ββ\n",
|
509 |
+
" [...]\n",
|
510 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1\n",
|
511 |
+
" 14%|βββββββββββββββββ | 27/189 [00:14<01:13, 2.21it/s]\n",
|
512 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1\n",
|
513 |
+
" 15%|ββββββββββββββββββ | 28/189 [00:14<01:13, 2.18it/s]\n",
|
514 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1\n",
|
515 |
+
" 15%|ββββββββββββββββββ | 29/189 [00:15<01:13, 2.18it/s]\n",
|
516 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1\n",
|
517 |
+
"[...]\n",
|
518 |
+
"This means the DeepSpeed loss scaler is unable to find a scaling coefficient to overcome loss overflow. To fix it, try a higher initial_scale_power value (32 usually works).\n",
|
519 |
+
"\n",
|
520 |
+
"DeepSpeed ZeRO is a powerful technology for training and loading very large models for inference with limited GPU resources, making it more accessible to everyone. To learn more about DeepSpeed, feel free to read the blog posts , documentation , and GitHub repository .\n",
|
521 |
+
"The following papers are also a great resource for learning more about ZeRO:\n",
|
522 |
+
"ZeRO: Memory Optimizations Toward Training Trillion Parameter Models ZeRO-Offload: Democratizing Billion-Scale Model Training ZeRO-Infinity: Breaking the GPU Memory Wall for Extreme Scale Deep Learning\n",
|
523 |
+
"< > Update on GitHub\n",
|
524 |
+
"HTML_TAG_END\n",
|
525 |
+
"The Embedding model sees this: \n",
|
526 |
+
" DeepSpeed is a PyTorch optimization library that makes distributed training memory-efficient and fast. At itβs core is the Zero Redundancy Optimizer (ZeRO) which enables training large models at scale. ZeRO works in several stages:\n",
|
527 |
+
"ZeRO-1, optimizer state partioning across GPUs ZeRO-2, gradient partitioning across GPUs ZeRO-3, parameteter partitioning across GPUs\n",
|
528 |
+
"In GPU-limited environments, ZeRO also enables offloading optimizer memory and computation from the GPU to the CPU to fit and train really large models on a single GPU. DeepSpeed is integrated with the Transformers Trainer class for all ZeRO stages and offloading. All you need to do is provide a config file or you can use a provided template. For inference, Transformers support ZeRO-3 and offloading since it allows loading huge models.\n",
|
529 |
+
"This guide will walk you through how to deploy DeepSpeed training, the features you can enable, how to setup the config files for different ZeRO stages, offloading, inference, and using DeepSpeed without the Trainer .\n",
|
530 |
+
"\n",
|
531 |
+
"DeepSpeed is available to install from PyPI or Transformers (for more detailed installation options, take a look at the DeepSpeed installation details or the GitHub README ).\n",
|
532 |
+
"If youβre having difficulties installing DeepSpeed, check the DeepSpeed CUDA installation guide. While DeepSpeed has a pip installable PyPI package, it is highly recommended to install it from source to best match your hardware and to support certain features, like 1-bit Adam, which arenβt available in the PyPI distribution.\n",
|
533 |
+
"PyPI Transformers\n",
|
534 |
+
"Copied pip install deepspeed\n",
|
535 |
+
"\n",
|
536 |
+
"Before you begin, it is a good idea to check whether you have enough GPU and CPU memory to fit your model. DeepSpeed provides a tool for estimating the required CPU/GPU memory. For example, to estimate the memory requirements for the bigscience/T0_3B model on a single GPU:\n",
|
537 |
+
"Copied $ python -c 'from transformers import AutoModel; \\\n",
|
538 |
+
"from deepspeed.runtime.zero.stage3 import estimate_zero3_model_states_mem_needs_all_live; \\\n",
|
539 |
+
"model = AutoModel.from_pretrained(\"bigscience/T0_3B\"); \\\n",
|
540 |
+
"estimate_zero3_model_states_mem_needs_all_live(model, num_gpus_per_node=1, num_nodes=1)' [...]\n",
|
541 |
+
"Estimated memory needed for params, optim states and gradients for a:\n",
|
542 |
+
"HW: Setup with 1 node, 1 GPU per node.\n",
|
543 |
+
"SW: Model with 2783M total params, 65M largest layer params.\n",
|
544 |
+
" per CPU | per GPU | Options\n",
|
545 |
+
" 70.00GB | 0.25GB | offload_param=cpu , offload_optimizer=cpu , zero_init=1\n",
|
546 |
+
" 70.00GB | 0.25GB | offload_param=cpu , offload_optimizer=cpu , zero_init=0\n",
|
547 |
+
" 62.23GB | 5.43GB | offload_param=none, offload_optimizer=cpu , zero_init=1\n",
|
548 |
+
" 62.23GB | 5.43GB | offload_param=none, offload_optimizer=cpu , zero_init=0\n",
|
549 |
+
" 0.37GB | 46.91GB | offload_param=none, offload_optimizer=none, zero_init=1\n",
|
550 |
+
" 15.56GB | 46.91GB | offload_param=none, offload_optimizer=none, zero_init=0\n",
|
551 |
+
"This means you either need a single 80GB GPU without CPU offload or a 8GB GPU and a ~60GB CPU to offload to (these are just the memory requirements for the parameters, optimizer states and gradients, and youβll need a bit more for the CUDA kernels and activations). You should also consider the tradeoff between cost and speed because itβll be cheaper to rent or buy a smaller GPU but itβll take longer to train your model.\n",
|
552 |
+
"If you have enough GPU memory make sure you disable CPU/NVMe offload to make everything faster.\n",
|
553 |
+
"\n",
|
554 |
+
"After youβve installed DeepSpeed and have a better idea of your memory requirements, the next step is selecting a ZeRO stage to use. In order of fastest and most memory-efficient:\n",
|
555 |
+
"| Fastest | Memory efficient |\n",
|
556 |
+
"|------------------|--------------------|\n",
|
557 |
+
"| ZeRO-1 | ZeRO-3 + offload |\n",
|
558 |
+
"| ZeRO-2 | ZeRO-3 |\n",
|
559 |
+
"| ZeRO-2 + offload | ZeRO-2 + offload |\n",
|
560 |
+
"| ZeRO-3 | ZeRO-2 |\n",
|
561 |
+
"| ZeRO-3 + offload | ZeRO-1 |\n",
|
562 |
+
"To find what works best for you, start with the fastest approach and if you run out of memory, try the next stage which is slower but more memory efficient. Feel free to work in whichever direction you prefer (starting with the most memory efficient or fastest) to discover the appropriate balance between speed and memory usage.\n",
|
563 |
+
"A general process you can use is (start with batch size of 1):\n",
|
564 |
+
"enable gradient checkpointing try ZeRO-2 try ZeRO-2 and offload the optimizer try ZeRO-3 try ZeRO-3 and offload parameters to the CPU try ZeRO-3 and offload parameters and the optimizer to the CPU try lowering various default values like a narrower search beam if youβre using the generate() method try mixed half-precision (fp16 on older GPU architectures and bf16 on Ampere) over full-precision weights add more hardware if possible or enable Infinity to offload parameters and the optimizer to a NVMe once youβre not running out of memory, measure effective throughput and then try to increase the batch size as large as you can to maximize GPU efficiency lastly, try to optimize your training setup by disabling some offload features or use a faster ZeRO stage and increasing/decreasing the batch size to find the best tradeoff between speed and memory usage\n",
|
565 |
+
"\n",
|
566 |
+
"DeepSpeed works with the Trainer class by way of a config file containing all the parameters for configuring how you want setup your training run. When you execute your training script, DeepSpeed logs the configuration it received from Trainer to the console so you can see exactly what configuration was used.\n",
|
567 |
+
"Find a complete list of DeepSpeed configuration options on the DeepSpeed Configuration JSON reference. You can also find more practical examples of various DeepSpeed configuration examples on the DeepSpeedExamples repository or the main DeepSpeed repository. To quickly find specific examples, you can: Copied git clone https://github.com/microsoft/DeepSpeedExamples cd DeepSpeedExamples\n",
|
568 |
+
"find . -name '*json' # find examples with the Lamb optimizer grep -i Lamb $(find . -name '*json' )\n",
|
569 |
+
"The DeepSpeed configuration file is passed as a path to a JSON file if youβre training from the command line interface or as a nested dict object if youβre using the Trainer in a notebook setting.\n",
|
570 |
+
"path to file nested dict\n",
|
571 |
+
"Copied TrainingArguments(..., deepspeed= \"path/to/deepspeed_config.json\" )\n",
|
572 |
+
"\n",
|
573 |
+
"There are three types of configuration parameters:\n",
|
574 |
+
"Some of the configuration parameters are shared by Trainer and DeepSpeed, and it can be difficult to identify errors when there are conflicting definitions. To make it easier, these shared configuration parameters are configured from the Trainer command line arguments. Some configuration parameters that are automatically derived from the model configuration so you donβt need to manually adjust these values. The Trainer uses a configuration value auto to determine set the most correct or efficient value. You could set your own configuration parameters explicitly, but you must take care to ensure the Trainer arguments and DeepSpeed configuration parameters agree. Mismatches may cause the training to fail in very difficult to detect ways! Some configuration parameters specific to DeepSpeed only which need to be manually set based on your training needs.\n",
|
575 |
+
"You could also modify the DeepSpeed configuration and edit TrainingArguments from it:\n",
|
576 |
+
"Create or load a DeepSpeed configuration to used as the main configuration Create a TrainingArguments object based on these DeepSpeed configuration values\n",
|
577 |
+
"Some values, such as scheduler.params.total_num_steps are calculated by the Trainer during training.\n",
|
578 |
+
"\n",
|
579 |
+
"There are three configurations, each corresponding to a different ZeRO stage. Stage 1 is not as interesting for scalability, and this guide focuses on stages 2 and 3. The zero_optimization configuration contains all the options for what to enable and how to configure them. For a more detailed explanation of each parameter, take a look at the DeepSpeed Configuration JSON reference.\n",
|
580 |
+
"DeepSpeed doesnβt validate parameter names and any typos fallback on the parameter's default setting. You can watch the DeepSpeed engine startup log messages to see what values it is going to use.\n",
|
581 |
+
"The following configurations must be setup with DeepSpeed because the Trainer doesnβt provide equivalent command line arguments.\n",
|
582 |
+
"ZeRO-1 ZeRO-2 ZeRO-3\n",
|
583 |
+
"ZeRO-1 shards the optimizer states across GPUs, and you can expect a tiny speed up. The ZeRO-1 config can be setup like this: Copied { \"zero_optimization\": { \"stage\": 1 }\n",
|
584 |
+
"}\n",
|
585 |
+
"\n",
|
586 |
+
"ZeRO-Infinity allows offloading model states to the CPU and/or NVMe to save even more memory. Smart partitioning and tiling algorithms allow each GPU to send and receive very small amounts of data during offloading such that a modern NVMe can fit an even larger total memory pool than is available to your training process. ZeRO-Infinity requires ZeRO-3.\n",
|
587 |
+
"Depending on the CPU and/or NVMe memory available, you can offload both the optimizer states and parameters , just one of them, or none. You should also make sure the nvme_path is pointing to an NVMe device, because while it still works with a normal hard drive or solid state drive, itβll be significantly slower. With a modern NVMe, you can expect peak transfer speeds of ~3.5GB/s for read and ~3GB/s for write operations. Lastly, run a benchmark on your training setup to determine the optimal aio configuration.\n",
|
588 |
+
"The example ZeRO-3/Infinity configuration file below sets most of the parameter values to auto , but you could also manually add these values.\n",
|
589 |
+
"Copied { \"fp16\": { \"enabled\": \"auto\" , \"loss_scale\": 0 , \"loss_scale_window\": 1000 , \"initial_scale_power\": 16 , \"hysteresis\": 2 , \"min_loss_scale\": 1 }, \"optimizer\": { \"type\": \"AdamW\" , \"params\": { \"lr\": \"auto\" , \"betas\": \"auto\" , \"eps\": \"auto\" , \"weight_decay\": \"auto\" }\n",
|
590 |
+
" }, \"scheduler\": { \"type\": \"WarmupLR\" , \"params\": { \"warmup_min_lr\": \"auto\" , \"warmup_max_lr\": \"auto\" , \"warmup_num_steps\": \"auto\" }\n",
|
591 |
+
" }, \"zero_optimization\": { \"stage\": 3 , \"offload_optimizer\": { \"device\": \"nvme\" , \"nvme_path\": \"/local_nvme\" , \"pin_memory\": true , \"buffer_count\": 4 , \"fast_init\": false }, \"offload_param\": { \"device\": \"nvme\" , \"nvme_path\": \"/local_nvme\" , \"pin_memory\": true , \"buffer_count\": 5 , \"buffer_size\": 1e8 , \"max_in_cpu\": 1e9 }, \"aio\": { \"block_size\": 262144 , \"queue_depth\": 32 , \"thread_count\": 1 , \"single_submit\": false , \"overlap_events\": true }, \"overlap_comm\": true , \"contiguous_gradients\": true , \"sub_group_size\": 1e9 , \"reduce_bucket_size\": \"auto\" , \"stage3_prefetch_bucket_size\": \"auto\" , \"stage3_param_persistence_threshold\": \"auto\" , \"stage3_max_live_parameters\": 1e9 , \"stage3_max_reuse_distance\": 1e9 , \"stage3_gather_16bit_weights_on_model_save\": true }, \"gradient_accumulation_steps\": \"auto\" , \"gradient_clipping\": \"auto\" , \"steps_per_print\": 2000 , \"train_batch_size\": \"auto\" , \"train_micro_batch_size_per_gpu\": \"auto\" , \"wall_clock_breakdown\": false }\n",
|
592 |
+
"\n",
|
593 |
+
"There are a number of important parameters to specify in the DeepSpeed configuration file which are briefly described in this section.\n",
|
594 |
+
"\n",
|
595 |
+
"Activation and gradient checkpointing trades speed for more GPU memory which allows you to overcome scenarios where your GPU is out of memory or to increase your batch size for better performance. To enable this feature:\n",
|
596 |
+
"For a Hugging Face model, set model.gradient_checkpointing_enable() or --gradient_checkpointing in the Trainer . For a non-Hugging Face model, use the DeepSpeed Activation Checkpointing API . You could also replace the Transformers modeling code and replace torch.utils.checkpoint with the DeepSpeed API. This approach is more flexible because you can offload the forward activations to the CPU memory instead of recalculating them.\n",
|
597 |
+
"\n",
|
598 |
+
"DeepSpeed and Transformers optimizer and scheduler can be mixed and matched as long as you donβt enable offload_optimizer . When offload_optimizer is enabled, you could use a non-DeepSpeed optimizer (except for LAMB) as long as it has both a CPU and GPU implementation.\n",
|
599 |
+
"The optimizer and scheduler parameters for the config file can be set from the command line to avoid hard to find errors. For example, if the learning rate is set to a different value in another place you can override it from the command line. Aside from the optimizer and scheduler parameters, youβll need to ensure your Trainer command line arguments match the DeepSpeed configuration.\n",
|
600 |
+
"optimizer scheduler\n",
|
601 |
+
"DeepSpeed offers several optimizers (Adam, AdamW, OneBitAdam, and LAMB) but you can also import other optimizers from PyTorch. If you donβt configure the optimizer in the config, the Trainer automatically selects AdamW and either uses the supplied values or the default values for the following parameters from the command line: lr , adam_beta1 , adam_beta2 , adam_epsilon , weight_decay . You can set the parameters to \"auto\" or manually input your own desired values. Copied { \"optimizer\": { \"type\": \"AdamW\" , \"params\": { \"lr\": \"auto\" , \"betas\": \"auto\" , \"eps\": \"auto\" , \"weight_decay\": \"auto\" }\n",
|
602 |
+
" }\n",
|
603 |
+
"} You can also use an unsupported optimizer by adding the following to the top level configuration. Copied { \"zero_allow_untested_optimizer\": true } From DeepSpeed==0.8.3 on, if you want to use offload, youβll also need to the following to the top level configuration because offload works best with DeepSpeedβs CPU Adam optimizer. Copied { \"zero_force_ds_cpu_optimizer\": false }\n",
|
604 |
+
"\n",
|
605 |
+
"Deepspeed supports fp32, fp16, and bf16 mixed precision.\n",
|
606 |
+
"fp32 fp16 bf16\n",
|
607 |
+
"If your model doesnβt work well with mixed precision, for example if it wasnβt pretrained in mixed precision, you may encounter overflow or underflow issues which can cause NaN loss. For these cases, you should use full fp32 precision by explicitly disabling the default fp16 mode. Copied { \"fp16\": { \"enabled\": false }\n",
|
608 |
+
"} For Ampere GPUs and PyTorch > 1.7, it automatically switches to the more efficient tf32 format for some operations but the results are still in fp32. You can control it from the Trainer by setting --tf32 to enable it, and --tf32 0 or --no_tf32 to disable it.\n",
|
609 |
+
"\n",
|
610 |
+
"The batch size can be auto-configured or explicitly set. If you choose to use the \"auto\" option, Trainer sets train_micro_batch_size_per_gpu to the value of args. per_device_train_batch_size and train_batch_size to args.world_size * args.per_device_train_batch_size * args.gradient_accumulation_steps .\n",
|
611 |
+
"Copied { \"train_micro_batch_size_per_gpu\": \"auto\" , \"train_batch_size\": \"auto\" }\n",
|
612 |
+
"\n",
|
613 |
+
"Gradient accumulation can be auto-configured or explicitly set. If you choose to use the \"auto\" option, Trainer sets it to the value of args.gradient_accumulation_steps .\n",
|
614 |
+
"Copied { \"gradient_accumulation_steps\": \"auto\" }\n",
|
615 |
+
"\n",
|
616 |
+
"Gradient clipping can be auto-configured or explicitly set. If you choose to use the \"auto\" option, Trainer sets it to the value of args.max_grad_norm .\n",
|
617 |
+
"Copied { \"gradient_clipping\": \"auto\" }\n",
|
618 |
+
"\n",
|
619 |
+
"For communication collectives like reduction, gathering and scattering operations, a separate data type is used.\n",
|
620 |
+
"All gather and scatter operations are performed in the same data type the data is in. For example, if youβre training with bf16, the data is also gathered in bf16 because gathering is a non-lossy operation.\n",
|
621 |
+
"Reduce operations are lossy, for example when gradients are averaged across multiple GPUs. When the communication is done in fp16 or bf16, it is more likely to be lossy because adding multiple numbers in low precision isnβt exact. This is especially the case with bf16 which has a lower precision than fp16. For this reason, fp16 is the default for reduction operations because the loss is minimal when averaging gradients.\n",
|
622 |
+
"You can choose the communication data type by setting the communication_data_type parameter in the config file. For example, choosing fp32 adds a small amount of overhead but ensures the reduction operation is accumulated in fp32 and when it is ready, it is downcasted to whichever half-precision dtype youβre training in.\n",
|
623 |
+
"Copied { \"communication_data_type\": \"fp32\" }\n",
|
624 |
+
"\n",
|
625 |
+
"DeepSpeed can be deployed by different launchers such as torchrun , the deepspeed launcher, or Accelerate . To deploy, add --deepspeed ds_config.json to the Trainer command line. Itβs recommended to use DeepSpeedβs add_config_arguments utility to add any necessary command line arguments to your code.\n",
|
626 |
+
"This guide will show you how to deploy DeepSpeed with the deepspeed launcher for different training setups. You can check out this post for more practical usage examples.\n",
|
627 |
+
"multi-GPU single-GPU\n",
|
628 |
+
"To deploy DeepSpeed on multiple GPUs, add the --num_gpus parameter. If you want to use all available GPUs, you donβt need to add --num_gpus . The example below uses 2 GPUs. Copied deepspeed --num_gpus=2 examples/pytorch/translation/run_translation.py \\\n",
|
629 |
+
"--deepspeed tests/deepspeed/ds_config_zero3.json \\\n",
|
630 |
+
"--model_name_or_path google-t5/t5-small --per_device_train_batch_size 1 \\\n",
|
631 |
+
"--output_dir output_dir --overwrite_output_dir --fp16 \\\n",
|
632 |
+
"--do_train --max_train_samples 500 --num_train_epochs 1 \\\n",
|
633 |
+
"--dataset_name wmt16 --dataset_config \"ro-en\" \\\n",
|
634 |
+
"--source_lang en --target_lang ro\n",
|
635 |
+
"\n",
|
636 |
+
"A node is one or more GPUs for running a workload. A more powerful setup is a multi-node setup which can be launched with the deepspeed launcher. For this guide, letβs assume there are two nodes with 8 GPUs each. The first node can be accessed ssh hostname1 and the second node with ssh hostname2 . Both nodes must be able to communicate with each other locally over ssh without a password.\n",
|
637 |
+
"By default, DeepSpeed expects your multi-node environment to use a shared storage. If this is not the case and each node can only see the local filesystem, you need to adjust the config file to include a checkpoint to allow loading without access to a shared filesystem:\n",
|
638 |
+
"Copied { \"checkpoint\": { \"use_node_local_storage\": true }\n",
|
639 |
+
"}\n",
|
640 |
+
"You could also use the Trainer βs --save_on_each_node argument to automatically add the above checkpoint to your config.\n",
|
641 |
+
"torchrun deepspeed\n",
|
642 |
+
"For torchrun , you have to ssh to each node and run the following command on both of them. The launcher waits until both nodes are synchronized before launching the training. Copied torchrun --nproc_per_node=8 --nnode=2 --node_rank=0 --master_addr=hostname1 \\\n",
|
643 |
+
"--master_port=9901 your_program.py <normal cl args> --deepspeed ds_config.json\n",
|
644 |
+
"\n",
|
645 |
+
"In a SLURM environment, youβll need to adapt your SLURM script to your specific SLURM environment. An example SLURM script may look like:\n",
|
646 |
+
"Copied #SBATCH --job-name=test-nodes # name #SBATCH --nodes=2 # nodes #SBATCH --ntasks-per-node=1 # crucial - only 1 task per dist per node! #SBATCH --cpus-per-task=10 # number of cores per tasks #SBATCH --gres=gpu:8 # number of gpus #SBATCH --time 20:00:00 # maximum execution time (HH:MM:SS) #SBATCH --output=%x-%j.out # output file name export GPUS_PER_NODE=8 export MASTER_ADDR=$(scontrol show hostnames $SLURM_JOB_NODELIST | head -n 1) export MASTER_PORT=9901\n",
|
647 |
+
"\n",
|
648 |
+
"srun --jobid $SLURM_JOBID bash -c 'python -m torch.distributed.run \\\n",
|
649 |
+
" --nproc_per_node $GPUS_PER_NODE --nnodes $SLURM_NNODES --node_rank $SLURM_PROCID \\\n",
|
650 |
+
" --master_addr $MASTER_ADDR --master_port $MASTER_PORT \\\n",
|
651 |
+
"your_program.py <normal cl args> --deepspeed ds_config.json'\n",
|
652 |
+
"Then you can schedule your multi-node deployment with the following command which launches training simultaneously on all nodes.\n",
|
653 |
+
"Copied sbatch launch.slurm\n",
|
654 |
+
"\n",
|
655 |
+
"The deepspeed launcher doesnβt support deployment from a notebook so youβll need to emulate the distributed environment. However, this only works for 1 GPU. If you want to use more than 1 GPU, you must use a multi-process environment for DeepSpeed to work. This means you have to use the deepspeed launcher which canβt be emulated as shown here.\n",
|
656 |
+
"Copied # DeepSpeed requires a distributed environment even when only one process is used. # This emulates a launcher in the notebook import os\n",
|
657 |
+
"\n",
|
658 |
+
"os.environ[ \"MASTER_ADDR\" ] = \"localhost\" os.environ[ \"MASTER_PORT\" ] = \"9994\" # modify if RuntimeError: Address already in use os.environ[ \"RANK\" ] = \"0\" os.environ[ \"LOCAL_RANK\" ] = \"0\" os.environ[ \"WORLD_SIZE\" ] = \"1\" # Now proceed as normal, plus pass the DeepSpeed config file training_args = TrainingArguments(..., deepspeed= \"ds_config_zero3.json\" )\n",
|
659 |
+
"trainer = Trainer(...)\n",
|
660 |
+
"trainer.train()\n",
|
661 |
+
"If you want to create the config file on the fly in the notebook in the current directory, you could have a dedicated cell.\n",
|
662 |
+
"Copied %%bash\n",
|
663 |
+
"cat << 'EOT' > ds_config_zero3.json\n",
|
664 |
+
"{ \"fp16\" : { \"enabled\" : \"auto\" , \"loss_scale\" : 0 , \"loss_scale_window\" : 1000 , \"initial_scale_power\" : 16 , \"hysteresis\" : 2 , \"min_loss_scale\" : 1 }, \"optimizer\" : { \"type\" : \"AdamW\" , \"params\" : { \"lr\" : \"auto\" , \"betas\" : \"auto\" , \"eps\" : \"auto\" , \"weight_decay\" : \"auto\" }\n",
|
665 |
+
" }, \"scheduler\" : { \"type\" : \"WarmupLR\" , \"params\" : { \"warmup_min_lr\" : \"auto\" , \"warmup_max_lr\" : \"auto\" , \"warmup_num_steps\" : \"auto\" }\n",
|
666 |
+
" }, \"zero_optimization\" : { \"stage\" : 3 , \"offload_optimizer\" : { \"device\" : \"cpu\" , \"pin_memory\" : true\n",
|
667 |
+
" }, \"offload_param\" : { \"device\" : \"cpu\" , \"pin_memory\" : true\n",
|
668 |
+
" }, \"overlap_comm\" : true, \"contiguous_gradients\" : true, \"sub_group_size\" : 1e9 , \"reduce_bucket_size\" : \"auto\" , \"stage3_prefetch_bucket_size\" : \"auto\" , \"stage3_param_persistence_threshold\" : \"auto\" , \"stage3_max_live_parameters\" : 1e9 , \"stage3_max_reuse_distance\" : 1e9 , \"stage3_gather_16bit_weights_on_model_save\" : true\n",
|
669 |
+
" }, \"gradient_accumulation_steps\" : \"auto\" , \"gradient_clipping\" : \"auto\" , \"steps_per_print\" : 2000 , \"train_batch_size\" : \"auto\" , \"train_micro_batch_size_per_gpu\" : \"auto\" , \"wall_clock_breakdown\" : false\n",
|
670 |
+
"}\n",
|
671 |
+
"EOT\n",
|
672 |
+
"If the training script is in a file and not in a notebook cell, you can launch deepspeed normally from the shell in a notebook cell. For example, to launch run_translation.py :\n",
|
673 |
+
"Copied !git clone https://github.com/huggingface/transformers\n",
|
674 |
+
"!cd transformers; deepspeed examples/pytorch/translation/run_translation.py ...\n",
|
675 |
+
"You could also use %%bash magic and write multi-line code to run the shell program, but you wonβt be able to view the logs until training is complete. With %%bash magic, you donβt need to emulate a distributed environment.\n",
|
676 |
+
"Copied %%bash\n",
|
677 |
+
"\n",
|
678 |
+
"git clone https://github.com/huggingface/transformers\n",
|
679 |
+
"cd transformers\n",
|
680 |
+
"deepspeed examples/pytorch/translation/run_translation.py ...\n",
|
681 |
+
"\n",
|
682 |
+
"DeepSpeed stores the main full precision fp32 weights in custom checkpoint optimizer files (the glob pattern looks like global_step*/*optim_states.pt ) and are saved under the normal checkpoint.\n",
|
683 |
+
"fp16 fp32\n",
|
684 |
+
"A model trained with ZeRO-2 saves the pytorch_model.bin weights in fp16. To save the model weights in fp16 for a model trained with ZeRO-3, you need to set \"stage3_gather_16bit_weights_on_model_save\": true because the model weights are partitioned across multiple GPUs. Otherwise, the Trainer wonβt save the weights in fp16 and it wonβt create a pytorch_model.bin file. This is because DeepSpeedβs state_dict contains a placeholder instead of the real weights and you wonβt be able to load them. Copied { \"zero_optimization\": { \"stage3_gather_16bit_weights_on_model_save\": true }\n",
|
685 |
+
"}\n",
|
686 |
+
"\n",
|
687 |
+
"ZeRO Inference places the model weights in CPU or NVMe memory to avoid burdening the GPU which makes it possible to run inference with huge models on a GPU. Inference doesnβt require any large additional amounts of memory for the optimizer states and gradients so you can fit much larger batches and/or sequence lengths on the same hardware.\n",
|
688 |
+
"ZeRO Inference shares the same configuration file as ZeRO-3 , and ZeRO-2 and ZeRO-1 configs wonβt work because they donβt provide any benefits for inference.\n",
|
689 |
+
"To run ZeRO Inference, pass your usual training arguments to the TrainingArguments class and add the --do_eval argument.\n",
|
690 |
+
"Copied deepspeed --num_gpus=2 your_program.py <normal cl args> --do_eval --deepspeed ds_config.json\n",
|
691 |
+
"\n",
|
692 |
+
"DeepSpeed also works with Transformers without the Trainer class. This is handled by the HfDeepSpeedConfig which only takes care of gathering ZeRO-3 parameters and splitting a model across multiple GPUs when you call from_pretrained() .\n",
|
693 |
+
"If you want everything automatically taken care of for you, try using DeepSpeed with the Trainer ! Youβll need to follow the DeepSpeed documentation , and manually configure the parameter values in the config file (you canβt use the \"auto\" value).\n",
|
694 |
+
"To efficiently deploy ZeRO-3, you must instantiate the HfDeepSpeedConfig object before the model and keep that object alive:\n",
|
695 |
+
"pretrained model non-pretrained model\n",
|
696 |
+
"Copied from transformers.integrations import HfDeepSpeedConfig from transformers import AutoModel import deepspeed\n",
|
697 |
+
"\n",
|
698 |
+
"ds_config = {...} # deepspeed config object or path to the file # must run before instantiating the model to detect zero 3 dschf = HfDeepSpeedConfig(ds_config) # keep this object alive model = AutoModel.from_pretrained( \"openai-community/gpt2\" )\n",
|
699 |
+
"engine = deepspeed.initialize(model=model, config_params=ds_config, ...)\n",
|
700 |
+
"\n",
|
701 |
+
"To run ZeRO Inference without the Trainer in cases where you canβt fit a model onto a single GPU, try using additional GPUs or/and offloading to CPU memory. The important nuance to understand here is that the way ZeRO is designed, you can process different inputs on different GPUs in parallel.\n",
|
702 |
+
"Make sure to:\n",
|
703 |
+
"disable CPU offload if you have enough GPU memory (since it slows things down). enable bf16 if you have an Ampere or newer GPU to make things faster. If you donβt have one of these GPUs, you may enable fp16 as long as you donβt use a model pretrained in bf16 (T5 models) because it may lead to an overflow error.\n",
|
704 |
+
"Take a look at the following script to get a better idea of how to run ZeRO Inference without the Trainer on a model that wonβt fit on a single GPU.\n",
|
705 |
+
"Copied #!/usr/bin/env python # This script demonstrates how to use Deepspeed ZeRO in an inference mode when one can't fit a model # into a single GPU # # 1. Use 1 GPU with CPU offload # 2. Or use multiple GPUs instead # # First you need to install deepspeed: pip install deepspeed # # Here we use a 3B \"bigscience/T0_3B\" model which needs about 15GB GPU RAM - so 1 largish or 2 # small GPUs can handle it. or 1 small GPU and a lot of CPU memory. # # To use a larger model like \"bigscience/T0\" which needs about 50GB, unless you have an 80GB GPU - # you will need 2-4 gpus. And then you can adapt the script to handle more gpus if you want to # process multiple inputs at once. # # The provided deepspeed config also activates CPU memory offloading, so chances are that if you # have a lot of available CPU memory and you don't mind a slowdown you should be able to load a # model that doesn't normally fit into a single GPU. If you have enough GPU memory the program will # run faster if you don't want offload to CPU - so disable that section then. # # To deploy on 1 gpu: # # deepspeed --num_gpus 1 t0.py # or: # python -m torch.distributed.run --nproc_per_node=1 t0.py # # To deploy on 2 gpus: # # deepspeed --num_gpus 2 t0.py # or: # python -m torch.distributed.run --nproc_per_node=2 t0.py from transformers import AutoTokenizer, AutoConfig, AutoModelForSeq2SeqLM from transformers.integrations import HfDeepSpeedConfig import deepspeed import os import torch\n",
|
706 |
+
"\n",
|
707 |
+
"os.environ[ \"TOKENIZERS_PARALLELISM\" ] = \"false\" # To avoid warnings about parallelism in tokenizers # distributed setup local_rank = int (os.getenv( \"LOCAL_RANK\" , \"0\" ))\n",
|
708 |
+
"world_size = int (os.getenv( \"WORLD_SIZE\" , \"1\" ))\n",
|
709 |
+
"torch.cuda.set_device(local_rank)\n",
|
710 |
+
"deepspeed.init_distributed()\n",
|
711 |
+
"\n",
|
712 |
+
"model_name = \"bigscience/T0_3B\" config = AutoConfig.from_pretrained(model_name)\n",
|
713 |
+
"model_hidden_size = config.d_model # batch size has to be divisible by world_size, but can be bigger than world_size train_batch_size = 1 * world_size # ds_config notes # # - enable bf16 if you use Ampere or higher GPU - this will run in mixed precision and will be # faster. # # - for older GPUs you can enable fp16, but it'll only work for non-bf16 pretrained models - e.g. # all official t5 models are bf16-pretrained # # - set offload_param.device to \"none\" or completely remove the `offload_param` section if you don't # - want CPU offload # # - if using `offload_param` you can manually finetune stage3_param_persistence_threshold to control # - which params should remain on gpus - the larger the value the smaller the offload size # # For in-depth info on Deepspeed config see # https://huggingface.co/docs/transformers/main/main_classes/deepspeed # keeping the same format as json for consistency, except it uses lower case for true/false # fmt: off ds_config = { \"fp16\" : { \"enabled\" : False }, \"bf16\" : { \"enabled\" : False }, \"zero_optimization\" : { \"stage\" : 3 , \"offload_param\" : { \"device\" : \"cpu\" , \"pin_memory\" : True }, \"overlap_comm\" : True , \"contiguous_gradients\" : True , \"reduce_bucket_size\" : model_hidden_size * model_hidden_size, \"stage3_prefetch_bucket_size\" : 0.9 * model_hidden_size * model_hidden_size, \"stage3_param_persistence_threshold\" : 10 * model_hidden_size\n",
|
714 |
+
" }, \"steps_per_print\" : 2000 , \"train_batch_size\" : train_batch_size, \"train_micro_batch_size_per_gpu\" : 1 , \"wall_clock_breakdown\" : False } # fmt: on # next line instructs transformers to partition the model directly over multiple gpus using # deepspeed.zero.Init when model's `from_pretrained` method is called. # # **it has to be run before loading the model AutoModelForSeq2SeqLM.from_pretrained(model_name)** # # otherwise the model will first be loaded normally and only partitioned at forward time which is # less efficient and when there is little CPU RAM may fail dschf = HfDeepSpeedConfig(ds_config) # keep this object alive # now a model can be loaded. model = AutoModelForSeq2SeqLM.from_pretrained(model_name) # initialise Deepspeed ZeRO and store only the engine object ds_engine = deepspeed.initialize(model=model, config_params=ds_config)[ 0 ]\n",
|
715 |
+
"ds_engine.module. eval () # inference # Deepspeed ZeRO can process unrelated inputs on each GPU. So for 2 gpus you process 2 inputs at once. # If you use more GPUs adjust for more. # And of course if you have just one input to process you then need to pass the same string to both gpus # If you use only one GPU, then you will have only rank 0. rank = torch.distributed.get_rank() if rank == 0 :\n",
|
716 |
+
" text_in = \"Is this review positive or negative? Review: this is the best cast iron skillet you will ever buy\" elif rank == 1 :\n",
|
717 |
+
" text_in = \"Is this review positive or negative? Review: this is the worst restaurant ever\" tokenizer = AutoTokenizer.from_pretrained(model_name)\n",
|
718 |
+
"inputs = tokenizer.encode(text_in, return_tensors= \"pt\" ).to(device=local_rank) with torch.no_grad():\n",
|
719 |
+
" outputs = ds_engine.module.generate(inputs, synced_gpus= True )\n",
|
720 |
+
"text_out = tokenizer.decode(outputs[ 0 ], skip_special_tokens= True ) print ( f\"rank {rank} :\\n in= {text_in} \\n out= {text_out} \" )\n",
|
721 |
+
"Save the script as t0.py and launch it:\n",
|
722 |
+
"Copied $ deepspeed --num_gpus 2 t0.py\n",
|
723 |
+
"rank0: in =Is this review positive or negative? Review: this is the best cast iron skillet you will ever buy\n",
|
724 |
+
" out=Positive\n",
|
725 |
+
"rank1: in =Is this review positive or negative? Review: this is the worst restaurant ever\n",
|
726 |
+
" out=negative\n",
|
727 |
+
"This is a very basic example and youβll want to adapt it to your use case.\n",
|
728 |
+
"\n",
|
729 |
+
"Using multiple GPUs with ZeRO-3 for generation requires synchronizing the GPUs by setting synced_gpus=True in the generate() method. Otherwise, if one GPU is finished generating before another one, the whole system hangs because the remaining GPUs havenβt received the weight shard from the GPU that finished first.\n",
|
730 |
+
"For Transformers>=4.28, if synced_gpus is automatically set to True if multiple GPUs are detected during generation.\n",
|
731 |
+
"\n",
|
732 |
+
"When you encounter an issue, you should consider whether DeepSpeed is the cause of the problem because often it isnβt (unless itβs super obviously and you can see DeepSpeed modules in the exception)! The first step should be to retry your setup without DeepSpeed, and if the problem persists, then you can report the issue. If the issue is a core DeepSpeed problem and unrelated to the Transformers integration, open an Issue on the DeepSpeed repository .\n",
|
733 |
+
"For issues related to the Transformers integration, please provide the following information:\n",
|
734 |
+
"the full DeepSpeed config file the command line arguments of the Trainer , or TrainingArguments arguments if youβre scripting the Trainer setup yourself (donβt dump the TrainingArguments which has dozens of irrelevant entries) the outputs of:\n",
|
735 |
+
"Copied python -c 'import torch; print(f\"torch: {torch.__version__}\")' python -c 'import transformers; print(f\"transformers: {transformers.__version__}\")' python -c 'import deepspeed; print(f\"deepspeed: {deepspeed.__version__}\")'\n",
|
736 |
+
"a link to a Google Colab notebook to reproduce the issue if impossible, a standard and non-custom dataset we can use and also try to use an existing example to reproduce the issue with\n",
|
737 |
+
"The following sections provide a guide for resolving two of the most common issues.\n",
|
738 |
+
"\n",
|
739 |
+
"When the DeepSpeed process is killed during launch without a traceback, that usually means the program tried to allocate more CPU memory than your system has or your process tried to allocate more CPU memory than allowed leading the OS kernel to terminate the process. In this case, check whether your configuration file has either offload_optimizer , offload_param or both configured to offload to the CPU.\n",
|
740 |
+
"If you have NVMe and ZeRO-3 setup, experiment with offloading to the NVMe ( estimate the memory requirements for your model).\n",
|
741 |
+
"\n",
|
742 |
+
"NaN loss often occurs when a model is pretrained in bf16 and then you try to use it with fp16 (especially relevant for TPU trained models). To resolve this, use fp32 or bf16 if your hardware supports it (TPU, Ampere GPUs or newer).\n",
|
743 |
+
"The other issue may be related to using fp16. For example, if this is your fp16 configuration:\n",
|
744 |
+
"Copied { \"fp16\": { \"enabled\": \"auto\" , \"loss_scale\": 0 , \"loss_scale_window\": 1000 , \"initial_scale_power\": 16 , \"hysteresis\": 2 , \"min_loss_scale\": 1 }\n",
|
745 |
+
"}\n",
|
746 |
+
"You might see the following OVERFLOW! messages in the logs:\n",
|
747 |
+
"Copied 0%| | 0/189 [00:00<?, ?it/s]\n",
|
748 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 262144, reducing to 262144\n",
|
749 |
+
" 1%|β | 1/189 [00:00<01:26, 2.17it/s]\n",
|
750 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 262144, reducing to 131072.0\n",
|
751 |
+
" 1%|ββ\n",
|
752 |
+
" [...]\n",
|
753 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1\n",
|
754 |
+
" 14%|βββββββββββββββββ | 27/189 [00:14<01:13, 2.21it/s]\n",
|
755 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1\n",
|
756 |
+
" 15%|ββββββββββββββββββ | 28/189 [00:14<01:13, 2.18it/s]\n",
|
757 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1\n",
|
758 |
+
" 15%|ββββββββββββββββββ | 29/189 [00:15<01:13, 2.18it/s]\n",
|
759 |
+
" [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1\n",
|
760 |
+
"[...]\n",
|
761 |
+
"This means the DeepSpeed loss scaler is unable to find a scaling coefficient to overcome loss overflow. To fix it, try a higher initial_scale_power value (32 usually works).\n",
|
762 |
+
"\n",
|
763 |
+
"DeepSpeed ZeRO is a powerful technology for training and loading very large models for inference with limited GPU resources, making it more accessible to everyone. To learn more about DeepSpeed, feel free to read the blog posts , documentation , and GitHub repository .\n",
|
764 |
+
"The following papers are also a great resource for learning more about ZeRO:\n",
|
765 |
+
"ZeRO: Memory Optimizations Toward Training Trillion Parameter Models ZeRO-Offload: Democratizing Billion-Scale Model Training ZeRO-Infinity: Breaking the GPU Memory Wall for Extreme Scale Deep Learning\n",
|
766 |
+
"< > Update on GitHub\n",
|
767 |
+
"HTML_TAG_END\n"
|
768 |
+
]
|
769 |
+
}
|
770 |
+
],
|
771 |
+
"source": [
|
772 |
+
"print(\n",
|
773 |
+
" \"The LLM sees this: \\n\",\n",
|
774 |
+
" documents[0].get_content(metadata_mode=MetadataMode.LLM),\n",
|
775 |
+
")\n",
|
776 |
+
"print(\n",
|
777 |
+
" \"The Embedding model sees this: \\n\",\n",
|
778 |
+
" documents[0].get_content(metadata_mode=MetadataMode.EMBED),\n",
|
779 |
+
")"
|
780 |
+
]
|
781 |
+
},
|
782 |
{
|
783 |
"cell_type": "code",
|
784 |
"execution_count": 4,
|
|
|
858 |
")"
|
859 |
]
|
860 |
},
|
861 |
+
{
|
862 |
+
"cell_type": "code",
|
863 |
+
"execution_count": null,
|
864 |
+
"metadata": {},
|
865 |
+
"outputs": [],
|
866 |
+
"source": [
|
867 |
+
"print(\n",
|
868 |
+
" \"The LLM sees this: \\n\",\n",
|
869 |
+
" document.get_content(metadata_mode=MetadataMode.LLM),\n",
|
870 |
+
")\n",
|
871 |
+
"print(\n",
|
872 |
+
" \"The Embedding model sees this: \\n\",\n",
|
873 |
+
" document.get_content(metadata_mode=MetadataMode.EMBED),\n",
|
874 |
+
")"
|
875 |
+
]
|
876 |
+
},
|
877 |
{
|
878 |
"cell_type": "code",
|
879 |
"execution_count": null,
|
scripts/custom_retriever.py
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import logging
|
2 |
+
from typing import List
|
3 |
+
|
4 |
+
from llama_index.core import QueryBundle
|
5 |
+
from llama_index.core.retrievers import BaseRetriever, VectorIndexRetriever
|
6 |
+
from llama_index.core.schema import NodeWithScore, TextNode
|
7 |
+
|
8 |
+
logger = logging.getLogger(__name__)
|
9 |
+
logging.basicConfig(level=logging.INFO)
|
10 |
+
|
11 |
+
|
12 |
+
class CustomRetriever(BaseRetriever):
|
13 |
+
"""Custom retriever that performs both semantic search and hybrid search."""
|
14 |
+
|
15 |
+
def __init__(
|
16 |
+
self,
|
17 |
+
vector_retriever: VectorIndexRetriever,
|
18 |
+
document_dict: dict,
|
19 |
+
) -> None:
|
20 |
+
"""Init params."""
|
21 |
+
|
22 |
+
self._vector_retriever = vector_retriever
|
23 |
+
self._document_dict = document_dict
|
24 |
+
super().__init__()
|
25 |
+
|
26 |
+
def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]:
|
27 |
+
"""Retrieve nodes given query."""
|
28 |
+
|
29 |
+
logger.info(f"Retrieving nodes for query: {query_bundle.query_str}")
|
30 |
+
|
31 |
+
nodes = self._vector_retriever.retrieve(query_bundle)
|
32 |
+
|
33 |
+
# Filter out nodes with the same ref_doc_id
|
34 |
+
def filter_nodes_by_unique_doc_id(nodes):
|
35 |
+
unique_nodes = {}
|
36 |
+
for node in nodes:
|
37 |
+
doc_id = node.node.ref_doc_id
|
38 |
+
if doc_id is not None and doc_id not in unique_nodes:
|
39 |
+
unique_nodes[doc_id] = node
|
40 |
+
return list(unique_nodes.values())
|
41 |
+
|
42 |
+
nodes = filter_nodes_by_unique_doc_id(nodes)
|
43 |
+
print(f"number of nodes after filtering: {len(nodes)}")
|
44 |
+
|
45 |
+
nodes_context = []
|
46 |
+
for node in nodes:
|
47 |
+
# print("Node ID\t", node.node_id)
|
48 |
+
# print("Title\t", node.metadata["title"])
|
49 |
+
# print("Text\t", node.text)
|
50 |
+
# print("Score\t", node.score)
|
51 |
+
# print("Metadata\t", node.metadata)
|
52 |
+
# print("-_" * 20)
|
53 |
+
if node.metadata["retrieve_doc"] == True:
|
54 |
+
# print("This node will be replaced by the document")
|
55 |
+
doc = self._document_dict[node.node.ref_doc_id]
|
56 |
+
# print(doc.text)
|
57 |
+
new_node = NodeWithScore(
|
58 |
+
node=TextNode(text=doc.text, metadata=node.metadata),
|
59 |
+
score=node.score,
|
60 |
+
)
|
61 |
+
nodes_context.append(new_node)
|
62 |
+
else:
|
63 |
+
nodes_context.append(node)
|
64 |
+
|
65 |
+
return nodes_context
|
scripts/gradio-ui.py
CHANGED
@@ -7,25 +7,57 @@ from typing import Optional
|
|
7 |
|
8 |
import chromadb
|
9 |
import gradio as gr
|
|
|
10 |
from dotenv import load_dotenv
|
11 |
from llama_index.agent.openai import OpenAIAgent
|
12 |
from llama_index.core import VectorStoreIndex, get_response_synthesizer
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
from llama_index.core.data_structs import Node
|
|
|
14 |
from llama_index.core.node_parser import SentenceSplitter
|
|
|
|
|
15 |
from llama_index.core.schema import BaseNode, MetadataMode, NodeWithScore, TextNode
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
from llama_index.embeddings.openai import OpenAIEmbedding
|
17 |
from llama_index.llms.gemini import Gemini
|
18 |
from llama_index.llms.openai import OpenAI
|
|
|
19 |
from llama_index.vector_stores.chroma import ChromaVectorStore
|
20 |
from tutor_prompts import (
|
21 |
TEXT_QA_TEMPLATE,
|
22 |
QueryValidation,
|
23 |
system_message_openai_agent,
|
24 |
system_message_validation,
|
|
|
25 |
)
|
26 |
|
27 |
load_dotenv(".env")
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
# from utils import init_mongo_db
|
30 |
|
31 |
logger = logging.getLogger(__name__)
|
@@ -35,7 +67,7 @@ logging.getLogger("httpx").setLevel(logging.WARNING)
|
|
35 |
|
36 |
# # This variables are used to intercept API calls
|
37 |
# # launch mitmweb
|
38 |
-
# cert_file = "/Users/omar/
|
39 |
# os.environ["REQUESTS_CA_BUNDLE"] = cert_file
|
40 |
# os.environ["SSL_CERT_FILE"] = cert_file
|
41 |
# os.environ["HTTPS_PROXY"] = "http://127.0.0.1:8080"
|
@@ -100,17 +132,21 @@ index = VectorStoreIndex.from_vector_store(
|
|
100 |
show_progress=True,
|
101 |
use_async=True,
|
102 |
)
|
103 |
-
|
104 |
-
|
105 |
similarity_top_k=10,
|
106 |
use_async=True,
|
107 |
embed_model=OpenAIEmbedding(model="text-embedding-3-large", mode="similarity"),
|
108 |
)
|
109 |
|
|
|
|
|
110 |
|
111 |
with open("scripts/ai-tutor-vector-db/document_dict.pkl", "rb") as f:
|
112 |
document_dict = pickle.load(f)
|
113 |
|
|
|
|
|
114 |
|
115 |
def format_sources(completion) -> str:
|
116 |
if len(completion.source_nodes) == 0:
|
@@ -151,7 +187,9 @@ def add_sources(answer_str, completion):
|
|
151 |
if formatted_sources == "":
|
152 |
yield answer_str
|
153 |
|
154 |
-
|
|
|
|
|
155 |
yield answer_str
|
156 |
|
157 |
|
@@ -165,38 +203,6 @@ def generate_completion(
|
|
165 |
print(f"query: {query}")
|
166 |
print(model)
|
167 |
print(sources)
|
168 |
-
nodes = retriever.retrieve(query)
|
169 |
-
|
170 |
-
# Filter out nodes with the same ref_doc_id
|
171 |
-
def filter_nodes_by_unique_doc_id(nodes):
|
172 |
-
unique_nodes = {}
|
173 |
-
for node in nodes:
|
174 |
-
doc_id = node.node.ref_doc_id
|
175 |
-
if doc_id is not None and doc_id not in unique_nodes:
|
176 |
-
unique_nodes[doc_id] = node
|
177 |
-
return list(unique_nodes.values())
|
178 |
-
|
179 |
-
nodes = filter_nodes_by_unique_doc_id(nodes)
|
180 |
-
print(f"number of nodes after filtering: {len(nodes)}")
|
181 |
-
|
182 |
-
nodes_context = []
|
183 |
-
for node in nodes:
|
184 |
-
print("Node ID\t", node.node_id)
|
185 |
-
print("Title\t", node.metadata["title"])
|
186 |
-
print("Text\t", node.text)
|
187 |
-
print("Score\t", node.score)
|
188 |
-
print("Metadata\t", node.metadata)
|
189 |
-
print("-_" * 20)
|
190 |
-
if node.metadata["retrieve_doc"] == True:
|
191 |
-
print("This node will be replaced by the document")
|
192 |
-
doc = document_dict[node.node.ref_doc_id]
|
193 |
-
print(doc.text)
|
194 |
-
new_node = NodeWithScore(
|
195 |
-
node=TextNode(text=doc.text, metadata=node.metadata), score=node.score
|
196 |
-
)
|
197 |
-
nodes_context.append(new_node)
|
198 |
-
else:
|
199 |
-
nodes_context.append(node)
|
200 |
|
201 |
if model == "gemini-1.5-flash" or model == "gemini-1.5-pro":
|
202 |
llm = Gemini(
|
@@ -215,7 +221,73 @@ def generate_completion(
|
|
215 |
streaming=True,
|
216 |
)
|
217 |
|
218 |
-
completion = response_synthesizer.synthesize(query, nodes=nodes_context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
|
220 |
answer_str = ""
|
221 |
for token in completion.response_gen:
|
@@ -246,9 +318,11 @@ model = gr.Dropdown(
|
|
246 |
"gemini-1.5-pro",
|
247 |
"gemini-1.5-flash",
|
248 |
"gpt-3.5-turbo",
|
|
|
|
|
249 |
],
|
250 |
label="Model",
|
251 |
-
value="
|
252 |
interactive=True,
|
253 |
)
|
254 |
|
|
|
7 |
|
8 |
import chromadb
|
9 |
import gradio as gr
|
10 |
+
from custom_retriever import CustomRetriever
|
11 |
from dotenv import load_dotenv
|
12 |
from llama_index.agent.openai import OpenAIAgent
|
13 |
from llama_index.core import VectorStoreIndex, get_response_synthesizer
|
14 |
+
from llama_index.core.agent import AgentRunner, ReActAgent
|
15 |
+
from llama_index.core.chat_engine import (
|
16 |
+
CondensePlusContextChatEngine,
|
17 |
+
CondenseQuestionChatEngine,
|
18 |
+
ContextChatEngine,
|
19 |
+
)
|
20 |
from llama_index.core.data_structs import Node
|
21 |
+
from llama_index.core.memory import ChatMemoryBuffer
|
22 |
from llama_index.core.node_parser import SentenceSplitter
|
23 |
+
from llama_index.core.query_engine import RetrieverQueryEngine
|
24 |
+
from llama_index.core.retrievers import VectorIndexRetriever
|
25 |
from llama_index.core.schema import BaseNode, MetadataMode, NodeWithScore, TextNode
|
26 |
+
from llama_index.core.tools import (
|
27 |
+
FunctionTool,
|
28 |
+
QueryEngineTool,
|
29 |
+
RetrieverTool,
|
30 |
+
ToolMetadata,
|
31 |
+
)
|
32 |
from llama_index.embeddings.openai import OpenAIEmbedding
|
33 |
from llama_index.llms.gemini import Gemini
|
34 |
from llama_index.llms.openai import OpenAI
|
35 |
+
from llama_index.llms.openai.utils import GPT4_MODELS
|
36 |
from llama_index.vector_stores.chroma import ChromaVectorStore
|
37 |
from tutor_prompts import (
|
38 |
TEXT_QA_TEMPLATE,
|
39 |
QueryValidation,
|
40 |
system_message_openai_agent,
|
41 |
system_message_validation,
|
42 |
+
system_prompt,
|
43 |
)
|
44 |
|
45 |
load_dotenv(".env")
|
46 |
|
47 |
+
GPT4_MODELS.update(
|
48 |
+
{
|
49 |
+
"gpt-4-1106-preview": 128000,
|
50 |
+
"gpt-4-0125-preview": 128000,
|
51 |
+
"gpt-4-turbo-preview": 128000,
|
52 |
+
"gpt-4-turbo-2024-04-09": 128000,
|
53 |
+
"gpt-4-turbo": 128000,
|
54 |
+
"gpt-4o": 128000,
|
55 |
+
"gpt-4o-2024-05-13": 128000,
|
56 |
+
"gpt-4o-mini": 128000,
|
57 |
+
# Add any other models you need
|
58 |
+
}
|
59 |
+
)
|
60 |
+
|
61 |
# from utils import init_mongo_db
|
62 |
|
63 |
logger = logging.getLogger(__name__)
|
|
|
67 |
|
68 |
# # This variables are used to intercept API calls
|
69 |
# # launch mitmweb
|
70 |
+
# cert_file = "/Users/omar/Documents/mitmproxy-ca-cert.pem"
|
71 |
# os.environ["REQUESTS_CA_BUNDLE"] = cert_file
|
72 |
# os.environ["SSL_CERT_FILE"] = cert_file
|
73 |
# os.environ["HTTPS_PROXY"] = "http://127.0.0.1:8080"
|
|
|
132 |
show_progress=True,
|
133 |
use_async=True,
|
134 |
)
|
135 |
+
vector_retriever = VectorIndexRetriever(
|
136 |
+
index=index,
|
137 |
similarity_top_k=10,
|
138 |
use_async=True,
|
139 |
embed_model=OpenAIEmbedding(model="text-embedding-3-large", mode="similarity"),
|
140 |
)
|
141 |
|
142 |
+
memory = ChatMemoryBuffer.from_defaults(token_limit=150000)
|
143 |
+
|
144 |
|
145 |
with open("scripts/ai-tutor-vector-db/document_dict.pkl", "rb") as f:
|
146 |
document_dict = pickle.load(f)
|
147 |
|
148 |
+
custom_retriever = CustomRetriever(vector_retriever, document_dict)
|
149 |
+
|
150 |
|
151 |
def format_sources(completion) -> str:
|
152 |
if len(completion.source_nodes) == 0:
|
|
|
187 |
if formatted_sources == "":
|
188 |
yield answer_str
|
189 |
|
190 |
+
if formatted_sources != "":
|
191 |
+
answer_str += "\n\n" + formatted_sources
|
192 |
+
|
193 |
yield answer_str
|
194 |
|
195 |
|
|
|
203 |
print(f"query: {query}")
|
204 |
print(model)
|
205 |
print(sources)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
|
207 |
if model == "gemini-1.5-flash" or model == "gemini-1.5-pro":
|
208 |
llm = Gemini(
|
|
|
221 |
streaming=True,
|
222 |
)
|
223 |
|
224 |
+
# completion = response_synthesizer.synthesize(query, nodes=nodes_context)
|
225 |
+
custom_query_engine = RetrieverQueryEngine(
|
226 |
+
retriever=custom_retriever,
|
227 |
+
response_synthesizer=response_synthesizer,
|
228 |
+
)
|
229 |
+
|
230 |
+
# agent = CondensePlusContextChatEngine.from_defaults(
|
231 |
+
# agent = CondenseQuestionChatEngine.from_defaults(
|
232 |
+
|
233 |
+
# agent = ContextChatEngine.from_defaults(
|
234 |
+
# retriever=custom_retriever,
|
235 |
+
# context_template=system_prompt,
|
236 |
+
# llm=llm,
|
237 |
+
# memory=memory,
|
238 |
+
# verbose=True,
|
239 |
+
# )
|
240 |
+
|
241 |
+
query_engine_tools = [
|
242 |
+
RetrieverTool(
|
243 |
+
retriever=custom_retriever,
|
244 |
+
metadata=ToolMetadata(
|
245 |
+
name="AI_information",
|
246 |
+
description="""Only use this tool if necessary. The 'AI_information' tool is a comprehensive repository for information in artificial intelligence (AI). When utilizing this tool, the input should be the user's question rewritten as a statement. The input can also be adapted to focus on specific aspects or further details of the current topic under discussion. This dynamic input approach allows for a tailored exploration of AI subjects, ensuring that responses are relevant and informative. Employ this tool to fetch nuanced information on topics such as model training, fine-tuning, and LLM augmentation, thereby facilitating a rich, context-aware dialogue. """,
|
247 |
+
),
|
248 |
+
)
|
249 |
+
]
|
250 |
+
# query_engine_tools = [
|
251 |
+
# QueryEngineTool(
|
252 |
+
# query_engine=custom_query_engine,
|
253 |
+
# metadata=ToolMetadata(
|
254 |
+
# name="AI_information",
|
255 |
+
# description="""Only use this tool if necessary. The 'AI_information' tool is a comprehensive repository for information in artificial intelligence (AI). When utilizing this tool, the input should be the user's question rewritten as a statement. The input can also be adapted to focus on specific aspects or further details of the current topic under discussion. This dynamic input approach allows for a tailored exploration of AI subjects, ensuring that responses are relevant and informative. Employ this tool to fetch nuanced information on topics such as model training, fine-tuning, and LLM augmentation, thereby facilitating a rich, context-aware dialogue. """,
|
256 |
+
# ),
|
257 |
+
# )
|
258 |
+
# ]
|
259 |
+
|
260 |
+
if model == "gemini-1.5-flash" or model == "gemini-1.5-pro":
|
261 |
+
# agent = AgentRunner.from_llm(
|
262 |
+
# llm=llm,
|
263 |
+
# tools=query_engine_tools,
|
264 |
+
# verbose=True,
|
265 |
+
# memory=memory,
|
266 |
+
# # system_prompt=system_message_openai_agent,
|
267 |
+
# )
|
268 |
+
agent = ReActAgent.from_tools(
|
269 |
+
llm=llm,
|
270 |
+
memory=memory,
|
271 |
+
tools=query_engine_tools,
|
272 |
+
verbose=True,
|
273 |
+
# system_prompt=system_message_openai_agent,
|
274 |
+
)
|
275 |
+
prompts = agent._get_prompt_modules()
|
276 |
+
print(prompts.values())
|
277 |
+
else:
|
278 |
+
agent = OpenAIAgent.from_tools(
|
279 |
+
llm=llm,
|
280 |
+
memory=memory,
|
281 |
+
tools=query_engine_tools,
|
282 |
+
verbose=True,
|
283 |
+
system_prompt=system_message_openai_agent,
|
284 |
+
)
|
285 |
+
|
286 |
+
# completion = custom_query_engine.query(query)
|
287 |
+
completion = agent.stream_chat(query)
|
288 |
+
|
289 |
+
# completion = agent.chat(query)
|
290 |
+
# return str(completion)
|
291 |
|
292 |
answer_str = ""
|
293 |
for token in completion.response_gen:
|
|
|
318 |
"gemini-1.5-pro",
|
319 |
"gemini-1.5-flash",
|
320 |
"gpt-3.5-turbo",
|
321 |
+
"gpt-4o-mini",
|
322 |
+
"gpt-4o",
|
323 |
],
|
324 |
label="Model",
|
325 |
+
value="gpt-4o-mini",
|
326 |
interactive=True,
|
327 |
)
|
328 |
|
scripts/tutor_prompts.py
CHANGED
@@ -14,27 +14,27 @@ default_user_prompt = (
|
|
14 |
system_prompt = (
|
15 |
"You are an AI teacher, answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or LLM). "
|
16 |
"Your answers are aimed to teach students, so they should be complete, clear, and easy to understand. "
|
17 |
-
"Topics covered include training models, fine-tuning models, giving 'memory' to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, Llama-Index, LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Understand the questions with this context."
|
18 |
"You are provided information in Hugging Face's documentation and a RAG course. "
|
19 |
-
"Only some information might be relevant to the question, so ignore the irrelevant part and use the relevant part to answer the question."
|
20 |
"Formulate your answer with the information given to you below. DO NOT use additional information, even if you know the answer. "
|
21 |
-
"If the answer is somewhere in the documentation below, answer the question, depending on the question and the variety of relevant information in the documentation, give complete and helpful answers."
|
22 |
-
"If code is provided in the information, share it with the students. It's important to provide complete code blocks."
|
23 |
"Here is the information you can use, the order is not important: \n\n"
|
24 |
"---------------------\n"
|
25 |
"{context_str}\n"
|
26 |
"---------------------\n\n"
|
27 |
"REMEMBER:\n"
|
28 |
-
"You are an AI teacher, answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine tuning models, giving memory to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, making LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context."
|
29 |
"Your answers are aimed to teach students, so they should be complete, clear, and easy to understand. "
|
30 |
"You are provided information found in Hugging Face's documentation and a RAG course. "
|
31 |
-
"Here are the rules you must follow
|
32 |
"* Only respond with information inside the documentation. DO NOT provide additional information, even if you know the answer. "
|
33 |
"* If the answer is in the documentation, answer the question (depending on the questions and the variety of relevant information in the documentation. Your answer needs to give a clear and complete explanation as if you were a teacher. "
|
34 |
"* Do not refer to the documentation directly, but use the information provided within it to answer questions. "
|
35 |
-
"* Do not reference any links, urls or hyperlinks in your answers.\n"
|
36 |
-
"* If code is provided in the information, share it with the students. It's important to provide complete code blocks so they can execute it.\n"
|
37 |
-
"* Make sure to format your answers in Markdown format, including code block and snippets.\n"
|
38 |
"Now answer the following question: \n"
|
39 |
)
|
40 |
|
@@ -82,11 +82,15 @@ class QueryValidation(BaseModel):
|
|
82 |
)
|
83 |
|
84 |
|
85 |
-
system_message_openai_agent = """You are
|
86 |
|
87 |
-
|
88 |
|
89 |
-
AI_information
|
|
|
|
|
|
|
|
|
90 |
|
91 |
Your responses are exclusively based on the output provided by the AI_information tool. Refrain from incorporating external knowledge or information not directly obtained from the tool's responses.
|
92 |
|
@@ -95,4 +99,10 @@ When the conversation deepens or shifts focus within a topic, adapt your inquiri
|
|
95 |
Provide comprehensive answers, ideally structured in up to ten paragraphs, drawing from the variety of relevant details furnished by the tool. The depth and breadth of your responses should align with the scope and specificity of the information retrieved.
|
96 |
|
97 |
Should the AI_information tool's repository lack information on the queried topic, politely inform the user that the question transcends the bounds of your current knowledge base, citing the absence of relevant content in the tool's documentation.
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
"""
|
|
|
14 |
system_prompt = (
|
15 |
"You are an AI teacher, answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or LLM). "
|
16 |
"Your answers are aimed to teach students, so they should be complete, clear, and easy to understand. "
|
17 |
+
"Topics covered include training models, fine-tuning models, giving 'memory' to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, Llama-Index, LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Understand the questions with this context. "
|
18 |
"You are provided information in Hugging Face's documentation and a RAG course. "
|
19 |
+
"Only some information might be relevant to the question, so ignore the irrelevant part and use the relevant part to answer the question. "
|
20 |
"Formulate your answer with the information given to you below. DO NOT use additional information, even if you know the answer. "
|
21 |
+
"If the answer is somewhere in the documentation below, answer the question, depending on the question and the variety of relevant information in the documentation, give complete and helpful answers. "
|
22 |
+
"If code is provided in the information, share it with the students. It's important to provide complete code blocks. "
|
23 |
"Here is the information you can use, the order is not important: \n\n"
|
24 |
"---------------------\n"
|
25 |
"{context_str}\n"
|
26 |
"---------------------\n\n"
|
27 |
"REMEMBER:\n"
|
28 |
+
"You are an AI teacher, answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine tuning models, giving memory to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, making LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context. "
|
29 |
"Your answers are aimed to teach students, so they should be complete, clear, and easy to understand. "
|
30 |
"You are provided information found in Hugging Face's documentation and a RAG course. "
|
31 |
+
"Here are the rules you must follow: \n"
|
32 |
"* Only respond with information inside the documentation. DO NOT provide additional information, even if you know the answer. "
|
33 |
"* If the answer is in the documentation, answer the question (depending on the questions and the variety of relevant information in the documentation. Your answer needs to give a clear and complete explanation as if you were a teacher. "
|
34 |
"* Do not refer to the documentation directly, but use the information provided within it to answer questions. "
|
35 |
+
"* Do not reference any links, urls or hyperlinks in your answers.\n "
|
36 |
+
"* If code is provided in the information, share it with the students. It's important to provide complete code blocks so they can execute it.\n "
|
37 |
+
"* Make sure to format your answers in Markdown format, including code block and snippets.\n "
|
38 |
"Now answer the following question: \n"
|
39 |
)
|
40 |
|
|
|
82 |
)
|
83 |
|
84 |
|
85 |
+
system_message_openai_agent = """You are an AI teacher, answering questions from students of an applied artificial intelligence course on Large Language Models (LLMs or llm). Topics covered include training models, fine tuning models, giving memory to LLMs, prompting, hallucinations and bias, vector databases, transformer architectures, embeddings, RAG frameworks, Langchain, making LLMs interact with tool use, AI agents, reinforcement learning with human feedback. Questions should be understood with this context.
|
86 |
|
87 |
+
Your answers are aimed to teach students, so they should be complete, clear, and easy to understand.
|
88 |
|
89 |
+
Utilize the AI_information tool to gather insights pertinent to the field of AI. This function accepts a string (user question rewritten as a statement) and returns informative content regarding the domain of AI.
|
90 |
+
|
91 |
+
Only some information returned by the tool might be relevant to the question, so ignore the irrelevant part and use the relevant part to answer the question.
|
92 |
+
|
93 |
+
AI_information: A tool for acquiring knowledge about AI. Directly forward the user's question, a refined version focusing on the current discussion topic to this tool.
|
94 |
|
95 |
Your responses are exclusively based on the output provided by the AI_information tool. Refrain from incorporating external knowledge or information not directly obtained from the tool's responses.
|
96 |
|
|
|
99 |
Provide comprehensive answers, ideally structured in up to ten paragraphs, drawing from the variety of relevant details furnished by the tool. The depth and breadth of your responses should align with the scope and specificity of the information retrieved.
|
100 |
|
101 |
Should the AI_information tool's repository lack information on the queried topic, politely inform the user that the question transcends the bounds of your current knowledge base, citing the absence of relevant content in the tool's documentation.
|
102 |
+
|
103 |
+
Do not refer to the documentation directly, but use the information provided within it to answer questions.
|
104 |
+
|
105 |
+
If code is provided in the information, share it with the students. It's important to provide complete code blocks so they can execute it.
|
106 |
+
|
107 |
+
Make sure to format your answers in Markdown format, including code block and snippets.
|
108 |
"""
|