make-ggml.py 5.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env python3
  2. """
  3. This script converts Hugging Face Llama, StarCoder, Falcon, Baichuan, and GPT-NeoX models to GGUF and quantizes them.
  4. Usage:
  5. python make-ggml.py {model_dir_or_hf_repo_name} --model_type {model_type} [--outname {output_name} (Optional)] [--outdir {output_directory} (Optional)] [--quants {quant_types} (Optional)] [--keep_fp16 (Optional)]
  6. Arguments:
  7. - model: (Required) The directory of the downloaded Hugging Face model or the name of the Hugging Face model repository. If the model directory does not exist, it will be downloaded from the Hugging Face model hub.
  8. - --model_type: (Required) The type of the model to be converted. Choose from llama, starcoder, falcon, baichuan, or gptneox.
  9. - --outname: (Optional) The name of the output model. If not specified, the last part of the model directory path or the Hugging Face model repo name will be used.
  10. - --outdir: (Optional) The directory where the output model(s) will be stored. If not specified, '../models/{outname}' will be used.
  11. - --quants: (Optional) The types of quantization to apply. This should be a space-separated list. The default is 'Q4_K_M Q5_K_S'.
  12. - --keep_fp16: (Optional) If specified, the FP16 model will not be deleted after the quantized models are created.
  13. Old quant types (some base model types require these):
  14. - Q4_0: small, very high quality loss - legacy, prefer using Q3_K_M
  15. - Q4_1: small, substantial quality loss - legacy, prefer using Q3_K_L
  16. - Q5_0: medium, balanced quality - legacy, prefer using Q4_K_M
  17. - Q5_1: medium, low quality loss - legacy, prefer using Q5_K_M
  18. New quant types (recommended):
  19. - Q2_K: smallest, extreme quality loss - not recommended
  20. - Q3_K: alias for Q3_K_M
  21. - Q3_K_S: very small, very high quality loss
  22. - Q3_K_M: very small, very high quality loss
  23. - Q3_K_L: small, substantial quality loss
  24. - Q4_K: alias for Q4_K_M
  25. - Q4_K_S: small, significant quality loss
  26. - Q4_K_M: medium, balanced quality - recommended
  27. - Q5_K: alias for Q5_K_M
  28. - Q5_K_S: large, low quality loss - recommended
  29. - Q5_K_M: large, very low quality loss - recommended
  30. - Q6_K: very large, extremely low quality loss
  31. - Q8_0: very large, extremely low quality loss - not recommended
  32. - F16: extremely large, virtually no quality loss - not recommended
  33. - F32: absolutely huge, lossless - not recommended
  34. """
  35. import subprocess
  36. subprocess.run(f"pip install huggingface-hub==0.16.4", shell=True, check=True)
  37. import argparse
  38. import os
  39. from huggingface_hub import snapshot_download
  40. def main(model, model_type, outname, outdir, quants, keep_fp16):
  41. if not os.path.isdir(model):
  42. print(f"Model not found at {model}. Downloading...")
  43. try:
  44. if outname is None:
  45. outname = model.split('/')[-1]
  46. model = snapshot_download(repo_id=model, cache_dir='../models/hf_cache')
  47. except Exception as e:
  48. raise Exception(f"Could not download the model: {e}")
  49. if outdir is None:
  50. outdir = f'../models/{outname}'
  51. if not os.path.isfile(f"{model}/config.json"):
  52. raise Exception(f"Could not find config.json in {model}")
  53. os.makedirs(outdir, exist_ok=True)
  54. print("Building llama.cpp")
  55. subprocess.run(f"cd .. && make quantize", shell=True, check=True)
  56. fp16 = f"{outdir}/{outname}.gguf.fp16.bin"
  57. print(f"Making unquantised GGUF at {fp16}")
  58. if not os.path.isfile(fp16):
  59. if model_type != "llama":
  60. subprocess.run(f"python3 ../convert-{model_type}-hf-to-gguf.py {model} 1 --outfile {fp16}", shell=True, check=True)
  61. else:
  62. subprocess.run(f"python3 ../convert.py {model} --outtype f16 --outfile {fp16}", shell=True, check=True)
  63. else:
  64. print(f"Unquantised GGML already exists at: {fp16}")
  65. print("Making quants")
  66. for type in quants:
  67. outfile = f"{outdir}/{outname}.gguf.{type}.bin"
  68. print(f"Making {type} : {outfile}")
  69. subprocess.run(f"../quantize {fp16} {outfile} {type}", shell=True, check=True)
  70. if not keep_fp16:
  71. os.remove(fp16)
  72. if __name__ == "__main__":
  73. parser = argparse.ArgumentParser(description='Convert/Quantize HF models to GGUF. If you have the HF model downloaded already, pass the path to the model dir. Otherwise, pass the Hugging Face model repo name. You need to be in the /examples folder for it to work.')
  74. parser.add_argument('model', help='Downloaded model dir or Hugging Face model repo name')
  75. parser.add_argument('--model_type', required=True, choices=['llama', 'starcoder', 'falcon', 'baichuan', 'gptneox'], help='Type of the model to be converted. Choose from llama, starcoder, falcon, baichuan, or gptneox.')
  76. parser.add_argument('--outname', default=None, help='Output model(s) name')
  77. parser.add_argument('--outdir', default=None, help='Output directory')
  78. parser.add_argument('--quants', nargs='*', default=["Q4_K_M", "Q5_K_S"], help='Quant types')
  79. parser.add_argument('--keep_fp16', action='store_true', help='Keep fp16 model', default=False)
  80. args = parser.parse_args()
  81. main(args.model, args.model_type, args.outname, args.outdir, args.quants, args.keep_fp16)