download_from_modelscope.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #!/usr/bin/env python
  2. """
  3. 从魔搭(ModelScope)下载 LLM 模型
  4. 支持模型列表(示例):
  5. - Qwen2.5-7B-Instruct(已有,可重新下载)
  6. - Qwen2.5-14B-Instruct
  7. - Qwen2.5-32B-Instruct
  8. - Qwen3.5-7B-Instruct(如果可用)
  9. - Llama-3-8B-Instruct
  10. - Llama-3.1-8B-Instruct
  11. 用法:
  12. # 下载 Qwen2.5-7B-Instruct
  13. python model/download_from_modelscope.py --model qwen2.5-7b
  14. # 下载 Llama-3-8B-Instruct
  15. python model/download_from_modelscope.py --model llama3-8b
  16. # 下载指定模型(自定义)
  17. python model/download_from_modelscope.py --model-id Qwen/Qwen2.5-7B-Instruct
  18. """
  19. import os
  20. import sys
  21. import argparse
  22. from pathlib import Path
  23. from typing import Optional
  24. # 模型映射表
  25. MODEL_MAPPING = {
  26. # Qwen 系列
  27. "qwen2.5-7b": "Qwen/Qwen2.5-7B-Instruct",
  28. "qwen2.5-14b": "Qwen/Qwen2.5-14B-Instruct",
  29. "qwen2.5-32b": "Qwen/Qwen2.5-32B-Instruct",
  30. "qwen2.5-72b": "Qwen/Qwen2.5-72B-Instruct",
  31. "qwen3.5-7b": "Qwen/Qwen3.5-7B-Instruct",
  32. "qwen3.5-14b": "Qwen/Qwen3.5-14B-Instruct",
  33. "qwen3.5-32b": "Qwen/Qwen3.5-32B-Instruct",
  34. # Llama 系列
  35. "llama3-8b": "LLM-Research/Meta-Llama-3-8B-Instruct",
  36. "llama3-70b": "LLM-Research/Meta-Llama-3-70B-Instruct",
  37. "llama3.1-8b": "LLM-Research/Meta-Llama-3.1-8B-Instruct",
  38. "llama3.1-70b": "LLM-Research/Meta-Llama-3.1-70B-Instruct",
  39. "llama3.2-3b": "LLM-Research/Llama-3.2-3B-Instruct", # 魔搭特供版本
  40. # Mistral 系列(已有)
  41. "mistral-7b": "LLM-Research/Mistral-7B-v0.3",
  42. # Gemma 系列
  43. "gemma-2b": "LLM-Research/gemma-2b-it",
  44. "gemma-7b": "LLM-Research/gemma-7b-it",
  45. "gemma-9b": "LLM-Research/gemma-2-9b-it",
  46. }
  47. def check_modelscope_installed():
  48. """检查 modelscope 是否安装"""
  49. try:
  50. from modelscope import snapshot_download
  51. return True
  52. except ImportError:
  53. print("错误:未安装 modelscope 库")
  54. print("请先运行以下命令安装:")
  55. print(" pip install modelscope")
  56. print(" 或")
  57. print(" pip install modelscope -c https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.txt")
  58. return False
  59. def download_model(model_id: str, output_dir: str, revision: str = "master") -> bool:
  60. """
  61. 从魔搭下载模型
  62. Args:
  63. model_id: 模型 ID,如 "Qwen/Qwen2.5-7B-Instruct"
  64. output_dir: 输出目录
  65. revision: 模型版本
  66. Returns:
  67. 下载是否成功
  68. """
  69. from modelscope import snapshot_download
  70. import inspect
  71. print(f"开始下载模型:{model_id}")
  72. print(f"输出目录:{output_dir}")
  73. print(f"版本:{revision}")
  74. print("-" * 50)
  75. try:
  76. # 检查 snapshot_download 支持的参数
  77. sig = inspect.signature(snapshot_download)
  78. params = {
  79. 'model_id': model_id,
  80. 'revision': revision,
  81. 'local_dir': output_dir,
  82. }
  83. # 根据版本决定是否使用 symlinks 参数
  84. if 'local_dir_use_symlinks' in sig.parameters:
  85. params['local_dir_use_symlinks'] = False
  86. elif 'use_symlinks' in sig.parameters:
  87. params['use_symlinks'] = False
  88. # 使用 snapshot_download 下载模型
  89. model_dir = snapshot_download(**params)
  90. print(f"\n下载完成!")
  91. print(f"模型路径:{model_dir}")
  92. # 列出下载的文件
  93. print("\n下载的文件:")
  94. for root, dirs, files in os.walk(output_dir):
  95. level = root.replace(output_dir, '').count(os.sep)
  96. indent = ' ' * 2 * level
  97. print(f'{indent}{os.path.basename(root)}/')
  98. subindent = ' ' * 2 * (level + 1)
  99. for file in files[:10]: # 只显示前 10 个文件
  100. print(f'{subindent}{file}')
  101. return True
  102. except Exception as e:
  103. print(f"\n下载失败:{e}")
  104. return False
  105. def get_model_info(model_name: str) -> Optional[dict]:
  106. """获取模型信息"""
  107. if model_name in MODEL_MAPPING:
  108. return {
  109. "name": model_name,
  110. "model_id": MODEL_MAPPING[model_name],
  111. "status": "已支持"
  112. }
  113. return None
  114. def list_available_models():
  115. """列出所有可用模型"""
  116. print("\n可用模型列表:")
  117. print("-" * 60)
  118. print(f"{'简写':<20} {'模型 ID':<35} {'状态'}")
  119. print("-" * 60)
  120. for name, model_id in MODEL_MAPPING.items():
  121. print(f"{name:<20} {model_id:<35} 已支持")
  122. print("-" * 60)
  123. print("\n使用方法:")
  124. print(" python model/download_from_modelscope.py --model <简写>")
  125. print(" python model/download_from_modelscope.py --model-id <完整模型 ID>")
  126. print()
  127. def main():
  128. parser = argparse.ArgumentParser(
  129. description="从魔搭(ModelScope)下载 LLM 模型",
  130. formatter_class=argparse.RawDescriptionHelpFormatter,
  131. epilog="""
  132. 示例:
  133. # 列出所有可用模型
  134. python model/download_from_modelscope.py --list
  135. # 下载 Qwen2.5-7B-Instruct
  136. python model/download_from_modelscope.py --model qwen2.5-7b
  137. # 下载 Llama-3-8B-Instruct
  138. python model/download_from_modelscope.py --model llama3-8b
  139. # 使用完整模型 ID 下载
  140. python model/download_from_modelscope.py --model-id Qwen/Qwen2.5-7B-Instruct
  141. """
  142. )
  143. parser.add_argument(
  144. "--model",
  145. type=str,
  146. choices=list(MODEL_MAPPING.keys()),
  147. help="使用简写下载模型(如 qwen2.5-7b, llama3-8b)"
  148. )
  149. parser.add_argument(
  150. "--model-id",
  151. type=str,
  152. help="使用完整模型 ID 下载(如 Qwen/Qwen2.5-7B-Instruct)"
  153. )
  154. parser.add_argument(
  155. "--output-dir",
  156. type=str,
  157. default=None,
  158. help="模型输出目录(默认:model/weights/{model_name})"
  159. )
  160. parser.add_argument(
  161. "--revision",
  162. type=str,
  163. default="master",
  164. help="模型版本(默认:master)"
  165. )
  166. parser.add_argument(
  167. "--list",
  168. action="store_true",
  169. help="列出所有可用模型"
  170. )
  171. args = parser.parse_args()
  172. # 列出模型
  173. if args.list:
  174. list_available_models()
  175. return 0
  176. # 检查参数
  177. if not args.model and not args.model_id:
  178. print("错误:请指定 --model 或 --model-id")
  179. print("使用 --list 查看可用模型")
  180. return 1
  181. # 检查安装
  182. if not check_modelscope_installed():
  183. return 1
  184. # 确定模型 ID
  185. if args.model:
  186. model_id = MODEL_MAPPING[args.model]
  187. model_name = args.model
  188. else:
  189. model_id = args.model_id
  190. model_name = model_id.split("/")[-1]
  191. # 确定输出目录
  192. if args.output_dir:
  193. output_dir = args.output_dir
  194. else:
  195. output_dir = os.path.join("model/weights", model_name)
  196. # 创建目录
  197. Path(output_dir).mkdir(parents=True, exist_ok=True)
  198. # 检查是否已存在
  199. config_file = os.path.join(output_dir, "config.json")
  200. if os.path.exists(config_file):
  201. print(f"警告:模型目录已存在:{output_dir}")
  202. response = input("是否覆盖下载?(y/N): ")
  203. if response.lower() != 'y':
  204. print("已取消")
  205. return 0
  206. # 下载模型
  207. success = download_model(model_id, output_dir, args.revision)
  208. if success:
  209. print("\n" + "=" * 50)
  210. print("下载成功!")
  211. print(f"\n下一步:更新 extract_representations.py 中的模型配置")
  212. print(f"添加新模型:{model_name}")
  213. print(f"模型路径:{output_dir}")
  214. print("=" * 50)
  215. return 0
  216. else:
  217. print("\n下载失败,请检查网络连接或模型 ID 是否正确")
  218. return 1
  219. if __name__ == "__main__":
  220. sys.exit(main())