download_50_samples.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #!/usr/bin/env python
  2. """
  3. 下载 50 条样本用于 MVP 实验测试
  4. 下载以下 2 个核心领域的语料:
  5. - news_en: 英文新闻 (CNN/DailyMail)
  6. - academic: 学术论文摘要 (arXiv)
  7. 每个领域 50 条样本,保存到 database/corpus/
  8. """
  9. import os
  10. import re
  11. import json
  12. from pathlib import Path
  13. from typing import List, Optional
  14. # 设置 HuggingFace 镜像(国内加速)
  15. os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
  16. from datasets import load_dataset
  17. def preprocess_text(text: str, lang: str = "en", min_len: int = 50, max_len: int = 200) -> Optional[str]:
  18. """
  19. 预处理文本:去特殊符号、控制长度
  20. Args:
  21. text: 原始文本
  22. lang: 语言(en/zh)
  23. min_len: 最小长度(英文=词数,中文=字符数)
  24. max_len: 最大长度
  25. Returns:
  26. 预处理后的文本,None 表示不符合长度被过滤
  27. """
  28. text = text.strip()
  29. if not text:
  30. return None
  31. if lang == "en":
  32. # 英文:保留字母、数字、标点、空格
  33. text = re.sub(r'[^\w\s.,!?;:()"\']', '', text)
  34. words = text.split()
  35. if len(words) < min_len or len(words) > max_len:
  36. return None
  37. text = ' '.join(words[:max_len]).strip()
  38. else:
  39. # 中文:保留汉字、数字、标点
  40. text = re.sub(r'[^\u4e00-\u9fff0-9.,!?;:()""\']', '', text)
  41. chars = list(text)
  42. if len(chars) < min_len or len(chars) > max_len:
  43. return None
  44. text = ''.join(chars[:max_len]).strip()
  45. return text if text else None
  46. def load_news_en(sample_num: int = 50) -> List[str]:
  47. """加载英文新闻语料 (CNN/DailyMail)"""
  48. corpus = []
  49. print("加载 CNN/DailyMail 数据集...")
  50. try:
  51. ds = load_dataset("cnn_dailymail", "3.0.0", split="train")
  52. # 增加采样数量,并降低长度要求以提高通过率
  53. count = 0
  54. for item in ds:
  55. if count >= 500: # 最多遍历 500 条
  56. break
  57. count += 1
  58. text = item["article"]
  59. processed = preprocess_text(text, lang="en", min_len=30, max_len=300)
  60. if processed and processed not in corpus:
  61. corpus.append(processed)
  62. if len(corpus) >= sample_num:
  63. break
  64. print(f" 成功提取 {len(corpus)} 条英文新闻")
  65. except Exception as e:
  66. print(f" 加载失败:{e}")
  67. return corpus
  68. def load_academic(sample_num: int = 50) -> List[str]:
  69. """
  70. 加载学术论文语料
  71. 备用方案:如果 arXiv 无法加载,使用维基百科科学类文章代替
  72. """
  73. corpus = []
  74. print("加载学术语料...")
  75. # 方案 1:尝试 arXiv
  76. try:
  77. print(" 尝试加载 arXiv 数据集...")
  78. ds = load_dataset("CShorten/arxiv-minimal", split="train", streaming=True)
  79. count = 0
  80. for item in ds:
  81. if count >= 1000:
  82. break
  83. count += 1
  84. abstract = item.get("abstract", "")
  85. categories = item.get("categories", [])
  86. if any(cat in categories for cat in ["cs.CL", "cs.LG", "stat.ML", "cs.AI"]):
  87. processed = preprocess_text(abstract, lang="en", min_len=30, max_len=300)
  88. if processed and processed not in corpus:
  89. corpus.append(processed)
  90. if len(corpus) >= sample_num:
  91. break
  92. if corpus:
  93. print(f" 成功提取 {len(corpus)} 篇 arXiv 论文摘要")
  94. return corpus
  95. except Exception as e:
  96. print(f" arXiv 加载失败:{e}")
  97. # 方案 2:使用维基百科(更可靠)
  98. print(" 使用备用方案:维基百科科学文章...")
  99. try:
  100. ds = load_dataset("wikimedia/wikipedia", "20231101.en", split="train", streaming=True)
  101. # 科学相关的关键词
  102. science_keywords = ["algorithm", "neural network", "machine learning",
  103. "computer science", "mathematics", "statistics",
  104. "artificial intelligence", "data science"]
  105. count = 0
  106. for item in ds:
  107. if count >= 2000:
  108. break
  109. count += 1
  110. text = item.get("text", "")
  111. title = item.get("title", "")
  112. # 筛选科学相关文章
  113. if any(kw in title.lower() or kw in text[:500].lower() for kw in science_keywords):
  114. processed = preprocess_text(text, lang="en", min_len=30, max_len=300)
  115. if processed and processed not in corpus:
  116. corpus.append(processed)
  117. if len(corpus) >= sample_num:
  118. break
  119. print(f" 成功提取 {len(corpus)} 篇维基百科科学文章")
  120. except Exception as e:
  121. print(f" 维基百科加载失败:{e}")
  122. return corpus
  123. def save_corpus(texts: List[str], domain: str, output_dir: str = "database/corpus") -> None:
  124. """保存语料到 JSONL 文件"""
  125. output_path = Path(output_dir) / domain / "texts.jsonl"
  126. output_path.parent.mkdir(parents=True, exist_ok=True)
  127. with open(output_path, "w", encoding="utf-8") as f:
  128. for i, text in enumerate(texts):
  129. record = {
  130. "text": text,
  131. "metadata": {
  132. "index": i,
  133. "domain": domain,
  134. }
  135. }
  136. f.write(json.dumps(record, ensure_ascii=False) + "\n")
  137. print(f" 已保存至:{output_path}")
  138. def main():
  139. print("=" * 50)
  140. print("MVP 实验数据集下载(50 条样本)")
  141. print("=" * 50)
  142. print()
  143. # 下载英文新闻
  144. print("\n[news_en]")
  145. news_texts = load_news_en(50)
  146. if news_texts:
  147. save_corpus(news_texts, "news_en")
  148. else:
  149. print(" 警告:未能获取有效语料")
  150. # 下载学术论文
  151. print("\n[academic]")
  152. academic_texts = load_academic(50)
  153. if academic_texts:
  154. save_corpus(academic_texts, "academic")
  155. else:
  156. print(" 警告:未能获取有效语料")
  157. print("\n" + "=" * 50)
  158. print("下载完成!")
  159. print("=" * 50)
  160. print()
  161. print("输出文件:")
  162. print(" - database/corpus/news_en/texts.jsonl")
  163. print(" - database/corpus/academic/texts.jsonl")
  164. print()
  165. print("下一步:提取模型表示")
  166. print(" python model/extract_representations.py")
  167. if __name__ == "__main__":
  168. main()