download_missing.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #!/usr/bin/env python
  2. """
  3. 补充下载缺失的领域数据
  4. """
  5. import os
  6. import re
  7. import json
  8. from pathlib import Path
  9. from typing import List
  10. os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
  11. from datasets import load_dataset
  12. def preprocess_text(text: str, lang: str = "en", min_len: int = 30, max_len: int = 300) -> str | None:
  13. text = text.strip()
  14. if not text:
  15. return None
  16. if lang == "en":
  17. text = re.sub(r'[^\w\s.,!?;:()"\']', '', text)
  18. words = text.split()
  19. if len(words) < min_len or len(words) > max_len:
  20. return None
  21. return ' '.join(words[:max_len]).strip()
  22. return None
  23. def save_corpus(texts: List[str], domain: str) -> bool:
  24. if not texts:
  25. return False
  26. output_path = Path(f"database/corpus/{domain}/texts.jsonl")
  27. output_path.parent.mkdir(parents=True, exist_ok=True)
  28. with open(output_path, "w", encoding="utf-8") as f:
  29. for i, text in enumerate(texts):
  30. f.write(json.dumps({"text": text, "metadata": {"index": i, "domain": domain}}, ensure_ascii=False) + "\n")
  31. print(f" ✅ 已保存:{domain} ({len(texts)} 条)")
  32. return True
  33. def load_code(sample_num: int = 50) -> List[str]:
  34. """加载代码语料 - 使用无需认证的数据集"""
  35. corpus = []
  36. print("尝试加载 Python 代码...")
  37. # 尝试 1: cosmopedia openstax (数学/代码相关)
  38. try:
  39. ds = load_dataset("HuggingFaceTB/cosmopedia", "openstax", split="train", streaming=True)
  40. count = 0
  41. for item in ds:
  42. if count >= 500:
  43. break
  44. count += 1
  45. text = item.get("text", "")
  46. # 筛选包含代码示例的文本
  47. if text and ('import ' in text or 'def ' in text or 'class ' in text or 'print(' in text):
  48. lines = text.strip().split('\n')
  49. if 5 <= len(lines) <= 80:
  50. code_clean = '\n'.join(line[:120] for line in lines[:40])
  51. if code_clean and code_clean not in corpus:
  52. corpus.append(code_clean)
  53. if len(corpus) >= sample_num:
  54. break
  55. if corpus:
  56. print(f" cosmopedia openstax: {len(corpus)} 条")
  57. return corpus
  58. except Exception as e:
  59. print(f" cosmopedia openstax 失败:{e}")
  60. # 尝试 2: 使用 algorithmica 数据集
  61. print(" 尝试 algorithmica...")
  62. try:
  63. ds = load_dataset("Laurencie/algorithmica", split="train", streaming=True)
  64. count = 0
  65. for item in ds:
  66. if count >= 500:
  67. break
  68. count += 1
  69. code = item.get("code", "") or item.get("content", "")
  70. if code:
  71. lines = code.strip().split('\n')
  72. if 3 <= len(lines) <= 60:
  73. code_clean = '\n'.join(line[:120] for line in lines[:30])
  74. if code_clean and code_clean not in corpus:
  75. corpus.append(code_clean)
  76. if len(corpus) >= sample_num:
  77. break
  78. if corpus:
  79. print(f" algorithmica: {len(corpus)} 条")
  80. return corpus
  81. except Exception as e:
  82. print(f" algorithmica 失败:{e}")
  83. # 尝试 3: 使用 leetcode 问题
  84. print(" 尝试 leetcode-problems...")
  85. try:
  86. ds = load_dataset("xiaomingl2000/leetcode-medium-questions", split="train", streaming=True)
  87. count = 0
  88. for item in ds:
  89. if count >= 500:
  90. break
  91. count += 1
  92. # 提取问题和解答
  93. question = item.get("question", "")
  94. solution = item.get("solution", "")
  95. if question or solution:
  96. text = f"{question}\n\n{solution}" if solution else question
  97. processed = preprocess_text(str(text), lang="en")
  98. if processed and processed not in corpus:
  99. corpus.append(processed)
  100. if len(corpus) >= sample_num:
  101. break
  102. if corpus:
  103. print(f" leetcode: {len(corpus)} 条")
  104. return corpus
  105. except Exception as e:
  106. print(f" leetcode 失败:{e}")
  107. return corpus
  108. def load_academic(sample_num: int = 50) -> List[str]:
  109. """补充学术语料"""
  110. corpus = []
  111. print("加载学术语料...")
  112. try:
  113. ds = load_dataset("wikimedia/wikipedia", "20231101.en", split="train", streaming=True)
  114. science_keywords = ["algorithm", "neural network", "machine learning", "computer science", "mathematics",
  115. "statistics", "artificial intelligence", "physics", "chemistry", "biology", "quantum",
  116. "deep learning", "optimization", "data structure", "complexity"]
  117. count = 0
  118. for item in ds:
  119. if count >= 5000:
  120. break
  121. count += 1
  122. text = item.get("text", "")
  123. title = item.get("title", "")
  124. # 更严格的筛选
  125. if any(kw in title.lower() for kw in science_keywords):
  126. processed = preprocess_text(text, lang="en")
  127. if processed and processed not in corpus:
  128. corpus.append(processed)
  129. if len(corpus) >= sample_num:
  130. break
  131. print(f" 维基百科科学:{len(corpus)} 条")
  132. except Exception as e:
  133. print(f" 失败:{e}")
  134. return corpus
  135. def main():
  136. print("=" * 50)
  137. print("补充下载缺失的领域")
  138. print("=" * 50)
  139. # 补充 code (已有 20 条)
  140. print("\n[code] 补充到 50 条")
  141. code_path = Path("database/corpus/code/texts.jsonl")
  142. code_texts = []
  143. if code_path.exists():
  144. with open(code_path) as f:
  145. for line in f:
  146. code_texts.append(json.loads(line)["text"])
  147. print(f" 已有 {len(code_texts)} 条")
  148. if len(code_texts) < 50:
  149. need = 50 - len(code_texts)
  150. new_texts = load_code(need)
  151. for t in new_texts:
  152. if t not in code_texts:
  153. code_texts.append(t)
  154. save_corpus(code_texts[:50], "code")
  155. else:
  156. print(" 已足够,无需补充")
  157. # 补充 academic (已有 20 条)
  158. print("\n[academic] 补充到 50 条")
  159. academic_path = Path("database/corpus/academic/texts.jsonl")
  160. academic_texts = []
  161. if academic_path.exists():
  162. with open(academic_path) as f:
  163. for line in f:
  164. academic_texts.append(json.loads(line)["text"])
  165. print(f" 已有 {len(academic_texts)} 条")
  166. if len(academic_texts) < 50:
  167. need = 50 - len(academic_texts)
  168. new_texts = load_academic(need)
  169. for t in new_texts:
  170. if t not in academic_texts:
  171. academic_texts.append(t)
  172. save_corpus(academic_texts[:50], "academic")
  173. else:
  174. print(" 已足够,无需补充")
  175. print("\n" + "=" * 50)
  176. print("完成!")
  177. print("=" * 50)
  178. if __name__ == "__main__":
  179. main()