models.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import json
  2. import os
  3. import time
  4. import zipfile
  5. from pathlib import Path
  6. import numpy as np
  7. import torch
  8. import transformers
  9. from accelerate import infer_auto_device_map, init_empty_weights
  10. from transformers import (AutoConfig, AutoModelForCausalLM, AutoTokenizer,
  11. BitsAndBytesConfig)
  12. import modules.shared as shared
  13. transformers.logging.set_verbosity_error()
  14. local_rank = None
  15. if shared.args.flexgen:
  16. from flexgen.flex_opt import CompressionConfig, ExecutionEnv, OptLM, Policy
  17. if shared.args.deepspeed:
  18. import deepspeed
  19. from transformers.deepspeed import (HfDeepSpeedConfig,
  20. is_deepspeed_zero3_enabled)
  21. from modules.deepspeed_parameters import generate_ds_config
  22. # Distributed setup
  23. local_rank = shared.args.local_rank if shared.args.local_rank is not None else int(os.getenv("LOCAL_RANK", "0"))
  24. world_size = int(os.getenv("WORLD_SIZE", "1"))
  25. torch.cuda.set_device(local_rank)
  26. deepspeed.init_distributed()
  27. ds_config = generate_ds_config(shared.args.bf16, 1 * world_size, shared.args.nvme_offload_dir)
  28. dschf = HfDeepSpeedConfig(ds_config) # Keep this object alive for the Transformers integration
  29. def load_model(model_name):
  30. print(f"Loading {model_name}...")
  31. t0 = time.time()
  32. shared.is_RWKV = model_name.lower().startswith('rwkv-')
  33. # Default settings
  34. if not any([shared.args.cpu, shared.args.load_in_8bit, shared.args.gptq_bits, shared.args.auto_devices, shared.args.disk, shared.args.gpu_memory is not None, shared.args.cpu_memory is not None, shared.args.deepspeed, shared.args.flexgen, shared.is_RWKV]):
  35. if any(size in shared.model_name.lower() for size in ('13b', '20b', '30b')):
  36. model = AutoModelForCausalLM.from_pretrained(Path(f"models/{shared.model_name}"), device_map='auto', load_in_8bit=True)
  37. else:
  38. model = AutoModelForCausalLM.from_pretrained(
  39. Path(f"models/{shared.model_name}"),
  40. low_cpu_mem_usage=True, torch_dtype=torch.bfloat16 if shared.args.bf16 else torch.float16
  41. )
  42. if torch.has_mps:
  43. device = torch.device('mps')
  44. model = model.to(device)
  45. else:
  46. model = model.cuda()
  47. # FlexGen
  48. elif shared.args.flexgen:
  49. # Initialize environment
  50. env = ExecutionEnv.create(shared.args.disk_cache_dir)
  51. # Offloading policy
  52. policy = Policy(1, 1,
  53. shared.args.percent[0], shared.args.percent[1],
  54. shared.args.percent[2], shared.args.percent[3],
  55. shared.args.percent[4], shared.args.percent[5],
  56. overlap=True, sep_layer=True, pin_weight=shared.args.pin_weight,
  57. cpu_cache_compute=False, attn_sparsity=1.0,
  58. compress_weight=shared.args.compress_weight,
  59. comp_weight_config=CompressionConfig(
  60. num_bits=4, group_size=64,
  61. group_dim=0, symmetric=False),
  62. compress_cache=False,
  63. comp_cache_config=CompressionConfig(
  64. num_bits=4, group_size=64,
  65. group_dim=2, symmetric=False))
  66. model = OptLM(f"facebook/{shared.model_name}", env, "models", policy)
  67. # DeepSpeed ZeRO-3
  68. elif shared.args.deepspeed:
  69. model = AutoModelForCausalLM.from_pretrained(Path(f"models/{shared.model_name}"), torch_dtype=torch.bfloat16 if shared.args.bf16 else torch.float16)
  70. model = deepspeed.initialize(model=model, config_params=ds_config, model_parameters=None, optimizer=None, lr_scheduler=None)[0]
  71. model.module.eval() # Inference
  72. print(f"DeepSpeed ZeRO-3 is enabled: {is_deepspeed_zero3_enabled()}")
  73. # RMKV model (not on HuggingFace)
  74. elif shared.is_RWKV:
  75. from modules.RWKV import RWKVModel, RWKVTokenizer
  76. model = RWKVModel.from_pretrained(Path(f'models/{model_name}'), dtype="fp32" if shared.args.cpu else "bf16" if shared.args.bf16 else "fp16", device="cpu" if shared.args.cpu else "cuda")
  77. tokenizer = RWKVTokenizer.from_pretrained(Path('models'))
  78. return model, tokenizer
  79. # Quantized model
  80. elif shared.args.gptq_bits > 0:
  81. from modules.GPTQ_loader import load_quantized
  82. model = load_quantized(model_name)
  83. # Custom
  84. else:
  85. params = {"low_cpu_mem_usage": True}
  86. if not shared.args.cpu and not torch.cuda.is_available() and not torch.has_mps:
  87. print("Warning: torch.cuda.is_available() returned False.\nThis means that no GPU has been detected.\nFalling back to CPU mode.\n")
  88. shared.args.cpu = True
  89. if shared.args.cpu:
  90. params["torch_dtype"] = torch.float32
  91. else:
  92. params["device_map"] = 'auto'
  93. if shared.args.load_in_8bit and any((shared.args.auto_devices, shared.args.gpu_memory)):
  94. params['quantization_config'] = BitsAndBytesConfig(load_in_8bit=True, llm_int8_enable_fp32_cpu_offload=True)
  95. elif shared.args.load_in_8bit:
  96. params['quantization_config'] = BitsAndBytesConfig(load_in_8bit=True)
  97. elif shared.args.bf16:
  98. params["torch_dtype"] = torch.bfloat16
  99. else:
  100. params["torch_dtype"] = torch.float16
  101. if shared.args.gpu_memory:
  102. memory_map = shared.args.gpu_memory
  103. max_memory = {}
  104. for i in range(len(memory_map)):
  105. max_memory[i] = f'{memory_map[i]}GiB'
  106. max_memory['cpu'] = f'{shared.args.cpu_memory or 99}GiB'
  107. params['max_memory'] = max_memory
  108. elif shared.args.auto_devices:
  109. total_mem = (torch.cuda.get_device_properties(0).total_memory / (1024*1024))
  110. suggestion = round((total_mem-1000) / 1000) * 1000
  111. if total_mem - suggestion < 800:
  112. suggestion -= 1000
  113. suggestion = int(round(suggestion/1000))
  114. 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")
  115. max_memory = {0: f'{suggestion}GiB', 'cpu': f'{shared.args.cpu_memory or 99}GiB'}
  116. params['max_memory'] = max_memory
  117. if shared.args.disk:
  118. params["offload_folder"] = shared.args.disk_cache_dir
  119. checkpoint = Path(f'models/{shared.model_name}')
  120. if shared.args.load_in_8bit and params.get('max_memory', None) is not None and params['device_map'] == 'auto':
  121. config = AutoConfig.from_pretrained(checkpoint)
  122. with init_empty_weights():
  123. model = AutoModelForCausalLM.from_config(config)
  124. model.tie_weights()
  125. params['device_map'] = infer_auto_device_map(
  126. model,
  127. dtype=torch.int8,
  128. max_memory=params['max_memory'],
  129. no_split_module_classes = model._no_split_modules
  130. )
  131. model = AutoModelForCausalLM.from_pretrained(checkpoint, **params)
  132. # Loading the tokenizer
  133. if shared.model_name.lower().startswith(('gpt4chan', 'gpt-4chan', '4chan')) and Path("models/gpt-j-6B/").exists():
  134. tokenizer = AutoTokenizer.from_pretrained(Path("models/gpt-j-6B/"))
  135. else:
  136. tokenizer = AutoTokenizer.from_pretrained(Path(f"models/{shared.model_name}/"))
  137. tokenizer.truncation_side = 'left'
  138. print(f"Loaded the model in {(time.time()-t0):.2f} seconds.")
  139. return model, tokenizer
  140. def load_soft_prompt(name):
  141. if name == 'None':
  142. shared.soft_prompt = False
  143. shared.soft_prompt_tensor = None
  144. else:
  145. with zipfile.ZipFile(Path(f'softprompts/{name}.zip')) as zf:
  146. zf.extract('tensor.npy')
  147. zf.extract('meta.json')
  148. j = json.loads(open('meta.json', 'r').read())
  149. print(f"\nLoading the softprompt \"{name}\".")
  150. for field in j:
  151. if field != 'name':
  152. if type(j[field]) is list:
  153. print(f"{field}: {', '.join(j[field])}")
  154. else:
  155. print(f"{field}: {j[field]}")
  156. print()
  157. tensor = np.load('tensor.npy')
  158. Path('tensor.npy').unlink()
  159. Path('meta.json').unlink()
  160. tensor = torch.Tensor(tensor).to(device=shared.model.device, dtype=shared.model.dtype)
  161. tensor = torch.reshape(tensor, (1, tensor.shape[0], tensor.shape[1]))
  162. shared.soft_prompt = True
  163. shared.soft_prompt_tensor = tensor
  164. return name