models.py 8.2 KB

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