| import os |
| import json |
| import shutil |
| import requests |
| from typing import List, Dict |
| import argparse |
|
|
| class DataCollector: |
| def __init__(self, output_base_dir: str): |
| self.output_base_dir = output_base_dir |
| os.makedirs(self.output_base_dir, exist_ok=True) |
|
|
| def collect_from_jsonl(self, file_path: str, fields: List[str]): |
| """ |
| Extracts specific fields from a JSONL file and categorizes them. |
| """ |
| print(f"Collecting from {file_path}...") |
| with open(file_path, 'r', encoding='utf-8') as f: |
| for line in f: |
| try: |
| data = json.loads(line) |
| |
| text_parts = [] |
| for field in fields: |
| if field in data: |
| val = data[field] |
| if isinstance(val, list): |
| val = " ".join(val) |
| text_parts.append(val) |
| |
| if text_parts: |
| data["text"] = ". ".join(text_parts) |
| |
| |
| category = fields[0] if fields else "general" |
| self._store_data(data, category) |
| except Exception as e: |
| print(f"Error parsing line: {e}") |
|
|
| def collect_from_url(self, url: str, fields: List[str], file_type: str = 'jsonl'): |
| """ |
| Downloads a file from a URL and processes it. |
| """ |
| print(f"Downloading from {url}...") |
| try: |
| response = requests.get(url, stream=True) |
| response.raise_for_status() |
| |
| temp_file = os.path.join(self.output_base_dir, "temp_downloaded_data") |
| with open(temp_file, 'wb') as f: |
| for chunk in response.iter_content(chunk_size=8192): |
| f.write(chunk) |
| |
| if file_type == 'jsonl': |
| self.collect_from_jsonl(temp_file, fields) |
| else: |
| |
| self.collect_from_directory(os.path.dirname(temp_file), [os.path.basename(temp_file)], fields[0] if fields else "web") |
| |
| os.remove(temp_file) |
| print("Download and ingestion complete.") |
| except Exception as e: |
| print(f"Error downloading from URL: {e}") |
|
|
| def collect_from_directory(self, dir_path: str, extensions: List[str], field_label: str): |
| """ |
| Collects files from a directory and labels them with a field. |
| """ |
| print(f"Scanning directory {dir_path} for {extensions}...") |
| for root, _, files in os.walk(dir_path): |
| for file in files: |
| if any(file.endswith(ext) for ext in extensions): |
| file_path = os.path.join(root, file) |
| |
| |
| data = { |
| "file_path": file_path, |
| "field": field_label, |
| "base_name": file |
| } |
| self._store_data(data, field_label) |
|
|
| def _store_data(self, data: Dict, category: str): |
| category_dir = os.path.join(self.output_base_dir, category) |
| os.makedirs(category_dir, exist_ok=True) |
| |
| |
| master_file = os.path.join(category_dir, "collected_data.jsonl") |
| with open(master_file, 'a', encoding='utf-8') as f: |
| f.write(json.dumps(data) + "\n") |
|
|
| def main(): |
| parser = argparse.ArgumentParser(description="Data Collector for Fine-tuner") |
| parser.add_argument("--source", type=str, required=True, help="Source file, directory, or URL") |
| parser.add_argument("--type", choices=['jsonl', 'dir', 'url'], required=True, help="Type of source") |
| parser.add_argument("--fields", nargs="+", help="Fields to extract or label") |
| parser.add_argument("--output", type=str, default="data/processed", help="Output directory") |
| |
| args = parser.parse_args() |
| |
| collector = DataCollector(args.output) |
| |
| if args.type == 'jsonl': |
| collector.collect_from_jsonl(args.source, args.fields or ["text"]) |
| elif args.type == 'dir': |
| collector.collect_from_directory(args.source, [".txt", ".py", ".md"], args.fields[0] if args.fields else "code") |
| elif args.type == 'url': |
| collector.collect_from_url(args.source, args.fields or ["text"], 'jsonl') |
|
|
| if __name__ == "__main__": |
| main() |
|
|