download_direction9_datasets.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. #!/usr/bin/env python
  2. """
  3. 方向 9 实验数据集下载脚本
  4. 根据「方向 9——跨模型谱收敛实验计划」下载所需数据集:
  5. - MATH: 数学推理
  6. - GSM8K: 多步算术
  7. - flores-200: 低资源语言
  8. - BIG-Bench Hard: 能力涌现探针
  9. - HumanEval: 代码生成
  10. - AlpacaEval: 指令跟随
  11. 用法:
  12. python database/download_direction9_datasets.py --all
  13. python database/download_direction9_datasets.py --dataset math --sample-num 500
  14. """
  15. import os
  16. import json
  17. import argparse
  18. from pathlib import Path
  19. from typing import List, Dict, Optional
  20. # 设置 HuggingFace 镜像
  21. os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
  22. from datasets import load_dataset
  23. def save_to_jsonl(texts: List[Dict], domain: str, output_dir: str = "database/corpus") -> None:
  24. """保存语料到 JSONL 文件"""
  25. output_path = Path(output_dir) / domain / "texts.jsonl"
  26. output_path.parent.mkdir(parents=True, exist_ok=True)
  27. with open(output_path, "w", encoding="utf-8") as f:
  28. for i, item in enumerate(texts):
  29. record = {
  30. "text": item.get("text", ""),
  31. "metadata": {
  32. "index": i,
  33. "domain": domain,
  34. **{k: v for k, v in item.items() if k != "text"}
  35. }
  36. }
  37. f.write(json.dumps(record, ensure_ascii=False) + "\n")
  38. print(f" 已保存至:{output_path}")
  39. def load_math(sample_num: int = 500) -> List[Dict]:
  40. """
  41. 加载数学推理数据集 - 使用 GSM8K + MetaMathQA 作为 MATH 替代
  42. MATH 数据集已不可用,使用替代数据源
  43. """
  44. corpus = []
  45. print("加载数学推理数据集 (GSM8K + MetaMathQA)...")
  46. # 加载 GSM8K (已在 gsm8k 数据集函数中处理,这里作为补充)
  47. try:
  48. ds = load_dataset("gsm8k", "main", split="train")
  49. count = 0
  50. for item in ds:
  51. if count >= sample_num // 2:
  52. break
  53. count += 1
  54. question = item.get("question", "")
  55. answer = item.get("answer", "")
  56. if question:
  57. corpus.append({
  58. "text": f"Question: {question}\n\nAnswer: {answer}",
  59. "type": "arithmetic",
  60. "source": "gsm8k"
  61. })
  62. except Exception as e:
  63. print(f" GSM8K 加载失败:{e}")
  64. # 加载 MetaMathQA 作为补充
  65. try:
  66. ds = load_dataset("MetaMathQA/MetaMathQA", split="train")
  67. count = 0
  68. for item in ds:
  69. if count >= sample_num // 2:
  70. break
  71. count += 1
  72. query = item.get("query", "")
  73. response = item.get("response", "")
  74. if query:
  75. corpus.append({
  76. "text": f"Question: {query}\n\nAnswer: {response}",
  77. "type": "math_reasoning",
  78. "source": "MetaMathQA"
  79. })
  80. except Exception as e:
  81. print(f" MetaMathQA 加载失败:{e}")
  82. print(f" 成功加载 {len(corpus)} 条数学题目")
  83. return corpus
  84. def load_gsm8k(sample_num: int = 500) -> List[Dict]:
  85. """
  86. 加载 GSM8K 数据集 - 多步算术推理
  87. https://huggingface.co/datasets/gsm8k
  88. """
  89. corpus = []
  90. print("加载 GSM8K 数据集...")
  91. try:
  92. ds = load_dataset("gsm8k", "main", split="test")
  93. for item in ds:
  94. if len(corpus) >= sample_num:
  95. break
  96. question = item.get("question", "")
  97. answer = item.get("answer", "")
  98. if question:
  99. corpus.append({
  100. "text": f"Question: {question}\n\nAnswer: {answer}",
  101. "type": "arithmetic"
  102. })
  103. print(f" 成功加载 {len(corpus)} 条算术题目")
  104. except Exception as e:
  105. print(f" 加载失败:{e}")
  106. return corpus
  107. def load_flores200(sample_num: int = 500) -> List[Dict]:
  108. """
  109. 加载低资源语言数据集
  110. 使用替代源:WMT 或 NLLB 数据集
  111. """
  112. corpus = []
  113. print("加载低资源语言数据集 (WMT/NLLB)...")
  114. # 尝试加载 NLLB 数据集 (包含多种低资源语言)
  115. try:
  116. ds = load_dataset("facebook/flores", split="dev")
  117. count = 0
  118. for item in ds:
  119. if count >= sample_num:
  120. break
  121. count += 1
  122. # 获取斯瓦希里语文本
  123. text = item.get("sentence_swa", "") or item.get("sentence", "")
  124. if text:
  125. corpus.append({
  126. "text": text,
  127. "language": "swa",
  128. "source": "flores"
  129. })
  130. print(f" 成功加载 {len(corpus)} 条低资源语言文本")
  131. except Exception as e:
  132. print(f" flores 加载失败:{e}")
  133. print(" 尝试使用 WMT 新闻翻译数据...")
  134. # 降级方案:使用 WMT 数据
  135. try:
  136. ds = load_dataset("wmt16", "ro-en", split="train")
  137. for item in ds:
  138. if len(corpus) >= sample_num:
  139. break
  140. text = item.get("translation", {}).get("ro", "")
  141. if text:
  142. corpus.append({
  143. "text": text,
  144. "language": "ro",
  145. "source": "wmt16"
  146. })
  147. print(f" [降级] 成功加载 {len(corpus)} 条文本")
  148. except Exception as e2:
  149. print(f" 降级方案也失败:{e2}")
  150. return corpus
  151. def load_bigbench_hard(sample_num: int = 500) -> List[Dict]:
  152. """
  153. 加载 BIG-Bench Hard 数据集 - 能力涌现探针
  154. 使用替代源:CoT 推理数据集或 GSM8K
  155. """
  156. corpus = []
  157. print("加载推理数据集 (CoT reasoning / GSM8K)...")
  158. try:
  159. # 尝试加载 CoT 数据集
  160. ds = load_dataset("lama-lab/big-bench-hard", split="train")
  161. count = 0
  162. for item in ds:
  163. if count >= sample_num:
  164. break
  165. count += 1
  166. question = item.get("question", "")
  167. answer = item.get("answer", "")
  168. task = item.get("task", "")
  169. if question:
  170. corpus.append({
  171. "text": f"Task: {task}\n\nQuestion: {question}\n\nAnswer: {answer}",
  172. "task": task,
  173. "type": "reasoning"
  174. })
  175. print(f" 成功加载 {len(corpus)} 条推理题目")
  176. except Exception as e:
  177. print(f" 加载失败:{e}")
  178. print(" 尝试使用 GSM8K 作为推理探针...")
  179. # 降级方案:使用 GSM8K 作为推理探针
  180. try:
  181. ds = load_dataset("gsm8k", "main", split="test")
  182. for item in ds:
  183. if len(corpus) >= sample_num:
  184. break
  185. question = item.get("question", "")
  186. answer = item.get("answer", "")
  187. if question:
  188. corpus.append({
  189. "text": f"Task: arithmetic_reasoning\nQuestion: {question}\n\nAnswer: {answer}",
  190. "task": "arithmetic_reasoning",
  191. "type": "reasoning"
  192. })
  193. print(f" [降级] 成功加载 {len(corpus)} 条推理题目")
  194. except Exception as e2:
  195. print(f" 降级方案也失败:{e2}")
  196. return corpus
  197. def load_humaneval(sample_num: int = 200) -> List[Dict]:
  198. """
  199. 加载 HumanEval 数据集 - 代码生成
  200. https://huggingface.co/datasets/openai_humaneval
  201. """
  202. corpus = []
  203. print("加载 HumanEval 数据集...")
  204. try:
  205. ds = load_dataset("openai_humaneval", split="test")
  206. for item in ds:
  207. if len(corpus) >= sample_num:
  208. break
  209. prompt = item.get("prompt", "")
  210. canonical_solution = item.get("canonical_solution", "")
  211. entry_point = item.get("entry_point", "")
  212. test = item.get("test", "")
  213. if prompt:
  214. corpus.append({
  215. "text": f"Description: {prompt}\n\nSolution: {canonical_solution}\n\nTests: {test}",
  216. "entry_point": entry_point,
  217. "type": "code_generation"
  218. })
  219. print(f" 成功加载 {len(corpus)} 条代码生成题目")
  220. except Exception as e:
  221. print(f" 加载失败:{e}")
  222. return corpus
  223. def load_alpaca_eval(sample_num: int = 200) -> List[Dict]:
  224. """
  225. 加载 AlpacaEval 数据集 - 指令跟随
  226. 使用替代源:Alpaca cleaned 数据集
  227. """
  228. corpus = []
  229. print("加载指令跟随数据集 (Alpaca)...")
  230. try:
  231. # 使用 Alpaca 数据集
  232. ds = load_dataset("yahma/alpaca-cleaned", split="train")
  233. count = 0
  234. for item in ds:
  235. if count >= sample_num:
  236. break
  237. count += 1
  238. instruction = item.get("instruction", "")
  239. input_text = item.get("input", "")
  240. output_text = item.get("output", "")
  241. if instruction:
  242. full_text = f"Instruction: {instruction}\n\nInput: {input_text}\n\nOutput: {output_text}"
  243. corpus.append({
  244. "text": full_text,
  245. "type": "instruction_following",
  246. "source": "alpaca-cleaned"
  247. })
  248. print(f" 成功加载 {len(corpus)} 条指令样本")
  249. except Exception as e:
  250. print(f" 加载失败:{e}")
  251. return corpus
  252. # 数据集加载器映射
  253. DATASET_LOADERS = {
  254. "math": load_math,
  255. "gsm8k": load_gsm8k,
  256. "flores200": load_flores200,
  257. "bigbench": load_bigbench_hard,
  258. "humaneval": load_humaneval,
  259. "alpaca": load_alpaca_eval,
  260. }
  261. def main():
  262. parser = argparse.ArgumentParser(
  263. description="下载方向 9 实验所需数据集",
  264. formatter_class=argparse.RawDescriptionHelpFormatter,
  265. epilog="""
  266. 示例:
  267. # 下载所有数据集
  268. python database/download_direction9_datasets.py --all
  269. # 下载数学推理数据集
  270. python database/download_direction9_datasets.py --dataset math --sample-num 500
  271. # 下载低资源语言数据集
  272. python database/download_direction9_datasets.py --dataset flores200 --sample-num 1000
  273. 可用数据集:
  274. - math: MATH 数学推理
  275. - gsm8k: GSM8K 多步算术
  276. - flores200: flores-200 低资源语言
  277. - bigbench: BIG-Bench Hard 推理
  278. - humaneval: HumanEval 代码生成
  279. - alpaca: AlpacaEval 指令跟随
  280. """
  281. )
  282. parser.add_argument(
  283. "--dataset",
  284. type=str,
  285. choices=list(DATASET_LOADERS.keys()),
  286. help="下载指定数据集"
  287. )
  288. parser.add_argument(
  289. "--all",
  290. action="store_true",
  291. help="下载所有数据集"
  292. )
  293. parser.add_argument(
  294. "--sample-num",
  295. type=int,
  296. default=500,
  297. help="每个数据集的采样数量 (默认:500)"
  298. )
  299. parser.add_argument(
  300. "--output-dir",
  301. type=str,
  302. default="database/corpus",
  303. help="输出目录 (默认:database/corpus)"
  304. )
  305. args = parser.parse_args()
  306. print("=" * 60)
  307. print("方向 9 实验数据集下载")
  308. print("=" * 60)
  309. if args.all:
  310. datasets = list(DATASET_LOADERS.keys())
  311. elif args.dataset:
  312. datasets = [args.dataset]
  313. else:
  314. print("错误:请指定 --dataset 或 --all")
  315. return
  316. for dataset_name in datasets:
  317. print(f"\n[{dataset_name}]")
  318. loader = DATASET_LOADERS[dataset_name]
  319. # 根据数据集类型调整样本数
  320. if dataset_name in ["humaneval", "alpaca"]:
  321. sample_num = min(args.sample_num, 200)
  322. else:
  323. sample_num = args.sample_num
  324. texts = loader(sample_num)
  325. if texts:
  326. save_to_jsonl(texts, dataset_name, args.output_dir)
  327. else:
  328. print(f" 警告:未能获取有效语料")
  329. print("\n" + "=" * 60)
  330. print("下载完成!")
  331. print("=" * 60)
  332. if __name__ == "__main__":
  333. main()