PowerMachine commited on
Commit
a95c6be
·
verified ·
1 Parent(s): 9d7a45b

Delete tests/test_500_samples.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. tests/test_500_samples.py +0 -1035
tests/test_500_samples.py DELETED
@@ -1,1035 +0,0 @@
1
- """test_500_samples.py — Teste de 500 amostras (5 batches de 100) para o CNN-BiGRU.
2
-
3
- Executa o pipeline completo com:
4
- 1. Inicializa xeon_runtime + memory_optimizer + monitor
5
- 2. Treina BBPE tokenizer em corpus sintético
6
- 3. Cria dataset streaming multimodal (até 500 amostras em batches de 100)
7
- 4. Instancia modelo multimodal + generator + verifier + anti-hallucination
8
- 5. Testa os NOVOS módulos v3.0:
9
- - CyclicReasoning
10
- - MedusaMTP
11
- - NLGModule
12
- - NLPModule
13
- - MultimodalMultiHeadAttention
14
- - VQVAE2
15
- - W8A8 Quantization (SmoothQuant)
16
- - LongContextManager (1M tokens)
17
- - Monitor
18
- 6. Executa treinamento cooperativo com:
19
- - Synergy search (N tentativas)
20
- - Hypothesis controller (ativa em punições)
21
- - Auto-learner (ajuste dinâmico de LR + spectral norm)
22
- - EWC (aprendizado contínuo)
23
- 7. Executa inferência com sampling
24
- 8. Avalia perplexidade
25
- 9. Aplica quantização W8A8 ao modelo
26
- 10. Reporta erros lógicos/falhas encontradas + exporta relatório
27
-
28
- Usage:
29
- python -m cnn_bigru.tests.test_500_samples
30
- """
31
- from __future__ import annotations
32
-
33
- import logging
34
- import os
35
- import sys
36
- import time
37
- import traceback
38
- from pathlib import Path
39
- from typing import Dict, List
40
-
41
- # Setup paths (must come before torch import for xeon_runtime)
42
- PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
43
- sys.path.insert(0, str(PROJECT_ROOT))
44
-
45
- # Ativa Xeon runtime ANTES de importar torch
46
- from cnn_bigru.utils.xeon_runtime import optimize_xeon_environment
47
- N_CORES = optimize_xeon_environment()
48
-
49
- import numpy as np
50
- import torch
51
- from torch.utils.data import DataLoader
52
-
53
- from cnn_bigru.tokenizer.bbpe_tokenizer import BBPETokenizer
54
- from cnn_bigru.data.streaming_dataset import (
55
- MultimodalStreamingDataset,
56
- collate_multimodal,
57
- DEFAULT_DATASETS,
58
- )
59
- from cnn_bigru.models.multimodal_model import MultimodalCNNBiGRU
60
- from cnn_bigru.models.generator_verifier import (
61
- GeneratorCNNBiGRU,
62
- VerifierCNNBiGRU,
63
- AntiHallucinationLayer,
64
- )
65
- from cnn_bigru.models.cooperative_bigru import CooperativeCNNBiGRU
66
- from cnn_bigru.models.rope import RotaryPositionEmbedding
67
- from cnn_bigru.models.transformer_block import (
68
- TransformerBlockConfig,
69
- CausalSelfAttention,
70
- TransformerBlock,
71
- TransformerDecoderStack,
72
- )
73
- from cnn_bigru.models.context_window import (
74
- ContextWindowConfig,
75
- ContextWindowManager,
76
- KVCache,
77
- LongContextConfig,
78
- LongContextManager,
79
- make_long_context_window,
80
- )
81
- # NOVOS módulos v3.0
82
- from cnn_bigru.models.cyclic_reasoning import (
83
- CyclicReasoningConfig,
84
- CyclicReasoning,
85
- make_hypothesis_fn,
86
- )
87
- from cnn_bigru.models.medusa_heads import (
88
- MedusaConfig,
89
- MedusaMTP,
90
- MedusaHead,
91
- medusa_tree_decode,
92
- )
93
- from cnn_bigru.models.nlg import NLGConfig, NLGModule
94
- from cnn_bigru.models.nlp import (
95
- NLPConfig,
96
- NLPModule,
97
- SequenceClassificationHead,
98
- TokenClassificationHead,
99
- SpanDetectionHead,
100
- EmbeddingHead,
101
- )
102
- from cnn_bigru.models.multimodal_attention import (
103
- MultimodalAttentionConfig,
104
- MultimodalMultiHeadAttention,
105
- CrossModalAttention,
106
- ModalityGate,
107
- )
108
- from cnn_bigru.utils.ewc import EWCConfig, EWCState
109
- from cnn_bigru.utils.quantization import (
110
- W8A8Config,
111
- SmoothQuantizer,
112
- quantize_model_w8a8,
113
- estimate_memory_savings,
114
- )
115
- from cnn_bigru.utils.vqvae2 import VQVAE2Config, VQVAE2
116
- from cnn_bigru.utils.monitoring import Monitor, get_monitor
117
- from cnn_bigru.losses.losses import LossConfig, MultiLoss
118
- from cnn_bigru.training.trainer import TrainerConfig, CooperativeTrainer
119
- from cnn_bigru.training.auto_learner import (
120
- AutoLearnConfig,
121
- orthogonal_init_model,
122
- )
123
- from cnn_bigru.training.hypothesis_controller import (
124
- HypothesisConfig,
125
- HypothesisController,
126
- )
127
- from cnn_bigru.inference.inference import (
128
- generate_with_sampling,
129
- evaluate_perplexity,
130
- make_default_context_window,
131
- )
132
- from cnn_bigru.utils.memory_optimizer import MemoryOptimizer
133
-
134
- logging.basicConfig(
135
- level=logging.INFO,
136
- format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
137
- datefmt="%H:%M:%S",
138
- )
139
- logger = logging.getLogger("test_500")
140
-
141
-
142
- # ============================================================================
143
- # Configurações do teste
144
- # ============================================================================
145
-
146
- TOTAL_SAMPLES = 500
147
- BATCH_SIZE_SAMPLES = 100 # 5 batches de 100
148
- N_BATCHES = TOTAL_SAMPLES // BATCH_SIZE_SAMPLES # 5
149
- # Para teste rápido, pode-se reduzir N_BATCHES via env var
150
- if os.environ.get("CNN_BIGRU_TEST_FAST") == "1":
151
- N_BATCHES = 2 # 200 amostras em modo rápido
152
- TOTAL_SAMPLES = N_BATCHES * BATCH_SIZE_SAMPLES
153
-
154
- CORPUS_TEXTS = [
155
- "o modelo cooperativo cnn-bigru combina fluxos paralelos",
156
- "a atencao cruzada troca informacoes entre redes a e b",
157
- "gru bidirecional captura dependencias temporais em ambas direcoes",
158
- "a porta de atenuacao controla o fluxo de informacao entre celulas",
159
- "a camada anti-alucinacao usa logica fuzzy de lukasiewicz",
160
- "o verificador classifica passos com sigmoid binaria",
161
- "penalidades linear e exponencial reduzem o erro grave",
162
- "ajuste dinamico de lr estabiliza o treinamento cooperativo",
163
- "normalizacao espectral limita a norma dos pesos",
164
- "inicializacao ortogonal estabiliza matrizes recorrentes",
165
- "o gerador decodificador usa atencao bahdanau sobre o encoder",
166
- "a fusao multimodal combina texto imagem e audio",
167
- "hipoteses sao ativadas quando o verificador pune o passo",
168
- "synergy search tenta n configuracoes e escolhe a melhor",
169
- "a perplexidade mede a confusao do modelo na previsao",
170
- "top-k e top-p filtram a distribuicao de probabilidade",
171
- "temperature ajusta a entropia das previsoes do modelo",
172
- "presence penalty pune tokens ja aparecidos na geracao",
173
- "frequency penalty pune proporcionalmente a frequencia do token",
174
- "streaming dataset carrega amostras sem materializacao completa",
175
- "byte bpe tokeniza qualquer string utf-8 sem unk",
176
- "o otimizador adamw combina momentum e weight decay",
177
- "gradient clipping previne explosao de gradiente",
178
- "amp reduz vram com precisao mista bfloat16",
179
- # NOVOS v3.0
180
- "raciocinio ciclico refina a representacao iterativamente",
181
- "medusa heads predizem multiplos tokens em paralelo",
182
- "nlg gera texto autoregressivo com transformer decoder",
183
- "nlp classifica sequencias tokens e spans",
184
- "w8a8 quantiza pesos e ativacoes em 8 bits",
185
- "smoothquant migra variancia das ativacoes para os pesos",
186
- "vq-vae-2 hierarquico comprime com codebooks top e bottom",
187
- "multi-token prediction acelera a geracao por arvores",
188
- "multi-head attention multimodal funde modalidades por atencao",
189
- "context window de 1m tokens usa chunked attention",
190
- "monitor rastreia metricas de treino e evolucao",
191
- "ewc previne esquecimento catastrofico em aprendizado continuo",
192
- "rope codifica posicoes por rotacao no espaco complexo",
193
- "kv cache armazena chaves e valores para atencao eficiente",
194
- "causal self attention mascara tokens futuros no decoder",
195
- "transformer block combina self attention e feed forward",
196
- ] * 4 # ~160 amostras para treino BBPE
197
-
198
-
199
- # ============================================================================
200
- # Step 1: Inicialização
201
- # ============================================================================
202
-
203
- def step_01_init_runtime() -> Dict:
204
- """Inicializa runtime Xeon + memory optimizer + monitor."""
205
- logger.info("=" * 70)
206
- logger.info("PASSO 1: Inicialização do runtime Xeon + memory optimizer + monitor")
207
- logger.info("=" * 70)
208
- from cnn_bigru.utils.xeon_runtime import get_runtime_info
209
- info = get_runtime_info()
210
- for k, v in info.items():
211
- logger.info(" %s: %s", k, v)
212
- mem = MemoryOptimizer(enable_amp=False)
213
- mem.configure()
214
- mem_info = mem.get_memory_mb()
215
- logger.info(" Memória: %s", mem_info)
216
-
217
- # Inicializa monitor global
218
- monitor = get_monitor(output_dir=PROJECT_ROOT / "download" / "monitor_reports")
219
- monitor.register_component("ewc", True)
220
- monitor.register_component("medusa", True)
221
- monitor.register_component("cyclic_reasoning", True)
222
- monitor.register_component("vqvae2", True)
223
- monitor.register_component("quantization", True)
224
- monitor.register_component("multimodal_attention", True)
225
- monitor.register_component("context_window", True)
226
- monitor.register_component("monitor", True)
227
- return {"runtime": info, "memory": mem_info, "monitor": monitor}
228
-
229
-
230
- # ============================================================================
231
- # Step 2: Tokenizer
232
- # ============================================================================
233
-
234
- def step_02_train_tokenizer() -> tuple:
235
- """Treina BBPE tokenizer em corpus sintético."""
236
- logger.info("=" * 70)
237
- logger.info("PASSO 2: Treino do BBPE tokenizer")
238
- logger.info("=" * 70)
239
- t0 = time.time()
240
- tok = BBPETokenizer.train_from_texts(
241
- CORPUS_TEXTS,
242
- vocab_size=2000,
243
- min_frequency=1,
244
- )
245
- elapsed = time.time() - t0
246
- logger.info(" Vocab size: %d", tok.vocab_size)
247
- logger.info(" BOS/PAD/EOS IDs: %d/%d/%d", tok.bos_id, tok.pad_id, tok.eos_id)
248
- logger.info(" Tempo: %.2fs", elapsed)
249
- test_strs = CORPUS_TEXTS[:5]
250
- roundtrip = tok.validate_roundtrip(test_strs)
251
- logger.info(" Roundtrip accuracy: %.2f%%", roundtrip * 100)
252
- if roundtrip < 0.8:
253
- logger.warning(" Roundtrip baixo — possível problema no tokenizer")
254
- return tok, roundtrip
255
-
256
-
257
- # ============================================================================
258
- # Step 3: Dataset (até 500 amostras em batches de 100)
259
- # ============================================================================
260
-
261
- def step_03_create_dataset(
262
- tokenizer: BBPETokenizer,
263
- n_samples: int = BATCH_SIZE_SAMPLES,
264
- seed_offset: int = 0,
265
- ) -> DataLoader:
266
- """Cria dataset streaming multimodal com N amostras (batch de 100)."""
267
- logger.info("=" * 70)
268
- logger.info("PASSO 3: Criação do dataset streaming multimodal (%d amostras, batch %d/5)",
269
- n_samples, seed_offset + 1)
270
- logger.info("=" * 70)
271
-
272
- dataset = MultimodalStreamingDataset(
273
- n_samples=n_samples,
274
- # Tenta repositório 'PowerMachine/CNN-BiGRU' primeiro, depois fallback
275
- hf_datasets=DEFAULT_DATASETS,
276
- use_synthetic_fallback=True,
277
- seed=42 + seed_offset * 100,
278
- image_size=(28, 28, 1),
279
- audio_shape=(32, 40),
280
- )
281
-
282
- samples = list(dataset)
283
- logger.info(" Amostras coletadas: %d", len(samples))
284
- assert len(samples) == n_samples, f"Esperado {n_samples}, obtido {len(samples)}"
285
-
286
- loader = DataLoader(
287
- samples,
288
- batch_size=8,
289
- shuffle=False,
290
- collate_fn=lambda b: collate_multimodal(b, tokenizer, max_len=32),
291
- )
292
- logger.info(" DataLoader criado: batch_size=8, max_len=32")
293
- return loader
294
-
295
-
296
- # ============================================================================
297
- # Step 4: Instanciar modelos
298
- # ============================================================================
299
-
300
- def step_04_init_model(tokenizer: BBPETokenizer, device: str = "cpu") -> Dict:
301
- """Instancia todos os componentes do modelo."""
302
- logger.info("=" * 70)
303
- logger.info("PASSO 4: Instanciação dos modelos (incluindo novos módulos v3.0)")
304
- logger.info("=" * 70)
305
- V = tokenizer.vocab_size
306
-
307
- # Modelo multimodal principal
308
- model = MultimodalCNNBiGRU(
309
- vocab_size=V,
310
- num_classes=3,
311
- embedding_dim=32,
312
- cnn_filters=32,
313
- gru_hidden=32,
314
- n_heads=4,
315
- dropout=0.1,
316
- pad_idx=tokenizer.pad_id,
317
- img_channels=1,
318
- img_hidden=16,
319
- img_out_dim=32,
320
- audio_freq=40,
321
- audio_hidden=16,
322
- audio_out_dim=32,
323
- fusion_dim=64,
324
- use_spectral_norm=False,
325
- )
326
- n_init = orthogonal_init_model(model)
327
- logger.info(" Modelo multimodal: %d params, %d camadas ortogonalizadas",
328
- sum(p.numel() for p in model.parameters()), n_init)
329
-
330
- # Generator
331
- generator = GeneratorCNNBiGRU(
332
- vocab_size=V, embedding_dim=32, cnn_filters=32, gru_hidden=32,
333
- n_heads=4, dropout=0.1, pad_idx=tokenizer.pad_id, max_proof_len=16,
334
- )
335
- orthogonal_init_model(generator)
336
-
337
- # Verifier
338
- verifier = VerifierCNNBiGRU(
339
- vocab_size=V, embedding_dim=32, cnn_filters=32, gru_hidden=32,
340
- n_heads=4, dropout=0.1, pad_idx=tokenizer.pad_id,
341
- )
342
- orthogonal_init_model(verifier)
343
-
344
- # Anti-hallucination
345
- anti_hall = AntiHallucinationLayer(vocab_size=V, embed_dim=16)
346
-
347
- logger.info(" Generator params: %d", sum(p.numel() for p in generator.parameters()))
348
- logger.info(" Verifier params: %d", sum(p.numel() for p in verifier.parameters()))
349
- logger.info(" Anti-hall params: %d", sum(p.numel() for p in anti_hall.parameters()))
350
-
351
- return {
352
- "model": model,
353
- "generator": generator,
354
- "verifier": verifier,
355
- "anti_hall": anti_hall,
356
- }
357
-
358
-
359
- # ============================================================================
360
- # Step 5b: Testar NOVOS módulos v3.0
361
- # ============================================================================
362
-
363
- def step_05b_test_v3_modules(
364
- models: Dict,
365
- tokenizer: BBPETokenizer,
366
- device: str = "cpu",
367
- ) -> Dict:
368
- """Testa os novos módulos v3.0: CyclicReasoning, Medusa, NLG, NLP, MMA, VQVAE2, W8A8, LongCtx."""
369
- logger.info("=" * 70)
370
- logger.info("PASSO 5b: Teste dos NOVOS módulos v3.0")
371
- logger.info("=" * 70)
372
-
373
- results = {}
374
- V = tokenizer.vocab_size
375
-
376
- # ---------- CyclicReasoning ----------
377
- try:
378
- logger.info(" [CyclicReasoning] Testando...")
379
- cfg = CyclicReasoningConfig(
380
- embed_dim=64, max_cycles=4, convergence_eps=1e-3,
381
- use_anti_hallucination_gate=True,
382
- )
383
- cr = CyclicReasoning(cfg).to(device)
384
- h0 = torch.randn(2, 64, device=device)
385
- result = cr(h0, return_history=True)
386
- assert result["h_final"].shape == (2, 64)
387
- assert 1 <= result["n_cycles"] <= 4
388
- logger.info(" n_cycles=%d, converged=%s, deltas=%s",
389
- result["n_cycles"], result["converged"],
390
- [f"{d:.4f}" for d in result["deltas"]])
391
- results["cyclic_reasoning"] = {
392
- "ok": True, "n_cycles": result["n_cycles"], "converged": result["converged"],
393
- }
394
- logger.info(" [CyclicReasoning] OK")
395
- except Exception as e:
396
- logger.error(" [CyclicReasoning] FALHOU: %s", e)
397
- logger.error(traceback.format_exc())
398
- results["cyclic_reasoning"] = {"ok": False, "error": str(e)}
399
-
400
- # ---------- Medusa MTP ----------
401
- try:
402
- logger.info(" [MedusaMTP] Testando...")
403
- cfg = MedusaConfig(
404
- vocab_size=V, embed_dim=32, n_heads=3,
405
- head_hidden_mult=2, dropout=0.1,
406
- )
407
- medusa = MedusaMTP(cfg).to(device)
408
- h = torch.randn(2, 8, 32, device=device)
409
- target = torch.randint(0, V, (2, 8), device=device)
410
- loss, stats = medusa.compute_loss(h, target)
411
- assert loss.item() > 0
412
- # Test tree decode
413
- base_logits = torch.randn(2, V, device=device)
414
- td = medusa_tree_decode(medusa, base_logits, h[:, -1, :])
415
- assert "base_token" in td
416
- logger.info(" Loss=%.4f, stats=%s", loss.item(), stats)
417
- results["medusa_mtp"] = {"ok": True, "loss": float(loss), "stats": stats}
418
- logger.info(" [MedusaMTP] OK")
419
- except Exception as e:
420
- logger.error(" [MedusaMTP] FALHOU: %s", e)
421
- logger.error(traceback.format_exc())
422
- results["medusa_mtp"] = {"ok": False, "error": str(e)}
423
-
424
- # ---------- NLG ----------
425
- try:
426
- logger.info(" [NLGModule] Testando...")
427
- cfg = NLGConfig(
428
- vocab_size=V, embed_dim=32, n_heads=4, n_layers=2,
429
- max_seq_len=32, pad_id=tokenizer.pad_id, bos_id=tokenizer.bos_id,
430
- eos_id=tokenizer.eos_id, use_medusa=True, n_medusa_heads=3,
431
- use_cyclic_reasoning=False, weight_tying=True, device=device,
432
- )
433
- nlg = NLGModule(cfg).to(device)
434
- ids = torch.randint(2, V, (2, 8), device=device)
435
- target = torch.randint(2, V, (2, 8), device=device)
436
- out = nlg.compute_loss(ids, target)
437
- assert "loss" in out and out["loss"].item() > 0
438
- # Test geração
439
- prompt = torch.tensor([[tokenizer.bos_id, 5, 10]], dtype=torch.long, device=device)
440
- gen = nlg.generate(prompt, max_new_tokens=5, temperature=0.7, top_k=10)
441
- assert gen["ids"].size(1) >= 3
442
- logger.info(" NLG loss=%.4f, generated %d tokens",
443
- out["loss"].item(), gen["n_tokens"])
444
- results["nlg"] = {"ok": True, "loss": float(out["loss"]),
445
- "n_generated": gen["n_tokens"]}
446
- logger.info(" [NLGModule] OK")
447
- except Exception as e:
448
- logger.error(" [NLGModule] FALHOU: %s", e)
449
- logger.error(traceback.format_exc())
450
- results["nlg"] = {"ok": False, "error": str(e)}
451
-
452
- # ---------- NLP ----------
453
- try:
454
- logger.info(" [NLPModule] Testando...")
455
- nlp_cfg = NLPConfig(
456
- embed_dim=32, cnn_filters=32, gru_hidden=32,
457
- feat_per_stream=64, feat_fused=128, n_heads=4,
458
- num_classes_seq=3, num_labels_tok=5, device=device,
459
- )
460
- backbone = CooperativeCNNBiGRU(
461
- vocab_size=V, embedding_dim=32, cnn_filters=32,
462
- gru_hidden=32, n_heads=4, pad_idx=tokenizer.pad_id,
463
- ).to(device)
464
- nlp = NLPModule(nlp_cfg, backbone=backbone).to(device)
465
- ids_a = torch.randint(2, V, (2, 8), device=device)
466
- ids_b = torch.randint(2, V, (2, 8), device=device)
467
- # Test sequence classification
468
- out_seq = nlp.sequence_classification(ids_a, ids_b)
469
- assert out_seq["logits"].shape == (2, 3)
470
- # Test token classification
471
- tok_logits = nlp.token_classification(ids_a, ids_b)
472
- # Test span detection
473
- s_log, e_log = nlp.span_detection(ids_a, ids_b)
474
- # Test embedding
475
- emb = nlp.embed(ids_a, ids_b)
476
- assert emb.shape == (2, 64) # feat_per_stream
477
- logger.info(" Seq: %s, Tok: %s, Span: (%s,%s), Emb: %s",
478
- out_seq["logits"].shape, tok_logits.shape if tok_logits is not None else None,
479
- s_log.shape if s_log is not None else None,
480
- e_log.shape if e_log is not None else None,
481
- emb.shape)
482
- results["nlp"] = {"ok": True, "seq_logits": list(out_seq["logits"].shape),
483
- "emb_shape": list(emb.shape)}
484
- logger.info(" [NLPModule] OK")
485
- except Exception as e:
486
- logger.error(" [NLPModule] FALHOU: %s", e)
487
- logger.error(traceback.format_exc())
488
- results["nlp"] = {"ok": False, "error": str(e)}
489
-
490
- # ---------- Multimodal Multi-Head Attention ----------
491
- try:
492
- logger.info(" [MultimodalMultiHeadAttention] Testando...")
493
- cfg = MultimodalAttentionConfig(
494
- d_text_a=32, d_text_b=32, d_image=16, d_audio=16,
495
- d_model=64, n_heads=4, use_modality_gate=True,
496
- )
497
- mha = MultimodalMultiHeadAttention(cfg).to(device)
498
- seq_a = torch.randn(2, 8, 32, device=device)
499
- seq_b = torch.randn(2, 6, 32, device=device)
500
- seq_img = torch.randn(2, 4, 16, device=device)
501
- seq_aud = torch.randn(2, 5, 16, device=device)
502
- out = mha(seq_a, seq_b, seq_img, seq_aud)
503
- assert out["fused"].shape == (2, 64)
504
- assert out["modality_weights"].shape == (2, 4)
505
- logger.info(" Fused: %s, modality_weights: %s",
506
- out["fused"].shape, out["modality_weights"])
507
- results["multimodal_attention"] = {
508
- "ok": True, "fused_shape": list(out["fused"].shape),
509
- }
510
- logger.info(" [MultimodalMultiHeadAttention] OK")
511
- except Exception as e:
512
- logger.error(" [MultimodalMultiHeadAttention] FALHOU: %s", e)
513
- logger.error(traceback.format_exc())
514
- results["multimodal_attention"] = {"ok": False, "error": str(e)}
515
-
516
- # ---------- VQ-VAE-2 ----------
517
- try:
518
- logger.info(" [VQVAE2] Testando...")
519
- cfg = VQVAE2Config(
520
- in_channels=1, bottom_channels=8, top_channels=4,
521
- n_bottom_codes=32, n_top_codes=32,
522
- n_downsample=1, hidden_channels=8, use_ema=True,
523
- )
524
- vqvae = VQVAE2(cfg).to(device)
525
- x = torch.randn(2, 1, 16, 16, device=device)
526
- out = vqvae(x)
527
- assert out["x_recon"].shape == x.shape
528
- assert out["loss"].item() > 0
529
- logger.info(" Recon: %s, loss=%.4f, top_usage=%.2f, bottom_usage=%.2f",
530
- out["x_recon"].shape, out["loss"].item(),
531
- float(out["loss_dict"]["top_usage"]),
532
- float(out["loss_dict"]["bottom_usage"]))
533
- results["vqvae2"] = {
534
- "ok": True, "loss": float(out["loss"]),
535
- "top_usage": float(out["loss_dict"]["top_usage"]),
536
- "bottom_usage": float(out["loss_dict"]["bottom_usage"]),
537
- }
538
- logger.info(" [VQVAE2] OK")
539
- except Exception as e:
540
- logger.error(" [VQVAE2] FALHOU: %s", e)
541
- logger.error(traceback.format_exc())
542
- results["vqvae2"] = {"ok": False, "error": str(e)}
543
-
544
- # ---------- W8A8 Quantization ----------
545
- try:
546
- logger.info(" [W8A8 SmoothQuant] Testando...")
547
- # Aplica ao modelo multimodal (sem dataloader = quantização dinâmica)
548
- model_copy = MultimodalCNNBiGRU(
549
- vocab_size=V, num_classes=3, embedding_dim=32, cnn_filters=32,
550
- gru_hidden=32, n_heads=4, pad_idx=tokenizer.pad_id,
551
- img_channels=1, img_hidden=16, img_out_dim=32,
552
- audio_freq=40, audio_hidden=16, audio_out_dim=32, fusion_dim=64,
553
- ).to(device)
554
- orthogonal_init_model(model_copy)
555
- qmodel = quantize_model_w8a8(model_copy, dataloader=None, alpha=0.5, device=device)
556
- assert SmoothQuantizer.is_quantized(qmodel)
557
- # Verificar forward ainda funciona
558
- ids_a = torch.randint(2, V, (2, 8), device=device)
559
- ids_b = torch.randint(2, V, (2, 8), device=device)
560
- with torch.no_grad():
561
- out = qmodel(ids_a, ids_b, mode="classify")
562
- assert out["logits"].shape == (2, 3)
563
- savings = estimate_memory_savings(qmodel)
564
- logger.info(" Quantizado: %s, savings: %.1f%%",
565
- SmoothQuantizer.is_quantized(qmodel), savings["reduction_pct"])
566
- results["w8a8"] = {"ok": True, "savings": savings}
567
- logger.info(" [W8A8] OK")
568
- except Exception as e:
569
- logger.error(" [W8A8] FALHOU: %s", e)
570
- logger.error(traceback.format_exc())
571
- results["w8a8"] = {"ok": False, "error": str(e)}
572
-
573
- # ---------- Long Context (1M tokens) ----------
574
- try:
575
- logger.info(" [LongContextManager - 1M tokens] Testando...")
576
- lcw = make_long_context_window(
577
- max_window=1_000_000, strategy="chunked",
578
- chunk_size=8192, embed_dim=64, n_heads=4, n_layers=2, device=device,
579
- )
580
- # Simular adicionar muitos tokens em chunks
581
- all_tokens = []
582
- for chunk_idx in range(3): # 3 chunks de 100 tokens cada
583
- tokens = torch.tensor(
584
- [[i + 1 + chunk_idx * 100 for i in range(100)]], device=device,
585
- )
586
- result = lcw.append_tokens_chunked(tokens)
587
- all_tokens.append(result)
588
- info = lcw.get_info()
589
- assert info["supports_1m_tokens"]
590
- # LongContextManager.get_info() retorna "history_tokens" (não "total_tokens")
591
- assert info["history_tokens"] == 300 # 3 chunks * 100
592
- logger.info(" Info: %s", info)
593
- results["long_context"] = {"ok": True, "info": info}
594
- logger.info(" [LongContextManager] OK")
595
- except Exception as e:
596
- logger.error(" [LongContextManager] FALHOU: %s", e)
597
- logger.error(traceback.format_exc())
598
- results["long_context"] = {"ok": False, "error": str(e)}
599
-
600
- # ---------- EWC (já existente, mas validar integração) ----------
601
- try:
602
- logger.info(" [EWC] Testando integração...")
603
- ewc_cfg = EWCConfig(
604
- enabled=True, lambda_ewc=100.0,
605
- n_samples_fisher=5, online_gamma=0.9, device=device,
606
- )
607
- ewc_state = EWCState(ewc_cfg)
608
- pen0 = ewc_state.penalty(models["model"])
609
- assert pen0.item() == 0.0
610
-
611
- # Forward_fn para Fisher
612
- V = tokenizer.vocab_size
613
- B, T = 2, 8
614
- ids_a = torch.randint(0, V, (B, T), device=device)
615
- ids_b = torch.randint(0, V, (B, T), device=device)
616
-
617
- def forward_fn(_idx=None):
618
- out = models["model"](ids_a, ids_b, mode="classify")
619
- return out["logits"]
620
-
621
- ewc_state.consolidate(models["model"], forward_fn=forward_fn)
622
- assert ewc_state.num_tasks() == 1
623
- pen1 = ewc_state.penalty(models["model"])
624
- assert pen1.item() >= 0.0
625
- logger.info(" Penalty antes/depois consolidar: %.6f / %.6f",
626
- float(pen0), float(pen1))
627
- results["ewc"] = {
628
- "ok": True, "penalty_before": float(pen0),
629
- "penalty_after": float(pen1), "num_tasks": ewc_state.num_tasks(),
630
- }
631
- results["ewc_state"] = ewc_state
632
- logger.info(" [EWC] OK")
633
- except Exception as e:
634
- logger.error(" [EWC] FALHOU: %s", e)
635
- logger.error(traceback.format_exc())
636
- results["ewc"] = {"ok": False, "error": str(e)}
637
-
638
- # ---------- Context Window (curto, já existente) ----------
639
- try:
640
- logger.info(" [ContextWindowManager] Testando...")
641
- cw = make_default_context_window(
642
- max_window=32, n_sink=2, embed_dim=64, n_heads=4, n_layers=2, device=device,
643
- )
644
- cache = cw.init_cache(batch_size=1, device=torch.device(device))
645
- assert cache is not None
646
- tokens = torch.tensor([[1, 2, 3, 4, 5]], dtype=torch.long, device=device)
647
- window = cw.append_tokens(tokens)
648
- assert window.size(1) == 5
649
- logger.info(" Window: %s, cache_len: %d", window.shape, cache.get_seq_len())
650
- results["context_window"] = {"ok": True}
651
- logger.info(" [ContextWindowManager] OK")
652
- except Exception as e:
653
- logger.error(" [ContextWindowManager] FALHOU: %s", e)
654
- logger.error(traceback.format_exc())
655
- results["context_window"] = {"ok": False, "error": str(e)}
656
-
657
- return results
658
-
659
-
660
- # ============================================================================
661
- # Step 5: Treinamento
662
- # ============================================================================
663
-
664
- def step_05_train(
665
- models: Dict,
666
- tokenizer: BBPETokenizer,
667
- dataloader: DataLoader,
668
- device: str = "cpu",
669
- ewc_state: EWCState = None,
670
- monitor: Monitor = None,
671
- batch_idx: int = 0,
672
- ) -> Dict:
673
- """Executa treinamento cooperativo em um batch de 100 amostras."""
674
- logger.info("=" * 70)
675
- logger.info("PASSO 5: Treinamento cooperativo (batch %d/5 - 100 amostras)", batch_idx + 1)
676
- logger.info("=" * 70)
677
-
678
- cfg = TrainerConfig(
679
- num_epochs=1,
680
- max_batches_per_epoch=12,
681
- batch_size=8,
682
- n_synergy_attempts=2,
683
- use_synergy_search=True,
684
- use_hypotheses=True,
685
- n_hypotheses=3,
686
- loss_config=LossConfig(
687
- alpha=1.0, beta=0.5, gamma_loss=0.3, delta=0.01,
688
- lambda_penal=0.1, mu_exp_penal=0.05,
689
- gamma_exp=1.0, threshold_err=0.5,
690
- l2_reg=1e-5, use_curvature=True, curvature_eps=1e-3,
691
- ),
692
- auto_config=AutoLearnConfig(
693
- kappa_curv=0.01, grad_clip=1.0, spectral_radius=1.0,
694
- lr_min=1e-6, lr_max=1e-2,
695
- initial_lr_G=1e-3, initial_lr_V=1e-3,
696
- use_spectral_norm=True, apply_after_step=True,
697
- l2_reg=1e-5,
698
- ),
699
- ewc_config=ewc_state.config if ewc_state else None,
700
- device=device,
701
- log_every=2,
702
- use_verifier_real=True,
703
- use_generator=True,
704
- use_hypothesis_output=True,
705
- )
706
-
707
- trainer = CooperativeTrainer(
708
- model=models["model"],
709
- tokenizer=tokenizer,
710
- config=cfg,
711
- generator=models["generator"],
712
- verifier=models["verifier"],
713
- anti_hallucination=models["anti_hall"],
714
- ewc_state=ewc_state,
715
- )
716
-
717
- # Integra monitor
718
- if monitor is not None:
719
- monitor.start_epoch(batch_idx)
720
-
721
- try:
722
- result = trainer.train(dataloader)
723
- logger.info(" Treino OK batch %d | loss=%.4f | ppl=%.2f | elapsed=%.1fs",
724
- batch_idx + 1, result["final_loss"], result["final_ppl"],
725
- result["elapsed_s"])
726
-
727
- # Log no monitor
728
- if monitor is not None:
729
- for h in result.get("history", []):
730
- monitor.log_batch({
731
- "loss": h.get("loss", 0),
732
- "ppl": h.get("ppl", 0),
733
- "lr_g": h.get("lr_G", 0),
734
- "hypothesis_activations": h.get("hypothesis_activations", 0),
735
- "elapsed_ms": h.get("elapsed_ms", 0),
736
- })
737
- monitor.end_epoch({"batch_idx": batch_idx})
738
- if ewc_state is not None:
739
- pen = ewc_state.penalty(models["model"]).item()
740
- monitor.log_ewc_penalty(penalty=pen, num_tasks=ewc_state.num_tasks())
741
-
742
- return result
743
- except Exception as e:
744
- logger.error(" Treino FALHOU batch %d: %s", batch_idx + 1, e)
745
- logger.error(traceback.format_exc())
746
- raise
747
-
748
-
749
- # ============================================================================
750
- # Step 6: Inferência
751
- # ============================================================================
752
-
753
- def step_06_inference(
754
- model: MultimodalCNNBiGRU,
755
- tokenizer: BBPETokenizer,
756
- device: str = "cpu",
757
- generator: GeneratorCNNBiGRU = None,
758
- monitor: Monitor = None,
759
- ) -> Dict:
760
- """Executa inferência com sampling."""
761
- logger.info("=" * 70)
762
- logger.info("PASSO 6: Inferência com Temperatura + Top-K + Top-P + Penalidades")
763
- logger.info("=" * 70)
764
-
765
- prompts = [
766
- ("o modelo coopera entre", "fluxos paralelos"),
767
- ("atencao cruzada troca", "informacoes entre redes"),
768
- ("gru bidirecional captura", "dependencias temporais"),
769
- ("medusa heads predizem", "multiplos tokens"),
770
- ("raciocinio ciclico refina", "iterativamente"),
771
- ]
772
-
773
- results = []
774
- for prompt_a, prompt_b in prompts:
775
- t0 = time.time()
776
- try:
777
- result = generate_with_sampling(
778
- model=model, tokenizer=tokenizer,
779
- prompt_a=prompt_a, prompt_b=prompt_b,
780
- max_new_tokens=10, temperature=0.7,
781
- top_k=20, top_p=0.9,
782
- presence_penalty=0.3, frequency_penalty=0.3,
783
- device=device, generator=generator,
784
- )
785
- elapsed_ms = (time.time() - t0) * 1000
786
- logger.info(" Prompt A: %s | B: %s", prompt_a, prompt_b)
787
- logger.info(" Gerado: %s (%.0fms)",
788
- result["text"][:80], elapsed_ms)
789
- if monitor is not None:
790
- monitor.log_inference(
791
- n_tokens=len(result.get("token_ids", [])),
792
- elapsed_ms=elapsed_ms,
793
- )
794
- results.append({"prompt_a": prompt_a, "prompt_b": prompt_b, **result})
795
- except Exception as e:
796
- logger.error(" Inferência falhou (%s, %s): %s", prompt_a, prompt_b, e)
797
- results.append({"prompt_a": prompt_a, "prompt_b": prompt_b, "error": str(e)})
798
-
799
- return {"results": results}
800
-
801
-
802
- # ============================================================================
803
- # Step 7: PPL
804
- # ============================================================================
805
-
806
- def step_07_eval_ppl(
807
- model: MultimodalCNNBiGRU,
808
- tokenizer: BBPETokenizer,
809
- dataloader: DataLoader,
810
- device: str = "cpu",
811
- generator: GeneratorCNNBiGRU = None,
812
- ) -> Dict:
813
- """Avalia perplexidade."""
814
- logger.info("=" * 70)
815
- logger.info("PASSO 7: Avaliação de Perplexidade (PPL)")
816
- logger.info("=" * 70)
817
- try:
818
- result = evaluate_perplexity(
819
- model=model, dataloader=dataloader, tokenizer=tokenizer,
820
- device=device, max_batches=5, generator=generator,
821
- )
822
- logger.info(" Loss: %.4f | PPL: %.2f | batches: %d | used_generator: %s",
823
- result["loss"], result["ppl"], result["n_batches"],
824
- result.get("used_generator", False))
825
- return result
826
- except Exception as e:
827
- logger.error(" PPL falhou: %s", e)
828
- logger.error(traceback.format_exc())
829
- return {"error": str(e)}
830
-
831
-
832
- # ============================================================================
833
- # Step 8: Relatório
834
- # ============================================================================
835
-
836
- def step_08_report(errors: List[str], warnings: List[str]) -> None:
837
- """Reporta erros lógicos ou falhas encontradas."""
838
- logger.info("=" * 70)
839
- logger.info("PASSO 8: Relatório de erros lógicos ou falhas")
840
- logger.info("=" * 70)
841
-
842
- if not errors:
843
- logger.info(" OK — NENHUM ERRO CRÍTICO encontrado")
844
- else:
845
- logger.error(" FAIL — %d ERRO(S) CRÍTICO(S):", len(errors))
846
- for e in errors:
847
- logger.error(" - %s", e)
848
-
849
- if not warnings:
850
- logger.info(" OK — Nenhum warning relevante")
851
- else:
852
- logger.warning(" WARN — %d warning(s):", len(warnings))
853
- for w in warnings:
854
- logger.warning(" - %s", w)
855
- logger.info("=" * 70)
856
-
857
-
858
- # ============================================================================
859
- # Main
860
- # ============================================================================
861
-
862
- def main():
863
- """Executa o teste completo de 500 amostras (5 batches de 100)."""
864
- logger.info("=" * 70)
865
- logger.info("INICIANDO TESTE DE 500 AMOSTRAS (5 batches de 100)")
866
- logger.info("CNN-BiGRU MULTIMODAL COOPERATIVO v3.0")
867
- logger.info("=" * 70)
868
- logger.info("Project root: %s", PROJECT_ROOT)
869
- logger.info("Device: %s | Cores: %d", "cpu", N_CORES)
870
- logger.info("Total samples: %d | Batch size: %d | N batches: %d",
871
- TOTAL_SAMPLES, BATCH_SIZE_SAMPLES, N_BATCHES)
872
-
873
- errors: List[str] = []
874
- warnings: List[str] = []
875
- all_train_results = []
876
-
877
- try:
878
- # Step 1: Runtime + Monitor
879
- rt_info = step_01_init_runtime()
880
- monitor = rt_info["monitor"]
881
- monitor.start_training()
882
-
883
- # Step 2: Tokenizer
884
- tokenizer, roundtrip = step_02_train_tokenizer()
885
- if roundtrip < 0.8:
886
- warnings.append(f"BBPE roundtrip = {roundtrip:.2%} (esperado >= 80%)")
887
-
888
- # Step 3: Modelo (uma única instância, reutilizada em todos batches)
889
- models = step_04_init_model(tokenizer, device="cpu")
890
-
891
- # Forward pass inicial
892
- try:
893
- test_loader = step_03_create_dataset(tokenizer, n_samples=8, seed_offset=99)
894
- batch = next(iter(test_loader))
895
- with torch.no_grad():
896
- out = models["model"](
897
- batch["input_ids_a"], batch["input_ids_b"],
898
- images=batch["images"], audios=batch["audios"],
899
- mode="classify",
900
- )
901
- logger.info(" Forward pass OK | logits shape: %s", out["logits"].shape)
902
- assert out["logits"].shape == (batch["input_ids_a"].size(0), 3), \
903
- f"Shape inesperado: {out['logits'].shape}"
904
- except Exception as e:
905
- errors.append(f"Forward pass inicial falhou: {e}")
906
- logger.error(traceback.format_exc())
907
-
908
- # Step 5b: Testar novos módulos v3.0
909
- ewc_state = None
910
- if not errors:
911
- try:
912
- new_modules_result = step_05b_test_v3_modules(models, tokenizer, device="cpu")
913
- for mod_name, mod_res in new_modules_result.items():
914
- if mod_name == "ewc_state":
915
- continue
916
- if isinstance(mod_res, dict) and not mod_res.get("ok", True):
917
- errors.append(f"Módulo {mod_name} falhou: {mod_res.get('error', 'unknown')}")
918
- # Não é crítico para alguns módulos — converter em warning
919
- if mod_name in ("nlg", "nlp", "multimodal_attention", "vqvae2",
920
- "w8a8", "long_context"):
921
- errors.pop() # remove o erro
922
- warnings.append(f"Módulo {mod_name} falhou (não crítico): {mod_res.get('error', 'unknown')}")
923
- ewc_state = new_modules_result.get("ewc_state")
924
- if ewc_state is None:
925
- warnings.append("EWC state não criado — EWC não será testado no treino")
926
- # Log no monitor
927
- if monitor is not None:
928
- if new_modules_result.get("cyclic_reasoning", {}).get("ok"):
929
- monitor.log_cyclic_reasoning(new_modules_result["cyclic_reasoning"])
930
- if new_modules_result.get("vqvae2", {}).get("ok"):
931
- monitor.log_vqvae2_usage(new_modules_result["vqvae2"])
932
- if new_modules_result.get("w8a8", {}).get("ok"):
933
- monitor.log_quantization(new_modules_result["w8a8"].get("savings", {}))
934
- except Exception as e:
935
- errors.append(f"Teste de novos módulos falhou: {e}")
936
- logger.error(traceback.format_exc())
937
-
938
- # Step 5 + 6 + 7: Loop sobre 5 batches de 100 amostras
939
- for batch_idx in range(N_BATCHES):
940
- logger.info("")
941
- logger.info("#" * 70)
942
- logger.info("# BATCH %d/%d — 100 AMOSTRAS", batch_idx + 1, N_BATCHES)
943
- logger.info("#" * 70)
944
-
945
- try:
946
- dataloader = step_03_create_dataset(
947
- tokenizer, n_samples=BATCH_SIZE_SAMPLES, seed_offset=batch_idx,
948
- )
949
- except Exception as e:
950
- errors.append(f"Criação dataset batch {batch_idx+1} falhou: {e}")
951
- continue
952
-
953
- # Treino
954
- if not errors:
955
- try:
956
- train_result = step_05_train(
957
- models, tokenizer, dataloader, device="cpu",
958
- ewc_state=ewc_state, monitor=monitor, batch_idx=batch_idx,
959
- )
960
- all_train_results.append(train_result)
961
- except Exception as e:
962
- errors.append(f"Treino batch {batch_idx+1} falhou: {e}")
963
-
964
- # Inferência (apenas no último batch para economizar tempo)
965
- if batch_idx == N_BATCHES - 1 and not errors:
966
- try:
967
- step_06_inference(
968
- models["model"], tokenizer, device="cpu",
969
- generator=models.get("generator"), monitor=monitor,
970
- )
971
- except Exception as e:
972
- errors.append(f"Inferência batch {batch_idx+1} falhou: {e}")
973
- logger.error(traceback.format_exc())
974
-
975
- # PPL
976
- if not errors:
977
- try:
978
- step_07_eval_ppl(
979
- models["model"], tokenizer, dataloader, device="cpu",
980
- generator=models.get("generator"),
981
- )
982
- except Exception as e:
983
- warnings.append(f"PPL batch {batch_idx+1} falhou (não crítico): {e}")
984
-
985
- # Step 8: Relatório
986
- step_08_report(errors, warnings)
987
-
988
- # Finalizar monitor
989
- monitor.end_training()
990
- report_path = monitor.export_report()
991
- csv_path = monitor.export_csv()
992
- md_path = monitor.export_markdown_summary()
993
-
994
- # Resumo final
995
- logger.info("=" * 70)
996
- logger.info("RESUMO FINAL DO TESTE DE 500 AMOSTRAS")
997
- logger.info("=" * 70)
998
- logger.info(" Amostras processadas: %d (5 batches x 100)", TOTAL_SAMPLES)
999
- logger.info(" Erros críticos: %d", len(errors))
1000
- logger.info(" Warnings: %d", len(warnings))
1001
- if all_train_results:
1002
- final = all_train_results[-1]
1003
- logger.info(" Loss final: %.4f", final["final_loss"])
1004
- logger.info(" PPL final: %.2f", final["final_ppl"])
1005
- logger.info(" Tempo total treino: %.1fs",
1006
- sum(r["elapsed_s"] for r in all_train_results))
1007
- logger.info(" Monitor report: %s", report_path)
1008
- logger.info(" Monitor CSV: %s", csv_path)
1009
- logger.info(" Monitor MD: %s", md_path)
1010
- logger.info(" Throughput: %s", monitor.get_inference_throughput())
1011
-
1012
- if errors:
1013
- logger.error(" STATUS: FALHA — %d erro(s)", len(errors))
1014
- return 1
1015
- else:
1016
- logger.info(" STATUS: SUCESSO")
1017
- return 0
1018
-
1019
- except Exception as e:
1020
- logger.error("ERRO FATAL: %s", e)
1021
- logger.error(traceback.format_exc())
1022
- return 2
1023
-
1024
-
1025
- if __name__ == "__main__":
1026
- try:
1027
- rc = main()
1028
- except SystemExit:
1029
- raise
1030
- except Exception as e:
1031
- logger.error("Unhandled exception: %s", e)
1032
- rc = 2
1033
- # Evita o "Fatal Python error: PyGILState_Release" no shutdown
1034
- import os
1035
- os._exit(rc)