NexusCoder / scripts /prepare_dataset.py
AdminReal's picture
Import NexusCoder from github.com/mhieuhonda/NexusCoder
eca5751 verified
Raw
History Blame Contribute Delete
5.74 kB
"""
Script chuẩn bị dataset cho training
====================================
Process raw collected data → cleaned, deduplicated, formatted training data.
Steps:
1. Load raw data from ./data/raw/
2. Clean text (TextCleaner)
3. Format code samples (CodeFormatter)
4. Filter by quality (QualityFilter)
5. Deduplicate (Deduplicator)
6. Save processed data to ./data/processed/
Usage:
python scripts/prepare_dataset.py --input ./data/raw --output ./data/processed
"""
import sys
import os
import json
import argparse
import logging
from pathlib import Path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
def load_raw_data(input_dir: str):
"""Load all JSONL files from input directory."""
files = [
f for f in os.listdir(input_dir)
if f.endswith(".jsonl")
]
total = 0
for fname in files:
fpath = os.path.join(input_dir, fname)
count = 0
with open(fpath, "r", encoding="utf-8") as f:
for line in f:
try:
item = json.loads(line)
yield item
count += 1
except json.JSONDecodeError:
continue
logger.info(f" Loaded {count} from {fname}")
total += count
logger.info(f"Total raw samples: {total}")
def process_data(input_dir: str, output_dir: str, max_samples: int = None):
"""Process raw data through cleaning, dedup, quality filter."""
from nexus.data.processors.cleaner import TextCleaner
from nexus.data.processors.quality_filter import QualityFilter
from nexus.data.processors.code_formatter import CodeFormatter
from nexus.data.processors.deduplicator import Deduplicator
from nexus.data.curriculum import CurriculumLearning
cleaner = TextCleaner()
quality_filter = QualityFilter()
code_formatter = CodeFormatter()
deduplicator = Deduplicator()
curriculum = CurriculumLearning()
os.makedirs(output_dir, exist_ok=True)
# Output files by difficulty
output_files = {
"easy": open(os.path.join(output_dir, "train_easy.jsonl"), "w", encoding="utf-8"),
"medium": open(os.path.join(output_dir, "train_medium.jsonl"), "w", encoding="utf-8"),
"hard": open(os.path.join(output_dir, "train_hard.jsonl"), "w", encoding="utf-8"),
"expert": open(os.path.join(output_dir, "train_expert.jsonl"), "w", encoding="utf-8"),
}
stats = {
"total_input": 0,
"cleaned": 0,
"quality_passed": 0,
"deduplicated": 0,
"by_difficulty": {"easy": 0, "medium": 0, "hard": 0, "expert": 0},
}
logger.info("Processing samples...")
for sample in load_raw_data(input_dir):
if max_samples and stats["total_input"] >= max_samples:
break
stats["total_input"] += 1
# Step 1: Clean
sample = cleaner.process(sample)
if sample is None:
continue
stats["cleaned"] += 1
# Step 2: Format code
sample = code_formatter.process(sample)
# Step 3: Quality filter
if not quality_filter.filter(sample):
continue
sample = next(quality_filter.process([sample]), None)
if sample is None:
continue
stats["quality_passed"] += 1
# Step 4: Dedup
if deduplicator.is_duplicate(sample.get("text", "")):
continue
deduplicator.add(sample["text"], sample)
stats["deduplicated"] += 1
# Step 5: Classify by difficulty
difficulty = curriculum.classify_sample(sample).value
output_files[difficulty].write(json.dumps(sample, ensure_ascii=False) + "\n")
stats["by_difficulty"][difficulty] += 1
if stats["deduplicated"] % 1000 == 0:
logger.info(f" Processed {stats['deduplicated']} unique samples...")
# Close files
for f in output_files.values():
f.close()
# Print stats
print("\n" + "=" * 60)
print(" PROCESSING COMPLETE")
print("=" * 60)
print(f" Input samples: {stats['total_input']:,}")
print(f" After cleaning: {stats['cleaned']:,}")
print(f" Quality passed: {stats['quality_passed']:,}")
print(f" After dedup: {stats['deduplicated']:,}")
print("-" * 60)
print(" By difficulty:")
for level, count in stats["by_difficulty"].items():
print(f" {level:8s}: {count:,}")
print("-" * 60)
print(f" Output dir: {output_dir}")
print("=" * 60)
# Save stats
stats_path = os.path.join(output_dir, "processing_stats.json")
with open(stats_path, "w", encoding="utf-8") as f:
json.dump(stats, f, indent=2)
return stats
def main():
parser = argparse.ArgumentParser(description="Nexus Coder Dataset Processor")
parser.add_argument("--input", type=str, default="./data/raw")
parser.add_argument("--output", type=str, default="./data/processed")
parser.add_argument("--max-samples", type=int, default=None)
args = parser.parse_args()
print("=" * 70)
print(" NEXUS CODER v0.2 - DATASET PROCESSOR")
print(" Tác giả: Hieu Louis")
print("=" * 70)
if not os.path.exists(args.input):
print(f"\n❌ Input dir not found: {args.input}")
print("Run scripts/collect_data.py first to collect raw data.")
return 1
process_data(args.input, args.output, args.max_samples)
return 0
if __name__ == "__main__":
sys.exit(main())