models.py 10 KB

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