models.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import json
  2. import os
  3. import time
  4. import zipfile
  5. from pathlib import Path
  6. import modules.shared as shared
  7. import numpy as np
  8. import torch
  9. import transformers
  10. from transformers import AutoModelForCausalLM
  11. from transformers import AutoTokenizer
  12. transformers.logging.set_verbosity_error()
  13. local_rank = None
  14. if shared.args.flexgen:
  15. from flexgen.flex_opt import (Policy, OptLM, TorchDevice, TorchDisk, TorchMixedDevice, CompressionConfig, Env, get_opt_config)
  16. if shared.args.deepspeed:
  17. import deepspeed
  18. from transformers.deepspeed import HfDeepSpeedConfig, is_deepspeed_zero3_enabled
  19. from modules.deepspeed_parameters import generate_ds_config
  20. # Distributed setup
  21. local_rank = shared.args.local_rank if shared.args.local_rank is not None else int(os.getenv("LOCAL_RANK", "0"))
  22. world_size = int(os.getenv("WORLD_SIZE", "1"))
  23. torch.cuda.set_device(local_rank)
  24. deepspeed.init_distributed()
  25. ds_config = generate_ds_config(shared.args.bf16, 1 * world_size, shared.args.nvme_offload_dir)
  26. dschf = HfDeepSpeedConfig(ds_config) # Keep this object alive for the Transformers integration
  27. def load_model(model_name):
  28. print(f"Loading {model_name}...")
  29. t0 = time.time()
  30. # Default settings
  31. if not (shared.args.cpu or shared.args.load_in_8bit or shared.args.auto_devices or shared.args.disk or shared.args.gpu_memory is not None or shared.args.cpu_memory is not None or shared.args.deepspeed or shared.args.flexgen):
  32. if any(size in shared.model_name.lower() for size in ('13b', '20b', '30b')):
  33. model = AutoModelForCausalLM.from_pretrained(Path(f"models/{shared.model_name}"), device_map='auto', load_in_8bit=True)
  34. else:
  35. model = AutoModelForCausalLM.from_pretrained(Path(f"models/{shared.model_name}"), low_cpu_mem_usage=True, torch_dtype=torch.bfloat16 if shared.args.bf16 else torch.float16).cuda()
  36. # FlexGen
  37. elif shared.args.flexgen:
  38. gpu = TorchDevice("cuda:0")
  39. cpu = TorchDevice("cpu")
  40. disk = TorchDisk(shared.args.disk_cache_dir)
  41. env = Env(gpu=gpu, cpu=cpu, disk=disk, mixed=TorchMixedDevice([gpu, cpu, disk]))
  42. # Offloading policy
  43. policy = Policy(1, 1,
  44. shared.args.percent[0], shared.args.percent[1],
  45. shared.args.percent[2], shared.args.percent[3],
  46. shared.args.percent[4], shared.args.percent[5],
  47. overlap=True, sep_layer=True, pin_weight=True,
  48. cpu_cache_compute=False, attn_sparsity=1.0,
  49. compress_weight=shared.args.compress_weight,
  50. comp_weight_config=CompressionConfig(
  51. num_bits=4, group_size=64,
  52. group_dim=0, symmetric=False),
  53. compress_cache=False,
  54. comp_cache_config=CompressionConfig(
  55. num_bits=4, group_size=64,
  56. group_dim=2, symmetric=False))
  57. opt_config = get_opt_config(f"facebook/{shared.model_name}")
  58. model = OptLM(opt_config, env, "models", policy)
  59. model.init_all_weights()
  60. # DeepSpeed ZeRO-3
  61. elif shared.args.deepspeed:
  62. model = AutoModelForCausalLM.from_pretrained(Path(f"models/{shared.model_name}"), torch_dtype=torch.bfloat16 if shared.args.bf16 else torch.float16)
  63. model = deepspeed.initialize(model=model, config_params=ds_config, model_parameters=None, optimizer=None, lr_scheduler=None)[0]
  64. model.module.eval() # Inference
  65. print(f"DeepSpeed ZeRO-3 is enabled: {is_deepspeed_zero3_enabled()}")
  66. # Custom
  67. else:
  68. command = "AutoModelForCausalLM.from_pretrained"
  69. params = ["low_cpu_mem_usage=True"]
  70. if not shared.args.cpu and not torch.cuda.is_available():
  71. print("Warning: no GPU has been detected.\nFalling back to CPU mode.\n")
  72. shared.args.cpu = True
  73. if shared.args.cpu:
  74. params.append("low_cpu_mem_usage=True")
  75. params.append("torch_dtype=torch.float32")
  76. else:
  77. params.append("device_map='auto'")
  78. params.append("load_in_8bit=True" if shared.args.load_in_8bit else "torch_dtype=torch.bfloat16" if shared.args.bf16 else "torch_dtype=torch.float16")
  79. if shared.args.gpu_memory:
  80. params.append(f"max_memory={{0: '{shared.args.gpu_memory or '99'}GiB', 'cpu': '{shared.args.cpu_memory or '99'}GiB'}}")
  81. elif not shared.args.load_in_8bit:
  82. total_mem = (torch.cuda.get_device_properties(0).total_memory/(1024*1024))
  83. suggestion = round((total_mem-1000)/1000)*1000
  84. if total_mem-suggestion < 800:
  85. suggestion -= 1000
  86. suggestion = int(round(suggestion/1000))
  87. print(f"\033[1;32;1mAuto-assiging --gpu-memory {suggestion} for your GPU to try to prevent out-of-memory errors.\nYou can manually set other values.\033[0;37;0m")
  88. params.append(f"max_memory={{0: '{suggestion}GiB', 'cpu': '{shared.args.cpu_memory or '99'}GiB'}}")
  89. if shared.args.disk:
  90. params.append(f"offload_folder='{shared.args.disk_cache_dir}'")
  91. command = f"{command}(Path(f'models/{shared.model_name}'), {', '.join(set(params))})"
  92. model = eval(command)
  93. # Loading the tokenizer
  94. if shared.model_name.lower().startswith(('gpt4chan', 'gpt-4chan', '4chan')) and Path(f"models/gpt-j-6B/").exists():
  95. tokenizer = AutoTokenizer.from_pretrained(Path("models/gpt-j-6B/"))
  96. else:
  97. tokenizer = AutoTokenizer.from_pretrained(Path(f"models/{shared.model_name}/"))
  98. tokenizer.truncation_side = 'left'
  99. print(f"Loaded the model in {(time.time()-t0):.2f} seconds.")
  100. return model, tokenizer
  101. def load_soft_prompt(name):
  102. if name == 'None':
  103. shared.soft_prompt = False
  104. shared.soft_prompt_tensor = None
  105. else:
  106. with zipfile.ZipFile(Path(f'softprompts/{name}.zip')) as zf:
  107. zf.extract('tensor.npy')
  108. zf.extract('meta.json')
  109. j = json.loads(open('meta.json', 'r').read())
  110. print(f"\nLoading the softprompt \"{name}\".")
  111. for field in j:
  112. if field != 'name':
  113. if type(j[field]) is list:
  114. print(f"{field}: {', '.join(j[field])}")
  115. else:
  116. print(f"{field}: {j[field]}")
  117. print()
  118. tensor = np.load('tensor.npy')
  119. Path('tensor.npy').unlink()
  120. Path('meta.json').unlink()
  121. tensor = torch.Tensor(tensor).to(device=shared.model.device, dtype=shared.model.dtype)
  122. tensor = torch.reshape(tensor, (1, tensor.shape[0], tensor.shape[1]))
  123. shared.soft_prompt = True
  124. shared.soft_prompt_tensor = tensor
  125. return name