| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- #!/usr/bin/env python
- """
- 下载所有领域的数据集(每个领域 200 条样本)
- 领域列表:
- - news_en: 英文新闻 (CNN/DailyMail)
- - news_zh: 中文新闻 (维基百科中文)
- - academic: 学术语料 (维基百科科学类)
- - code: 代码语料 (Cosmopedia)
- - dialogue: 对话语料 (OpenAssistant/oasst1)
- - literature: 文学语料 (维基百科人文类)
- 用法:
- python database/download_200_samples.py
- """
- import os
- import re
- import json
- from pathlib import Path
- from typing import List, Optional
- # 设置 HuggingFace 镜像(国内加速)
- os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
- from datasets import load_dataset
- def preprocess_text(text: str, lang: str = "en", min_len: int = 30, max_len: int = 300) -> Optional[str]:
- """预处理文本:去特殊符号、控制长度"""
- text = text.strip()
- if not text:
- return None
- if lang == "en":
- text = re.sub(r'[^\w\s.,!?;:()"\']', '', text)
- words = text.split()
- if len(words) < min_len or len(words) > max_len:
- return None
- return ' '.join(words[:max_len]).strip()
- else:
- text = re.sub(r'[^\u4e00-\u9fff0-9.,!?;:()"\',,。!?、;:""()【】《》]', '', text)
- chars = list(text)
- if len(chars) < min_len or len(chars) > max_len:
- return None
- return ''.join(chars[:max_len]).strip()
- def save_corpus(texts: List[str], domain: str, output_dir: str = "database/corpus") -> bool:
- """保存语料到 JSONL 文件"""
- if not texts:
- print(f" ⚠️ 警告:没有语料可保存")
- return False
- output_path = Path(output_dir) / domain / "texts.jsonl"
- output_path.parent.mkdir(parents=True, exist_ok=True)
- with open(output_path, "w", encoding="utf-8") as f:
- for i, text in enumerate(texts):
- record = {
- "text": text,
- "metadata": {
- "index": i,
- "domain": domain,
- }
- }
- f.write(json.dumps(record, ensure_ascii=False) + "\n")
- print(f" ✅ 已保存至:{output_path} ({len(texts)} 条)")
- return True
- # ==================== 各领域加载函数 ====================
- def load_news_en(sample_num: int = 200) -> List[str]:
- """加载英文新闻语料 (CNN/DailyMail)"""
- corpus = []
- print("加载 CNN/DailyMail 数据集...")
- try:
- ds = load_dataset("cnn_dailymail", "3.0.0", split="train")
- count = 0
- for item in ds:
- if count >= 2000:
- break
- count += 1
- text = item["article"]
- processed = preprocess_text(text, lang="en", min_len=30, max_len=300)
- if processed and processed not in corpus:
- corpus.append(processed)
- if len(corpus) >= sample_num:
- break
- print(f" 成功提取 {len(corpus)} 条英文新闻")
- except Exception as e:
- print(f" 加载失败:{e}")
- return corpus
- def load_news_zh(sample_num: int = 200) -> List[str]:
- """加载中文新闻语料 (维基百科中文)"""
- corpus = []
- print("加载维基百科中文数据集...")
- try:
- ds = load_dataset("wikimedia/wikipedia", "20231101.zh", split="train", streaming=True)
- count = 0
- for item in ds:
- if count >= 5000:
- break
- count += 1
- text = item.get("text", "")
- if text:
- processed = preprocess_text(text, lang="zh", min_len=50, max_len=200)
- if processed and processed not in corpus:
- corpus.append(processed)
- if len(corpus) >= sample_num:
- break
- print(f" 成功提取 {len(corpus)} 条中文维基百科文章")
- except Exception as e:
- print(f" 加载失败:{e}")
- return corpus
- def load_academic(sample_num: int = 200) -> List[str]:
- """加载学术语料 (维基百科科学类)"""
- corpus = []
- print("加载维基百科科学文章...")
- science_keywords = [
- "algorithm", "neural network", "machine learning", "computer science", "mathematics",
- "statistics", "artificial intelligence", "physics", "chemistry", "biology", "quantum",
- "deep learning", "optimization", "data structure", "complexity", "relativity",
- "thermodynamics", "electromagnetism", "genetics", "evolution", "ecosystem",
- "calculus", "topology", "algebra", "geometry", "probability", "enzyme", "protein",
- "dna", "rna", "cell", "molecule", "atom", "electron", "photon", "galaxy", "star"
- ]
- try:
- ds = load_dataset("wikimedia/wikipedia", "20231101.en", split="train", streaming=True)
- count = 0
- for item in ds:
- if count >= 50000:
- break
- count += 1
- text = item.get("text", "")
- title = item.get("title", "")
- # 从标题或内容前 500 字符中筛选
- if any(kw in title.lower() or kw in text[:500].lower() for kw in science_keywords):
- processed = preprocess_text(text, lang="en")
- if processed and processed not in corpus:
- corpus.append(processed)
- if len(corpus) >= sample_num:
- break
- print(f" 成功提取 {len(corpus)} 篇维基百科科学文章")
- except Exception as e:
- print(f" 加载失败:{e}")
- return corpus
- def load_code(sample_num: int = 200) -> List[str]:
- """加载代码语料 (Cosmopedia Openstax)"""
- corpus = []
- print("加载 Cosmopedia Openstax 代码数据集...")
- try:
- ds = load_dataset("HuggingFaceTB/cosmopedia", "openstax", split="train", streaming=True)
- count = 0
- for item in ds:
- if count >= 2000:
- break
- count += 1
- text = item.get("text", "")
- if text and ('import ' in text or 'def ' in text or 'class ' in text or 'print(' in text or 'for ' in text):
- lines = text.strip().split('\n')
- if 5 <= len(lines) <= 80:
- code_clean = '\n'.join(line[:120] for line in lines[:40])
- if code_clean and code_clean not in corpus:
- corpus.append(code_clean)
- if len(corpus) >= sample_num:
- break
- print(f" 成功提取 {len(corpus)} 段代码")
- except Exception as e:
- print(f" 加载失败:{e}")
- return corpus
- def load_dialogue(sample_num: int = 200) -> List[str]:
- """加载对话语料 (OpenAssistant/oasst1)"""
- corpus = []
- print("加载 OpenAssistant/oasst1 数据集...")
- try:
- ds = load_dataset("OpenAssistant/oasst1", split="train")
- messages = {}
- for item in ds:
- msg_id = item.get("message_id", "")
- parent_id = item.get("parent_id", "")
- text = item.get("text", "")
- role = item.get("role", "")
- if parent_id not in messages:
- messages[parent_id] = []
- messages[parent_id].append({
- "id": msg_id,
- "role": role,
- "text": text
- })
- for root_msgs in messages.values():
- if len(root_msgs) >= 2:
- dialogue_parts = []
- for msg in root_msgs[:4]:
- dialogue_parts.append(f"{msg['role']}: {msg['text']}")
- dialogue = " ".join(dialogue_parts)
- processed = preprocess_text(dialogue, lang="en", min_len=30, max_len=300)
- if processed and processed not in corpus:
- corpus.append(processed)
- if len(corpus) >= sample_num:
- break
- print(f" 成功提取 {len(corpus)} 段对话")
- except Exception as e:
- print(f" 加载失败:{e}")
- return corpus
- def load_literature(sample_num: int = 200) -> List[str]:
- """加载文学语料 (维基百科人文类)"""
- corpus = []
- print("加载维基百科人文文章...")
- literature_keywords = [
- "novel", "poetry", "fiction", "literature", "shakespeare",
- "dickens", "austen", "tolkien", "hemingway", "orwell",
- "pride and prejudice", "great gatsby", "1984", "lord of the rings",
- "romeo and juliet", "hamlet", "macbeth", "jane eyre", "wuthering heights",
- "moby dick", "war and peace", "crime and punishment", "ulysses",
- "writer", "author", "book", "story", "character", "plot", "narrative",
- "prose", "verse", "sonnet", "drama", "tragedy", "comedy", "english literature"
- ]
- try:
- ds = load_dataset("wikimedia/wikipedia", "20231101.en", split="train", streaming=True)
- count = 0
- for item in ds:
- if count >= 50000:
- break
- count += 1
- text = item.get("text", "")
- title = item.get("title", "")
- # 从标题或内容前 500 字符中筛选
- if any(kw in title.lower() or kw in text[:500].lower() for kw in literature_keywords):
- processed = preprocess_text(text, lang="en")
- if processed and processed not in corpus:
- corpus.append(processed)
- if len(corpus) >= sample_num:
- break
- print(f" 成功提取 {len(corpus)} 段文学文本")
- except Exception as e:
- print(f" 加载失败:{e}")
- return corpus
- # ==================== 主流程 ====================
- DOMAIN_LOADERS = {
- "news_en": load_news_en,
- "news_zh": load_news_zh,
- "academic": load_academic,
- "code": load_code,
- "dialogue": load_dialogue,
- "literature": load_literature,
- }
- def main():
- print("=" * 60)
- print("数据集下载 - 完整语料库(每个领域 200 条样本)")
- print("=" * 60)
- print()
- domains = list(DOMAIN_LOADERS.keys())
- sample_num = 200
- print(f"目标领域:{domains}")
- print(f"每个领域采样数:{sample_num}")
- print(f"输出目录:database/corpus/")
- print()
- results = {}
- for domain in domains:
- print(f"\n{'='*40}")
- print(f"[{domain}]")
- print(f"{'='*40}")
- loader = DOMAIN_LOADERS[domain]
- texts = loader(sample_num)
- if texts:
- success = save_corpus(texts, domain)
- results[domain] = len(texts) if success else 0
- else:
- print(f" ⚠️ 警告:未能获取有效语料")
- results[domain] = 0
- print("\n" + "=" * 60)
- print("下载完成! 汇总:")
- print("=" * 60)
- for domain, count in results.items():
- status = "✅" if count > 0 else "❌"
- print(f" {status} {domain}: {count} 条")
- total = sum(results.values())
- print(f"\n总计:{total} 条")
- print()
- print("下一步:提取模型表示")
- print(" python model/extract_representations.py")
- if __name__ == "__main__":
- main()
|