File size: 5,081 Bytes
b47957e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
import os
import requests
import numpy as np
import pickle
from datasets import load_dataset
from tqdm import tqdm
# --- CONFIGURAÇÕES ---
DATA_CACHE_DIR = os.path.dirname(__file__)
SEPARATOR = "\n\n<|END_OF_DOCUMENT|>\n\n" # O modelo aprende que aqui muda o assunto
TARGET_SIZE_PER_DOMAIN = 4_000_000 # 4MB por domínio = ~16MB total (Ótimo para o Mac)
def get_python_data(target_chars):
print("🔹 Baixando Código Python (The Stack)...")
# Streaming: Baixa apenas o necessário
dataset = load_dataset("bigcode/the-stack-smol", data_dir="data/python", split="train", streaming=True)
text_accum = []
current_len = 0
for sample in tqdm(dataset, desc="Coletando Python", total=target_chars//100):
code = sample['content']
# Filtro básico: Pula arquivos muito pequenos ou gigantescos
if 100 < len(code) < 10000:
text_accum.append(code)
current_len += len(code)
if current_len >= target_chars: break
return SEPARATOR.join(text_accum)
def get_math_data(target_chars):
print("🔹 Baixando Matemática (DeepMind Algebra)...")
# Algebra linear exige que a rede não "perca o fio da meada"
dataset = load_dataset("math_dataset", "algebra__linear_1d", split="train", streaming=True)
text_accum = []
current_len = 0
for sample in tqdm(dataset, desc="Coletando Math"):
# Formata como pergunta e resposta
qa = f"Q: {sample['question'].strip()}\nA: {sample['answer'].strip()}"
text_accum.append(qa)
current_len += len(qa)
if current_len >= target_chars: break
return SEPARATOR.join(text_accum)
def get_tinystories_data(target_chars):
print("🔹 Baixando TinyStories (Raciocínio Narrativo)...")
# TinyStories é famoso por ensinar IAs pequenas a falar coerentemente
dataset = load_dataset("roneneldan/TinyStories", split="train", streaming=True)
text_accum = []
current_len = 0
for sample in tqdm(dataset, desc="Coletando Stories"):
story = sample['text']
text_accum.append(story)
current_len += len(story)
if current_len >= target_chars: break
return SEPARATOR.join(text_accum)
def get_classic_lit_data():
print("🔹 Baixando Literatura (War and Peace)...")
url = 'https://raw.githubusercontent.com/mmcky/nyu-econ-370/master/notebooks/data/book-war-and-peace.txt'
try:
text = requests.get(url).text
return text
except:
print("Erro ao baixar livro. Pulando...")
return ""
def prepare_super_dataset():
print(f"--- 🧠 PREPARING MULTI-DOMAIN DATASET ({TARGET_SIZE_PER_DOMAIN/1e6 * 4} MB target) ---")
# 1. Coleta dos 4 domínios
# Usamos try/except para garantir que o script não pare se a internet falhar em um
parts = []
try: parts.append(get_python_data(TARGET_SIZE_PER_DOMAIN))
except Exception as e: print(f"Erro no Python: {e}")
try: parts.append(get_math_data(TARGET_SIZE_PER_DOMAIN))
except Exception as e: print(f"Erro no Math: {e}")
try: parts.append(get_tinystories_data(TARGET_SIZE_PER_DOMAIN))
except Exception as e: print(f"Erro no TinyStories: {e}")
try: parts.append(get_classic_lit_data())
except Exception as e: print(f"Erro no Livro: {e}")
# 2. Mistura e Limpeza
print("\nCombinando tudo...")
full_text = SEPARATOR.join(parts)
print(f"\n📊 ESTATÍSTICAS FINAIS:")
print(f"Total Caracteres: {len(full_text):,}")
print(f"Tamanho em Disco: {len(full_text)/1024/1024:.2f} MB")
# 3. Tokenizer (Character Level)
# Como temos matemática e código, o vocabulário vai aumentar um pouco (símbolos)
print("Construindo vocabulário...")
chars = sorted(list(set(full_text)))
vocab_size = len(chars)
print(f"Vocab Size: {vocab_size}")
print(f"Chars (Amostra): {''.join(chars[30:80])}...")
stoi = { ch:i for i,ch in enumerate(chars) }
itos = { i:ch for i,ch in enumerate(chars) }
meta = {
'vocab_size': vocab_size,
'stoi': stoi,
'itos': itos,
}
with open(os.path.join(DATA_CACHE_DIR, 'meta.pkl'), 'wb') as f:
pickle.dump(meta, f)
def encode(s):
return [stoi[c] for c in s]
# 4. Split e Salvamento
print("Codificando e salvando (Isso pode levar um minuto)...")
n = len(full_text)
split_idx = int(n * 0.9) # 90% Treino, 10% Validação
train_data = full_text[:split_idx]
val_data = full_text[split_idx:]
# uint16 suporta vocabulário até 65535 (suficiente para char-level)
train_ids = np.array(encode(train_data), dtype=np.uint16)
val_ids = np.array(encode(val_data), dtype=np.uint16)
train_ids.tofile(os.path.join(DATA_CACHE_DIR, 'train.bin'))
val_ids.tofile(os.path.join(DATA_CACHE_DIR, 'val.bin'))
print(f"✅ PRONTO! Arquivos salvos em {DATA_CACHE_DIR}")
print("Agora rode: python train.py")
if __name__ == '__main__':
prepare_super_dataset() |