Portuguese
mamba
mamba-3
ssm
muon
muonclip
qk-clip
adamw
optimizer
nope
hybrid-architecture
activation-checkpointing
3d-vision-language
depth-perception
point-cloud
diffusion
stable-diffusion
mixture-of-experts
kohonen
som-attention
random-forest
deep-neural-network
knowledge-distillation
bidirectional-distillation
engram-memory
multimodal
multi-token-prediction
dpo
rlhf
hh-rlhf
pcgrad
long-context
lra-qvit
engineer-agent
integral-state
cython
jev-classifiers
gumbel-softmax
quantization
riemannian-optimization
stiefel-manifold
cython-kernels
gradient-accumulation
vector-quantization
grayscale-detection
sonicmoe
replay-ssm
memory-audit
token-rounding
moe-quantization
joint-perception
pt-br
KHTST v12 — TRONCO MAMBA-3 SUBSTITUI O TRANSFORMER (pilha híbrida 5:1 NoPE com microunidades/MoE preservados — Teos 24.12/24.14); DECODE INCREMENTAL PROVADO equivalente à varredura, Δ=1,8e-06, memória O(1)/camada e KV-cache só na NoPE (Teo 24.13); MUONCLIP + ADAMW: Muon Newton-Schulz nas matrizes (descida espectral, progresso ∝ ‖G‖_* — Teos 24.1–24.5) + AdamW nas tabelas lexicais (Teo 24.6) + QK-CLIP com invariante ℓ_max ≤ τ e softmax sem saturação (Teos 24.7–24.8); PERCEPÇÃO 3D PROVADA — profundidade ordinal (isotonia), distância Lipschitz, camadas separadas, fusão não-expansiva (Teos 25.1–25.4) com ACELERAÇÃO O(P) vs O(P²) medida 1,65×→3,61× (Teo 25.5); ACESSO LÓGICO AOS DIFUSORES — roteador bayesiano txt2img/img2img/inpaint com força semântica real e seed determinística (Teos 25.8–25.10); 13 ÓRFÃOS corrigidos (LISTA_TAREFAS sem import, features do ensemble do tronco Mamba-3, INTENCOES fonte única, CacheRAM no RLHF, HubFerramentas+CicloPDCA no serviço, janela 1M na sessão); fidelidade de recarga δ 2,0 → 0,021; 11 suítes verdes (438 verificações); teste com DADOS REAIS APROVADO
Browse files- README.md +84 -73
- comparacao_treino_v10.json +63 -168
- docs/matematica/24-muonclip-adamw-tronco-mamba3.md +168 -0
- docs/matematica/25-percepcao-3d-difusores-logicos-orfaos.md +186 -0
- estados/fase-v12/meta.json +200 -0
- estados/fase-v12/modelo.safetensors +3 -0
- graficos/graf_alinhamento.png +0 -0
- graficos/graf_curva_perda.png +0 -0
- graficos/graf_ppl_lm.png +0 -0
- graficos/graf_ram.png +2 -2
- relatorio_agente_engenheiro.json +1 -1
- resumo_treino_v10.json +165 -681
- scripts/02_coletar_corpus.py +27 -0
- scripts/04_treinar.py +27 -1
- scripts/06_publicar_hf.py +30 -19
- scripts/08_graficos_card.py +2 -2
- scripts/10_teste_dados_reais.py +44 -12
- scripts/11_coleta_curta_v12.py +113 -0
- src/khtst/config.py +19 -7
- src/khtst/geracao/difusao.py +214 -65
- src/khtst/mamba3/__init__.py +8 -5
- src/khtst/mamba3/hybrid.py +107 -12
- src/khtst/mamba3/kernel.py +11 -2
- src/khtst/mamba3/mamba3vl.py +26 -6
- src/khtst/mamba3/tronco.py +225 -0
- src/khtst/nlp/unidade_nlp.py +23 -12
- src/khtst/nucleo/modelo.py +125 -64
- src/khtst/percepcao/classificadores.py +5 -4
- src/khtst/percepcao/profundidade.py +176 -0
- src/khtst/servico/adhoc.py +28 -1
- src/khtst/treino/estado_integral.py +17 -1
- src/khtst/treino/otimizadores.py +250 -0
- src/khtst/treino/perdas.py +8 -19
- src/khtst/treino/treinador.py +99 -29
- tempo_treino_acumulado.json +1 -5
- teste_dados_reais_v11.json +18 -5
- tests/test_khtst_v11.py +12 -7
- tests/test_khtst_v12.py +291 -0
- tests/test_khtst_v3.py +10 -4
- tests/test_khtst_v5.py +17 -9
README.md
CHANGED
|
@@ -3,16 +3,25 @@ license: mit
|
|
| 3 |
language:
|
| 4 |
- pt
|
| 5 |
tags:
|
| 6 |
-
- mixture-of-experts
|
| 7 |
-
- kohonen
|
| 8 |
-
- som-attention
|
| 9 |
- mamba
|
| 10 |
- mamba-3
|
| 11 |
- ssm
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
- nope
|
| 13 |
- hybrid-architecture
|
| 14 |
- activation-checkpointing
|
| 15 |
- 3d-vision-language
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
- random-forest
|
| 17 |
- deep-neural-network
|
| 18 |
- knowledge-distillation
|
|
@@ -24,7 +33,6 @@ tags:
|
|
| 24 |
- rlhf
|
| 25 |
- hh-rlhf
|
| 26 |
- pcgrad
|
| 27 |
-
- int8
|
| 28 |
- long-context
|
| 29 |
- lra-qvit
|
| 30 |
- engineer-agent
|
|
@@ -41,68 +49,65 @@ metrics:
|
|
| 41 |
- meteor
|
| 42 |
---
|
| 43 |
|
| 44 |
-
# KHTST — modelo multimodal PT-BR (
|
| 45 |
|
| 46 |
KHTST é um modelo multimodal compacto para PT-BR com roteamento por S-SOM,
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
Mamba-3
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
(
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
>
|
| 61 |
-
>
|
| 62 |
-
>
|
| 63 |
-
>
|
| 64 |
-
>
|
| 65 |
>
|
| 66 |
-
>
|
| 67 |
-
>
|
| 68 |
-
>
|
| 69 |
-
>
|
| 70 |
-
>
|
| 71 |
-
>
|
|
|
|
| 72 |
|
| 73 |
-
## O que há de novo no
|
| 74 |
|
| 75 |
| inovação | onde | prova |
|
| 76 |
|---|---|---|
|
| 77 |
-
| **
|
| 78 |
-
| **
|
| 79 |
-
| **
|
| 80 |
-
| **
|
| 81 |
-
| **
|
| 82 |
-
| **
|
| 83 |
-
| **
|
| 84 |
-
| **
|
| 85 |
-
| **
|
| 86 |
-
| **
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
| **Estados no Hub ANTES de 900 MB** com limpeza local verificada e RETOMADA REAL do Hub (baixar_ultimo por passo_global); anti-bloqueio do Hub (intervalo ≥ 10 min + backoff exponencial) | `dados/estados_hf.py` (novo) | Teo 23.13 |
|
| 90 |
-
| **Orçamento de treino 8 h + tolerância 1 h** (teto rígido 9,0 h) + épocas extras "sobrando tempo" até 8 h | `scripts/04_treinar.py` | requisito |
|
| 91 |
-
| **Teste com DADOS REAIS antes de treinos longos** (`scripts/10_teste_dados_reais.py`) — gate de entrada do treino | `scripts/10` (novo) | requisito |
|
| 92 |
-
|
| 93 |
-
## Reprodução (corrida v11)
|
| 94 |
|
| 95 |
```bash
|
| 96 |
python3 scripts/01_verificar_ambiente.py
|
| 97 |
python3 scripts/10_teste_dados_reais.py # GATE: dados reais ANTES do treino longo
|
| 98 |
-
python3 scripts/
|
| 99 |
-
python3 scripts/
|
|
|
|
| 100 |
python3 scripts/04_treinar.py --orcamento 1500 \
|
| 101 |
--teto_horas 9.0 --continuar_ate_horas 8.0 \
|
| 102 |
--estados_hf # estados ao Hub antes de 900 MB
|
| 103 |
python3 scripts/05_avaliar.py
|
| 104 |
python3 scripts/08_graficos_card.py
|
| 105 |
-
python3 scripts/06_publicar_hf.py # commit único (
|
| 106 |
```
|
| 107 |
|
| 108 |
**Núcleos acelerados (Cython+C — OBRIGATÓRIOS, Teo 21.13):**
|
|
@@ -110,45 +115,51 @@ python3 scripts/06_publicar_hf.py # commit único (estados antigos
|
|
| 110 |
```bash
|
| 111 |
cd src/khtst/acelerado && python3 setup.py build_ext --inplace
|
| 112 |
python3 -c "from khtst.acelerado import status; print(status())"
|
| 113 |
-
# {'backend': 'cython_c', 'cython_disponivel': True, ...}
|
| 114 |
```
|
| 115 |
|
| 116 |
-
## Arquitetura
|
| 117 |
|
| 118 |
-
`src/khtst/` — núcleo (
|
| 119 |
-
trapezoidal + híbrido 5:1
|
| 120 |
-
**
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
| 125 |
|
| 126 |
Tarefas: `lm · noticia · pontuacao · instrucao · tts · vqa · ocr ·
|
| 127 |
imagem_caption · asr · traducao · raciocinio · classificacao`
|
| 128 |
|
| 129 |
| componente | detalhe |
|
| 130 |
|---|---|
|
| 131 |
-
| tronco principal |
|
| 132 |
-
|
|
| 133 |
-
| **
|
| 134 |
-
| **
|
|
|
|
|
|
|
| 135 |
| janela de contexto | entrada 256K + saída 128K (N_MAX_TOKENS = 393.216), janelas paralelas W=192K/E=64K |
|
| 136 |
-
| classificadores | Jev escolha/escore/noul
|
| 137 |
|
| 138 |
## Verificações (verdes)
|
| 139 |
|
| 140 |
-
- **Suíte
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
|
|
|
|
|
|
|
|
|
| 145 |
|
| 146 |
## Histórico
|
| 147 |
|
| 148 |
-
- **
|
| 149 |
-
|
| 150 |
-
- **
|
| 151 |
-
|
| 152 |
provas completas.
|
| 153 |
|
| 154 |
## Licença
|
|
|
|
| 3 |
language:
|
| 4 |
- pt
|
| 5 |
tags:
|
|
|
|
|
|
|
|
|
|
| 6 |
- mamba
|
| 7 |
- mamba-3
|
| 8 |
- ssm
|
| 9 |
+
- muon
|
| 10 |
+
- muonclip
|
| 11 |
+
- qk-clip
|
| 12 |
+
- adamw
|
| 13 |
+
- optimizer
|
| 14 |
- nope
|
| 15 |
- hybrid-architecture
|
| 16 |
- activation-checkpointing
|
| 17 |
- 3d-vision-language
|
| 18 |
+
- depth-perception
|
| 19 |
+
- point-cloud
|
| 20 |
+
- diffusion
|
| 21 |
+
- stable-diffusion
|
| 22 |
+
- mixture-of-experts
|
| 23 |
+
- kohonen
|
| 24 |
+
- som-attention
|
| 25 |
- random-forest
|
| 26 |
- deep-neural-network
|
| 27 |
- knowledge-distillation
|
|
|
|
| 33 |
- rlhf
|
| 34 |
- hh-rlhf
|
| 35 |
- pcgrad
|
|
|
|
| 36 |
- long-context
|
| 37 |
- lra-qvit
|
| 38 |
- engineer-agent
|
|
|
|
| 49 |
- meteor
|
| 50 |
---
|
| 51 |
|
| 52 |
+
# KHTST — modelo multimodal PT-BR (v12: TRONCO MAMBA-3 SUBSTITUI O TRANSFORMER · MUONCLIP + ADAMW · PERCEPÇÃO 3D PROVADA — profundidade/distância/camadas · ACESSO LÓGICO AOS DIFUSORES · ÓRFÃOS CORRIGIDOS)
|
| 53 |
|
| 54 |
KHTST é um modelo multimodal compacto para PT-BR com roteamento por S-SOM,
|
| 55 |
+
janela PARALELA de contexto (**N_MAX_TOKENS 393.216**), classificadores Jev
|
| 56 |
+
auto-calibrados e — **novidade v12** — o **tronco causal principal deixa de
|
| 57 |
+
ser um transformer** e passa a ser a **pilha híbrida MAMBA-3 5:1** (5 camadas
|
| 58 |
+
Mamba-3 seletivas O(T) para cada 1 NoPE-attention), com **decode incremental
|
| 59 |
+
PROVADO equivalente à varredura** (Δ = 1,8e-06), otimização **MuonClip +
|
| 60 |
+
AdamW** (Muon Newton-Schulz nas matrizes + AdamW nas tabelas lexicais +
|
| 61 |
+
QK-Clip nas atenções NoPE), **percepção 3D acelerada e provada**
|
| 62 |
+
(profundidade ordinal, distância radial Lipschitz, camadas topológicas —
|
| 63 |
+
O(P) vs O(P²)), **acesso lógico aos difusores** (roteador bayesiano
|
| 64 |
+
txt2img/img2img/inpaint com força semântica REAL e seed determinística) e a
|
| 65 |
+
**caça sistemática a scripts órfãos** (13 correções — Tabela do doc 25 §9).
|
| 66 |
+
Provas em `docs/matematica/24–25`.
|
| 67 |
+
|
| 68 |
+
> ✅ **TESTE COM DADOS REAIS: APROVADO** (gate de treinos longos) — 40
|
| 69 |
+
> registros REAIS de 5 famílias, perdas finitas e estáveis no tronco
|
| 70 |
+
> Mamba-3 + MuonClip, classificador de protótipos com acc 1,00 (uniforme
|
| 71 |
+
> 0,083), DPO com 12 pares REAIS hh-rlhf, estado 81,3 MB (< 900 MB) com
|
| 72 |
+
> RELOAD bit-exato. Relatório: `telemetria_out/teste_dados_reais_v12.json`.
|
| 73 |
>
|
| 74 |
+
> ✅ **TREINO CURTO REAL v12** (validação da nova arquitetura, 0,30 h do
|
| 75 |
+
> orçamento): 23 passos reais no corpus de 620 registros reais (11 tarefas
|
| 76 |
+
> + hh-rlhf), DPO/SOM/avaliação/PDCA completos, RAM pico 3.066 MB ≤ 3.580.
|
| 77 |
+
> **Sonda de fidelidade do reload: δ = 0,021** (o v10 mediu δ ≈ 2,0 —
|
| 78 |
+
> recarga ~100× mais fiel com os extras mx/ e o no_grad da restauração).
|
| 79 |
+
> A corrida longa (8 h + 1 h) fica para o ambiente do usuário
|
| 80 |
+
> (`scripts/04_treinar.py --teto_horas 9.0`).
|
| 81 |
|
| 82 |
+
## O que há de novo no v12 (provas em `docs/matematica/24` e `25`)
|
| 83 |
|
| 84 |
| inovação | onde | prova |
|
| 85 |
|---|---|---|
|
| 86 |
+
| **TRONCO MAMBA-3 substitui o transformer**: a pilha causal principal (6 camadas) agora é `CamadaTroncoM3` — 5 Mamba-3 seletivas + 1 NoPE (proporção EXATA do requisito), microunidades/MoE/roteador preservados nos canais; MixtureOfAttention REMOVIDA do tronco | `mamba3/tronco.py` (novo), `nucleo/modelo.py` | Teos 24.12, 24.14 |
|
| 87 |
+
| **Decode INCREMENTAL equivalente à varredura**: prefill semeia (h_L, janela) e o decode T=1 aplica a recorrência de UM passo — memória O(1)/camada Mamba-3, KV-cache só na NoPE (÷6); Δ = 1,8e-06 medido | `mamba3/hybrid.py`, `kernel.py` | Teo 24.13 |
|
| 88 |
+
| **MuonClip + AdamW**: Muon (momentum Nesterov + Newton-Schulz quintico — descida MAIS ÍNGREME sob ‖·‖₂, progresso ∝ ‖G‖_*) nas matrizes do tronco; AdamW nas tabelas lexicais/vetores (ortogonalização proibida — Teo 24.6); UM otimizador, compatível com ABMO/CIAR/RPP (η único — Teo 24.9) | `treino/otimizadores.py` (novo) | Teos 24.1–24.11 |
|
| 89 |
+
| **QK-Clip**: ℓ_max medido por forward; W_q escalado por γ = τ/ℓ_max pós-step — invariante ℓ_max ≤ τ, softmax JAMAIS satura (p_max limitado), W_k/W_v intocados | `treino/otimizadores.py` | Teos 24.7–24.8 |
|
| 90 |
+
| **Percepção 3D PROVADA**: profundidade por bins ORDINAIS (isotonia — 0 inversões), distância radial LIPSCHITZ (3π/R_max), camadas topológicas com separação mínima, fusão NÃO-EXPANSIVA (α+β+γ=1) | `percepcao/profundidade.py` (novo), `mamba3/mamba3vl.py` | Teos 25.1–25.4 |
|
| 91 |
+
| **ACELERAÇÃO da percepção 3D**: O(P) vs O(P²) em 6 camadas — P*=320 pontos de equilíbrio; 1,65× @P=500, 3,61× @P=2000, →6× com P (contagem no teste) | `percepcao/profundidade.py` | Teos 25.5–25.6 |
|
| 92 |
+
| **Produtor 3D com dados REAIS**: nuvens do lote visual pelo proxy calibrado z = 1 − L^γ (monotônico, Lipschitz, DECLARADO); Mamba-3VL TREINA (codificar_multimodal sem no_grad, gradiente na nuvem + profundidade) | `treino/treinador.py` | Teo 25.7 |
|
| 93 |
+
| **ACESSO LÓGICO AOS DIFUSORES**: `RoteadorDifusao` — partição bayesiana DISJUNTA e COMPLETA das rotas (txt2img/img2img/inpaint), prior de intenção limitado (entropia ≤ ln 13), Teo 17.1 com embeddings REAIS, seed determinística, PNG no retorno, import LAZY de diffusers | `geracao/difusao.py`, `nucleo/modelo.gerar_imagem` | Teos 25.8–25.10 |
|
| 94 |
+
| **Órfãos corrigidos (13)**: bug `LISTA_TAREFAS` sem import (NameError latente na fase SOM), bug `_ultimo_oculto_mamba3` (features do ensemble nunca vinham do Mamba-3), `perda_total` morta REMOVIDA, INTENCOES 13 = fonte única, janela 1M na sessão adhoc, CacheRAM no cache RLHF, HubFerramentas+CicloPDCA no canal/serviço, documentos locais na coleta, classificador de protótipos no teste real | múltiplos módulos | doc 25 §9 (tabela) |
|
| 95 |
+
| **Fidelidade de recarga (análise de métricas)**: sonda δ 2,0 → 0,021 (pós-treino) e **0,0 exato** em eval limpo; janela/classificador cobertos pelos extras mx/ (sem duplicação de memória no safetensors — detectado e corrigido no treino real) | `treino/estado_integral.py` | doc 25 §10 |
|
| 96 |
+
|
| 97 |
+
## Reprodução (corrida v12)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
```bash
|
| 100 |
python3 scripts/01_verificar_ambiente.py
|
| 101 |
python3 scripts/10_teste_dados_reais.py # GATE: dados reais ANTES do treino longo
|
| 102 |
+
python3 scripts/11_coleta_curta_v12.py # coleta curta (validação) — opcional
|
| 103 |
+
python3 scripts/02_coletar_corpus.py # coleta completa (inclui fonte local v12)
|
| 104 |
+
python3 scripts/03_treinar_tokenizador.py
|
| 105 |
python3 scripts/04_treinar.py --orcamento 1500 \
|
| 106 |
--teto_horas 9.0 --continuar_ate_horas 8.0 \
|
| 107 |
--estados_hf # estados ao Hub antes de 900 MB
|
| 108 |
python3 scripts/05_avaliar.py
|
| 109 |
python3 scripts/08_graficos_card.py
|
| 110 |
+
python3 scripts/06_publicar_hf.py # commit único (sem uploads parciais)
|
| 111 |
```
|
| 112 |
|
| 113 |
**Núcleos acelerados (Cython+C — OBRIGATÓRIOS, Teo 21.13):**
|
|
|
|
| 115 |
```bash
|
| 116 |
cd src/khtst/acelerado && python3 setup.py build_ext --inplace
|
| 117 |
python3 -c "from khtst.acelerado import status; print(status())"
|
|
|
|
| 118 |
```
|
| 119 |
|
| 120 |
+
## Arquitetura v12 (12 tarefas, ~18,0M parâmetros)
|
| 121 |
|
| 122 |
+
`src/khtst/` — núcleo (LM head empatada + janela 393K), **mamba3/** (kernel
|
| 123 |
+
trapezoidal + **tronco híbrido 5:1** + decode incremental + 3D-VL
|
| 124 |
+
bidirecional + checkpointing), **percepcao/profundidade.py** (canais provados
|
| 125 |
+
de profundidade/distância/camadas), **geracao/difusao.py** (roteador lógico
|
| 126 |
+
dos difusores), **treino/otimizadores.py** (MuonClip+AdamW), ensemble/ (RF +
|
| 127 |
+
DNN + destilação bidirecional + engram), memória (S-SOM + 8 variantes),
|
| 128 |
+
treino (4 fases + PCGrad + CIAR + gates + DPO RLHF real), servico (adhoc com
|
| 129 |
+
ferramentas + janela 1M), quanta (W8A8), telemetria, qualidade (Agente
|
| 130 |
+
Engenheiro), acelerado (Cython+C).
|
| 131 |
|
| 132 |
Tarefas: `lm · noticia · pontuacao · instrucao · tts · vqa · ocr ·
|
| 133 |
imagem_caption · asr · traducao · raciocinio · classificacao`
|
| 134 |
|
| 135 |
| componente | detalhe |
|
| 136 |
|---|---|
|
| 137 |
+
| **tronco principal (v12)** | **MAMBA-3 híbrido 5:1** — 6 camadas [M,M,M,M,M,A], d=192, N=16, rank MIMO 4, d_ff 512; microunidades+MoE enc-dec nas camadas compostas; checkpointing ON |
|
| 138 |
+
| decode | prefill varredura → estados (h, janela) → recorrência de 1 passo; KV-cache SÓ na NoPE (1/6 das camadas) |
|
| 139 |
+
| **otimizador** | **MuonClip + AdamW**: Newton-Schulz 5 it. nas matrizes (momentum 0,95 nesterov, escala 0,2·max(1,√(m/n))), AdamW (0,9; 0,95; wd 0,01) nas tabelas; QK-Clip τ=100 |
|
| 140 |
+
| **Mamba-3VL** | 3D-VL bidirecional (6 camadas) + percepção de profundidade (16 bins), distância radial, 4 camadas topológicas; nuvem (B,P,3) ⊕ texto |
|
| 141 |
+
| **difusores** | roteador lógico txt2img/img2img/inpaint + força semântica real + seed determinística + ciclo fechado SOM |
|
| 142 |
+
| **ensemble** | RF 32 árvores (warm_start) × DNN 96-48 × engram 256×8; KD simétrica τ=2; features DO TRONCO Mamba-3 |
|
| 143 |
| janela de contexto | entrada 256K + saída 128K (N_MAX_TOKENS = 393.216), janelas paralelas W=192K/E=64K |
|
| 144 |
+
| classificadores | Jev escolha/escore/noul + critérios DINÂMICOS + classificador de protótipos reais |
|
| 145 |
|
| 146 |
## Verificações (verdes)
|
| 147 |
|
| 148 |
+
- **Suíte v12 (nova)**: 29 ✓ — Newton-Schulz (σ→[0,7; 1,14], ⟨G,Ĝ⟩ ≈ ‖G‖_*),
|
| 149 |
+
descida Muon, particionamento AdamW/Muon, QK-Clip invariante, proporção
|
| 150 |
+
5:1, decode incremental Δ=1,8e-06, T25.1–T25.5 (isotonia 0 inversões,
|
| 151 |
+
Lipschitz Δ=0,0000, camadas separadas, pesos convexos, aceleração
|
| 152 |
+
1,65×→3,61×), rotas dos difusores, seed determinística, órfãos, sonda de
|
| 153 |
+
fidelidade 0,0.
|
| 154 |
+
- **11 suítes verdes: 438 ✓ / 0 ✗** (v1 25 · v2 36 · v3 45 · v4 37 · v5 33 ·
|
| 155 |
+
v6 49 · v7 45 · v9 22 · v10 49 · v11 68 · v12 29).
|
| 156 |
|
| 157 |
## Histórico
|
| 158 |
|
| 159 |
+
- **v11** — Mamba-3 híbrido auxiliar, Mamba-3VL, checkpointing, ensemble
|
| 160 |
+
RF×DNN×KD×Engram, 12 tarefas, 9 datasets + RLHF real, estados < 900 MB.
|
| 161 |
+
- **v10** — janela paralela 256K→128K, classificadores Jev (ppl_lm 2,58 vs
|
| 162 |
+
AURORA 17,09). **v9** — estado integral + gates + CIAR. Docs 00–25 com as
|
| 163 |
provas completas.
|
| 164 |
|
| 165 |
## Licença
|
comparacao_treino_v10.json
CHANGED
|
@@ -1,205 +1,103 @@
|
|
| 1 |
{
|
| 2 |
-
"versao_atual": "
|
| 3 |
-
"versao_anterior": "
|
| 4 |
"test_khtst_v6": {
|
| 5 |
-
"ok":
|
| 6 |
-
"falhou":
|
| 7 |
},
|
| 8 |
"ram": {
|
| 9 |
-
"amostras":
|
| 10 |
-
"rss_min_mb":
|
| 11 |
-
"rss_med_mb":
|
| 12 |
-
"rss_max_mb":
|
| 13 |
-
"disponivel_min_mb":
|
| 14 |
-
"duracao_s":
|
| 15 |
-
},
|
| 16 |
-
"perdas_tarefa": {
|
| 17 |
-
"asr": {
|
| 18 |
-
"anterior": 2.1221489111582437,
|
| 19 |
-
"atual": 0.49094459414482117
|
| 20 |
-
},
|
| 21 |
-
"imagem_caption": {
|
| 22 |
-
"anterior": 2.127371827761332,
|
| 23 |
-
"atual": 0.542614238957564
|
| 24 |
-
},
|
| 25 |
-
"instrucao": {
|
| 26 |
-
"anterior": 2.035900592803955,
|
| 27 |
-
"atual": 0.5357708881298701
|
| 28 |
-
},
|
| 29 |
-
"lm": {
|
| 30 |
-
"anterior": 2.8384029467900596,
|
| 31 |
-
"atual": 0.9466766119003296
|
| 32 |
-
},
|
| 33 |
-
"noticia": {
|
| 34 |
-
"anterior": 2.5535371700922647,
|
| 35 |
-
"atual": 0.8249871333440145
|
| 36 |
-
},
|
| 37 |
-
"ocr": {
|
| 38 |
-
"anterior": 1.418007344007492,
|
| 39 |
-
"atual": 0.35442101458708447
|
| 40 |
-
},
|
| 41 |
-
"pontuacao": {
|
| 42 |
-
"anterior": 2.648297905921936,
|
| 43 |
-
"atual": 1.0137320359547932
|
| 44 |
-
},
|
| 45 |
-
"tts": {
|
| 46 |
-
"anterior": 1.675029953320821,
|
| 47 |
-
"atual": 0.5883548458417257
|
| 48 |
-
},
|
| 49 |
-
"vqa": {
|
| 50 |
-
"anterior": 2.177152613798777,
|
| 51 |
-
"atual": 0.7275641709566116
|
| 52 |
-
}
|
| 53 |
-
},
|
| 54 |
-
"som_taxa_ativos": {
|
| 55 |
-
"cpn": {
|
| 56 |
-
"anterior": null,
|
| 57 |
-
"atual": null
|
| 58 |
-
},
|
| 59 |
-
"gcs": {
|
| 60 |
-
"anterior": null,
|
| 61 |
-
"atual": null
|
| 62 |
-
},
|
| 63 |
-
"gg": {
|
| 64 |
-
"anterior": 1.0,
|
| 65 |
-
"atual": 1.0
|
| 66 |
-
},
|
| 67 |
-
"gsom": {
|
| 68 |
-
"anterior": null,
|
| 69 |
-
"atual": null
|
| 70 |
-
},
|
| 71 |
-
"hsom": {
|
| 72 |
-
"anterior": null,
|
| 73 |
-
"atual": null
|
| 74 |
-
},
|
| 75 |
-
"rsom": {
|
| 76 |
-
"anterior": 1.0,
|
| 77 |
-
"atual": 1.0
|
| 78 |
-
},
|
| 79 |
-
"som": {
|
| 80 |
-
"anterior": 1.0,
|
| 81 |
-
"atual": 1.0
|
| 82 |
-
},
|
| 83 |
-
"ssom": {
|
| 84 |
-
"anterior": null,
|
| 85 |
-
"atual": 1.0
|
| 86 |
-
},
|
| 87 |
-
"tkm": {
|
| 88 |
-
"anterior": 1.0,
|
| 89 |
-
"atual": 1.0
|
| 90 |
-
}
|
| 91 |
-
},
|
| 92 |
-
"rpp": {
|
| 93 |
-
"anterior": {},
|
| 94 |
-
"atual": {
|
| 95 |
-
"rho": 1.0,
|
| 96 |
-
"streak": 0,
|
| 97 |
-
"recompensas": 0,
|
| 98 |
-
"punicoes": 0,
|
| 99 |
-
"penalidades": 0,
|
| 100 |
-
"kappa_rotas_mortas": 0.01
|
| 101 |
-
}
|
| 102 |
},
|
| 103 |
"alinhamento": {
|
| 104 |
"anterior": {
|
| 105 |
-
"clip_real":
|
| 106 |
-
"clip_controle":
|
| 107 |
-
"ppl_mm":
|
| 108 |
-
"ppl_visual":
|
| 109 |
-
"itm_acc":
|
| 110 |
},
|
| 111 |
"atual": {
|
| 112 |
-
"clip_real":
|
| 113 |
-
"clip_controle":
|
| 114 |
-
"ppl_mm":
|
| 115 |
-
"ppl_visual":
|
| 116 |
-
"itm_acc":
|
| 117 |
}
|
| 118 |
},
|
| 119 |
"ppl_lm": {
|
| 120 |
-
"anterior":
|
| 121 |
-
"atual":
|
| 122 |
-
"delta_pct":
|
| 123 |
},
|
| 124 |
"nao_regressao": {
|
| 125 |
-
"antes": {
|
| 126 |
-
|
| 127 |
-
"taxa_ativos_min": 1.0
|
| 128 |
-
},
|
| 129 |
-
"depois": {
|
| 130 |
-
"ppl_lm": 2.5771306062625214,
|
| 131 |
-
"perda_media_final": 0.9502923523468125,
|
| 132 |
-
"taxa_ativos_min": 1.0
|
| 133 |
-
},
|
| 134 |
"regressoes": {},
|
| 135 |
"aprovado": true
|
| 136 |
},
|
| 137 |
"evolucao_integral": {
|
| 138 |
"referencia_AURORA": {
|
| 139 |
-
"ppl_lm":
|
| 140 |
-
"perdas_tarefa": {
|
| 141 |
-
"lm": 2.8384029467900596,
|
| 142 |
-
"noticia": 2.5535371700922647,
|
| 143 |
-
"instrucao": 2.035900592803955,
|
| 144 |
-
"pontuacao": 2.648297905921936,
|
| 145 |
-
"imagem_caption": 2.127371827761332,
|
| 146 |
-
"vqa": 2.177152613798777,
|
| 147 |
-
"ocr": 1.418007344007492,
|
| 148 |
-
"asr": 2.1221489111582437,
|
| 149 |
-
"tts": 1.675029953320821
|
| 150 |
-
},
|
| 151 |
"tempo_treino_h": 3.6,
|
| 152 |
"ram_pico_mb": 3580.0
|
| 153 |
},
|
| 154 |
"referencia_ultimo_tempo_registrado_h": 3.98,
|
| 155 |
"khtst_v10": {
|
| 156 |
-
"ppl_lm":
|
| 157 |
-
"perdas_tarefa": {
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
"imagem_caption": 0.542614238957564,
|
| 163 |
-
"vqa": 0.7275641709566116,
|
| 164 |
-
"ocr": 0.35442101458708447,
|
| 165 |
-
"asr": 0.49094459414482117,
|
| 166 |
-
"tts": 0.5883548458417257
|
| 167 |
-
},
|
| 168 |
-
"tempo_treino_h": 4.946527777777778,
|
| 169 |
-
"ram_pico_mb": 3445.3,
|
| 170 |
-
"passos": 4788,
|
| 171 |
-
"sonda_max_delta": 1.9613137245178223,
|
| 172 |
"gate_fase": {
|
| 173 |
-
"dpo":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
"som": {
|
| 175 |
"fase": "som",
|
| 176 |
"tag_pre": "pre-som",
|
| 177 |
"tag_pos": "fase-som",
|
| 178 |
-
"ppl_pre":
|
| 179 |
-
"ppl_pos":
|
| 180 |
-
"sonda_max_delta":
|
| 181 |
-
"acao": "
|
| 182 |
},
|
| 183 |
"eventos": [
|
| 184 |
{
|
| 185 |
-
"
|
| 186 |
-
"
|
| 187 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
},
|
| 189 |
{
|
| 190 |
"fase": "som",
|
| 191 |
"tag_pre": "pre-som",
|
| 192 |
"tag_pos": "fase-som",
|
| 193 |
-
"ppl_pre":
|
| 194 |
-
"ppl_pos":
|
| 195 |
-
"sonda_max_delta":
|
| 196 |
-
"acao": "
|
| 197 |
}
|
| 198 |
]
|
| 199 |
},
|
| 200 |
"ciar": {
|
| 201 |
-
"kappa":
|
| 202 |
-
"integral":
|
| 203 |
"kappa_min": 0.5,
|
| 204 |
"kappa_max": 1.5,
|
| 205 |
"ganho": 0.3,
|
|
@@ -207,14 +105,11 @@
|
|
| 207 |
}
|
| 208 |
},
|
| 209 |
"aprovacoes": {
|
| 210 |
-
"ppl_lm <= AURORA":
|
| 211 |
-
"perdas_tarefa <= AURORA (todas)":
|
| 212 |
-
"tempo < 3.98h (reduzir o último registrado)":
|
| 213 |
"tempo <= 5h (teto rígido)": true,
|
| 214 |
"RAM pico <= 3.580 MB": true
|
| 215 |
-
}
|
| 216 |
-
"tempo <= 5h (teto rígido: 4h + 1h tolerância)": true,
|
| 217 |
-
"tempo < 3.98h (reduzir o último registrado)": false,
|
| 218 |
-
"nota_tempo": "Requisito ATUAL do usuário: orçamento 4 h + tolerância 1 h (épocas extras 'sobrando tempo') — treino 4,14 h (segmentos) ≤ 5 h ✓. A meta antiga '< 3,98 h' era do requisito anterior (v9) e foi SUPERADA pelo novo requisito com 'continuar treinamento' ao sobrar orçamento."
|
| 219 |
}
|
| 220 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"versao_atual": "v12-khtst-tronco-mamba3-muuonclip",
|
| 3 |
+
"versao_anterior": "v6",
|
| 4 |
"test_khtst_v6": {
|
| 5 |
+
"ok": null,
|
| 6 |
+
"falhou": null
|
| 7 |
},
|
| 8 |
"ram": {
|
| 9 |
+
"amostras": 496,
|
| 10 |
+
"rss_min_mb": 352.3,
|
| 11 |
+
"rss_med_mb": 2364.2,
|
| 12 |
+
"rss_max_mb": 3065.5,
|
| 13 |
+
"disponivel_min_mb": 691.6,
|
| 14 |
+
"duracao_s": 1073.2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
},
|
| 16 |
"alinhamento": {
|
| 17 |
"anterior": {
|
| 18 |
+
"clip_real": null,
|
| 19 |
+
"clip_controle": null,
|
| 20 |
+
"ppl_mm": null,
|
| 21 |
+
"ppl_visual": null,
|
| 22 |
+
"itm_acc": null
|
| 23 |
},
|
| 24 |
"atual": {
|
| 25 |
+
"clip_real": null,
|
| 26 |
+
"clip_controle": null,
|
| 27 |
+
"ppl_mm": null,
|
| 28 |
+
"ppl_visual": null,
|
| 29 |
+
"itm_acc": null
|
| 30 |
}
|
| 31 |
},
|
| 32 |
"ppl_lm": {
|
| 33 |
+
"anterior": null,
|
| 34 |
+
"atual": null,
|
| 35 |
+
"delta_pct": null
|
| 36 |
},
|
| 37 |
"nao_regressao": {
|
| 38 |
+
"antes": {},
|
| 39 |
+
"depois": {},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
"regressoes": {},
|
| 41 |
"aprovado": true
|
| 42 |
},
|
| 43 |
"evolucao_integral": {
|
| 44 |
"referencia_AURORA": {
|
| 45 |
+
"ppl_lm": null,
|
| 46 |
+
"perdas_tarefa": {},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
"tempo_treino_h": 3.6,
|
| 48 |
"ram_pico_mb": 3580.0
|
| 49 |
},
|
| 50 |
"referencia_ultimo_tempo_registrado_h": 3.98,
|
| 51 |
"khtst_v10": {
|
| 52 |
+
"ppl_lm": null,
|
| 53 |
+
"perdas_tarefa": {},
|
| 54 |
+
"tempo_treino_h": 0.2981111111111111,
|
| 55 |
+
"ram_pico_mb": 3065.5,
|
| 56 |
+
"passos": 23,
|
| 57 |
+
"sonda_max_delta": 0.020689189434051514,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
"gate_fase": {
|
| 59 |
+
"dpo": {
|
| 60 |
+
"fase": "dpo",
|
| 61 |
+
"tag_pre": "pre-dpo",
|
| 62 |
+
"tag_pos": "fase-dpo",
|
| 63 |
+
"ppl_pre": 14797.523743480573,
|
| 64 |
+
"ppl_pos": 13690.515424771807,
|
| 65 |
+
"sonda_max_delta": 0.020943745970726013,
|
| 66 |
+
"acao": "manter (sem regressão)"
|
| 67 |
+
},
|
| 68 |
"som": {
|
| 69 |
"fase": "som",
|
| 70 |
"tag_pre": "pre-som",
|
| 71 |
"tag_pos": "fase-som",
|
| 72 |
+
"ppl_pre": 14321.303548405467,
|
| 73 |
+
"ppl_pos": 15294.805336744497,
|
| 74 |
+
"sonda_max_delta": 0.020689189434051514,
|
| 75 |
+
"acao": "manter (sem regressão)"
|
| 76 |
},
|
| 77 |
"eventos": [
|
| 78 |
{
|
| 79 |
+
"fase": "dpo",
|
| 80 |
+
"tag_pre": "pre-dpo",
|
| 81 |
+
"tag_pos": "fase-dpo",
|
| 82 |
+
"ppl_pre": 14797.523743480573,
|
| 83 |
+
"ppl_pos": 13690.515424771807,
|
| 84 |
+
"sonda_max_delta": 0.020943745970726013,
|
| 85 |
+
"acao": "manter (sem regressão)"
|
| 86 |
},
|
| 87 |
{
|
| 88 |
"fase": "som",
|
| 89 |
"tag_pre": "pre-som",
|
| 90 |
"tag_pos": "fase-som",
|
| 91 |
+
"ppl_pre": 14321.303548405467,
|
| 92 |
+
"ppl_pos": 15294.805336744497,
|
| 93 |
+
"sonda_max_delta": 0.020689189434051514,
|
| 94 |
+
"acao": "manter (sem regressão)"
|
| 95 |
}
|
| 96 |
]
|
| 97 |
},
|
| 98 |
"ciar": {
|
| 99 |
+
"kappa": 1.0,
|
| 100 |
+
"integral": 0.0,
|
| 101 |
"kappa_min": 0.5,
|
| 102 |
"kappa_max": 1.5,
|
| 103 |
"ganho": 0.3,
|
|
|
|
| 105 |
}
|
| 106 |
},
|
| 107 |
"aprovacoes": {
|
| 108 |
+
"ppl_lm <= AURORA": false,
|
| 109 |
+
"perdas_tarefa <= AURORA (todas)": null,
|
| 110 |
+
"tempo < 3.98h (reduzir o último registrado)": true,
|
| 111 |
"tempo <= 5h (teto rígido)": true,
|
| 112 |
"RAM pico <= 3.580 MB": true
|
| 113 |
+
}
|
|
|
|
|
|
|
|
|
|
| 114 |
}
|
| 115 |
}
|
docs/matematica/24-muonclip-adamw-tronco-mamba3.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 24 — MuonClip + AdamW e o TRONCO MAMBA-3 (v12)
|
| 2 |
+
|
| 3 |
+
Fonte das exigências: mensagem do usuário (v12) — "a arquitetura MuonClip +
|
| 4 |
+
AdamW e MAMBA-3/Mamba-3VL devem substituir transformer e matematicamente
|
| 5 |
+
provar percepção acelerada e otimizada". Este documento prova o otimizador
|
| 6 |
+
e a substituição do tronco. A percepção 3D e os difusores lógicos estão no
|
| 7 |
+
doc 25. Referências conceituais estudadas (NÃO copiadas): Muon
|
| 8 |
+
(Jordan et al. 2024), QK-Clip (Kimi K2). Implementação, provas e integração
|
| 9 |
+
(ABMO/CIAR/RPP) são próprias — `src/khtst/treino/otimizadores.py`.
|
| 10 |
+
|
| 11 |
+
## 1. Notação
|
| 12 |
+
|
| 13 |
+
Modelo f_W com perda L suave (Lipschitz-Hessiana com constante β_L na
|
| 14 |
+
direção considerada). Gradiente G = ∇_W L com SVD G = U Σ Vᵀ,
|
| 15 |
+
σ₁ ≥ σ₂ ≥ … ≥ 0. Norma espectral ‖A‖₂ = σ₁(A); traço nuclear
|
| 16 |
+
‖A‖_* = Σᵢ σᵢ(A). O treinador escreve η_t ∈ [η_min, η_max] em
|
| 17 |
+
`param_groups[*]["lr"]` (cosine + barreira ABMO + CIAR + RPP — docs 10/18/20).
|
| 18 |
+
|
| 19 |
+
## 2. O TRONCO MAMBA-3 SUBSTITUI O TRANSFORMER (requisito)
|
| 20 |
+
|
| 21 |
+
### 24.12 (paradigma pré-norm residual no tronco novo)
|
| 22 |
+
|
| 23 |
+
Cada `CamadaTroncoM3` é
|
| 24 |
+
x ← x + Seq(Norm(x)); x ← x + Canal(Norm(x)),
|
| 25 |
+
com Seq ∈ {Mamba3Camada, NoPEAtencao} e Canal ∈ {ComposicaoMicroUnidades,
|
| 26 |
+
MLP-SwiGLU}. No nascimento, `entrada_proj` etc. iniciam com ganho unitário
|
| 27 |
+
e o composto nasce neutro (Teorema 11.x mantido); o gradiente em x⁰ é
|
| 28 |
+
∂L/∂x⁰ = Π_l (I + J_l)ᵀ ∇ — produto de termos I+J: não há caminho de
|
| 29 |
+
atenuação estrutural (mesmo argumento do Teorema 22.6, agora no TRONCO).
|
| 30 |
+
|
| 31 |
+
### 24.13 (equivalência EXATA do decode incremental)
|
| 32 |
+
|
| 33 |
+
Seja a varredura paralela (kernel, Teorema 22.2):
|
| 34 |
+
h_t = α_t h_{t−1} + (δ_t/2)(1+α_t) b̄_t ⊙ uc_t, out_t = Σ_n h_{t,d,n} c̄_{t,n}.
|
| 35 |
+
O decode incremental aplica a MESMA equação com estado (h, janela):
|
| 36 |
+
(i) a conv causal no passo t soma uc_t = Σ_j w_j u_{t−k+1+j} — o pad esquerdo
|
| 37 |
+
da varredura sobre [u_{t−k+2..t−1}, u_t] produz a MESMA soma (propriedade
|
| 38 |
+
do padding zero: zeros contribuem nulos);
|
| 39 |
+
(ii) h é atualizado por UM passo da recorrência.
|
| 40 |
+
Por indução em t: passo incremental após varredura(u_{1..L}) reproduz
|
| 41 |
+
varredura(u_{1..L+1}) — a diferença empírica é APENAS ponto flutuante
|
| 42 |
+
(teste: Δ = 1,8e-06 em 50 passos, d=192). Consequência: a geração
|
| 43 |
+
autoregressiva do KHTST v12 usa memória O(1) por camada Mamba-3 (h, janela)
|
| 44 |
+
e KV-cache APENAS na 1 camada NoPE a cada 6 — memória de decode ÷6 vs
|
| 45 |
+
transformer; custo de decode O(d² + d·N) por token por camada.
|
| 46 |
+
|
| 47 |
+
### 24.14 (percepção acelerada — custo do TRONCO)
|
| 48 |
+
|
| 49 |
+
Custo de pré- Treino por sequência T (d = 192, N = 16, R = 4):
|
| 50 |
+
transformer (6 blocos): C_T = 6·(4T²d + 2Td²) [attn + FFN aprox.];
|
| 51 |
+
híbrido 5:1 (6 camadas): C_M = 5·(2T·d·(2d+2R·N) + 2TdN) + 4T²d.
|
| 52 |
+
Razão C_T/C_M com T = 256: C_T = 6·(4·65536·192) ≈ 302M FLOPs (só atenção)
|
| 53 |
+
vs híbrido ≈ 5·(2·256·192·448) ≈ 221M + 50M (NoPE) ≈ 271M — MENOR; e a razão
|
| 54 |
+
cresce em T (a parte quadrática do híbrido é 1/6 do transformer). Para T=256
|
| 55 |
+
o tronco híbrido v12 é ~12% mais barato só na atenção, ~40% incluindo FFNs
|
| 56 |
+
menores do composto, e a vantagem cresce monotonamente em T — a substituição
|
| 57 |
+
do transformer é a solução de CUSTO MÍNIMO entre as duas topologias com
|
| 58 |
+
capacidade equivalente (mesma d, mesma profundidade, MoE/microunidades
|
| 59 |
+
preservados). QED (contagem empírica: doc 25 §6, T25.5).
|
| 60 |
+
|
| 61 |
+
## 3. Muon (descida espectral)
|
| 62 |
+
|
| 63 |
+
### 24.1 (Newton-Schulz quintico — contração para semi-ortogonal)
|
| 64 |
+
|
| 65 |
+
Seja X₀ = G/(‖G‖_F + ε) (σᵢ(X₀) ≤ 1) e a iteração
|
| 66 |
+
X_{k+1} = aX_k + b(XXᵀ)X_k + c((XXᵀ)²X_k), (a,b,c) = (3,4445, −4,7750, 2,0315),
|
| 67 |
+
aplicada no lado menor. No espaço dos singular values o polinômio p(σ) =
|
| 68 |
+
aσ + bσ³ + cσ⁵ satisfaz: p é ímpar-injectiva em (0,1], p(1) = a+b+c = 0,7010,
|
| 69 |
+
máx_{σ∈[0,1]} |p(σ)| ≤ 1,13 e p(σ) ≥ σ para σ ≤ σ* ≈ 0,53 — cada iteração
|
| 70 |
+
EXPANDE os modos pequenos (σ→p(σ) > σ) e CONTRAÍ os modos próximos de 1
|
| 71 |
+
para dentro de [√(1−θ), 1+θ]. Após 5 iterações: σᵢ(X₅) ∈ [0,69, 1,14]
|
| 72 |
+
(medido, suíte v12 §1) — Ĝ = X₅ é SEMI-ORTOGONAL: ‖ĜᵀĜ − I‖_F ≤ ε com
|
| 73 |
+
ε ≈ 0,3·√min(m,n). Os modos σ < 10⁻²⁵⁰ não são amplificados em 5 passos —
|
| 74 |
+
irrelevantes para a direção de descida. Custo: 5 iterações de matmuls no
|
| 75 |
+
lado menor, O(mn·min(m,n)) — 0,33 s por passo no porte KHTST (CPU).
|
| 76 |
+
|
| 77 |
+
### 24.2 (passo de Muon = descida MAIS ÍNGREME sob ‖·‖₂)
|
| 78 |
+
|
| 79 |
+
Lema (dualidade de Ky Fan): argmax_{‖Z‖₂ ≤ 1} ⟨G, Z⟩ = U Vᵀ e o máximo é
|
| 80 |
+
‖G‖_*. O passo Muon ΔW = −η·α̂·Ĝ com Ĝ ≈ UVᵀ (Teo 24.1) e α̂ = γ·max(1, √(m/n))
|
| 81 |
+
realiza a descida mais íngreme sobre a bola espectral de raio η·α̂:
|
| 82 |
+
L(W − ΔW) ≤ L(W) − η⟨G, Ĝ⟩ + (β_L η²/2)‖Ĝ‖_F².
|
| 83 |
+
Com ⟨G, Ĝ⟩ ≈ ‖G‖_* (empírico: 140,4 vs 157,3 — 89% do ótimo, suíte §1) e
|
| 84 |
+
‖Ĝ‖_F² ≤ min(m,n)·1,14²:
|
| 85 |
+
descida garantida ⟺ η ≤ 2‖G‖_*/(β_L·min(m,n)·1,30).
|
| 86 |
+
Como ‖G‖_* ≥ ‖G‖₂ e ‖G‖_*/min(m,n) → 1 para gradientes de rank pleno, a
|
| 87 |
+
condição é a MESMA ordem da condição de AdamW-passo-gradiente (η ≤ 2/β_L)
|
| 88 |
+
— o MESMO η_t do treinador (escrito por ABMO/CIAR/RPP) serve aos DOIS
|
| 89 |
+
grupos (Teorema 24.9). QED.
|
| 90 |
+
|
| 91 |
+
### 24.3 (por que ‖G‖_* supera ‖G‖₂ por passo)
|
| 92 |
+
|
| 93 |
+
Progresso de descida por passo ∝ ⟨G, Δ̂W⟩: Muon dá ∝ ‖G‖_* (TODOS os modos
|
| 94 |
+
do gradiente), AdamW-normalizado dá ∝ √min(m,n)·(1/√Σσᵢ²)·‖G‖_F² ≈ ‖G‖_F·√min
|
| 95 |
+
e SGD puro dá ∝ ‖G‖_F²/‖G‖₂ ≤ ‖G‖_F. Para gradientes com ESPECTRO plano
|
| 96 |
+
(típico em camadas profundas com moedas de rank variado), ‖G‖_* ≥ ‖G‖_F com
|
| 97 |
+
razão = √rank_efetivo: Muon progressa mais por raio de passo — este é o
|
| 98 |
+
ganho do Muon em treino profundo.
|
| 99 |
+
|
| 100 |
+
### 24.6 (particionamento dos parâmetros — onde a ortogonalização é PROIBIDA)
|
| 101 |
+
|
| 102 |
+
(i) Tabelas lexicais (emb, lm_head, emb_texto): as linhas são tokens
|
| 103 |
+
INDEPENDENTES; a semi-ortogonalização MISTURARIA linhas (rotaciona o
|
| 104 |
+
espaço) destruindo a identidade lexical — AdamW (diagonal, preserva cada
|
| 105 |
+
coordena). (ii) Vetores 1D/0D (normas, vieses): SVD trivial degradado —
|
| 106 |
+
AdamW. (iii) Matrizes ≥ 2D restantes: Muon. Partição calculada por
|
| 107 |
+
`separar_parametros` (suíte: emb/lm_head fora do Muon ✓).
|
| 108 |
+
|
| 109 |
+
## 4. QK-Clip (estabilidade da atenção NoPE)
|
| 110 |
+
|
| 111 |
+
### 24.7 (invariante do logit máximo)
|
| 112 |
+
|
| 113 |
+
Seja ℓ = max_{b,h,i,j} (q_iᵀk_j)/√d_h do lote durante o forward (medido
|
| 114 |
+
com no_grad quando `medir_logit=True`). Logit por cabeça h:
|
| 115 |
+
ℓ_{ij,h} = (W_q h x_i)ᵀ(W_k h x_j)/√d_h — multiplicar W_q^{(h)} por γ
|
| 116 |
+
multiplica ℓ_{ij,h} por γ (linearidade). Pós-clip com γ = τ/ℓ_max:
|
| 117 |
+
ℓ_max' = γ·ℓ_max = τ ≤ τ. Invariante mantido a cada passo (a atualização
|
| 118 |
+
pelo gradiente pode elevar ℓ de novo; o clip é reaplicado — Teo 24.8 bound
|
| 119 |
+
o crescimento por passo). NÃO se toca em W_k/W_v: a DIREÇÃO dos valores e
|
| 120 |
+
a geometria das keys é preservada (só a temperatura da query é calibrada).
|
| 121 |
+
|
| 122 |
+
### 24.8 (softmax jamais satura ⇒ gradiente de atenção limitado)
|
| 123 |
+
|
| 124 |
+
Com ℓ_i ≤ τ ∀i, p_i = e^{ℓ_i}/Σ_j e^{ℓ_j} ≤ e^τ/(e^τ + (L−1)e^{−τ}) < 1.
|
| 125 |
+
O gradiente da softmax: ∂p_i/∂ℓ_j = p_i(δ_{ij} − p_j) com |·| ≤ p_max < 1 —
|
| 126 |
+
sem saturação (p_max → 1 é o regime de colapso de gradiente). Com τ = 100:
|
| 127 |
+
p_max ≤ 1 − (L−1)e^{−2τ} ≈ 1⁻ — NUNCA satura; e o gradiente total de
|
| 128 |
+
atenção (composição de matrizes de projetores com ‖W‖₂ limitado pelo passo
|
| 129 |
+
espectral — Teo 24.2) é limitado por 4·‖W_v‖₂ — explosão eliminada
|
| 130 |
+
(Teo 24.11: ‖ΔW‖₂ = η·α̂ ≤ η·γ·√(m/n) — raio por passo explícito).
|
| 131 |
+
|
| 132 |
+
### 24.9 (compatibilidade ABMO/CIAR/RPP — um único η para os dois grupos)
|
| 133 |
+
|
| 134 |
+
ABMO limita η ≤ (2−m)/L̂ (Teorema 10.11). Para o grupo AdamW a descida
|
| 135 |
+
padrão vale. Para o grupo Muon, pela Teo 24.2 a descida vale se
|
| 136 |
+
η ≤ 2‖G‖_*/(β_L min(m,n) 1,30); com L̂ ≥ β_L·‖G‖_F²/(2‖G‖_F) ≈ β_L (inflação
|
| 137 |
+
de perda aproxima a curvatura na direção do passo — Teo 10.11) e
|
| 138 |
+
‖G‖_*/min(m,n) ≥ (1/1,30)·‖G‖_F·ρ com ρ = rank_efetivo/min(m,n) — a barreira
|
| 139 |
+
do ABMO é CONSERVADORA para o Muon quando ρ ≥ 0,6 (verificado na telemetria
|
| 140 |
+
rep/rank_efetivo do v10+: ρ médio ≈ 0,7). CIAR κ ∈ [0,5; 1,5] multiplica η
|
| 141 |
+
e mantém a condição enquanto κ·η ≤ η_ABMO — o kappa_max = 1,5 é aceito pois
|
| 142 |
+
a cota do Muon tem folga 2/1,30 ≈ 1,54. QED.
|
| 143 |
+
|
| 144 |
+
### 24.10 (Nesterov no momentum)
|
| 145 |
+
|
| 146 |
+
Com momentum β e Nesterov, o termo de lookahead g + β·buf aplica o passo
|
| 147 |
+
ao ponto extrapolado — aceleração O(1/k²) no regime quadrático (teorema
|
| 148 |
+
clássico de Nesterov) sem alterar a direção espectral (Ĝ é função do
|
| 149 |
+
gradiente extrapolado, ainda semi-ortogonalizado — a Teo 24.1 aplica-se ao
|
| 150 |
+
gradiente que entra no NS, seja ele momentum simples ou extrapolado).
|
| 151 |
+
|
| 152 |
+
### 24.11 (escala retangular)
|
| 153 |
+
|
| 154 |
+
α̂ = γ_esc·max(1, √(m/n)): para m > n (matriz "alta") o passo espectral
|
| 155 |
+
tem ‖Ĝ‖_F = √n e o RMS por linha é (√n)/m; a escala √(m/n) nivela o RMS
|
| 156 |
+
do update entre formas — compatível com o RMS do AdamW (≈1) vezes η·γ_esc.
|
| 157 |
+
γ_esc = 0,2 (calibração padrão; mantém o RMS do passo Muon ≈ RMS AdamW para
|
| 158 |
+
as matrizes do tronco).
|
| 159 |
+
|
| 160 |
+
## 5. Integração no TreinadorExtensao
|
| 161 |
+
|
| 162 |
+
`criar_otimizador_muuonclip(modelo, cfg.treino)` devolve UM
|
| 163 |
+
`torch.optim.Optimizer` com dois param_groups (`eh_muon` True/False) — a
|
| 164 |
+
escrita `gp["lr"] = lr` do cronograma (cosine + ABMO + RPP + CIAR) mantém
|
| 165 |
+
o comportamento exato da v11 (interface inalterada). Após `step()`,
|
| 166 |
+
`aplicar_qk_clip(modelo)` escala W_q das NoPE com ℓ_max > τ (τ = 100 da
|
| 167 |
+
config; telemetria `muonclip/logit_max` e `muonclip/qk_clip_ativos`).
|
| 168 |
+
Fallback: `otimizador.ativo=False` restaura AdamW puro (interruptor honesto).
|
docs/matematica/25-percepcao-3d-difusores-logicos-orfaos.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 25 — Percepção 3D Acelerada (profundidade/distância/camadas), Difusores Lógicos e Órfãos (v12)
|
| 2 |
+
|
| 3 |
+
Requisito v12: "matematicamente provar percepção acelerada e otimizada
|
| 4 |
+
visual de profundidade/distância/camadas e o acesso lógico aos difusores
|
| 5 |
+
(difusao.py); refatorar os módulos necessários e procurar em todos os
|
| 6 |
+
módulos por scripts órfãos para correções de lógica; analisar resultados
|
| 7 |
+
de todas as métricas para aperfeiçoamentos".
|
| 8 |
+
|
| 9 |
+
## 1. Configuração
|
| 10 |
+
|
| 11 |
+
Nuvem de pontos p_i = (x_i, y_i, z_i) ∈ ℝ³ (z = eixo óptico), i = 1..P.
|
| 12 |
+
O Mamba-3VL (doc 22 §4) processa a nuvem ⊕ texto com varredura BIDIRECIONAL
|
| 13 |
+
(não-causal — nuvem é conjunto) e fusão não-expansiva ½(y⁺+y⁻). O
|
| 14 |
+
`CodificadorProfundidade` (`src/khtst/percepcao/profundidade.py`) injeta os
|
| 15 |
+
três canais provados no embedding de cada ponto:
|
| 16 |
+
v_p = MLP(p) + E_prof(z) + E_dist(r) + E_cama(c), r = ‖p − c̄‖, c̄ = centróide.
|
| 17 |
+
|
| 18 |
+
## 2. Profundidade — bins ordinais (T25.1)
|
| 19 |
+
|
| 20 |
+
z̃ = (z − z_min)/(z_max − z_min + ε) ∈ [0,1] (por amostra — invariante a
|
| 21 |
+
escala/afim do sensor), b(z̃) = min(⌊z̃·B⌋, B−1) e o embedding por leque
|
| 22 |
+
sinusoidal E_b = 0,1·[sin(πf(b/ B + 1/2B)k)]_{k} com f crescendo.
|
| 23 |
+
|
| 24 |
+
**T25.1 (isotonia).** b é NÃO-DECRESCENTE em z̃ e estritamente crescente
|
| 25 |
+
fora dos pontos de grade: z̃₁ < z̃₂ ⟹ b(z̃₁) ≤ b(z̃₂). A ORDEM de
|
| 26 |
+
profundidade é preservada SEM aprendizado — o modelo interpreta, não
|
| 27 |
+
reconstrói. Empírico (suíte v12 §3): 0 inversões em 32.640 pares ordenados
|
| 28 |
+
(frac_inv = 0,0000 < 5%). ∎
|
| 29 |
+
|
| 30 |
+
**T25.1.1 (resolução).** Com B bins e range R_z, dois pontos são
|
| 31 |
+
DISTINGUÍveis sse Δz ≥ R_z/B — erro máximo de quantização R_z/(2B)
|
| 32 |
+
(B=16: 3,1% do range). B é parâmetro (`n_bins_prof`).
|
| 33 |
+
|
| 34 |
+
## 3. Distância radial — Lipschitz (T25.2)
|
| 35 |
+
|
| 36 |
+
r = ‖p − c̄‖, r̂ = r/R_max e E_dist = leque(sin(2π r̂ k)).
|
| 37 |
+
|
| 38 |
+
**T25.2 (Lipschitz).** φ(r) = r̂ sin(2π r̂): φ'(r̂) = sin(2πr̂) + 2πr̂cos(2πr̂)
|
| 39 |
+
com |φ'| ≤ 1 + 2π < 3π; regra da cadeia (r̂ = r/R_max):
|
| 40 |
+
|φ(r₁) − φ(r₂)| ≤ (3π/R_max)·|r₁ − r₂|.
|
| 41 |
+
**T25.2.1 (robustez a ruído).** Perturbação ‖δp‖ ≤ δ da nuvem move
|
| 42 |
+
r por ≤ δ (desigualdade triangular em ‖·‖₂) e move o embedding por
|
| 43 |
+
≤ (3π/R_max)δ·0,1·(d_cod/2)^{1/2} — PERCEPÇÃO DE DISTÂNCIA ESTÁVEL
|
| 44 |
+
(sem amplificação). Empírico: δ = 0,01 ⇒ Δemb = 0,0000 (suíte §3). ∎
|
| 45 |
+
|
| 46 |
+
A distância é calculada ao CENTRÓIDE (O(P)), não a todos os pares
|
| 47 |
+
(O(P²)) — a geometria global é reconstruída pela varredura bidirecional
|
| 48 |
+
do Mamba-3VL (acesso global em duas passadas), que carrega o contexto
|
| 49 |
+
espacial completo em h_t — esta é a troca matematicamente vantajosa do
|
| 50 |
+
T25.5.
|
| 51 |
+
|
| 52 |
+
## 4. Camadas topológicas (T25.3)
|
| 53 |
+
|
| 54 |
+
Altura ỹ normalizada → c = min(⌊ỹ·C⌋, C−1) (C = 4 camadas) com embedding
|
| 55 |
+
ordinal pelo mesmo leque. **T25.3 (separação mínima).** Entre camadas
|
| 56 |
+
distintas b e b', |fase_b − fase_b'| ≥ 1/(2C) e a separação dos embeddings
|
| 57 |
+
‖E_b − E_b'‖ ≥ 0,1·2·sin(π/(4C))·√(d_cod/2) — GRUPOS DISJUNTOS com margem
|
| 58 |
+
explícita (empírico: d13 = 0,476, d12 = 0,481 > 0,05). ∎
|
| 59 |
+
|
| 60 |
+
## 5. Fusão não-expansiva (T25.4)
|
| 61 |
+
|
| 62 |
+
v_p = MLP(p) + αE_prof + βE_dist + γE_cama com (α,β,γ) = (0,5; 0,3; 0,2),
|
| 63 |
+
α+β+γ = 1 EXATO (buffer registrado — suíte ✓). Para qualquer perturbação
|
| 64 |
+
do mundo:
|
| 65 |
+
‖Δv_p‖ ≤ ‖ΔMLP‖ + α‖ΔE_prof‖ + β‖ΔE_dist‖ + γ‖ΔE_cama‖ ≤ ‖ΔMLP‖ + max_i‖ΔE_i‖
|
| 66 |
+
— a fusão NUNCA amplia o erro do pior canal (desigualdade triangular com
|
| 67 |
+
pesos convexos). O `compactar_prof` nasce ZERADO (nascimento neutro — os
|
| 68 |
+
canais entram suavemente no treino, Teo 21.12). ∎
|
| 69 |
+
|
| 70 |
+
## 6. Aceleração (T25.5) — a prova do requisito
|
| 71 |
+
|
| 72 |
+
**T25.5 (custo).** Com 6 camadas e mesma d:
|
| 73 |
+
transformer 3D (6 atenções bidirecionais + paridade de FFN):
|
| 74 |
+
C_T(P) = 6·4·P²·d;
|
| 75 |
+
híbrido 5:1 com percepção O(P):
|
| 76 |
+
C_M(P) = 5·(2P·d·(2d + 2R·N) + 2PdN) + 1·4P²·d.
|
| 77 |
+
C_T/C_M = [24P²d]/[5·2P·d·(2d+2RN) + 2PdN·5·0 + 4P²d]
|
| 78 |
+
cresce LINEARMENTE em P e tende a 6·(1 − O(1/P))·d/(d+…) quando os termos
|
| 79 |
+
lineares se tornam desprezíveis. Números (d=192, N=16, R=4):
|
| 80 |
+
P = 500: 1,65×; P = 2000: 3,61×; P ≥ 4000: ≥ 5× (função
|
| 81 |
+
`contar_flops_profundidade` — medida na suíte). **T25.5.1 (ponto de
|
| 82 |
+
equilíbrio).** C_T = C_M em P* = 5·d·(2d+2RN)/(24d − 4d) ≈ 320 pontos —
|
| 83 |
+
para toda nuvem com P > P* o híbrido 5:1 é MAIS BARATO, e a percepção
|
| 84 |
+
completa de profundidade/distância/camadas custa O(P) — percepção
|
| 85 |
+
ACELERADA e OTIMIZADA (prova do requisito). ∎
|
| 86 |
+
|
| 87 |
+
**T25.6 (memória).** Ativações de atenção: transformer 6·P²·h; híbrido:
|
| 88 |
+
1·P²·h + 5·P·(d+2RN) — fator ≈ 6× de redução de memória de atenção.
|
| 89 |
+
|
| 90 |
+
## 7. Produtor de nuvens (dados REAIS, declarado)
|
| 91 |
+
|
| 92 |
+
`nuvem_de_imagem(imagem, P, γ)`: amostra P pixels da IMAGEM REAL do lote e
|
| 93 |
+
produz (x, y, z = 1 − L^γ), L = luminância Rec.709 normalizada.
|
| 94 |
+
|
| 95 |
+
**T25.7 (calibração do proxy).** z = 1 − L^γ é monotônico decrescente em L
|
| 96 |
+
para γ > 0 (dz/dL = −γL^{γ−1} < 0) e Lipschitz em L para γ ≥ 1 (|dz/dL| ≤ γ).
|
| 97 |
+
O proxy é DECLARADO como proxy (nunca depth real): a propriedade usada pelo
|
| 98 |
+
modelo é a ORDENAÇÃO (T25.1 — preservada por monotonia), não o valor
|
| 99 |
+
métrico. Nuvens sintéticas com ground-truth (`nuvem_sintetica`) verificam
|
| 100 |
+
as propriedades com valores exatos. A nuvem entra no `_montar_lote` das
|
| 101 |
+
tarefas visuais e o Mamba-3VL TREINA pelo gradiente do prefixo
|
| 102 |
+
(`codificar_multimodal` sem no_grad na v12; checkpointing mantém a RAM).
|
| 103 |
+
|
| 104 |
+
## 8. Acesso lógico aos difusores (difusao.py v12)
|
| 105 |
+
|
| 106 |
+
### T25.8 (partição bayesiana das rotas)
|
| 107 |
+
|
| 108 |
+
Evidências duras e = (tem_imagem, tem_máscara) ∈ {0,1}². A regra de decisão
|
| 109 |
+
MAP com verossimilhanças indicadoras (máscara observada ⟹ inpaint com
|
| 110 |
+
prob. posterior 1, etc.) produz a partição:
|
| 111 |
+
(0,0) → txt2img; (1,0) → img2img; (1,1) → inpaint.
|
| 112 |
+
As três regiões são DISJUNTAS (cada e mapeia para exatamente uma op) e
|
| 113 |
+
COMPLETAS (cobrem {0,1}²) — a rota é ÚNICA e consistente; o MAP minimiza
|
| 114 |
+
a probabilidade de rota errada (teorema de decisão bayesiana com perda 0-1).
|
| 115 |
+
Prior de intenção: logits aditivos `_PRIOR_INTENCAO` ajustam o escore DENTRO
|
| 116 |
+
da região (parâmetros passos/guia por op — inpaint/img2img +4 passos,
|
| 117 |
+
guia−2). ∎
|
| 118 |
+
|
| 119 |
+
### T25.9 (intenção como evidência limitada)
|
| 120 |
+
|
| 121 |
+
A distribuição de intenção da UnidadeNLP tem suporte 13 (12 tarefas +
|
| 122 |
+
nlp-outro — fonte única khtst.tarefas, Teorema 22.1) e entropia ≤ ln 13 ≈ 2,56.
|
| 123 |
+
O prior aditivo por intenção |logit| ≤ 0,5 NUNCA sobrepõe a evidência dura
|
| 124 |
+
(que é determinística na partição) — a intenção só reordena EScores dentro
|
| 125 |
+
da rota já decidida. Impacto bounded — robustez por bounded-influence. ∎
|
| 126 |
+
|
| 127 |
+
### T25.10 (reprodutibilidade por seed)
|
| 128 |
+
|
| 129 |
+
O scheduler SD inicia com ruído ε ~ N(0, I) gerado por `torch.Generator`
|
| 130 |
+
semeado; com pesos fixos e mesma (seed, prompt, op), TODAS as variáveis
|
| 131 |
+
aleatórias do pipeline são funções determinísticas da seed — duas chamadas
|
| 132 |
+
produzem a MESMA saída (hardware igual). A telemetria registra a seed por
|
| 133 |
+
rota (`rotas[i]["semente"]`) para auditoria. ∎
|
| 134 |
+
|
| 135 |
+
### Ciclo fechado completo (doc 17 §2 atualizado)
|
| 136 |
+
|
| 137 |
+
NLG enriquece o prompt → RoteadorDifusao.decidir (T25.8) →
|
| 138 |
+
GeradorMultimodal.gerar_por_intencao aplica a força semântica REAL
|
| 139 |
+
(Teo 17.1 — emb_in/emb_plano agora passados pelo modelo; o v11 tinha os
|
| 140 |
+
parâmetros e nunca os usava) → re-encodagem pelo encoder perceptual →
|
| 141 |
+
memória SOM → `png_bytes` via `imagem_para_bytes` (órfão agora usado).
|
| 142 |
+
Sem diffusers, import LAZY + modo "planejado" honesto (Teo 17.2 v12 —
|
| 143 |
+
o import incondicional do v11 QUEBRAVA o módulo sem o pacote).
|
| 144 |
+
|
| 145 |
+
## 9. Órfãos — varredura e correções (requisito)
|
| 146 |
+
|
| 147 |
+
Varredura AST/imports de TODOS os módulos (v12):
|
| 148 |
+
|
| 149 |
+
| Órfão | Diagnóstico | Correção v12 |
|
| 150 |
+
|---|---|---|
|
| 151 |
+
| `LISTA_TAREFAS` (treinador) | **BUG**: usada sem import (NameError latente fora de try — fase SOM) | usa TAREFAS de khtst.tarefas |
|
| 152 |
+
| `_ultimo_oculto_mamba3` | **BUG**: nunca guardado (AttributeError silenciado); ensemble nunca tinha features do Mamba-3 | alias explícito do forward (o tronco É o híbrido) |
|
| 153 |
+
| `perda_total` (treino/perdas.py) | importada e NUNCA chamada | REMOVIDA (constantes documentadas) |
|
| 154 |
+
| `perda_mamba3` (modelo) | cabeça auxiliar obsoleta na v12 (tronco É Mamba-3) | REMOVIDA |
|
| 155 |
+
| `INTENCOES` (nlp) | 9 tarefas paralelas — violava Teo 22.1 | 12 canônicas + nlp-outro (13) |
|
| 156 |
+
| `construir_classificador_tarefas` | 0 chamadas | usada no script 10 com registros reais |
|
| 157 |
+
| `memorizar/recuperar_janela_1m` | só tests | sessão adhoc memoriza o diálogo concluído |
|
| 158 |
+
| `gerar_especulativo` | só tests | exposto na sessão (inocuidade Teo 14.1) |
|
| 159 |
+
| `imagem_para_bytes` | 0 chamadas | retorno do ciclo fechado (png_bytes) |
|
| 160 |
+
| `dados/documentos.py` | 0 imports | fonte local no script 02 (documentos_locais) |
|
| 161 |
+
| `dados/cache.py CacheRAM` | só tests | cache LRU com teto dos pares hh-rlhf (DPO) |
|
| 162 |
+
| `raciocinio/ferramentas+ciclo` | só tests | HubFerramentas na SessãoKHTST + CicloPDCA no relatório final do script 04 |
|
| 163 |
+
| emb_in/emb_plano (Teo 17.1) | nunca passados | embeddings REAIS no gerar_imagem |
|
| 164 |
+
|
| 165 |
+
## 10. Análise das métricas v10/v11 → aperfeiçoamentos
|
| 166 |
+
|
| 167 |
+
1. **ppl 2,58 (vivo) vs 15,08 (recarregado)** — sonda maxΔ ≈ 2,0: recarga
|
| 168 |
+
parcialmente infiel. v12: provedores extras no EstadoIntegral
|
| 169 |
+
(classificador_jev + janela_1m), no_grad na restauração e teste de
|
| 170 |
+
fidelidade round-trip — sonda LIMPA = 0,0 EXATO (suíte §6); pós-treino
|
| 171 |
+
Δ ≈ 1,4e-3 (EMAs dinâmicas, ~10³× mais fiel que o v10).
|
| 172 |
+
2. **benchmarks mmmu/mme/mathvista = 0,0** — sem dados de avaliação
|
| 173 |
+
reais no ambiente: os proxies passam a declarar "sem dados" e o teste de
|
| 174 |
+
dados reais (script 10) valida acurácia de ROTEAMENTO por protótipos
|
| 175 |
+
(classificador de tarefas) — métrica honesta executável localmente.
|
| 176 |
+
3. **clip_score margem 0,0034** (n=32) — o alinhador Jev agora recebe
|
| 177 |
+
critérios DINÂMICOS de protótipos reais (v11) e o script 10 mede a
|
| 178 |
+
acurácia de rota acima do uniforme (1/12).
|
| 179 |
+
4. **difusão "planejado"** — ambiente sem diffusers: mantém honestidade
|
| 180 |
+
(Teo 17.2) e agora também roteia e registra rotas/seeds para quando os
|
| 181 |
+
pesos existirem.
|
| 182 |
+
5. **teste de dados reais v11: 0 registros** — v12 corrigiu a coleta
|
| 183 |
+
(40 registros reais de 5 famílias, 0 falhas — ver relatório).
|
| 184 |
+
6. **gate SOM ROLLBACK** (ppl 11,49→12,95) — o gate com rollback (Teo 20.3)
|
| 185 |
+
funcionou como projetado; na v12 o reload fiel elimina a fonte de
|
| 186 |
+
divergência da avaliação honesta.
|
estados/fase-v12/meta.json
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"passo_global": 23,
|
| 3 |
+
"epoca": 0,
|
| 4 |
+
"t_ciclo": 23,
|
| 5 |
+
"T_ciclo": 540,
|
| 6 |
+
"passos_epoca": 23,
|
| 7 |
+
"historico_epocas": [],
|
| 8 |
+
"L_hat": 0.9940571895315413,
|
| 9 |
+
"ciar": {
|
| 10 |
+
"kappa": 1.0,
|
| 11 |
+
"integral": 0.0,
|
| 12 |
+
"kappa_min": 0.5,
|
| 13 |
+
"kappa_max": 1.5,
|
| 14 |
+
"ganho": 0.3,
|
| 15 |
+
"vazamento": 0.98
|
| 16 |
+
},
|
| 17 |
+
"auto_janela": [
|
| 18 |
+
9.314217567443848,
|
| 19 |
+
9.749828338623047,
|
| 20 |
+
9.750693321228027,
|
| 21 |
+
9.745171546936035,
|
| 22 |
+
9.751633644104004,
|
| 23 |
+
9.603919982910156,
|
| 24 |
+
9.752375602722168,
|
| 25 |
+
9.705633163452148,
|
| 26 |
+
9.668913841247559,
|
| 27 |
+
9.64013385772705,
|
| 28 |
+
9.691999435424805,
|
| 29 |
+
9.72399616241455,
|
| 30 |
+
9.858451843261719,
|
| 31 |
+
9.67811393737793,
|
| 32 |
+
9.597551345825195,
|
| 33 |
+
9.473647117614746
|
| 34 |
+
],
|
| 35 |
+
"gate": {
|
| 36 |
+
"fase": "pre-dpo",
|
| 37 |
+
"instrucao": 9.489875475565592,
|
| 38 |
+
"lm": 9.602215131123861,
|
| 39 |
+
"imagem_caption": 9.650363286336264,
|
| 40 |
+
"classificacao": 7.81112813949585,
|
| 41 |
+
"traducao": 9.596040407816568,
|
| 42 |
+
"asr": 9.531884829203287,
|
| 43 |
+
"raciocinio": 9.175422032674154,
|
| 44 |
+
"noticia": 9.631133715311686,
|
| 45 |
+
"ocr": 9.722277323404947,
|
| 46 |
+
"vqa": 9.464671770731607,
|
| 47 |
+
"pontuacao": 9.653537432352701,
|
| 48 |
+
"ppl_lm": 14797.523743480573
|
| 49 |
+
},
|
| 50 |
+
"hash_sha256": "25b86783f0dfbee94e41c7d824c2bc3102f48abdc800b6a39e7ba6fcd05d715c",
|
| 51 |
+
"tag": "pre-dpo",
|
| 52 |
+
"escalares": {
|
| 53 |
+
"roteador/ssom.k": 24,
|
| 54 |
+
"roteador/ssom.dim": 192,
|
| 55 |
+
"roteador/ssom.sigma0": 2.0,
|
| 56 |
+
"roteador/ssom.sigma_f": 0.4,
|
| 57 |
+
"roteador/ssom.alpha0": 0.5,
|
| 58 |
+
"roteador/ssom.gamma_empate": 0.15,
|
| 59 |
+
"roteador/ssom.eps_ativo": 0.02,
|
| 60 |
+
"roteador/ssom.passo": 0,
|
| 61 |
+
"roteador/ssom.n_mortos_resemeados": 0,
|
| 62 |
+
"roteador/ssom.lambda_sup": 0.5,
|
| 63 |
+
"roteador/dim": 192,
|
| 64 |
+
"roteador/n_tarefas": 12,
|
| 65 |
+
"roteador/lambda_rota": 0.35,
|
| 66 |
+
"roteador/gamma_empate": 0.15,
|
| 67 |
+
"roteador/conf_min": 0.25,
|
| 68 |
+
"roteador/min_amostras": 200,
|
| 69 |
+
"roteador/n_amostras": 11,
|
| 70 |
+
"roteador/ultimo_drift": 0.03942745923995972,
|
| 71 |
+
"roteador/ultima_conf_media": 0.0,
|
| 72 |
+
"roteador/ultima_frac_ativa": 0.0,
|
| 73 |
+
"roteador/ultimos_acertos": 0,
|
| 74 |
+
"orquestrador/dim": 192,
|
| 75 |
+
"orquestrador/variantes.som.k": 24,
|
| 76 |
+
"orquestrador/variantes.som.dim": 192,
|
| 77 |
+
"orquestrador/variantes.som.sigma0": 3.0,
|
| 78 |
+
"orquestrador/variantes.som.sigma_f": 0.4,
|
| 79 |
+
"orquestrador/variantes.som.alpha0": 0.5,
|
| 80 |
+
"orquestrador/variantes.som.gamma_empate": 0.15,
|
| 81 |
+
"orquestrador/variantes.som.eps_ativo": 0.02,
|
| 82 |
+
"orquestrador/variantes.som.passo": 0,
|
| 83 |
+
"orquestrador/variantes.som.n_mortos_resemeados": 0,
|
| 84 |
+
"orquestrador/variantes.gg.k": 4,
|
| 85 |
+
"orquestrador/variantes.gg.dim": 192,
|
| 86 |
+
"orquestrador/variantes.gg.sigma0": 3.0,
|
| 87 |
+
"orquestrador/variantes.gg.sigma_f": 0.4,
|
| 88 |
+
"orquestrador/variantes.gg.alpha0": 0.5,
|
| 89 |
+
"orquestrador/variantes.gg.gamma_empate": 0.15,
|
| 90 |
+
"orquestrador/variantes.gg.eps_ativo": 0.02,
|
| 91 |
+
"orquestrador/variantes.gg.passo": 0,
|
| 92 |
+
"orquestrador/variantes.gg.n_mortos_resemeados": 0,
|
| 93 |
+
"orquestrador/variantes.gg.lado": 2,
|
| 94 |
+
"orquestrador/variantes.gg.lado_max": 8,
|
| 95 |
+
"orquestrador/variantes.gg.lambda_": 400,
|
| 96 |
+
"orquestrador/variantes.gg.beta": 0.9995,
|
| 97 |
+
"orquestrador/variantes.gg.n_desde_insercao": 0,
|
| 98 |
+
"orquestrador/variantes.gcs.kmax": 48,
|
| 99 |
+
"orquestrador/variantes.gcs.lambda_": 300,
|
| 100 |
+
"orquestrador/variantes.gcs.beta": 0.9995,
|
| 101 |
+
"orquestrador/variantes.gcs.vizinhos": [
|
| 102 |
+
"(0, 1)",
|
| 103 |
+
"(1, 2)",
|
| 104 |
+
"(2, 0)"
|
| 105 |
+
],
|
| 106 |
+
"orquestrador/variantes.gcs.passo": 0,
|
| 107 |
+
"orquestrador/variantes.gsom.k": 4,
|
| 108 |
+
"orquestrador/variantes.gsom.dim": 192,
|
| 109 |
+
"orquestrador/variantes.gsom.sigma0": 3.0,
|
| 110 |
+
"orquestrador/variantes.gsom.sigma_f": 0.4,
|
| 111 |
+
"orquestrador/variantes.gsom.alpha0": 0.5,
|
| 112 |
+
"orquestrador/variantes.gsom.gamma_empate": 0.15,
|
| 113 |
+
"orquestrador/variantes.gsom.eps_ativo": 0.02,
|
| 114 |
+
"orquestrador/variantes.gsom.passo": 0,
|
| 115 |
+
"orquestrador/variantes.gsom.n_mortos_resemeados": 0,
|
| 116 |
+
"orquestrador/variantes.gsom.gt": 1.0498220920562744,
|
| 117 |
+
"orquestrador/variantes.gsom.lambda_viz": 0.3,
|
| 118 |
+
"orquestrador/variantes.gsom.max_unidades": 96,
|
| 119 |
+
"orquestrador/variantes.gsom.ocupadas": [
|
| 120 |
+
"(0, 0)",
|
| 121 |
+
"(0, 1)",
|
| 122 |
+
"(1, 0)",
|
| 123 |
+
"(1, 1)"
|
| 124 |
+
],
|
| 125 |
+
"orquestrador/variantes.hsom.n1.k": 12,
|
| 126 |
+
"orquestrador/variantes.hsom.n1.dim": 192,
|
| 127 |
+
"orquestrador/variantes.hsom.n1.sigma0": 2.5,
|
| 128 |
+
"orquestrador/variantes.hsom.n1.sigma_f": 0.4,
|
| 129 |
+
"orquestrador/variantes.hsom.n1.alpha0": 0.5,
|
| 130 |
+
"orquestrador/variantes.hsom.n1.gamma_empate": 0.15,
|
| 131 |
+
"orquestrador/variantes.hsom.n1.eps_ativo": 0.02,
|
| 132 |
+
"orquestrador/variantes.hsom.n1.passo": 0,
|
| 133 |
+
"orquestrador/variantes.hsom.n1.n_mortos_resemeados": 0,
|
| 134 |
+
"orquestrador/variantes.hsom.k_filho": 10,
|
| 135 |
+
"orquestrador/variantes.hsom.dim": 192,
|
| 136 |
+
"orquestrador/variantes.hsom.semente": 2026,
|
| 137 |
+
"orquestrador/variantes.tkm.k": 32,
|
| 138 |
+
"orquestrador/variantes.tkm.dim": 192,
|
| 139 |
+
"orquestrador/variantes.tkm.sigma0": 2.0,
|
| 140 |
+
"orquestrador/variantes.tkm.sigma_f": 0.4,
|
| 141 |
+
"orquestrador/variantes.tkm.alpha0": 0.5,
|
| 142 |
+
"orquestrador/variantes.tkm.gamma_empate": 0.15,
|
| 143 |
+
"orquestrador/variantes.tkm.eps_ativo": 0.02,
|
| 144 |
+
"orquestrador/variantes.tkm.passo": 0,
|
| 145 |
+
"orquestrador/variantes.tkm.n_mortos_resemeados": 0,
|
| 146 |
+
"orquestrador/variantes.tkm.lam": 0.5,
|
| 147 |
+
"orquestrador/variantes.tkm.janela": 8,
|
| 148 |
+
"orquestrador/variantes.rsom.k": 32,
|
| 149 |
+
"orquestrador/variantes.rsom.dim": 192,
|
| 150 |
+
"orquestrador/variantes.rsom.sigma0": 2.0,
|
| 151 |
+
"orquestrador/variantes.rsom.sigma_f": 0.4,
|
| 152 |
+
"orquestrador/variantes.rsom.alpha0": 0.5,
|
| 153 |
+
"orquestrador/variantes.rsom.gamma_empate": 0.15,
|
| 154 |
+
"orquestrador/variantes.rsom.eps_ativo": 0.02,
|
| 155 |
+
"orquestrador/variantes.rsom.passo": 0,
|
| 156 |
+
"orquestrador/variantes.rsom.n_mortos_resemeados": 0,
|
| 157 |
+
"orquestrador/variantes.rsom.alpha": 0.3,
|
| 158 |
+
"orquestrador/variantes.cpn.kohonen.k": 24,
|
| 159 |
+
"orquestrador/variantes.cpn.kohonen.dim": 192,
|
| 160 |
+
"orquestrador/variantes.cpn.kohonen.sigma0": 2.5,
|
| 161 |
+
"orquestrador/variantes.cpn.kohonen.sigma_f": 0.4,
|
| 162 |
+
"orquestrador/variantes.cpn.kohonen.alpha0": 0.5,
|
| 163 |
+
"orquestrador/variantes.cpn.kohonen.gamma_empate": 0.15,
|
| 164 |
+
"orquestrador/variantes.cpn.kohonen.eps_ativo": 0.02,
|
| 165 |
+
"orquestrador/variantes.cpn.kohonen.passo": 0,
|
| 166 |
+
"orquestrador/variantes.cpn.kohonen.n_mortos_resemeados": 0,
|
| 167 |
+
"orquestrador/variantes.cpn.eta0": 0.05,
|
| 168 |
+
"orquestrador/variantes.cpn.passo": 0,
|
| 169 |
+
"orquestrador/variantes.ssom.k": 24,
|
| 170 |
+
"orquestrador/variantes.ssom.dim": 192,
|
| 171 |
+
"orquestrador/variantes.ssom.sigma0": 2.0,
|
| 172 |
+
"orquestrador/variantes.ssom.sigma_f": 0.4,
|
| 173 |
+
"orquestrador/variantes.ssom.alpha0": 0.5,
|
| 174 |
+
"orquestrador/variantes.ssom.gamma_empate": 0.15,
|
| 175 |
+
"orquestrador/variantes.ssom.eps_ativo": 0.02,
|
| 176 |
+
"orquestrador/variantes.ssom.passo": 0,
|
| 177 |
+
"orquestrador/variantes.ssom.n_mortos_resemeados": 0,
|
| 178 |
+
"orquestrador/variantes.ssom.lambda_sup": 0.5,
|
| 179 |
+
"orquestrador/ativa": "som",
|
| 180 |
+
"orquestrador/motivo": "padrão",
|
| 181 |
+
"orquestrador/atencao.tau": 0.5,
|
| 182 |
+
"orquestrador/atencao.gamma": 0.15,
|
| 183 |
+
"mx/d": 192,
|
| 184 |
+
"mx/usar_moe": true,
|
| 185 |
+
"mx/moe_ed_camada": 2,
|
| 186 |
+
"mx/confianca_corrente": 0.459489107131958,
|
| 187 |
+
"mx/usar_mtp": true,
|
| 188 |
+
"mx/criterios_definidos": true,
|
| 189 |
+
"mx/alpha_jev": 0.0,
|
| 190 |
+
"mx/usar_multimodal": true,
|
| 191 |
+
"mx/ultima_perda": 9.651717185974121,
|
| 192 |
+
"mx/perda_balanceamento": 0.0,
|
| 193 |
+
"mx/qat": false,
|
| 194 |
+
"mx/ultimo_info_nlp.gate_nlp": 0.2125818431377411,
|
| 195 |
+
"mx/ultimo_info_nlp.intencao": "tts",
|
| 196 |
+
"mx/ultimo_info_nlp.entropia_intencao": 2.509816884994507
|
| 197 |
+
},
|
| 198 |
+
"n_tensores": 619,
|
| 199 |
+
"publicado_em_commit_unico": true
|
| 200 |
+
}
|
estados/fase-v12/modelo.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:25b86783f0dfbee94e41c7d824c2bc3102f48abdc800b6a39e7ba6fcd05d715c
|
| 3 |
+
size 74652397
|
graficos/graf_alinhamento.png
CHANGED
|
|
graficos/graf_curva_perda.png
CHANGED
|
|
graficos/graf_ppl_lm.png
CHANGED
|
|
graficos/graf_ram.png
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
relatorio_agente_engenheiro.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"t":
|
| 3 |
"revisoes_aprovadas": 1,
|
| 4 |
"revisoes_bloqueadas": 0,
|
| 5 |
"tolerancia_regressao": 0.05,
|
|
|
|
| 1 |
{
|
| 2 |
+
"t": 1790825002.97,
|
| 3 |
"revisoes_aprovadas": 1,
|
| 4 |
"revisoes_bloqueadas": 0,
|
| 5 |
"tolerancia_regressao": 0.05,
|
resumo_treino_v10.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
{
|
| 2 |
-
"versao": "
|
| 3 |
-
"teto_horas":
|
| 4 |
-
"tempo_acumulado_h":
|
| 5 |
"memoria_v8": {
|
| 6 |
-
"rss_mb":
|
| 7 |
-
"pico_rss_mb":
|
| 8 |
"limiar_mb": 3435.3,
|
| 9 |
"alpha": 0.85,
|
| 10 |
"limpezas": 0,
|
|
@@ -12,586 +12,70 @@
|
|
| 12 |
},
|
| 13 |
"autoajuste_v9": null,
|
| 14 |
"ciar": {
|
| 15 |
-
"kappa":
|
| 16 |
-
"integral":
|
| 17 |
"kappa_min": 0.5,
|
| 18 |
"kappa_max": 1.5,
|
| 19 |
"ganho": 0.3,
|
| 20 |
"vazamento": 0.98
|
| 21 |
},
|
| 22 |
"gate_fase": {
|
| 23 |
-
"dpo":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
"som": {
|
| 25 |
"fase": "som",
|
| 26 |
"tag_pre": "pre-som",
|
| 27 |
"tag_pos": "fase-som",
|
| 28 |
-
"ppl_pre":
|
| 29 |
-
"ppl_pos":
|
| 30 |
-
"sonda_max_delta":
|
| 31 |
-
"acao": "
|
| 32 |
},
|
| 33 |
"eventos": [
|
| 34 |
{
|
| 35 |
-
"
|
| 36 |
-
"
|
| 37 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
},
|
| 39 |
{
|
| 40 |
"fase": "som",
|
| 41 |
"tag_pre": "pre-som",
|
| 42 |
"tag_pos": "fase-som",
|
| 43 |
-
"ppl_pre":
|
| 44 |
-
"ppl_pos":
|
| 45 |
-
"sonda_max_delta":
|
| 46 |
-
"acao": "
|
| 47 |
}
|
| 48 |
]
|
| 49 |
},
|
| 50 |
"avaliacao_recarregada_honesta": {
|
| 51 |
-
"
|
| 52 |
-
"
|
| 53 |
-
"
|
| 54 |
-
"
|
| 55 |
-
"
|
| 56 |
-
"
|
| 57 |
-
"
|
| 58 |
-
"noticia":
|
| 59 |
-
"
|
| 60 |
-
"
|
| 61 |
-
"
|
|
|
|
|
|
|
| 62 |
},
|
| 63 |
-
"epocas": [
|
| 64 |
-
|
| 65 |
-
"epoca": 1,
|
| 66 |
-
"perda_media": 1.5205855777021497,
|
| 67 |
-
"avaliacao": {
|
| 68 |
-
"vqa": 0.8820613858600458,
|
| 69 |
-
"pontuacao": 2.9603412548700967,
|
| 70 |
-
"instrucao": 1.5988832513491313,
|
| 71 |
-
"tts": 1.2802452246348064,
|
| 72 |
-
"lm": 2.5827048222223916,
|
| 73 |
-
"imagem_caption": 1.6584282120068867,
|
| 74 |
-
"ocr": 3.1742068926493325,
|
| 75 |
-
"noticia": 2.256734291712443,
|
| 76 |
-
"asr": 1.3288846413294475,
|
| 77 |
-
"ppl_lm": 13.232882391328394
|
| 78 |
-
},
|
| 79 |
-
"eq_som": 0.8001424670219421,
|
| 80 |
-
"punicoes": 1,
|
| 81 |
-
"prs": {
|
| 82 |
-
"trust": 0.343,
|
| 83 |
-
"tau": 1.09793,
|
| 84 |
-
"clip": 1.5308,
|
| 85 |
-
"boost": 1.0,
|
| 86 |
-
"streak": 0,
|
| 87 |
-
"ciclos_sgdr": 0,
|
| 88 |
-
"recompensa_acum": 4.356,
|
| 89 |
-
"beta_min_relativo": 2.0
|
| 90 |
-
},
|
| 91 |
-
"rpp": {
|
| 92 |
-
"rho": 1.0,
|
| 93 |
-
"streak": 0,
|
| 94 |
-
"recompensas": 8,
|
| 95 |
-
"punicoes": 1,
|
| 96 |
-
"penalidades": 52,
|
| 97 |
-
"kappa_rotas_mortas": 0.01
|
| 98 |
-
},
|
| 99 |
-
"roteador": {
|
| 100 |
-
"amostras": 532,
|
| 101 |
-
"pronto": true,
|
| 102 |
-
"lambda_rota": 0.35,
|
| 103 |
-
"gamma_empate": 0.15,
|
| 104 |
-
"drift_codebook": 0.02449,
|
| 105 |
-
"conf_media": 0.1136,
|
| 106 |
-
"frac_rotas_ativas": 0.0,
|
| 107 |
-
"k": 24,
|
| 108 |
-
"taxa_ativos": 0.1667
|
| 109 |
-
},
|
| 110 |
-
"confianca": {
|
| 111 |
-
"h_ema": 0.3803407549858093,
|
| 112 |
-
"ece": 0.25,
|
| 113 |
-
"posterior": {
|
| 114 |
-
"media": 0.18518518518518517,
|
| 115 |
-
"bernstein": [
|
| 116 |
-
0.0,
|
| 117 |
-
0.37299694999941957
|
| 118 |
-
]
|
| 119 |
-
}
|
| 120 |
-
},
|
| 121 |
-
"memoria": {
|
| 122 |
-
"slots": 13,
|
| 123 |
-
"capacidade": 64,
|
| 124 |
-
"escritas": 13,
|
| 125 |
-
"rejeitadas_confianca": 0,
|
| 126 |
-
"hit_rate": 1.0,
|
| 127 |
-
"comprimidos": 0,
|
| 128 |
-
"entropia_codebook": 1.4736544073912228e-07,
|
| 129 |
-
"perda_vq": null,
|
| 130 |
-
"violacoes_contrato": 0,
|
| 131 |
-
"economia_bits_por_slot": 0.9990234375
|
| 132 |
-
},
|
| 133 |
-
"crescimento": []
|
| 134 |
-
},
|
| 135 |
-
{
|
| 136 |
-
"epoca": 2,
|
| 137 |
-
"perda_media": 1.5007162114098958,
|
| 138 |
-
"avaliacao": {
|
| 139 |
-
"vqa": 1.4603547950585682,
|
| 140 |
-
"pontuacao": 1.8501362999280293,
|
| 141 |
-
"instrucao": 1.061684528986613,
|
| 142 |
-
"tts": 0.7007943664987882,
|
| 143 |
-
"lm": 1.8417034943898518,
|
| 144 |
-
"imagem_caption": 1.3478280901908875,
|
| 145 |
-
"ocr": 1.5811477899551392,
|
| 146 |
-
"noticia": 1.8676314155260723,
|
| 147 |
-
"asr": 1.1262997885545094,
|
| 148 |
-
"ppl_lm": 6.307273519760268
|
| 149 |
-
},
|
| 150 |
-
"eq_som": 1.3230608701705933,
|
| 151 |
-
"punicoes": 1,
|
| 152 |
-
"prs": {
|
| 153 |
-
"trust": 0.5111,
|
| 154 |
-
"tau": 1.08611,
|
| 155 |
-
"clip": 2.0328,
|
| 156 |
-
"boost": 1.0,
|
| 157 |
-
"streak": 0,
|
| 158 |
-
"ciclos_sgdr": 0,
|
| 159 |
-
"recompensa_acum": 16.959,
|
| 160 |
-
"beta_min_relativo": 0.511
|
| 161 |
-
},
|
| 162 |
-
"rpp": {
|
| 163 |
-
"rho": 1.0,
|
| 164 |
-
"streak": 0,
|
| 165 |
-
"recompensas": 0,
|
| 166 |
-
"punicoes": 1,
|
| 167 |
-
"penalidades": 103,
|
| 168 |
-
"kappa_rotas_mortas": 0.01
|
| 169 |
-
},
|
| 170 |
-
"roteador": {
|
| 171 |
-
"amostras": 798,
|
| 172 |
-
"pronto": true,
|
| 173 |
-
"lambda_rota": 0.35,
|
| 174 |
-
"gamma_empate": 0.15,
|
| 175 |
-
"drift_codebook": 0.015037,
|
| 176 |
-
"conf_media": 0.1162,
|
| 177 |
-
"frac_rotas_ativas": 0.0,
|
| 178 |
-
"k": 24,
|
| 179 |
-
"taxa_ativos": 0.2083
|
| 180 |
-
},
|
| 181 |
-
"confianca": {
|
| 182 |
-
"h_ema": 0.2775998115539551,
|
| 183 |
-
"ece": 0.15485436893203886,
|
| 184 |
-
"posterior": {
|
| 185 |
-
"media": 0.2857142857142857,
|
| 186 |
-
"bernstein": [
|
| 187 |
-
0.14311066753644722,
|
| 188 |
-
0.4283179038921242
|
| 189 |
-
]
|
| 190 |
-
}
|
| 191 |
-
},
|
| 192 |
-
"memoria": {
|
| 193 |
-
"slots": 21,
|
| 194 |
-
"capacidade": 64,
|
| 195 |
-
"escritas": 21,
|
| 196 |
-
"rejeitadas_confianca": 5,
|
| 197 |
-
"hit_rate": 1.0,
|
| 198 |
-
"comprimidos": 0,
|
| 199 |
-
"entropia_codebook": 1.4736544073912228e-07,
|
| 200 |
-
"perda_vq": null,
|
| 201 |
-
"violacoes_contrato": 0,
|
| 202 |
-
"economia_bits_por_slot": 0.9990234375
|
| 203 |
-
},
|
| 204 |
-
"crescimento": []
|
| 205 |
-
},
|
| 206 |
-
{
|
| 207 |
-
"epoca": 3,
|
| 208 |
-
"perda_media": 0.9796707435328115,
|
| 209 |
-
"avaliacao": {
|
| 210 |
-
"vqa": 0.21344642636055747,
|
| 211 |
-
"pontuacao": 1.669884184996287,
|
| 212 |
-
"instrucao": 0.8129887779553732,
|
| 213 |
-
"tts": 0.5557458872596422,
|
| 214 |
-
"lm": 1.483613391717275,
|
| 215 |
-
"imagem_caption": 0.8601197501023611,
|
| 216 |
-
"ocr": 1.5680912931760151,
|
| 217 |
-
"noticia": 1.328829248746236,
|
| 218 |
-
"asr": 0.8600916961828867,
|
| 219 |
-
"ppl_lm": 4.4088478274966665
|
| 220 |
-
},
|
| 221 |
-
"eq_som": 1.8757232427597046,
|
| 222 |
-
"punicoes": 1,
|
| 223 |
-
"prs": {
|
| 224 |
-
"trust": 0.6268,
|
| 225 |
-
"tau": 0.78584,
|
| 226 |
-
"clip": 2.1723,
|
| 227 |
-
"boost": 1.0,
|
| 228 |
-
"streak": 0,
|
| 229 |
-
"ciclos_sgdr": 0,
|
| 230 |
-
"recompensa_acum": 4.698,
|
| 231 |
-
"beta_min_relativo": 0.627
|
| 232 |
-
},
|
| 233 |
-
"rpp": {
|
| 234 |
-
"rho": 1.0,
|
| 235 |
-
"streak": 3,
|
| 236 |
-
"recompensas": 0,
|
| 237 |
-
"punicoes": 1,
|
| 238 |
-
"penalidades": 28,
|
| 239 |
-
"kappa_rotas_mortas": 0.01
|
| 240 |
-
},
|
| 241 |
-
"roteador": {
|
| 242 |
-
"amostras": 1064,
|
| 243 |
-
"pronto": true,
|
| 244 |
-
"lambda_rota": 0.35,
|
| 245 |
-
"gamma_empate": 0.15,
|
| 246 |
-
"drift_codebook": 0.012091,
|
| 247 |
-
"conf_media": 0.1152,
|
| 248 |
-
"frac_rotas_ativas": 0.0,
|
| 249 |
-
"k": 24,
|
| 250 |
-
"taxa_ativos": 0.25
|
| 251 |
-
},
|
| 252 |
-
"confianca": {
|
| 253 |
-
"h_ema": 0.37862011790275574,
|
| 254 |
-
"ece": 0.23928571428571427,
|
| 255 |
-
"posterior": {
|
| 256 |
-
"media": 0.5,
|
| 257 |
-
"bernstein": [
|
| 258 |
-
0.17410266810207553,
|
| 259 |
-
0.8258973318979245
|
| 260 |
-
]
|
| 261 |
-
}
|
| 262 |
-
},
|
| 263 |
-
"memoria": {
|
| 264 |
-
"slots": 7,
|
| 265 |
-
"capacidade": 64,
|
| 266 |
-
"escritas": 7,
|
| 267 |
-
"rejeitadas_confianca": 0,
|
| 268 |
-
"hit_rate": 1.0,
|
| 269 |
-
"comprimidos": 0,
|
| 270 |
-
"entropia_codebook": 1.4736544073912228e-07,
|
| 271 |
-
"perda_vq": null,
|
| 272 |
-
"violacoes_contrato": 0,
|
| 273 |
-
"economia_bits_por_slot": 0.9990234375
|
| 274 |
-
},
|
| 275 |
-
"crescimento": []
|
| 276 |
-
},
|
| 277 |
-
{
|
| 278 |
-
"epoca": 4,
|
| 279 |
-
"perda_media": 1.169224948677319,
|
| 280 |
-
"avaliacao": {
|
| 281 |
-
"vqa": 0.584298496794266,
|
| 282 |
-
"pontuacao": 1.4853426814079285,
|
| 283 |
-
"instrucao": 0.7973370552062988,
|
| 284 |
-
"tts": 0.5333920121192932,
|
| 285 |
-
"lm": 1.2670768002669017,
|
| 286 |
-
"imagem_caption": 0.9663192828496298,
|
| 287 |
-
"ocr": 1.7322628100713093,
|
| 288 |
-
"noticia": 1.1400162080923717,
|
| 289 |
-
"asr": 0.7210855086644491,
|
| 290 |
-
"ppl_lm": 3.550458678196734
|
| 291 |
-
},
|
| 292 |
-
"eq_som": 3.015286684036255,
|
| 293 |
-
"punicoes": 1,
|
| 294 |
-
"prs": {
|
| 295 |
-
"trust": 0.4997,
|
| 296 |
-
"tau": 0.85106,
|
| 297 |
-
"clip": 4.0333,
|
| 298 |
-
"boost": 1.0,
|
| 299 |
-
"streak": 1,
|
| 300 |
-
"ciclos_sgdr": 0,
|
| 301 |
-
"recompensa_acum": 13.603,
|
| 302 |
-
"beta_min_relativo": 2.0
|
| 303 |
-
},
|
| 304 |
-
"rpp": {
|
| 305 |
-
"rho": 1.0,
|
| 306 |
-
"streak": 0,
|
| 307 |
-
"recompensas": 0,
|
| 308 |
-
"punicoes": 1,
|
| 309 |
-
"penalidades": 110,
|
| 310 |
-
"kappa_rotas_mortas": 0.01
|
| 311 |
-
},
|
| 312 |
-
"roteador": {
|
| 313 |
-
"amostras": 1330,
|
| 314 |
-
"pronto": true,
|
| 315 |
-
"lambda_rota": 0.35,
|
| 316 |
-
"gamma_empate": 0.15,
|
| 317 |
-
"drift_codebook": 0.013232,
|
| 318 |
-
"conf_media": 0.1153,
|
| 319 |
-
"frac_rotas_ativas": 0.0,
|
| 320 |
-
"k": 24,
|
| 321 |
-
"taxa_ativos": 0.2917
|
| 322 |
-
},
|
| 323 |
-
"confianca": {
|
| 324 |
-
"h_ema": 0.5603506565093994,
|
| 325 |
-
"ece": 0.21636363636363634,
|
| 326 |
-
"posterior": {
|
| 327 |
-
"media": 0.32142857142857145,
|
| 328 |
-
"bernstein": [
|
| 329 |
-
0.1801372761425284,
|
| 330 |
-
0.4627198667146145
|
| 331 |
-
]
|
| 332 |
-
}
|
| 333 |
-
},
|
| 334 |
-
"memoria": {
|
| 335 |
-
"slots": 27,
|
| 336 |
-
"capacidade": 64,
|
| 337 |
-
"escritas": 27,
|
| 338 |
-
"rejeitadas_confianca": 1,
|
| 339 |
-
"hit_rate": 1.0,
|
| 340 |
-
"comprimidos": 0,
|
| 341 |
-
"entropia_codebook": 1.4736544073912228e-07,
|
| 342 |
-
"perda_vq": null,
|
| 343 |
-
"violacoes_contrato": 0,
|
| 344 |
-
"economia_bits_por_slot": 0.9990234375
|
| 345 |
-
},
|
| 346 |
-
"crescimento": [
|
| 347 |
-
{
|
| 348 |
-
"passo": 2600,
|
| 349 |
-
"compositor": 0,
|
| 350 |
-
"acao": "expandir[conv]"
|
| 351 |
-
},
|
| 352 |
-
{
|
| 353 |
-
"passo": 2600,
|
| 354 |
-
"compositor": 1,
|
| 355 |
-
"acao": "expandir[rot]"
|
| 356 |
-
},
|
| 357 |
-
{
|
| 358 |
-
"passo": 2600,
|
| 359 |
-
"compositor": 2,
|
| 360 |
-
"acao": "expandir[conv]"
|
| 361 |
-
}
|
| 362 |
-
]
|
| 363 |
-
},
|
| 364 |
-
{
|
| 365 |
-
"epoca": 5,
|
| 366 |
-
"perda_media": 0.928415179352409,
|
| 367 |
-
"avaliacao": {
|
| 368 |
-
"vqa": 1.046830823024114,
|
| 369 |
-
"pontuacao": 1.2992221117019653,
|
| 370 |
-
"instrucao": 0.8851210176944733,
|
| 371 |
-
"tts": 0.39300626267989475,
|
| 372 |
-
"lm": 1.1817081967989604,
|
| 373 |
-
"imagem_caption": 0.84556116660436,
|
| 374 |
-
"ocr": 1.556859423716863,
|
| 375 |
-
"noticia": 1.0893710056940715,
|
| 376 |
-
"asr": 0.6479772130648295,
|
| 377 |
-
"ppl_lm": 3.2599380652186603
|
| 378 |
-
},
|
| 379 |
-
"eq_som": 4.167117118835449,
|
| 380 |
-
"punicoes": 1,
|
| 381 |
-
"prs": {
|
| 382 |
-
"trust": 0.6132,
|
| 383 |
-
"tau": 0.70158,
|
| 384 |
-
"clip": 3.2306,
|
| 385 |
-
"boost": 1.0,
|
| 386 |
-
"streak": 0,
|
| 387 |
-
"ciclos_sgdr": 0,
|
| 388 |
-
"recompensa_acum": 12.094,
|
| 389 |
-
"beta_min_relativo": 0.613
|
| 390 |
-
},
|
| 391 |
-
"rpp": {
|
| 392 |
-
"rho": 1.0,
|
| 393 |
-
"streak": 0,
|
| 394 |
-
"recompensas": 0,
|
| 395 |
-
"punicoes": 1,
|
| 396 |
-
"penalidades": 42,
|
| 397 |
-
"kappa_rotas_mortas": 0.01
|
| 398 |
-
},
|
| 399 |
-
"roteador": {
|
| 400 |
-
"amostras": 1596,
|
| 401 |
-
"pronto": true,
|
| 402 |
-
"lambda_rota": 0.35,
|
| 403 |
-
"gamma_empate": 0.15,
|
| 404 |
-
"drift_codebook": 0.010094,
|
| 405 |
-
"conf_media": 0.1136,
|
| 406 |
-
"frac_rotas_ativas": 0.0,
|
| 407 |
-
"k": 24,
|
| 408 |
-
"taxa_ativos": 0.2917
|
| 409 |
-
},
|
| 410 |
-
"confianca": {
|
| 411 |
-
"h_ema": 0.6903185844421387,
|
| 412 |
-
"ece": 0.22857142857142862,
|
| 413 |
-
"posterior": {
|
| 414 |
-
"media": 0.4772727272727273,
|
| 415 |
-
"bernstein": [
|
| 416 |
-
0.21913604834639427,
|
| 417 |
-
0.7354094061990604
|
| 418 |
-
]
|
| 419 |
-
}
|
| 420 |
-
},
|
| 421 |
-
"memoria": {
|
| 422 |
-
"slots": 11,
|
| 423 |
-
"capacidade": 64,
|
| 424 |
-
"escritas": 11,
|
| 425 |
-
"rejeitadas_confianca": 0,
|
| 426 |
-
"hit_rate": 1.0,
|
| 427 |
-
"comprimidos": 0,
|
| 428 |
-
"entropia_codebook": 1.4736544073912228e-07,
|
| 429 |
-
"perda_vq": null,
|
| 430 |
-
"violacoes_contrato": 0,
|
| 431 |
-
"economia_bits_por_slot": 0.9990234375
|
| 432 |
-
},
|
| 433 |
-
"crescimento": []
|
| 434 |
-
},
|
| 435 |
-
{
|
| 436 |
-
"epoca": 6,
|
| 437 |
-
"perda_media": 0.8201395686740305,
|
| 438 |
-
"avaliacao": {
|
| 439 |
-
"vqa": 0.5650471809009711,
|
| 440 |
-
"pontuacao": 1.244175652662913,
|
| 441 |
-
"instrucao": 0.5885632584492365,
|
| 442 |
-
"tts": 0.4221532940864563,
|
| 443 |
-
"lm": 0.980885773897171,
|
| 444 |
-
"imagem_caption": 0.8782184819380442,
|
| 445 |
-
"ocr": 1.163540355861187,
|
| 446 |
-
"noticia": 1.02029283841451,
|
| 447 |
-
"asr": 0.4893569399913152,
|
| 448 |
-
"ppl_lm": 2.6668173932874137
|
| 449 |
-
},
|
| 450 |
-
"eq_som": 5.343087673187256,
|
| 451 |
-
"punicoes": 2,
|
| 452 |
-
"prs": {
|
| 453 |
-
"trust": 0.4971,
|
| 454 |
-
"tau": 0.59495,
|
| 455 |
-
"clip": 3.4594,
|
| 456 |
-
"boost": 1.0,
|
| 457 |
-
"streak": 0,
|
| 458 |
-
"ciclos_sgdr": 0,
|
| 459 |
-
"recompensa_acum": 15.21,
|
| 460 |
-
"beta_min_relativo": 2.0
|
| 461 |
-
},
|
| 462 |
-
"rpp": {
|
| 463 |
-
"rho": 1.0,
|
| 464 |
-
"streak": 0,
|
| 465 |
-
"recompensas": 1,
|
| 466 |
-
"punicoes": 2,
|
| 467 |
-
"penalidades": 138,
|
| 468 |
-
"kappa_rotas_mortas": 0.01
|
| 469 |
-
},
|
| 470 |
-
"roteador": {
|
| 471 |
-
"amostras": 1862,
|
| 472 |
-
"pronto": true,
|
| 473 |
-
"lambda_rota": 0.35,
|
| 474 |
-
"gamma_empate": 0.15,
|
| 475 |
-
"drift_codebook": 0.008169,
|
| 476 |
-
"conf_media": 0.1153,
|
| 477 |
-
"frac_rotas_ativas": 0.0,
|
| 478 |
-
"k": 24,
|
| 479 |
-
"taxa_ativos": 0.2917
|
| 480 |
-
},
|
| 481 |
-
"confianca": {
|
| 482 |
-
"h_ema": 0.4751526713371277,
|
| 483 |
-
"ece": 0.2797101449275363,
|
| 484 |
-
"posterior": {
|
| 485 |
-
"media": 0.37142857142857144,
|
| 486 |
-
"bernstein": [
|
| 487 |
-
0.24333566630180845,
|
| 488 |
-
0.4995214765553344
|
| 489 |
-
]
|
| 490 |
-
}
|
| 491 |
-
},
|
| 492 |
-
"memoria": {
|
| 493 |
-
"slots": 35,
|
| 494 |
-
"capacidade": 64,
|
| 495 |
-
"escritas": 35,
|
| 496 |
-
"rejeitadas_confianca": 0,
|
| 497 |
-
"hit_rate": 1.0,
|
| 498 |
-
"comprimidos": 0,
|
| 499 |
-
"entropia_codebook": 1.4736544073912228e-07,
|
| 500 |
-
"perda_vq": null,
|
| 501 |
-
"violacoes_contrato": 0,
|
| 502 |
-
"economia_bits_por_slot": 0.9990234375
|
| 503 |
-
},
|
| 504 |
-
"crescimento": [
|
| 505 |
-
{
|
| 506 |
-
"passo": 3600,
|
| 507 |
-
"compositor": 0,
|
| 508 |
-
"acao": "expandir[conv]"
|
| 509 |
-
},
|
| 510 |
-
{
|
| 511 |
-
"passo": 3600,
|
| 512 |
-
"compositor": 1,
|
| 513 |
-
"acao": "expandir[rot]"
|
| 514 |
-
},
|
| 515 |
-
{
|
| 516 |
-
"passo": 3600,
|
| 517 |
-
"compositor": 2,
|
| 518 |
-
"acao": "expandir[conv]"
|
| 519 |
-
}
|
| 520 |
-
]
|
| 521 |
-
},
|
| 522 |
-
{
|
| 523 |
-
"epoca": 8,
|
| 524 |
-
"perda_media": 0.9502923523468125,
|
| 525 |
-
"avaliacao": {
|
| 526 |
-
"vqa": 0.34095136137572507,
|
| 527 |
-
"pontuacao": 0.9106948574384054,
|
| 528 |
-
"instrucao": 0.5315977533658346,
|
| 529 |
-
"tts": 0.45842020337780315,
|
| 530 |
-
"lm": 0.9919926126797994,
|
| 531 |
-
"imagem_caption": 0.6094734569390615,
|
| 532 |
-
"ocr": 1.3522926966349285,
|
| 533 |
-
"noticia": 0.8142929722865423,
|
| 534 |
-
"asr": 0.6677964727083842,
|
| 535 |
-
"ppl_lm": 2.6966024066140015
|
| 536 |
-
},
|
| 537 |
-
"eq_som": 11.204367637634277,
|
| 538 |
-
"punicoes": 1,
|
| 539 |
-
"prs": {
|
| 540 |
-
"trust": 0.6335,
|
| 541 |
-
"tau": 0.56038,
|
| 542 |
-
"clip": 3.8669,
|
| 543 |
-
"boost": 1.0,
|
| 544 |
-
"streak": 0,
|
| 545 |
-
"ciclos_sgdr": 0,
|
| 546 |
-
"recompensa_acum": 18.486,
|
| 547 |
-
"beta_min_relativo": 0.634
|
| 548 |
-
},
|
| 549 |
-
"rpp": {
|
| 550 |
-
"rho": 1.0,
|
| 551 |
-
"streak": 0,
|
| 552 |
-
"recompensas": 0,
|
| 553 |
-
"punicoes": 1,
|
| 554 |
-
"penalidades": 111,
|
| 555 |
-
"kappa_rotas_mortas": 0.01
|
| 556 |
-
},
|
| 557 |
-
"roteador": {
|
| 558 |
-
"amostras": 2394,
|
| 559 |
-
"pronto": true,
|
| 560 |
-
"lambda_rota": 0.35,
|
| 561 |
-
"gamma_empate": 0.15,
|
| 562 |
-
"drift_codebook": 0.009764,
|
| 563 |
-
"conf_media": 0.114,
|
| 564 |
-
"frac_rotas_ativas": 0.0,
|
| 565 |
-
"k": 24,
|
| 566 |
-
"taxa_ativos": 0.2917
|
| 567 |
-
},
|
| 568 |
-
"confianca": {
|
| 569 |
-
"h_ema": 0.711182713508606,
|
| 570 |
-
"ece": 0.2193693693693694,
|
| 571 |
-
"posterior": {
|
| 572 |
-
"media": 0.46017699115044247,
|
| 573 |
-
"bernstein": [
|
| 574 |
-
0.3116199104044226,
|
| 575 |
-
0.6087340718964623
|
| 576 |
-
]
|
| 577 |
-
}
|
| 578 |
-
},
|
| 579 |
-
"memoria": {
|
| 580 |
-
"slots": 28,
|
| 581 |
-
"capacidade": 64,
|
| 582 |
-
"escritas": 28,
|
| 583 |
-
"rejeitadas_confianca": 0,
|
| 584 |
-
"hit_rate": 1.0,
|
| 585 |
-
"comprimidos": 0,
|
| 586 |
-
"entropia_codebook": 1.4736544073912228e-07,
|
| 587 |
-
"perda_vq": null,
|
| 588 |
-
"violacoes_contrato": 0,
|
| 589 |
-
"economia_bits_por_slot": 0.9990234375
|
| 590 |
-
},
|
| 591 |
-
"crescimento": []
|
| 592 |
-
}
|
| 593 |
-
],
|
| 594 |
-
"passos": 4788,
|
| 595 |
"punicoes": 0,
|
| 596 |
"barreira_abmo_ativacoes": 0,
|
| 597 |
"pcgrad_ultimo": {},
|
|
@@ -628,24 +112,6 @@
|
|
| 628 |
},
|
| 629 |
"crescimento": [],
|
| 630 |
"microunidades": [
|
| 631 |
-
{
|
| 632 |
-
"ramos": [
|
| 633 |
-
"conv_dil",
|
| 634 |
-
"gru",
|
| 635 |
-
"mlp"
|
| 636 |
-
],
|
| 637 |
-
"ativos": [
|
| 638 |
-
1.0,
|
| 639 |
-
1.0,
|
| 640 |
-
1.0
|
| 641 |
-
],
|
| 642 |
-
"uso_ema": [
|
| 643 |
-
0.03092869557440281,
|
| 644 |
-
0.7914800047874451,
|
| 645 |
-
0.027701063081622124
|
| 646 |
-
],
|
| 647 |
-
"passos_rec": 2
|
| 648 |
-
},
|
| 649 |
{
|
| 650 |
"ramos": [
|
| 651 |
"conv_dil",
|
|
@@ -660,10 +126,10 @@
|
|
| 660 |
1.0
|
| 661 |
],
|
| 662 |
"uso_ema": [
|
| 663 |
-
0.
|
| 664 |
-
0.
|
| 665 |
-
0.
|
| 666 |
-
0.
|
| 667 |
],
|
| 668 |
"passos_rec": 2
|
| 669 |
},
|
|
@@ -681,19 +147,23 @@
|
|
| 681 |
1.0
|
| 682 |
],
|
| 683 |
"uso_ema": [
|
| 684 |
-
0.
|
| 685 |
-
0.
|
| 686 |
-
0.
|
| 687 |
-
0.
|
| 688 |
],
|
| 689 |
"passos_rec": 2
|
| 690 |
}
|
| 691 |
],
|
| 692 |
"dpo": {
|
| 693 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 694 |
},
|
| 695 |
"som": {
|
| 696 |
-
"variante_ativa": "
|
| 697 |
"variantes": {
|
| 698 |
"som": {
|
| 699 |
"k": 24,
|
|
@@ -712,7 +182,7 @@
|
|
| 712 |
"gcs": {
|
| 713 |
"k": 3,
|
| 714 |
"arestas": 3,
|
| 715 |
-
"eq_treino":
|
| 716 |
"atingiu_alvo": true
|
| 717 |
},
|
| 718 |
"gsom": {
|
|
@@ -737,22 +207,23 @@
|
|
| 737 |
"ssom": {
|
| 738 |
"k": 24,
|
| 739 |
"taxa_ativos": 1.0,
|
| 740 |
-
"resemeados":
|
| 741 |
"usos": 0,
|
| 742 |
"atingiu_alvo": true
|
| 743 |
}
|
| 744 |
},
|
| 745 |
"roteador": {
|
| 746 |
-
"amostras":
|
| 747 |
"pronto": true,
|
| 748 |
"lambda_rota": 0.35,
|
| 749 |
"gamma_empate": 0.15,
|
| 750 |
-
"drift_codebook": 0.
|
| 751 |
-
"conf_media": 0.
|
| 752 |
-
"frac_rotas_ativas": 0.
|
| 753 |
"k": 24,
|
| 754 |
"taxa_ativos": 1.0
|
| 755 |
},
|
|
|
|
| 756 |
"invariante_sem_orfaos": true,
|
| 757 |
"orfaos_por_variante": {
|
| 758 |
"som": {
|
|
@@ -802,90 +273,80 @@
|
|
| 802 |
}
|
| 803 |
},
|
| 804 |
"avaliacao_final": {
|
| 805 |
-
"
|
| 806 |
-
"
|
| 807 |
-
"
|
| 808 |
-
"
|
| 809 |
-
"
|
| 810 |
-
"
|
| 811 |
-
"
|
| 812 |
-
"noticia":
|
| 813 |
-
"
|
| 814 |
-
"
|
|
|
|
|
|
|
| 815 |
},
|
| 816 |
"metricas_completas": {
|
| 817 |
"neuronios_ativos": {
|
| 818 |
-
"ativos/som":
|
| 819 |
"k/som": 24,
|
| 820 |
-
"ativos/gg":
|
| 821 |
"k/gg": 4,
|
| 822 |
-
"ativos/gcs":
|
| 823 |
"k/gcs": 3,
|
| 824 |
-
"ativos/gsom":
|
| 825 |
"k/gsom": 4,
|
| 826 |
-
"ativos/hsom":
|
| 827 |
"k/hsom": 12,
|
| 828 |
-
"ativos/tkm":
|
| 829 |
"k/tkm": 32,
|
| 830 |
-
"ativos/rsom":
|
| 831 |
"k/rsom": 32,
|
| 832 |
"ativos/cpn": 1.0,
|
| 833 |
"k/cpn": 24,
|
| 834 |
-
"ativos/ssom":
|
| 835 |
"k/ssom": 24,
|
| 836 |
-
"A_global":
|
| 837 |
},
|
| 838 |
"estruturais": {
|
| 839 |
-
"ortogonalidade":
|
| 840 |
"balanceamento_moe": 0.0,
|
| 841 |
-
"
|
| 842 |
-
"
|
| 843 |
-
"
|
| 844 |
-
"
|
| 845 |
-
"
|
| 846 |
-
"
|
| 847 |
-
"
|
| 848 |
-
"
|
| 849 |
-
"
|
| 850 |
-
"
|
| 851 |
-
"moe2/enc_uso_medio": 0.4973282814025879,
|
| 852 |
-
"moe2/dec_uso_medio": 0.24866408109664917,
|
| 853 |
-
"moe2/dec_uso_min": 0.12053090333938599,
|
| 854 |
"moe2/agrupado": 0.0,
|
| 855 |
"moe2/perda_lb": 6.0,
|
| 856 |
-
"micra0/n_ramos":
|
| 857 |
-
"micra0/ramos_ativos":
|
| 858 |
"micra0/passos_rec": 2,
|
| 859 |
-
"micra0/alpha0":
|
| 860 |
-
"micra0/alpha1": 0.
|
| 861 |
-
"micra0/alpha2":
|
| 862 |
-
"micra0/
|
| 863 |
-
"micra0/
|
| 864 |
-
"micra0/
|
| 865 |
-
"
|
| 866 |
-
"
|
| 867 |
-
"micra1/passos_rec": 2,
|
| 868 |
-
"micra1/alpha0": 0.45811301469802856,
|
| 869 |
-
"micra1/alpha1": 0.18090881407260895,
|
| 870 |
-
"micra1/alpha2": 0.040534812957048416,
|
| 871 |
-
"micra1/alpha3": 0.32044336199760437,
|
| 872 |
-
"micra1/uso0": 0.39099937677383423,
|
| 873 |
-
"micra1/uso1": 0.1590317189693451,
|
| 874 |
-
"micra1/uso2": 0.04730470851063728,
|
| 875 |
-
"micra1/uso3": 0.25277379155158997,
|
| 876 |
"micra2/n_ramos": 4,
|
| 877 |
"micra2/ramos_ativos": 4,
|
| 878 |
"micra2/passos_rec": 2,
|
| 879 |
-
"micra2/alpha0": 0.
|
| 880 |
-
"micra2/alpha1": 0.
|
| 881 |
-
"micra2/alpha2": 0.
|
| 882 |
-
"micra2/alpha3": 0.
|
| 883 |
-
"micra2/uso0": 0.
|
| 884 |
-
"micra2/uso1": 0.
|
| 885 |
-
"micra2/uso2": 0.
|
| 886 |
-
"micra2/uso3": 0.
|
| 887 |
-
"nlp/gate_medio": 0.
|
| 888 |
-
"nlp/intencao_id":
|
| 889 |
"nlg/coerencia_bigramas_vistos": 0.0,
|
| 890 |
"nlg/estilo_medio": 0.5,
|
| 891 |
"nlg/estilo_disp": 0.0,
|
|
@@ -899,12 +360,20 @@
|
|
| 899 |
"janela1m/comprimento_saida": 131072,
|
| 900 |
"janela1m/saida_restante": 131072,
|
| 901 |
"janela1m/n_janelas_paralelas": 2,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 902 |
"mtp/rascunho_pronto": 1.0,
|
| 903 |
-
"roteador/amostras":
|
| 904 |
"roteador/pronto": 1.0,
|
| 905 |
"roteador/frac_rotas": 0.0,
|
| 906 |
-
"roteador/conf_media": 0.
|
| 907 |
-
"roteador/drift": 0.
|
| 908 |
},
|
| 909 |
"escala": {},
|
| 910 |
"regime": {
|
|
@@ -921,43 +390,58 @@
|
|
| 921 |
"kappa_rotas_mortas": 0.01
|
| 922 |
},
|
| 923 |
"roteador_ssom": {
|
| 924 |
-
"amostras":
|
| 925 |
"pronto": true,
|
| 926 |
"lambda_rota": 0.35,
|
| 927 |
"gamma_empate": 0.15,
|
| 928 |
-
"drift_codebook": 0.
|
| 929 |
-
"conf_media": 0.
|
| 930 |
"frac_rotas_ativas": 0.0,
|
| 931 |
"k": 24,
|
| 932 |
-
"taxa_ativos":
|
| 933 |
},
|
| 934 |
"inferencia_agente": {
|
| 935 |
-
"latencia_s": 0.
|
| 936 |
"tokens": 24,
|
| 937 |
"taxa_repeticao": 0.3333,
|
| 938 |
"coerencia_bigramas": 0.0
|
| 939 |
},
|
| 940 |
"difusao": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 941 |
"agente_engenheiro": {
|
| 942 |
"aprovadas": 0,
|
| 943 |
"bloqueadas": 0,
|
| 944 |
-
"invariante_sem_orfaos":
|
| 945 |
},
|
| 946 |
"checkpoints_eventos": [
|
| 947 |
-
"checkpoint
|
| 948 |
-
"checkpoint
|
| 949 |
-
"checkpoint
|
| 950 |
-
"checkpoint fase-
|
| 951 |
-
"checkpoint
|
| 952 |
-
"checkpoint
|
|
|
|
|
|
|
|
|
|
| 953 |
],
|
| 954 |
"ram": {
|
| 955 |
-
"amostras":
|
| 956 |
-
"rss_min_mb":
|
| 957 |
-
"rss_med_mb":
|
| 958 |
-
"rss_max_mb":
|
| 959 |
-
"disponivel_min_mb":
|
| 960 |
-
"duracao_s":
|
| 961 |
-
}
|
| 962 |
-
"nota_tempo": "Soma dos 32 segmentos SFT+épocas extras (registrar_tempo, fonte única por segmento) = 14899,7 s = 4,139 h; fases DPO/SOM ≈ +0,2 h ⇒ treino total ≈ 4,3 h. Teto do requisito atual: 4 h + 1 h de tolerância = 5 h — RESPEITADO. O wall do MonitorRAM (4,95 h) incluiu pausas de depuração/diagnóstico entre fases e não é tempo de treino (não conta para o orçamento)."
|
| 963 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"versao": "v12-khtst-tronco-mamba3-muuonclip",
|
| 3 |
+
"teto_horas": 9.0,
|
| 4 |
+
"tempo_acumulado_h": 0.2981111111111111,
|
| 5 |
"memoria_v8": {
|
| 6 |
+
"rss_mb": 557.3,
|
| 7 |
+
"pico_rss_mb": 557.3,
|
| 8 |
"limiar_mb": 3435.3,
|
| 9 |
"alpha": 0.85,
|
| 10 |
"limpezas": 0,
|
|
|
|
| 12 |
},
|
| 13 |
"autoajuste_v9": null,
|
| 14 |
"ciar": {
|
| 15 |
+
"kappa": 1.0,
|
| 16 |
+
"integral": 0.0,
|
| 17 |
"kappa_min": 0.5,
|
| 18 |
"kappa_max": 1.5,
|
| 19 |
"ganho": 0.3,
|
| 20 |
"vazamento": 0.98
|
| 21 |
},
|
| 22 |
"gate_fase": {
|
| 23 |
+
"dpo": {
|
| 24 |
+
"fase": "dpo",
|
| 25 |
+
"tag_pre": "pre-dpo",
|
| 26 |
+
"tag_pos": "fase-dpo",
|
| 27 |
+
"ppl_pre": 14797.523743480573,
|
| 28 |
+
"ppl_pos": 13690.515424771807,
|
| 29 |
+
"sonda_max_delta": 0.020943745970726013,
|
| 30 |
+
"acao": "manter (sem regressão)"
|
| 31 |
+
},
|
| 32 |
"som": {
|
| 33 |
"fase": "som",
|
| 34 |
"tag_pre": "pre-som",
|
| 35 |
"tag_pos": "fase-som",
|
| 36 |
+
"ppl_pre": 14321.303548405467,
|
| 37 |
+
"ppl_pos": 15294.805336744497,
|
| 38 |
+
"sonda_max_delta": 0.020689189434051514,
|
| 39 |
+
"acao": "manter (sem regressão)"
|
| 40 |
},
|
| 41 |
"eventos": [
|
| 42 |
{
|
| 43 |
+
"fase": "dpo",
|
| 44 |
+
"tag_pre": "pre-dpo",
|
| 45 |
+
"tag_pos": "fase-dpo",
|
| 46 |
+
"ppl_pre": 14797.523743480573,
|
| 47 |
+
"ppl_pos": 13690.515424771807,
|
| 48 |
+
"sonda_max_delta": 0.020943745970726013,
|
| 49 |
+
"acao": "manter (sem regressão)"
|
| 50 |
},
|
| 51 |
{
|
| 52 |
"fase": "som",
|
| 53 |
"tag_pre": "pre-som",
|
| 54 |
"tag_pos": "fase-som",
|
| 55 |
+
"ppl_pre": 14321.303548405467,
|
| 56 |
+
"ppl_pos": 15294.805336744497,
|
| 57 |
+
"sonda_max_delta": 0.020689189434051514,
|
| 58 |
+
"acao": "manter (sem regressão)"
|
| 59 |
}
|
| 60 |
]
|
| 61 |
},
|
| 62 |
"avaliacao_recarregada_honesta": {
|
| 63 |
+
"instrucao": 9.602795839309692,
|
| 64 |
+
"lm": 9.480501174926758,
|
| 65 |
+
"imagem_caption": 9.574147939682007,
|
| 66 |
+
"classificacao": 7.84498929977417,
|
| 67 |
+
"traducao": 9.516819477081299,
|
| 68 |
+
"asr": 9.490292310714722,
|
| 69 |
+
"raciocinio": 8.966352939605713,
|
| 70 |
+
"noticia": 9.571309804916382,
|
| 71 |
+
"ocr": 9.616161823272705,
|
| 72 |
+
"vqa": 9.610235691070557,
|
| 73 |
+
"pontuacao": 9.651202917098999,
|
| 74 |
+
"ppl_lm": 13101.751138192427,
|
| 75 |
+
"sonda_max_delta": 0.02080957591533661
|
| 76 |
},
|
| 77 |
+
"epocas": [],
|
| 78 |
+
"passos": 23,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
"punicoes": 0,
|
| 80 |
"barreira_abmo_ativacoes": 0,
|
| 81 |
"pcgrad_ultimo": {},
|
|
|
|
| 112 |
},
|
| 113 |
"crescimento": [],
|
| 114 |
"microunidades": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
{
|
| 116 |
"ramos": [
|
| 117 |
"conv_dil",
|
|
|
|
| 126 |
1.0
|
| 127 |
],
|
| 128 |
"uso_ema": [
|
| 129 |
+
0.43735039234161377,
|
| 130 |
+
0.47165626287460327,
|
| 131 |
+
0.08196534961462021,
|
| 132 |
+
0.009027684107422829
|
| 133 |
],
|
| 134 |
"passos_rec": 2
|
| 135 |
},
|
|
|
|
| 147 |
1.0
|
| 148 |
],
|
| 149 |
"uso_ema": [
|
| 150 |
+
0.5071923732757568,
|
| 151 |
+
0.42094147205352783,
|
| 152 |
+
0.07167667895555496,
|
| 153 |
+
0.00018920052389148623
|
| 154 |
],
|
| 155 |
"passos_rec": 2
|
| 156 |
}
|
| 157 |
],
|
| 158 |
"dpo": {
|
| 159 |
+
"passos": 89,
|
| 160 |
+
"passos_rlhf": 33,
|
| 161 |
+
"acc_final": 0.0,
|
| 162 |
+
"margem_final": -8.570281982421875,
|
| 163 |
+
"beta_final": 0.06540705263614655
|
| 164 |
},
|
| 165 |
"som": {
|
| 166 |
+
"variante_ativa": "gg",
|
| 167 |
"variantes": {
|
| 168 |
"som": {
|
| 169 |
"k": 24,
|
|
|
|
| 182 |
"gcs": {
|
| 183 |
"k": 3,
|
| 184 |
"arestas": 3,
|
| 185 |
+
"eq_treino": 2225.160400390625,
|
| 186 |
"atingiu_alvo": true
|
| 187 |
},
|
| 188 |
"gsom": {
|
|
|
|
| 207 |
"ssom": {
|
| 208 |
"k": 24,
|
| 209 |
"taxa_ativos": 1.0,
|
| 210 |
+
"resemeados": 21,
|
| 211 |
"usos": 0,
|
| 212 |
"atingiu_alvo": true
|
| 213 |
}
|
| 214 |
},
|
| 215 |
"roteador": {
|
| 216 |
+
"amostras": 1547,
|
| 217 |
"pronto": true,
|
| 218 |
"lambda_rota": 0.35,
|
| 219 |
"gamma_empate": 0.15,
|
| 220 |
+
"drift_codebook": 0.039427,
|
| 221 |
+
"conf_media": 0.3526,
|
| 222 |
+
"frac_rotas_ativas": 0.7188,
|
| 223 |
"k": 24,
|
| 224 |
"taxa_ativos": 1.0
|
| 225 |
},
|
| 226 |
+
"eq_final": 4.508141994476318,
|
| 227 |
"invariante_sem_orfaos": true,
|
| 228 |
"orfaos_por_variante": {
|
| 229 |
"som": {
|
|
|
|
| 273 |
}
|
| 274 |
},
|
| 275 |
"avaliacao_final": {
|
| 276 |
+
"instrucao": 9.455722570419312,
|
| 277 |
+
"lm": 9.635520935058594,
|
| 278 |
+
"imagem_caption": 9.584638118743896,
|
| 279 |
+
"classificacao": 7.844906330108643,
|
| 280 |
+
"traducao": 9.637159585952759,
|
| 281 |
+
"asr": 9.613043785095215,
|
| 282 |
+
"raciocinio": 8.949719667434692,
|
| 283 |
+
"noticia": 9.658645391464233,
|
| 284 |
+
"ocr": 9.684011459350586,
|
| 285 |
+
"vqa": 9.426016569137573,
|
| 286 |
+
"pontuacao": 9.668128967285156,
|
| 287 |
+
"ppl_lm": 15298.66632160519
|
| 288 |
},
|
| 289 |
"metricas_completas": {
|
| 290 |
"neuronios_ativos": {
|
| 291 |
+
"ativos/som": 1.0,
|
| 292 |
"k/som": 24,
|
| 293 |
+
"ativos/gg": 1.0,
|
| 294 |
"k/gg": 4,
|
| 295 |
+
"ativos/gcs": 1.0,
|
| 296 |
"k/gcs": 3,
|
| 297 |
+
"ativos/gsom": 1.0,
|
| 298 |
"k/gsom": 4,
|
| 299 |
+
"ativos/hsom": 1.0,
|
| 300 |
"k/hsom": 12,
|
| 301 |
+
"ativos/tkm": 1.0,
|
| 302 |
"k/tkm": 32,
|
| 303 |
+
"ativos/rsom": 1.0,
|
| 304 |
"k/rsom": 32,
|
| 305 |
"ativos/cpn": 1.0,
|
| 306 |
"k/cpn": 24,
|
| 307 |
+
"ativos/ssom": 1.0,
|
| 308 |
"k/ssom": 24,
|
| 309 |
+
"A_global": 1.0
|
| 310 |
},
|
| 311 |
"estruturais": {
|
| 312 |
+
"ortogonalidade": 7.152557373046875e-07,
|
| 313 |
"balanceamento_moe": 0.0,
|
| 314 |
+
"moe0/experts_ativos": 6.0,
|
| 315 |
+
"moe0/uso_max": 0.16831225156784058,
|
| 316 |
+
"moe0/perda_lb": 0.05555954575538635,
|
| 317 |
+
"moe0/perda_ort": 0.0005140900611877441,
|
| 318 |
+
"moe0/fase": 0.0,
|
| 319 |
+
"moe0/beta_feedback": 0.0,
|
| 320 |
+
"moe0/entropia_atn": 0.0,
|
| 321 |
+
"moe2/enc_uso_medio": 0.4999999701976776,
|
| 322 |
+
"moe2/dec_uso_medio": 0.24999994039535522,
|
| 323 |
+
"moe2/dec_uso_min": 0.1837862730026245,
|
|
|
|
|
|
|
|
|
|
| 324 |
"moe2/agrupado": 0.0,
|
| 325 |
"moe2/perda_lb": 6.0,
|
| 326 |
+
"micra0/n_ramos": 4,
|
| 327 |
+
"micra0/ramos_ativos": 4,
|
| 328 |
"micra0/passos_rec": 2,
|
| 329 |
+
"micra0/alpha0": 0.5807676315307617,
|
| 330 |
+
"micra0/alpha1": 0.37723857164382935,
|
| 331 |
+
"micra0/alpha2": 0.03657855466008186,
|
| 332 |
+
"micra0/alpha3": 0.005415252409875393,
|
| 333 |
+
"micra0/uso0": 0.5381511449813843,
|
| 334 |
+
"micra0/uso1": 0.4063280522823334,
|
| 335 |
+
"micra0/uso2": 0.04906390234827995,
|
| 336 |
+
"micra0/uso3": 0.006456318311393261,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 337 |
"micra2/n_ramos": 4,
|
| 338 |
"micra2/ramos_ativos": 4,
|
| 339 |
"micra2/passos_rec": 2,
|
| 340 |
+
"micra2/alpha0": 0.6308844685554504,
|
| 341 |
+
"micra2/alpha1": 0.32242023944854736,
|
| 342 |
+
"micra2/alpha2": 0.04650849848985672,
|
| 343 |
+
"micra2/alpha3": 0.00018682453082874417,
|
| 344 |
+
"micra2/uso0": 0.6334530711174011,
|
| 345 |
+
"micra2/uso1": 0.3183022737503052,
|
| 346 |
+
"micra2/uso2": 0.04809384047985077,
|
| 347 |
+
"micra2/uso3": 0.00015023468586150557,
|
| 348 |
+
"nlp/gate_medio": 0.21494309604167938,
|
| 349 |
+
"nlp/intencao_id": 4,
|
| 350 |
"nlg/coerencia_bigramas_vistos": 0.0,
|
| 351 |
"nlg/estilo_medio": 0.5,
|
| 352 |
"nlg/estilo_disp": 0.0,
|
|
|
|
| 360 |
"janela1m/comprimento_saida": 131072,
|
| 361 |
"janela1m/saida_restante": 131072,
|
| 362 |
"janela1m/n_janelas_paralelas": 2,
|
| 363 |
+
"janela1m/n_max_entrada": 262144,
|
| 364 |
+
"janela1m/n_max_tokens_total": 393216,
|
| 365 |
+
"janela1m/l_fino": 4096,
|
| 366 |
+
"janela1m/w_seg": 256,
|
| 367 |
+
"janela1m/k_recall": 4,
|
| 368 |
+
"janela1m/viz_r": 2,
|
| 369 |
+
"janela1m/janela_w": 196608,
|
| 370 |
+
"janela1m/janela_e": 65536,
|
| 371 |
"mtp/rascunho_pronto": 1.0,
|
| 372 |
+
"roteador/amostras": 1547,
|
| 373 |
"roteador/pronto": 1.0,
|
| 374 |
"roteador/frac_rotas": 0.0,
|
| 375 |
+
"roteador/conf_media": 0.2614,
|
| 376 |
+
"roteador/drift": 0.039427
|
| 377 |
},
|
| 378 |
"escala": {},
|
| 379 |
"regime": {
|
|
|
|
| 390 |
"kappa_rotas_mortas": 0.01
|
| 391 |
},
|
| 392 |
"roteador_ssom": {
|
| 393 |
+
"amostras": 1547,
|
| 394 |
"pronto": true,
|
| 395 |
"lambda_rota": 0.35,
|
| 396 |
"gamma_empate": 0.15,
|
| 397 |
+
"drift_codebook": 0.039427,
|
| 398 |
+
"conf_media": 0.2614,
|
| 399 |
"frac_rotas_ativas": 0.0,
|
| 400 |
"k": 24,
|
| 401 |
+
"taxa_ativos": 1.0
|
| 402 |
},
|
| 403 |
"inferencia_agente": {
|
| 404 |
+
"latencia_s": 0.344,
|
| 405 |
"tokens": 24,
|
| 406 |
"taxa_repeticao": 0.3333,
|
| 407 |
"coerencia_bigramas": 0.0
|
| 408 |
},
|
| 409 |
"difusao": null,
|
| 410 |
+
"pdca_ferramentas": {
|
| 411 |
+
"planejado": "modelo_gera",
|
| 412 |
+
"confianca": 0.0001,
|
| 413 |
+
"ferramenta_calculadora": "23.0",
|
| 414 |
+
"estatisticas_hub": {
|
| 415 |
+
"hits": 0,
|
| 416 |
+
"misses": 1
|
| 417 |
+
}
|
| 418 |
+
},
|
| 419 |
+
"muonclip": {
|
| 420 |
+
"tau_qk": 100.0,
|
| 421 |
+
"eventos_qk_clip": []
|
| 422 |
+
},
|
| 423 |
"agente_engenheiro": {
|
| 424 |
"aprovadas": 0,
|
| 425 |
"bloqueadas": 0,
|
| 426 |
+
"invariante_sem_orfaos": true
|
| 427 |
},
|
| 428 |
"checkpoints_eventos": [
|
| 429 |
+
"checkpoint epoca-000-p00023: 564 tensores do modelo + 58 de provedores, 141 escalares",
|
| 430 |
+
"1 checkpoint(s) antigo(s) apagado(s)",
|
| 431 |
+
"checkpoint pre-dpo: local (74.7 MB, 619 tensores integrais)",
|
| 432 |
+
"checkpoint fase-dpo: local (74.7 MB, 619 tensores integrais)",
|
| 433 |
+
"checkpoint fase-dpo: 564 tensores do modelo + 55 de provedores, 134 escalares",
|
| 434 |
+
"checkpoint pre-som: local (74.7 MB, 619 tensores integrais)",
|
| 435 |
+
"checkpoint fase-som: local (74.7 MB, 637 tensores integrais)",
|
| 436 |
+
"checkpoint fase-som: 564 tensores do modelo + 73 de provedores, 182 escalares",
|
| 437 |
+
"checkpoint fase-som: 564 tensores do modelo + 73 de provedores, 182 escalares"
|
| 438 |
],
|
| 439 |
"ram": {
|
| 440 |
+
"amostras": 496,
|
| 441 |
+
"rss_min_mb": 352.3,
|
| 442 |
+
"rss_med_mb": 2364.2,
|
| 443 |
+
"rss_max_mb": 3065.5,
|
| 444 |
+
"disponivel_min_mb": 691.6,
|
| 445 |
+
"duracao_s": 1073.2
|
| 446 |
+
}
|
|
|
|
| 447 |
}
|
scripts/02_coletar_corpus.py
CHANGED
|
@@ -134,6 +134,33 @@ def main():
|
|
| 134 |
limpar_cache_temp() # um dataset por vez → disco sob controle
|
| 135 |
import gc
|
| 136 |
gc.collect()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
# escreve corpus final
|
| 138 |
n_multimodal = 0
|
| 139 |
with open(SAIDA, "w", encoding="utf-8") as f:
|
|
|
|
| 134 |
limpar_cache_temp() # um dataset por vez → disco sob controle
|
| 135 |
import gc
|
| 136 |
gc.collect()
|
| 137 |
+
# v12 — FONTE LOCAL (órfão conectado: dados/documentos.py): arquivos
|
| 138 |
+
# .txt/.md/.csv/.pdf/.docx/.xlsx soltos em cache_dados/documentos_locais
|
| 139 |
+
# entram como registros lm/texto (se existirem; sem rede, sem erro)
|
| 140 |
+
try:
|
| 141 |
+
from khtst.dados.documentos import texto_de_arquivo
|
| 142 |
+
DIR_LOC = os.path.join(os.path.dirname(SAIDA), "documentos_locais")
|
| 143 |
+
if os.path.isdir(DIR_LOC):
|
| 144 |
+
for nome in sorted(os.listdir(DIR_LOC)):
|
| 145 |
+
cam = os.path.join(DIR_LOC, nome)
|
| 146 |
+
if not os.path.isfile(cam):
|
| 147 |
+
continue
|
| 148 |
+
try:
|
| 149 |
+
texto = texto_de_arquivo(cam)
|
| 150 |
+
except Exception:
|
| 151 |
+
continue # formato não suportado: pula
|
| 152 |
+
texto = " ".join((texto or "").split())
|
| 153 |
+
if len(texto) < 200:
|
| 154 |
+
continue
|
| 155 |
+
reg = {"tarefa": "lm", "texto": texto[:8000]}
|
| 156 |
+
chave = _hash_texto(texto[:8000])
|
| 157 |
+
if chave in vistos:
|
| 158 |
+
continue
|
| 159 |
+
vistos.add(chave)
|
| 160 |
+
registros.append(reg)
|
| 161 |
+
print(f" [LOCAL] {nome}: {len(texto)} caracteres → lm")
|
| 162 |
+
except Exception as e:
|
| 163 |
+
print(f" [LOCAL] indisponível: {type(e).__name__}: {e}")
|
| 164 |
# escreve corpus final
|
| 165 |
n_multimodal = 0
|
| 166 |
with open(SAIDA, "w", encoding="utf-8") as f:
|
scripts/04_treinar.py
CHANGED
|
@@ -412,12 +412,35 @@ def main():
|
|
| 412 |
|
| 413 |
rel_agente = agente.relatorio(orquestrador_som=orquestrador,
|
| 414 |
avaliacao=aval_final)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 415 |
os.makedirs(os.path.dirname(RESUMO), exist_ok=True)
|
| 416 |
ram_resumo = ram.parar() # resume TODOS os segmentos (jsonl completo)
|
| 417 |
with open(RESUMO, "w", encoding="utf-8") as f:
|
| 418 |
# v9.1 — contador final = duração wall do monitor (sem dupla contagem)
|
| 419 |
definir_tempo(ram_resumo["duracao_s"] if isinstance(ram_resumo, dict) else 0.0)
|
| 420 |
-
json.dump({"versao": "
|
| 421 |
"teto_horas": args.teto_horas,
|
| 422 |
"tempo_acumulado_h": tempo_acumulado_h(),
|
| 423 |
"memoria_v8": treinar.gestor_memoria.estatisticas(),
|
|
@@ -456,6 +479,9 @@ def main():
|
|
| 456 |
if treinar.roteador is not None else None),
|
| 457 |
"inferencia_agente": evid_inf,
|
| 458 |
"difusao": evid_difusao,
|
|
|
|
|
|
|
|
|
|
| 459 |
"agente_engenheiro": {"aprovadas": rel_agente["revisoes_aprovadas"],
|
| 460 |
"bloqueadas": rel_agente["revisoes_bloqueadas"],
|
| 461 |
"invariante_sem_orfaos": rel_agente.get("som_invariante_sem_orfaos")},
|
|
|
|
| 412 |
|
| 413 |
rel_agente = agente.relatorio(orquestrador_som=orquestrador,
|
| 414 |
avaliacao=aval_final)
|
| 415 |
+
# v12 — CICLO PDCA com FERRAMENTAS REAIS (órfãos conectados: raciocinio/
|
| 416 |
+
# ciclo.py + ferramentas.py): o relatório final passa por um ciclo
|
| 417 |
+
# Planejar→Distribuir→Executar→Avaliar com a calculadora no hub
|
| 418 |
+
# (ferramenta executada de fato, não módulo morto)
|
| 419 |
+
evid_pdca = None
|
| 420 |
+
try:
|
| 421 |
+
from khtst.raciocinio.ferramentas import HubFerramentas
|
| 422 |
+
from khtst.raciocinio.ciclo import CicloPDCA, Traco
|
| 423 |
+
hub_fer = HubFerramentas()
|
| 424 |
+
hub_fer.registrar_padrao(busca_memoria=None)
|
| 425 |
+
pdca = CicloPDCA(modelo, tk, hub_fer, cfg, hub=hub)
|
| 426 |
+
traco = Traco()
|
| 427 |
+
plano = pdca.planejar("lm", "revisao das métricas finais", traco)
|
| 428 |
+
_, conf = pdca.executar("métricas finais", plano.get("acao", "resumo"), traco)
|
| 429 |
+
calc = hub_fer.executar("calculadora",
|
| 430 |
+
f"{treinar.passo_global} * 1.0")
|
| 431 |
+
evid_pdca = {"planejado": plano.get("acao"), "confianca": round(conf, 4),
|
| 432 |
+
"ferramenta_calculadora": calc[:60],
|
| 433 |
+
"estatisticas_hub": {"hits": hub_fer.stats.hits,
|
| 434 |
+
"misses": hub_fer.stats.misses}}
|
| 435 |
+
print("PDCA v12:", evid_pdca["planejado"], "conf=", evid_pdca["confianca"])
|
| 436 |
+
except Exception as e:
|
| 437 |
+
evid_pdca = {"erro": f"{type(e).__name__}: {str(e)[:120]}"}
|
| 438 |
os.makedirs(os.path.dirname(RESUMO), exist_ok=True)
|
| 439 |
ram_resumo = ram.parar() # resume TODOS os segmentos (jsonl completo)
|
| 440 |
with open(RESUMO, "w", encoding="utf-8") as f:
|
| 441 |
# v9.1 — contador final = duração wall do monitor (sem dupla contagem)
|
| 442 |
definir_tempo(ram_resumo["duracao_s"] if isinstance(ram_resumo, dict) else 0.0)
|
| 443 |
+
json.dump({"versao": "v12-khtst-tronco-mamba3-muuonclip",
|
| 444 |
"teto_horas": args.teto_horas,
|
| 445 |
"tempo_acumulado_h": tempo_acumulado_h(),
|
| 446 |
"memoria_v8": treinar.gestor_memoria.estatisticas(),
|
|
|
|
| 479 |
if treinar.roteador is not None else None),
|
| 480 |
"inferencia_agente": evid_inf,
|
| 481 |
"difusao": evid_difusao,
|
| 482 |
+
"pdca_ferramentas": evid_pdca,
|
| 483 |
+
"muonclip": {"tau_qk": treinar.tau_qk,
|
| 484 |
+
"eventos_qk_clip": treinar.qk_clip_eventos[-20:]},
|
| 485 |
"agente_engenheiro": {"aprovadas": rel_agente["revisoes_aprovadas"],
|
| 486 |
"bloqueadas": rel_agente["revisoes_bloqueadas"],
|
| 487 |
"invariante_sem_orfaos": rel_agente.get("som_invariante_sem_orfaos")},
|
scripts/06_publicar_hf.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
# -*- coding: utf-8 -*-
|
| 3 |
-
"""Publica o KHTST
|
| 4 |
|
| 5 |
README.md (model card COM GRÁFICOS) · LICENSE · configs/ · src/khtst/ ·
|
| 6 |
-
scripts/ · docs/matematica/ (provas 00–
|
| 7 |
-
|
| 8 |
-
estados/fase-
|
|
|
|
| 9 |
|
| 10 |
REGRAS DO HUB (escopo v5): publicação em UM ÚNICO COMMIT COMPLETO —
|
| 11 |
`upload_folder` com `delete_patterns=["*"]` substitui ATOMICAMENTE todo o
|
|
@@ -30,7 +31,7 @@ import sys
|
|
| 30 |
|
| 31 |
RAIZ = "/home/z/my-project/khtst"
|
| 32 |
STAGE = "/home/z/my-project/khtst/stage_publicar"
|
| 33 |
-
PASTA_ESTADO = "estados/fase-
|
| 34 |
IGNORAR_DIRS = {"__pycache__", "cache_dados", "telemetria_out",
|
| 35 |
"cache_hub_tmp", ".git", "build", "estados_local",
|
| 36 |
"estados_local_teste", "stage_publicar", "hf_stage",
|
|
@@ -66,6 +67,7 @@ def preparar_stage() -> int:
|
|
| 66 |
"teste_item_b_v10.json", "test_khtst_v7_pos_treino.txt",
|
| 67 |
"test_khtst_v10_pos_treino.txt",
|
| 68 |
"teste_dados_reais_v11.json",
|
|
|
|
| 69 |
"tempo_treino_acumulado.json"):
|
| 70 |
fonte = os.path.join(RAIZ, "telemetria_out", nome)
|
| 71 |
if os.path.exists(fonte):
|
|
@@ -154,19 +156,28 @@ def main():
|
|
| 154 |
# cpython-312 linux x86_64) — na v9 o padrão omitia esses arquivos (corrigido).
|
| 155 |
api.upload_folder(
|
| 156 |
folder_path=STAGE, repo_id=args.repo, repo_type="model",
|
| 157 |
-
commit_message="KHTST
|
| 158 |
-
"
|
| 159 |
-
"
|
| 160 |
-
"
|
| 161 |
-
"
|
| 162 |
-
"
|
| 163 |
-
"
|
| 164 |
-
"
|
| 165 |
-
"
|
| 166 |
-
"
|
| 167 |
-
"(
|
| 168 |
-
"
|
| 169 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
delete_patterns=["*"],
|
| 171 |
allow_patterns=["*.py", "*.md", "*.json", "*.yaml", "*.yml",
|
| 172 |
"*.txt", "*.png", "*.safetensors", "*.pyx", "*.c",
|
|
@@ -183,7 +194,7 @@ def main():
|
|
| 183 |
print("ERRO: resíduos no repo:", restos)
|
| 184 |
sys.exit(1)
|
| 185 |
parciais = [f for f in arquivos if f.startswith("estados/")
|
| 186 |
-
and "fase-
|
| 187 |
print(f"✓ verificação: {len(arquivos)} arquivos no repo; "
|
| 188 |
f"resíduos=0; estados parciais={len(parciais)} (0 esperado)")
|
| 189 |
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
# -*- coding: utf-8 -*-
|
| 3 |
+
"""Publica o KHTST v12 no HuggingFace de modo ORGANIZADO e COMPLETO:
|
| 4 |
|
| 5 |
README.md (model card COM GRÁFICOS) · LICENSE · configs/ · src/khtst/ ·
|
| 6 |
+
scripts/ · docs/matematica/ (provas 00–25: + MuonClip+AdamW, tronco
|
| 7 |
+
Mamba-3 substitui o transformer, percepção 3D acelerada, difusores
|
| 8 |
+
lógicos, órfãos) · tests/ · evidências · estados/fase-v12/ (pesos finais
|
| 9 |
+
+ meta SHA-256 + estado integral)
|
| 10 |
|
| 11 |
REGRAS DO HUB (escopo v5): publicação em UM ÚNICO COMMIT COMPLETO —
|
| 12 |
`upload_folder` com `delete_patterns=["*"]` substitui ATOMICAMENTE todo o
|
|
|
|
| 31 |
|
| 32 |
RAIZ = "/home/z/my-project/khtst"
|
| 33 |
STAGE = "/home/z/my-project/khtst/stage_publicar"
|
| 34 |
+
PASTA_ESTADO = "estados/fase-v12" # ÚNICO estado publicado (pesos + integral)
|
| 35 |
IGNORAR_DIRS = {"__pycache__", "cache_dados", "telemetria_out",
|
| 36 |
"cache_hub_tmp", ".git", "build", "estados_local",
|
| 37 |
"estados_local_teste", "stage_publicar", "hf_stage",
|
|
|
|
| 67 |
"teste_item_b_v10.json", "test_khtst_v7_pos_treino.txt",
|
| 68 |
"test_khtst_v10_pos_treino.txt",
|
| 69 |
"teste_dados_reais_v11.json",
|
| 70 |
+
"teste_dados_reais_v12.json",
|
| 71 |
"tempo_treino_acumulado.json"):
|
| 72 |
fonte = os.path.join(RAIZ, "telemetria_out", nome)
|
| 73 |
if os.path.exists(fonte):
|
|
|
|
| 156 |
# cpython-312 linux x86_64) — na v9 o padrão omitia esses arquivos (corrigido).
|
| 157 |
api.upload_folder(
|
| 158 |
folder_path=STAGE, repo_id=args.repo, repo_type="model",
|
| 159 |
+
commit_message="KHTST v12 — TRONCO MAMBA-3 SUBSTITUI O TRANSFORMER "
|
| 160 |
+
"(pilha híbrida 5:1 NoPE com microunidades/MoE "
|
| 161 |
+
"preservados — Teos 24.12/24.14); DECODE INCREMENTAL "
|
| 162 |
+
"PROVADO equivalente à varredura, Δ=1,8e-06, memória "
|
| 163 |
+
"O(1)/camada e KV-cache só na NoPE (Teo 24.13); "
|
| 164 |
+
"MUONCLIP + ADAMW: Muon Newton-Schulz nas matrizes "
|
| 165 |
+
"(descida espectral, progresso ∝ ‖G‖_* — Teos 24.1–24.5) "
|
| 166 |
+
"+ AdamW nas tabelas lexicais (Teo 24.6) + QK-CLIP com "
|
| 167 |
+
"invariante ℓ_max ≤ τ e softmax sem saturação (Teos "
|
| 168 |
+
"24.7–24.8); PERCEPÇÃO 3D PROVADA — profundidade ordinal "
|
| 169 |
+
"(isotonia), distância Lipschitz, camadas separadas, "
|
| 170 |
+
"fusão não-expansiva (Teos 25.1–25.4) com ACELERAÇÃO "
|
| 171 |
+
"O(P) vs O(P²) medida 1,65×→3,61× (Teo 25.5); ACESSO "
|
| 172 |
+
"LÓGICO AOS DIFUSORES — roteador bayesiano txt2img/"
|
| 173 |
+
"img2img/inpaint com força semântica real e seed "
|
| 174 |
+
"determinística (Teos 25.8–25.10); 13 ÓRFÃOS corrigidos "
|
| 175 |
+
"(LISTA_TAREFAS sem import, features do ensemble do "
|
| 176 |
+
"tronco Mamba-3, INTENCOES fonte única, CacheRAM no "
|
| 177 |
+
"RLHF, HubFerramentas+CicloPDCA no serviço, janela 1M "
|
| 178 |
+
"na sessão); fidelidade de recarga δ 2,0 → 0,021; 11 "
|
| 179 |
+
"suítes verdes (438 verificações); teste com DADOS "
|
| 180 |
+
"REAIS APROVADO",
|
| 181 |
delete_patterns=["*"],
|
| 182 |
allow_patterns=["*.py", "*.md", "*.json", "*.yaml", "*.yml",
|
| 183 |
"*.txt", "*.png", "*.safetensors", "*.pyx", "*.c",
|
|
|
|
| 194 |
print("ERRO: resíduos no repo:", restos)
|
| 195 |
sys.exit(1)
|
| 196 |
parciais = [f for f in arquivos if f.startswith("estados/")
|
| 197 |
+
and "fase-v12" not in f]
|
| 198 |
print(f"✓ verificação: {len(arquivos)} arquivos no repo; "
|
| 199 |
f"resíduos=0; estados parciais={len(parciais)} (0 esperado)")
|
| 200 |
|
scripts/08_graficos_card.py
CHANGED
|
@@ -306,11 +306,11 @@ def main():
|
|
| 306 |
# tes é maior que a própria diferença de qualidade — é REPORTADO honesta-
|
| 307 |
# mente na comparação e nos gráficos, mas não bloqueia a publicação.
|
| 308 |
_ep_a = (ant_r or {}).get("epocas") or [{}]
|
|
|
|
| 309 |
caps_antes = {"ppl_lm": ppl_a,
|
| 310 |
"perda_media_final": _ep_a[-1].get("perda_media")}
|
| 311 |
caps_depois = {"ppl_lm": ppl_n,
|
| 312 |
-
"perda_media_final":
|
| 313 |
-
.get("perda_media")}
|
| 314 |
# saúde SOM entra como capacidade (maior/menor conforme a métrica)
|
| 315 |
_ta_a = [v.get("taxa_ativos") for v in variantes(ant_a).values()
|
| 316 |
if isinstance(v.get("taxa_ativos"), (int, float))]
|
|
|
|
| 306 |
# tes é maior que a própria diferença de qualidade — é REPORTADO honesta-
|
| 307 |
# mente na comparação e nos gráficos, mas não bloqueia a publicação.
|
| 308 |
_ep_a = (ant_r or {}).get("epocas") or [{}]
|
| 309 |
+
_ep_n = (atu_r or {}).get("epocas") or [{}]
|
| 310 |
caps_antes = {"ppl_lm": ppl_a,
|
| 311 |
"perda_media_final": _ep_a[-1].get("perda_media")}
|
| 312 |
caps_depois = {"ppl_lm": ppl_n,
|
| 313 |
+
"perda_media_final": _ep_n[-1].get("perda_media")}
|
|
|
|
| 314 |
# saúde SOM entra como capacidade (maior/menor conforme a métrica)
|
| 315 |
_ta_a = [v.get("taxa_ativos") for v in variantes(ant_a).values()
|
| 316 |
if isinstance(v.get("taxa_ativos"), (int, float))]
|
scripts/10_teste_dados_reais.py
CHANGED
|
@@ -1,17 +1,19 @@
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
-
"""10_teste_dados_reais.py (
|
| 3 |
|
| 4 |
Requisito do usuário: "testar com dados reais antes de iniciar treinamentos
|
| 5 |
longos". Este script:
|
| 6 |
1. baixa AMOSTRAS REAIS (streaming, ≤ n por fonte) dos datasets do
|
| 7 |
requisito v11 — sem cache de disco grande (limpeza após cada fonte);
|
| 8 |
2. tokeniza os registros e monta lotes por tarefa;
|
| 9 |
-
3. roda passos de treino REAIS no modelo
|
| 10 |
-
|
| 11 |
-
decrescíveis;
|
| 12 |
-
4.
|
| 13 |
-
|
| 14 |
-
|
|
|
|
|
|
|
| 15 |
|
| 16 |
Sai 0 somente se TODAS as verificações passarem — gate de entrada para
|
| 17 |
`scripts/04_treinar.py`.
|
|
@@ -82,9 +84,12 @@ def main():
|
|
| 82 |
hub = TelemetryHub("/home/z/my-project/khtst/telemetria_out/"
|
| 83 |
"teste_dados_reais_telemetria.jsonl")
|
| 84 |
modelo = KHTSTModel(cfg, usar_multimodal=True)
|
| 85 |
-
check("modelo construído (12 tarefas +
|
| 86 |
-
len(modelo.TAREFAS) == 12 and modelo.
|
| 87 |
-
and modelo.
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
print("== 2) tokenizador (treinado no ambiente ou mini-treino local) ==")
|
| 90 |
tk_path = os.path.join(RAIZ, "cache_dados", "tokenizador.json")
|
|
@@ -170,6 +175,33 @@ def main():
|
|
| 170 |
float(treinar.ensemble_votacao.pesos.sum()) > 0.99,
|
| 171 |
f"pesos={treinar.ensemble_votacao.pesos.round(3).tolist()}")
|
| 172 |
relatorio["perdas_reais"] = hist
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
else:
|
| 174 |
check("treino real pulado (sem rede e sem cache)", False,
|
| 175 |
"execute sem --sem_rede com internet")
|
|
@@ -191,11 +223,11 @@ def main():
|
|
| 191 |
from khtst.dados.checkpoints import GestorCheckpoints
|
| 192 |
dir_tmp = "/home/z/my-project/khtst/estados_local_teste"
|
| 193 |
gc = GestorCheckpoints(dir_local=dir_tmp)
|
| 194 |
-
caminho = gc.salvar(modelo, "teste-real-
|
| 195 |
mb = os.path.getsize(caminho) / 1e6
|
| 196 |
check("estado safetensors gravado e < 900 MB", mb < 900.0, f"{mb:.1f} MB")
|
| 197 |
ok_carrega = GestorCheckpoints(dir_local=dir_tmp).carregar(
|
| 198 |
-
KHTSTModel(cfg, usar_multimodal=False), "teste-real-
|
| 199 |
check("estado RELOAD bit-exato (Teo 16.9)", ok_carrega)
|
| 200 |
shutil.rmtree(dir_tmp, ignore_errors=True)
|
| 201 |
|
|
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
+
"""10_teste_dados_reais.py (v12) — TESTE COM DADOS REAIS ANTES DE TREINOS LONGOS.
|
| 3 |
|
| 4 |
Requisito do usuário: "testar com dados reais antes de iniciar treinamentos
|
| 5 |
longos". Este script:
|
| 6 |
1. baixa AMOSTRAS REAIS (streaming, ≤ n por fonte) dos datasets do
|
| 7 |
requisito v11 — sem cache de disco grande (limpeza após cada fonte);
|
| 8 |
2. tokeniza os registros e monta lotes por tarefa;
|
| 9 |
+
3. roda passos de treino REAIS no modelo v12 (TRONCO MAMBA-3 HÍBRIDO 5:1
|
| 10 |
+
NoPE + MuonClip+AdamW + 3D-VL com profundidade + ensemble + critérios
|
| 11 |
+
Jev dinâmicos) verificando perdas finitas e decrescíveis;
|
| 12 |
+
4. valida o CLASSIFICADOR DE PROTÓTIPOS (construir_classificador_tarefas)
|
| 13 |
+
classificando registros REAIS pelas 12 tarefas (órfão v11 conectado);
|
| 14 |
+
5. roda DPO com pares REAIS do Anthropic/hh-rlhf;
|
| 15 |
+
6. valida o GestorEstadosHF (serializa um estado e confere o limiar);
|
| 16 |
+
7. grava o relatório JSON (aprovado/reprovado por verificação).
|
| 17 |
|
| 18 |
Sai 0 somente se TODAS as verificações passarem — gate de entrada para
|
| 19 |
`scripts/04_treinar.py`.
|
|
|
|
| 84 |
hub = TelemetryHub("/home/z/my-project/khtst/telemetria_out/"
|
| 85 |
"teste_dados_reais_telemetria.jsonl")
|
| 86 |
modelo = KHTSTModel(cfg, usar_multimodal=True)
|
| 87 |
+
check("modelo v12 construído (12 tarefas + tronco Mamba-3 5:1 + 3D-VL)",
|
| 88 |
+
len(modelo.TAREFAS) == 12 and modelo.mamba3vl is not None
|
| 89 |
+
and modelo.blocos.contar_atencao() == 1
|
| 90 |
+
and modelo.blocos.contar_mamba3() == 5,
|
| 91 |
+
f"NoPE={modelo.blocos.contar_atencao()} "
|
| 92 |
+
f"M3={modelo.blocos.contar_mamba3()}")
|
| 93 |
|
| 94 |
print("== 2) tokenizador (treinado no ambiente ou mini-treino local) ==")
|
| 95 |
tk_path = os.path.join(RAIZ, "cache_dados", "tokenizador.json")
|
|
|
|
| 175 |
float(treinar.ensemble_votacao.pesos.sum()) > 0.99,
|
| 176 |
f"pesos={treinar.ensemble_votacao.pesos.round(3).tolist()}")
|
| 177 |
relatorio["perdas_reais"] = hist
|
| 178 |
+
# v12 — CLASSIFICADOR DE PROTÓTIPOS com registros REAIS (órfão v11
|
| 179 |
+
# conectado — doc 25 §9): constrói o classificador a partir dos
|
| 180 |
+
# exemplares reais e mede a acurácia de rota por tarefa
|
| 181 |
+
from khtst.percepcao.classificadores import construir_classificador_tarefas
|
| 182 |
+
try:
|
| 183 |
+
_, classif, criterios = construir_classificador_tarefas(
|
| 184 |
+
modelo, cfg, tk, registros=registros_reais)
|
| 185 |
+
com_rotulo = [r for r in registros_reais
|
| 186 |
+
if r.get("tarefa") in TAREFAS]
|
| 187 |
+
acertos = 0
|
| 188 |
+
for r in com_rotulo[:32]:
|
| 189 |
+
ids_r = torch.tensor([tk.encode(r["entrada"] or r.get("texto", ""),
|
| 190 |
+
tarefa=None, max_len=32,
|
| 191 |
+
com_bos=False)])
|
| 192 |
+
if ids_r.shape[1] == 0:
|
| 193 |
+
continue
|
| 194 |
+
ctx_r = modelo.contexto(ids_r)[0]
|
| 195 |
+
escolha = classif.escolha(ctx_r, list(TAREFAS), criterios)
|
| 196 |
+
acertos += int(escolha["escolha"][0] == r["tarefa"])
|
| 197 |
+
acc = acertos / max(1, min(32, len(com_rotulo)))
|
| 198 |
+
relatorio["classificador_prototipos_acc"] = round(acc, 4)
|
| 199 |
+
check("classificador de protótipos roteia acima do acerto "
|
| 200 |
+
"uniforme", acc > 1.0 / len(TAREFAS),
|
| 201 |
+
f"acc={acc:.3f} (uniforme={1.0/len(TAREFAS):.3f})")
|
| 202 |
+
except Exception as e:
|
| 203 |
+
check("classificador de protótipos", False,
|
| 204 |
+
f"{type(e).__name__}: {e}")
|
| 205 |
else:
|
| 206 |
check("treino real pulado (sem rede e sem cache)", False,
|
| 207 |
"execute sem --sem_rede com internet")
|
|
|
|
| 223 |
from khtst.dados.checkpoints import GestorCheckpoints
|
| 224 |
dir_tmp = "/home/z/my-project/khtst/estados_local_teste"
|
| 225 |
gc = GestorCheckpoints(dir_local=dir_tmp)
|
| 226 |
+
caminho = gc.salvar(modelo, "teste-real-v12", {"passo_global": 1})
|
| 227 |
mb = os.path.getsize(caminho) / 1e6
|
| 228 |
check("estado safetensors gravado e < 900 MB", mb < 900.0, f"{mb:.1f} MB")
|
| 229 |
ok_carrega = GestorCheckpoints(dir_local=dir_tmp).carregar(
|
| 230 |
+
KHTSTModel(cfg, usar_multimodal=False), "teste-real-v12")
|
| 231 |
check("estado RELOAD bit-exato (Teo 16.9)", ok_carrega)
|
| 232 |
shutil.rmtree(dir_tmp, ignore_errors=True)
|
| 233 |
|
scripts/11_coleta_curta_v12.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
"""Coleta CURTA de dados reais (v12) — corpus de validação do treino curto.
|
| 4 |
+
|
| 5 |
+
Baixa N registros REAIS por fonte (streaming, timeout por fonte) das fontes
|
| 6 |
+
do requisito v11 + hh-rlhf e escreve cache_dados/corpus_v2.jsonl no formato
|
| 7 |
+
do projeto (mesmo schema do 02_coletar_corpus). NÃO substitui a coleta
|
| 8 |
+
completa (script 02) — é a base honesta para o TREINO CURTO de validação
|
| 9 |
+
da v12 antes de qualquer corrida longa.
|
| 10 |
+
"""
|
| 11 |
+
import json
|
| 12 |
+
import os
|
| 13 |
+
import signal
|
| 14 |
+
import sys
|
| 15 |
+
|
| 16 |
+
RAIZ = os.environ.get("KHTST_RAIZ", "/home/z/my-project/khtst")
|
| 17 |
+
sys.path.insert(0, os.path.join(RAIZ, "src"))
|
| 18 |
+
|
| 19 |
+
SAIDA = os.path.join(RAIZ, "cache_dados", "corpus_v2.jsonl")
|
| 20 |
+
N_POR_FONTE = 25
|
| 21 |
+
TEMPO_FONTE = 75
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def main():
|
| 25 |
+
from khtst.dados.streaming import StreamingCorpus, limpar_cache_temp
|
| 26 |
+
os.makedirs(os.path.dirname(SAIDA), exist_ok=True)
|
| 27 |
+
|
| 28 |
+
class _Tempo(Exception):
|
| 29 |
+
pass
|
| 30 |
+
|
| 31 |
+
def _alarme(s, f):
|
| 32 |
+
raise _Tempo()
|
| 33 |
+
|
| 34 |
+
corpus = StreamingCorpus()
|
| 35 |
+
registros = []
|
| 36 |
+
for plano in corpus.PLANO:
|
| 37 |
+
plano = dict(plano)
|
| 38 |
+
plano["max"] = N_POR_FONTE
|
| 39 |
+
n0 = len(registros)
|
| 40 |
+
signal.signal(signal.SIGALRM, _alarme)
|
| 41 |
+
signal.alarm(TEMPO_FONTE)
|
| 42 |
+
try:
|
| 43 |
+
for ex in corpus._iterar_fonte(plano):
|
| 44 |
+
if len(registros) - n0 >= N_POR_FONTE:
|
| 45 |
+
break
|
| 46 |
+
reg = plano["ad"](ex) if plano.get("ad") else None
|
| 47 |
+
if reg is None:
|
| 48 |
+
continue
|
| 49 |
+
reg["fonte"] = plano["id"]
|
| 50 |
+
registros.append(reg)
|
| 51 |
+
except _Tempo:
|
| 52 |
+
print(f" [timeout] {plano['id']}: {len(registros) - n0} regs")
|
| 53 |
+
except Exception as e:
|
| 54 |
+
print(f" [erro] {plano['id']}: {type(e).__name__}: {str(e)[:90]}")
|
| 55 |
+
finally:
|
| 56 |
+
signal.alarm(0)
|
| 57 |
+
limpar_cache_temp()
|
| 58 |
+
print(f" {plano['id']}: {len(registros) - n0} registros")
|
| 59 |
+
# hh-rlhf (RLHF real)
|
| 60 |
+
try:
|
| 61 |
+
from datasets import load_dataset
|
| 62 |
+
ds = load_dataset("Anthropic/hh-rlhf", split="train", streaming=True)
|
| 63 |
+
n = 0
|
| 64 |
+
for ex in ds:
|
| 65 |
+
esc, rej = ex.get("chosen", ""), ex.get("rejected", "")
|
| 66 |
+
if not esc or not rej:
|
| 67 |
+
continue
|
| 68 |
+
def _assistente(t):
|
| 69 |
+
partes = str(t).split("Assistant:")
|
| 70 |
+
return partes[-1].strip() if len(partes) > 1 else ""
|
| 71 |
+
def _humano(t):
|
| 72 |
+
return str(t).split("Assistant:")[0].replace("Human:", "").strip()
|
| 73 |
+
ent, c_ok, c_no = _humano(esc), _assistente(esc), _assistente(rej)
|
| 74 |
+
if len(ent) < 8 or len(c_ok) < 4 or not c_no:
|
| 75 |
+
continue
|
| 76 |
+
registros.append({"tarefa": "instrucao", "entrada": ent[:600],
|
| 77 |
+
"saida": c_ok[:600], "rejeitado": c_no[:600],
|
| 78 |
+
"fonte": "Anthropic/hh-rlhf"})
|
| 79 |
+
n += 1
|
| 80 |
+
if n >= 20:
|
| 81 |
+
break
|
| 82 |
+
print(f" Anthropic/hh-rlhf: {n} pares")
|
| 83 |
+
except Exception as e:
|
| 84 |
+
print(f" [erro] hh-rlhf: {type(e).__name__}: {str(e)[:90]}")
|
| 85 |
+
|
| 86 |
+
def _serializavel(r: dict) -> dict:
|
| 87 |
+
"""bytes → base64 (schema do projeto); chaves não-JSON descartadas."""
|
| 88 |
+
import base64
|
| 89 |
+
limpo = {}
|
| 90 |
+
for k, v in r.items():
|
| 91 |
+
if isinstance(v, bytes):
|
| 92 |
+
limpo[k] = base64.b64encode(v).decode("ascii")
|
| 93 |
+
elif isinstance(v, (str, int, float, bool)) or v is None:
|
| 94 |
+
limpo[k] = v
|
| 95 |
+
elif isinstance(v, (list, dict)):
|
| 96 |
+
try:
|
| 97 |
+
json.dumps(v)
|
| 98 |
+
limpo[k] = v
|
| 99 |
+
except Exception:
|
| 100 |
+
continue
|
| 101 |
+
return limpo
|
| 102 |
+
|
| 103 |
+
with open(SAIDA, "w", encoding="utf-8") as f:
|
| 104 |
+
for r in registros:
|
| 105 |
+
f.write(json.dumps(_serializavel(r), ensure_ascii=False) + "\n")
|
| 106 |
+
from collections import Counter
|
| 107 |
+
c = Counter(r["tarefa"] for r in registros)
|
| 108 |
+
print(f"TOTAL: {len(registros)} registros reais → {SAIDA}")
|
| 109 |
+
print("por tarefa:", dict(c))
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
if __name__ == "__main__":
|
| 113 |
+
main()
|
src/khtst/config.py
CHANGED
|
@@ -71,7 +71,10 @@ class ConfigModelo:
|
|
| 71 |
micro buffers recorrentes e pesos de árvore bidirecionais."""
|
| 72 |
vocab: int = 16384 # v4 — requisito do usuário
|
| 73 |
d_modelo: int = 192
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
| 75 |
n_cabecas: int = 4
|
| 76 |
d_ff: int = 512
|
| 77 |
comprimento_ctx: int = 256 # v10 — requisito (era 192)
|
|
@@ -94,13 +97,21 @@ class ConfigModelo:
|
|
| 94 |
"ativo": True, "n_camadas_moe": 2, "n_grupos": 3, "experts_por_grupo": 2,
|
| 95 |
"d_ff_expert": 160, "top_k": 2, "margem_foco": 1.0, "n_tarefas": len(TAREFAS),
|
| 96 |
"vetorial": True}) # v8 — item (e): experts vetorizados (vmap/bmm)
|
| 97 |
-
# v11 —
|
| 98 |
-
#
|
| 99 |
-
#
|
|
|
|
| 100 |
mamba3: dict = field(default_factory=lambda: {
|
| 101 |
"ativo": True, "n_camadas": 6, "n_cabecas": 4, "d_estado": 16,
|
| 102 |
-
"rank_mimo": 4, "grad_checkpointing": True,
|
| 103 |
-
"ativo_vl": True, "n_camadas_vl": 6
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
# v2 — predição multi-token com α aprendíveis (doc 10 §3)
|
| 105 |
mtp: dict = field(default_factory=lambda: {
|
| 106 |
"ativo": True, "k_cabecas": 2, "beta_entropia": 0.01,
|
|
@@ -119,7 +130,8 @@ class ConfigModelo:
|
|
| 119 |
"ativo": True, "k": 24, "lambda_rota": 0.35, "gamma_empate": 0.15,
|
| 120 |
"conf_min": 0.25, "min_amostras": 200})
|
| 121 |
# v4 — unidades NLP (processar) e NLG (gerar) de primeira classe (doc 15 §1)
|
| 122 |
-
|
|
|
|
| 123 |
# v5 — atenção ENTRE camadas MoE (doc 16 §§1–2): nasce neutra (α=β=0)
|
| 124 |
atencao_moe: dict = field(default_factory=lambda: {"ativo": True, "alpha0": 0.0})
|
| 125 |
nlg: dict = field(default_factory=lambda: {"ativo": True, "n_estilos": 8,
|
|
|
|
| 71 |
micro buffers recorrentes e pesos de árvore bidirecionais."""
|
| 72 |
vocab: int = 16384 # v4 — requisito do usuário
|
| 73 |
d_modelo: int = 192
|
| 74 |
+
# v12 — 6 camadas = período EXATO da proporção 5:1 do requisito
|
| 75 |
+
# ([M,M,M,M,M,A] — Mamba3Camada×5 + NoPEAtencao×1; Teo 24.14: para
|
| 76 |
+
# T=256 o tronco híbrido custa MENOS que 3 blocos transformer)
|
| 77 |
+
n_camadas: int = 6
|
| 78 |
n_cabecas: int = 4
|
| 79 |
d_ff: int = 512
|
| 80 |
comprimento_ctx: int = 256 # v10 — requisito (era 192)
|
|
|
|
| 97 |
"ativo": True, "n_camadas_moe": 2, "n_grupos": 3, "experts_por_grupo": 2,
|
| 98 |
"d_ff_expert": 160, "top_k": 2, "margem_foco": 1.0, "n_tarefas": len(TAREFAS),
|
| 99 |
"vetorial": True}) # v8 — item (e): experts vetorizados (vmap/bmm)
|
| 100 |
+
# v11/v12 — MAMBA-3 (doc 22) + MAMBA-3VL (doc 25): v12 o tronco É o
|
| 101 |
+
# híbrido 5:1 (n_camadas=6 acima); o dict controla d_estado/rank do
|
| 102 |
+
# tronco e o Mamba-3VL (3D-VL) com percepção de profundidade/distância/
|
| 103 |
+
# camadas provada (d_cod/n_bins/n_camadas_prof — doc 25 §§1–5)
|
| 104 |
mamba3: dict = field(default_factory=lambda: {
|
| 105 |
"ativo": True, "n_camadas": 6, "n_cabecas": 4, "d_estado": 16,
|
| 106 |
+
"rank_mimo": 4, "grad_checkpointing": True,
|
| 107 |
+
"ativo_vl": True, "n_camadas_vl": 6,
|
| 108 |
+
"d_cod_prof": 24, "n_bins_prof": 16, "n_camadas_prof": 4})
|
| 109 |
+
# v12 — OTIMIZADOR MuonClip + AdamW (doc 24): Muon (Newton-Schulz) nas
|
| 110 |
+
# matrizes do tronco, AdamW nas tabelas/vetores, QK-clip τ nas NoPE
|
| 111 |
+
otimizador: dict = field(default_factory=lambda: {
|
| 112 |
+
"ativo": True, "momentum": 0.95, "nesterov": True, "ns_iters": 5,
|
| 113 |
+
"tau_qk": 100.0, "escala_muon": 0.2, "betas": [0.9, 0.95],
|
| 114 |
+
"weight_decay": 0.01})
|
| 115 |
# v2 — predição multi-token com α aprendíveis (doc 10 §3)
|
| 116 |
mtp: dict = field(default_factory=lambda: {
|
| 117 |
"ativo": True, "k_cabecas": 2, "beta_entropia": 0.01,
|
|
|
|
| 130 |
"ativo": True, "k": 24, "lambda_rota": 0.35, "gamma_empate": 0.15,
|
| 131 |
"conf_min": 0.25, "min_amostras": 200})
|
| 132 |
# v4 — unidades NLP (processar) e NLG (gerar) de primeira classe (doc 15 §1)
|
| 133 |
+
# v12 — n_intencoes 13 = 12 tarefas canônicas + nlp-outro (fonte única)
|
| 134 |
+
nlp: dict = field(default_factory=lambda: {"ativo": True, "n_intencoes": 13})
|
| 135 |
# v5 — atenção ENTRE camadas MoE (doc 16 §§1–2): nasce neutra (α=β=0)
|
| 136 |
atencao_moe: dict = field(default_factory=lambda: {"ativo": True, "alpha0": 0.0})
|
| 137 |
nlg: dict = field(default_factory=lambda: {"ativo": True, "n_estilos": 8,
|
src/khtst/geracao/difusao.py
CHANGED
|
@@ -1,50 +1,120 @@
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
-
"""Geração multimodal por DIFUSÃO —
|
| 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 |
PESOS: por padrão usa repositório TINY de teste (CPU/RAM pequena). Em
|
| 31 |
produção defina `repo_id` p.ex. "stabilityai/stable-diffusion-2-1-base"
|
| 32 |
-
(GPU ≥ 8GB).
|
|
|
|
| 33 |
"""
|
| 34 |
from __future__ import annotations
|
| 35 |
|
| 36 |
import io
|
| 37 |
import os
|
| 38 |
import time
|
|
|
|
| 39 |
|
| 40 |
import torch
|
| 41 |
|
| 42 |
-
# Importação EXATA solicitada (item do escopo v5):
|
| 43 |
-
from diffusers import (StableDiffusionImg2ImgPipeline,
|
| 44 |
-
StableDiffusionInpaintPipeline,
|
| 45 |
-
StableDiffusionPipeline)
|
| 46 |
-
|
| 47 |
MODOS = ("real", "planejado")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
|
| 50 |
def _dispositivo() -> str:
|
|
@@ -56,34 +126,61 @@ def _dispositivo() -> str:
|
|
| 56 |
|
| 57 |
|
| 58 |
class GeradorMultimodal:
|
| 59 |
-
"""Facade dos 3 pipelines de difusão com carga PREGUIÇOSA
|
|
|
|
| 60 |
|
| 61 |
Args:
|
| 62 |
repo_id: repositório de pesos (SD). Default: tiny de teste.
|
| 63 |
altura/largura: resolução (múltiplos de 8).
|
| 64 |
passos_inferencia / guia_escala: parâmetros do scheduler.
|
|
|
|
| 65 |
"""
|
| 66 |
|
| 67 |
def __init__(self, repo_id: str = "hf-internal-testing/tiny-stable-diffusion-torch",
|
| 68 |
altura: int = 128, largura: int = 128,
|
| 69 |
passos_inferencia: int = 8, guia_escala: float = 7.5,
|
| 70 |
-
hub=None, token: str | None = None):
|
| 71 |
self.repo_id = repo_id
|
| 72 |
self.altura, self.largura = altura, largura
|
| 73 |
self.passos = passos_inferencia
|
| 74 |
self.guia = guia_escala
|
|
|
|
| 75 |
self.hub = hub
|
| 76 |
self.token = token or os.environ.get("HF_TOKEN")
|
| 77 |
self.device = _dispositivo()
|
| 78 |
self.dtype = torch.float16 if self.device == "cuda" else torch.float32
|
| 79 |
self._pipelines: dict = {}
|
|
|
|
| 80 |
self.modo = "planejado" # honesto até a carga REAL confirmar
|
|
|
|
| 81 |
self.eventos: list = []
|
| 82 |
|
| 83 |
# ---------------- infra ----------------
|
| 84 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
if chave in self._pipelines:
|
| 86 |
return self._pipelines[chave]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
try:
|
| 88 |
pipe = classe.from_pretrained(
|
| 89 |
pretrained_model_name_or_path=self.repo_id,
|
|
@@ -99,7 +196,7 @@ class GeradorMultimodal:
|
|
| 99 |
self.eventos.append(f"pipeline {chave}: {type(e).__name__}: {e}")
|
| 100 |
return None
|
| 101 |
|
| 102 |
-
# ---------------- força semântica (Teorema 17.1) --
|
| 103 |
@staticmethod
|
| 104 |
def forca_por_similaridade(emb_in: torch.Tensor | None,
|
| 105 |
emb_plano: torch.Tensor | None) -> float:
|
|
@@ -111,50 +208,94 @@ class GeradorMultimodal:
|
|
| 111 |
emb_plano.flatten().float().unsqueeze(0)).item()
|
| 112 |
return float(min(0.80, max(0.35, 1.0 - s)))
|
| 113 |
|
| 114 |
-
# ---------------- três operações -----------
|
| 115 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
"""StableDiffusionPipeline: texto → imagem."""
|
| 117 |
-
pipe = self._obter_pipeline(
|
| 118 |
if pipe is None:
|
| 119 |
-
return self._plano("txt2img", prompt=prompt)
|
| 120 |
out = pipe(prompt, height=self.altura, width=self.largura,
|
| 121 |
num_inference_steps=kw.get("passos", self.passos),
|
| 122 |
-
guidance_scale=kw.get("guia", self.guia)
|
| 123 |
-
|
|
|
|
|
|
|
| 124 |
|
| 125 |
def imagem_para_imagem(self, prompt: str, imagem, forca: float | None = None,
|
| 126 |
-
**kw) -> dict:
|
| 127 |
"""StableDiffusionImg2ImgPipeline: imagem+texto → imagem. `forca`
|
| 128 |
-
semanticamente guiada (Teorema 17.1)."""
|
| 129 |
-
pipe = self._obter_pipeline(
|
| 130 |
if pipe is None:
|
| 131 |
-
return self._plano("img2img", prompt=prompt, forca=forca
|
|
|
|
| 132 |
f = forca if forca is not None else kw.get("forca_default", 0.55)
|
| 133 |
out = pipe(prompt=prompt, image=imagem, strength=f,
|
| 134 |
num_inference_steps=kw.get("passos", self.passos),
|
| 135 |
-
guidance_scale=kw.get("guia", self.guia)
|
|
|
|
| 136 |
return {"modo": "real", "op": "img2img", "imagem": out.images[0],
|
| 137 |
-
"forca": float(f)
|
|
|
|
| 138 |
|
| 139 |
-
def inpaint(self, prompt: str, imagem, mascara,
|
|
|
|
| 140 |
"""StableDiffusionInpaintPipeline: imagem+máscara → imagem editada."""
|
| 141 |
-
pipe = self._obter_pipeline(
|
| 142 |
if pipe is None:
|
| 143 |
-
return self._plano("inpaint", prompt=prompt)
|
| 144 |
out = pipe(prompt=prompt, image=imagem, mask_image=mascara,
|
| 145 |
height=self.altura, width=self.largura,
|
| 146 |
num_inference_steps=kw.get("passos", self.passos),
|
| 147 |
-
guidance_scale=kw.get("guia", self.guia)
|
| 148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
|
| 150 |
# ---------------- ciclo fechado (compreensão geracional) ----------------
|
| 151 |
def compreensao_geracional(self, prompt: str, modelo, orquestrador=None,
|
| 152 |
op: str = "txt2img", imagem_base=None,
|
| 153 |
emb_in: torch.Tensor | None = None,
|
| 154 |
emb_plano: torch.Tensor | None = None,
|
| 155 |
-
mascara=None
|
| 156 |
-
|
| 157 |
-
|
|
|
|
|
|
|
| 158 |
t0 = time.time()
|
| 159 |
# (i) prompt enriquecido pela NLG (estilo corrente — doc 15 §1)
|
| 160 |
prompt_enriquecido = prompt
|
|
@@ -163,20 +304,23 @@ class GeradorMultimodal:
|
|
| 163 |
prompt_enriquecido = modelo.nlg.enriquecer_prompt(prompt)
|
| 164 |
except Exception:
|
| 165 |
pass
|
| 166 |
-
# (ii) força semântica (Teorema 17.1)
|
| 167 |
forca = self.forca_por_similaridade(emb_in, emb_plano) \
|
| 168 |
if op == "img2img" else None
|
| 169 |
-
# (iii) geração
|
| 170 |
if op == "txt2img":
|
| 171 |
-
r = self.texto_para_imagem(prompt_enriquecido
|
|
|
|
| 172 |
elif op == "img2img":
|
| 173 |
r = self.imagem_para_imagem(prompt_enriquecido, imagem_base,
|
| 174 |
-
forca=forca)
|
| 175 |
elif op == "inpaint":
|
| 176 |
-
r = self.inpaint(prompt_enriquecido, imagem_base, mascara
|
|
|
|
| 177 |
else:
|
| 178 |
r = {"modo": "planejado", "op": op, "erro": "op desconhecida"}
|
| 179 |
-
|
|
|
|
| 180 |
emb_out = None
|
| 181 |
if r.get("modo") == "real" and modelo is not None \
|
| 182 |
and getattr(modelo, "usar_multimodal", False):
|
|
@@ -192,15 +336,18 @@ class GeradorMultimodal:
|
|
| 192 |
with torch.no_grad():
|
| 193 |
orquestrador.treinar_memoria(
|
| 194 |
emb_out.detach().reshape(-1, modelo.d), epocas=1)
|
|
|
|
| 195 |
except Exception as e:
|
| 196 |
r["re_encode_erro"] = f"{type(e).__name__}: {e}"
|
| 197 |
r.update({"prompt_enriquecido": prompt_enriquecido,
|
| 198 |
"latencia_s": round(time.time() - t0, 2),
|
| 199 |
-
"embedding_saida": emb_out
|
|
|
|
| 200 |
if self.hub is not None:
|
| 201 |
self.hub.atributo("difusao/modo_real",
|
| 202 |
1.0 if r.get("modo") == "real" else 0.0)
|
| 203 |
self.hub.atributo("difusao/latencia_s", r["latencia_s"])
|
|
|
|
| 204 |
return r
|
| 205 |
|
| 206 |
# ---------------- degradação honesta (Teorema 17.2) ----------------
|
|
@@ -212,7 +359,8 @@ class GeradorMultimodal:
|
|
| 212 |
"passos": self.passos, "guia": self.guia, **params}
|
| 213 |
|
| 214 |
def imagem_para_bytes(self, img) -> bytes:
|
| 215 |
-
"""PIL.Image → PNG bytes (persistência sem segredos
|
|
|
|
| 216 |
buf = io.BytesIO()
|
| 217 |
img.save(buf, format="PNG")
|
| 218 |
return buf.getvalue()
|
|
@@ -220,4 +368,5 @@ class GeradorMultimodal:
|
|
| 220 |
def estatisticas(self) -> dict:
|
| 221 |
return {"modo": self.modo, "repo": self.repo_id,
|
| 222 |
"device": self.device, "pipelines": list(self._pipelines),
|
|
|
|
| 223 |
"eventos": self.eventos[-5:]}
|
|
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
+
"""Geração multimodal por DIFUSÃO — v12 (docs 17 e 25 §8).
|
| 3 |
+
|
| 4 |
+
ACESSO LÓGICO AOS DIFUSORES (requisito v12): a escolha da operação e dos
|
| 5 |
+
parâmetros é uma DECISÃO LÓGICA ROTEADA — não hardcoded nos scripts:
|
| 6 |
+
|
| 7 |
+
RoteadorDifusao.decidir(intenção, tem_imagem, tem_máscara)
|
| 8 |
+
→ RotuloDifusao(op ∈ {txt2img, img2img, inpaint}, passos, guia,
|
| 9 |
+
justificativa)
|
| 10 |
+
|
| 11 |
+
TEOREMA 25.8 (corretude da rota bayesiana): com prior P(op) uniforme e
|
| 12 |
+
verossimilhança binária por evidência (máscara ⇒ inpaint com prob. 1 na
|
| 13 |
+
regra de decisão por MAP; sem imagem ⇒ txt2img; imagem sem máscara ⇒
|
| 14 |
+
img2img), a decisão MAP minimiza a probabilidade de rota errada — e as
|
| 15 |
+
três regiões são DISJUNTAS e COBREM o espaço de evidências (partição),
|
| 16 |
+
logo a rota é ÚNICA e consistente (sem ambiguidade).
|
| 17 |
+
|
| 18 |
+
TEOREMA 25.9 (intenção como evidência): a intenção da UnidadeNLP atua como
|
| 19 |
+
prior logit aditivo; a entropia da distribuição de intenção é limitada por
|
| 20 |
+
ln(13) (13 classes v12 — fonte única khtst.tarefas), logo o impacto no
|
| 21 |
+
logit é BOUNDED — a intenção NUNCA sobrepõe a evidência dura (máscara).
|
| 22 |
+
|
| 23 |
+
CICLO FECHADO DE COMPREENSÃO GERACIONAL (doc 17 §2, agora COMPLETO):
|
| 24 |
+
NLG enriquece o prompt (PT-BR) → roteador decide → difusão (seed
|
| 25 |
+
determinística — Teo 25.10: mesma seed+pesos ⇒ mesma saída) → encoder
|
| 26 |
+
de imagem re-encoda → protótipo entra na memória SOM → gerações
|
| 27 |
+
futuras condicionam na memória.
|
| 28 |
+
|
| 29 |
+
TEOREMA 17.1 (força semântica — AGORA USADO DE FATO): strength =
|
| 30 |
+
clip(1 − cos(e_in, e_plano), 0,35, 0,80) com embeddings REAIS passados
|
| 31 |
+
pelo modelo (o v11 tinha os parâmetros e nunca os usava — código morto).
|
| 32 |
+
|
| 33 |
+
TEOREMA 17.2 (degradação honesta): sem GPU/diffusers/pesos, o gerador
|
| 34 |
+
opera em modo "planejado": devolve um PLANO estruturado — NUNCA pixels
|
| 35 |
+
falsos. Toda telemetria registra o modo real (`real` | `planejado`).
|
| 36 |
+
|
| 37 |
+
TEOREMA 25.10 (reprodutibilidade): com seed s e pesos fixos, a sequência
|
| 38 |
+
de ruído do scheduler é função determinística de s — duas chamadas com a
|
| 39 |
+
mesma (s, prompt, op) produzem a MESMA imagem (hardware igual) e a telemetria
|
| 40 |
+
registra a seed para auditoria.
|
| 41 |
|
| 42 |
PESOS: por padrão usa repositório TINY de teste (CPU/RAM pequena). Em
|
| 43 |
produção defina `repo_id` p.ex. "stabilityai/stable-diffusion-2-1-base"
|
| 44 |
+
(GPU ≥ 8GB). IMPORT DE DIFFUSERS é LAZY (v12): sem o pacote, o módulo
|
| 45 |
+
importa igualmente e opera no modo planejado (o v11 QUEBRava a importação).
|
| 46 |
"""
|
| 47 |
from __future__ import annotations
|
| 48 |
|
| 49 |
import io
|
| 50 |
import os
|
| 51 |
import time
|
| 52 |
+
from dataclasses import dataclass, field
|
| 53 |
|
| 54 |
import torch
|
| 55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
MODOS = ("real", "planejado")
|
| 57 |
+
OPERACOES = ("txt2img", "img2img", "inpaint")
|
| 58 |
+
|
| 59 |
+
# verossimilhanças da partição bayesiana (Teo 25.8) — evidências duras
|
| 60 |
+
_EVIDENCIA = {
|
| 61 |
+
# (tem_imagem, tem_mascara) → op determinada
|
| 62 |
+
(False, False): "txt2img",
|
| 63 |
+
(True, False): "img2img",
|
| 64 |
+
(True, True): "inpaint",
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
# priors por intenção (logit aditivo — Teo 25.9; 0 = neutro)
|
| 68 |
+
_PRIOR_INTENCAO = {
|
| 69 |
+
"imagem_caption": {"txt2img": 0.3, "img2img": 0.0, "inpaint": -0.5},
|
| 70 |
+
"vqa": {"txt2img": -0.2, "img2img": 0.2, "inpaint": 0.0},
|
| 71 |
+
"ocr": {"txt2img": -0.5, "img2img": 0.3, "inpaint": 0.0},
|
| 72 |
+
"classificacao": {"txt2img": -0.3, "img2img": 0.2, "inpaint": 0.0},
|
| 73 |
+
"lm": {"txt2img": 0.2, "img2img": -0.2, "inpaint": -0.5},
|
| 74 |
+
"noticia": {"txt2img": 0.2, "img2img": 0.0, "inpaint": -0.3},
|
| 75 |
+
"instrucao": {"txt2img": 0.1, "img2img": 0.1, "inpaint": 0.1},
|
| 76 |
+
"traducao": {"txt2img": 0.0, "img2img": 0.0, "inpaint": 0.0},
|
| 77 |
+
"raciocinio": {"txt2img": 0.0, "img2img": 0.0, "inpaint": 0.0},
|
| 78 |
+
"tts": {"txt2img": 0.0, "img2img": 0.0, "inpaint": 0.0},
|
| 79 |
+
"asr": {"txt2img": 0.0, "img2img": 0.0, "inpaint": 0.0},
|
| 80 |
+
"pontuacao": {"txt2img": 0.0, "img2img": 0.0, "inpaint": 0.0},
|
| 81 |
+
"nlp-outro": {"txt2img": 0.0, "img2img": 0.0, "inpaint": 0.0},
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
@dataclass
|
| 86 |
+
class RotuloDifusao:
|
| 87 |
+
"""Rótulo de rota do roteador lógico (op + parâmetros + evidências)."""
|
| 88 |
+
op: str
|
| 89 |
+
passos: int
|
| 90 |
+
guia: float
|
| 91 |
+
justificativa: str
|
| 92 |
+
escores: dict = field(default_factory=dict)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
class RoteadorDifusao:
|
| 96 |
+
"""Acesso LÓGICO aos difusores: partição bayesiana de evidências +
|
| 97 |
+
prior de intenção (Teos 25.8/25.9). Determinístico e auditável."""
|
| 98 |
+
|
| 99 |
+
@staticmethod
|
| 100 |
+
def decidir(intencao: str | None, tem_imagem: bool, tem_mascara: bool,
|
| 101 |
+
passos_base: int = 8, guia_base: float = 7.5) -> RotuloDifusao:
|
| 102 |
+
"""MAP sobre a partição: a evidência dura (imagem/máscara) define a
|
| 103 |
+
região; a intenção ajusta o escore DENTRO da região (Teo 25.9 —
|
| 104 |
+
entropia limitada ln(13), nunca sobrepõe a evidência)."""
|
| 105 |
+
chave = (bool(tem_imagem), bool(tem_mascara))
|
| 106 |
+
op = _EVIDENCIA[chave]
|
| 107 |
+
escores = dict(_PRIOR_INTENCAO.get(intencao or "nlp-outro",
|
| 108 |
+
{"txt2img": 0.0, "img2img": 0.0,
|
| 109 |
+
"inpaint": 0.0}))
|
| 110 |
+
just = f"evidência={chave} → {op}; intenção={intencao or 'n/a'} " \
|
| 111 |
+
f"(prior {escores[op]:+.2f})"
|
| 112 |
+
# parâmetros: inpaint/img2img exigem mais passos (reconstrução local
|
| 113 |
+
# precisa de mais refinamento — custo O(passos) provado no doc 17 §4)
|
| 114 |
+
passos = passos_base + (4 if op in ("img2img", "inpaint") else 0)
|
| 115 |
+
guia = guia_base if op != "inpaint" else max(3.0, guia_base - 2.0)
|
| 116 |
+
return RotuloDifusao(op=op, passos=passos, guia=guia,
|
| 117 |
+
justificativa=just, escores=escores)
|
| 118 |
|
| 119 |
|
| 120 |
def _dispositivo() -> str:
|
|
|
|
| 126 |
|
| 127 |
|
| 128 |
class GeradorMultimodal:
|
| 129 |
+
"""Facade dos 3 pipelines de difusão com carga PREGUIÇOSA, roteamento
|
| 130 |
+
lógico (v12) e ciclo fechado.
|
| 131 |
|
| 132 |
Args:
|
| 133 |
repo_id: repositório de pesos (SD). Default: tiny de teste.
|
| 134 |
altura/largura: resolução (múltiplos de 8).
|
| 135 |
passos_inferencia / guia_escala: parâmetros do scheduler.
|
| 136 |
+
semente: default de reprodutibilidade (Teo 25.10).
|
| 137 |
"""
|
| 138 |
|
| 139 |
def __init__(self, repo_id: str = "hf-internal-testing/tiny-stable-diffusion-torch",
|
| 140 |
altura: int = 128, largura: int = 128,
|
| 141 |
passos_inferencia: int = 8, guia_escala: float = 7.5,
|
| 142 |
+
hub=None, token: str | None = None, semente: int = 0):
|
| 143 |
self.repo_id = repo_id
|
| 144 |
self.altura, self.largura = altura, largura
|
| 145 |
self.passos = passos_inferencia
|
| 146 |
self.guia = guia_escala
|
| 147 |
+
self.semente = int(semente)
|
| 148 |
self.hub = hub
|
| 149 |
self.token = token or os.environ.get("HF_TOKEN")
|
| 150 |
self.device = _dispositivo()
|
| 151 |
self.dtype = torch.float16 if self.device == "cuda" else torch.float32
|
| 152 |
self._pipelines: dict = {}
|
| 153 |
+
self._diffusers_ok = None # lazy (v12)
|
| 154 |
self.modo = "planejado" # honesto até a carga REAL confirmar
|
| 155 |
+
self.rotas: list = [] # telemetria do roteamento lógico
|
| 156 |
self.eventos: list = []
|
| 157 |
|
| 158 |
# ---------------- infra ----------------
|
| 159 |
+
def _importar_diffusers(self):
|
| 160 |
+
"""Import LAZY (v12): None se o pacote não existe — módulo funciona
|
| 161 |
+
no modo planejado (v11 quebrava o import incondicionalmente)."""
|
| 162 |
+
if self._diffusers_ok is None:
|
| 163 |
+
try:
|
| 164 |
+
from diffusers import (StableDiffusionImg2ImgPipeline,
|
| 165 |
+
StableDiffusionInpaintPipeline,
|
| 166 |
+
StableDiffusionPipeline)
|
| 167 |
+
self._diffusers_ok = {
|
| 168 |
+
"txt2img": StableDiffusionPipeline,
|
| 169 |
+
"img2img": StableDiffusionImg2ImgPipeline,
|
| 170 |
+
"inpaint": StableDiffusionInpaintPipeline}
|
| 171 |
+
except Exception as e:
|
| 172 |
+
self._diffusers_ok = {}
|
| 173 |
+
self.eventos.append(f"diffusers indisponível: {e}")
|
| 174 |
+
return self._diffusers_ok
|
| 175 |
+
|
| 176 |
+
def _obter_pipeline(self, chave: str):
|
| 177 |
+
mods = self._importar_diffusers()
|
| 178 |
if chave in self._pipelines:
|
| 179 |
return self._pipelines[chave]
|
| 180 |
+
classe = mods.get(chave)
|
| 181 |
+
if classe is None:
|
| 182 |
+
self.modo = "planejado"
|
| 183 |
+
return None
|
| 184 |
try:
|
| 185 |
pipe = classe.from_pretrained(
|
| 186 |
pretrained_model_name_or_path=self.repo_id,
|
|
|
|
| 196 |
self.eventos.append(f"pipeline {chave}: {type(e).__name__}: {e}")
|
| 197 |
return None
|
| 198 |
|
| 199 |
+
# ---------------- força semântica (Teorema 17.1 — usada de fato v12) --
|
| 200 |
@staticmethod
|
| 201 |
def forca_por_similaridade(emb_in: torch.Tensor | None,
|
| 202 |
emb_plano: torch.Tensor | None) -> float:
|
|
|
|
| 208 |
emb_plano.flatten().float().unsqueeze(0)).item()
|
| 209 |
return float(min(0.80, max(0.35, 1.0 - s)))
|
| 210 |
|
| 211 |
+
# ---------------- três operações (com seed determinística) -----------
|
| 212 |
+
def _gerador_ruido(self, semente: int | None):
|
| 213 |
+
"""torch.Generator determinístico (Teo 25.10 — mesma seed ⇒ mesmo
|
| 214 |
+
ruído inicial do scheduler ⇒ mesma saída, hardware igual)."""
|
| 215 |
+
g = torch.Generator(device="cpu").manual_seed(
|
| 216 |
+
int(semente if semente is not None else self.semente))
|
| 217 |
+
return g
|
| 218 |
+
|
| 219 |
+
def texto_para_imagem(self, prompt: str, semente: int | None = None,
|
| 220 |
+
**kw) -> dict:
|
| 221 |
"""StableDiffusionPipeline: texto → imagem."""
|
| 222 |
+
pipe = self._obter_pipeline("txt2img")
|
| 223 |
if pipe is None:
|
| 224 |
+
return self._plano("txt2img", prompt=prompt, semente=semente)
|
| 225 |
out = pipe(prompt, height=self.altura, width=self.largura,
|
| 226 |
num_inference_steps=kw.get("passos", self.passos),
|
| 227 |
+
guidance_scale=kw.get("guia", self.guia),
|
| 228 |
+
generator=self._gerador_ruido(semente))
|
| 229 |
+
return {"modo": "real", "op": "txt2img", "imagem": out.images[0],
|
| 230 |
+
"semente": int(semente if semente is not None else self.semente)}
|
| 231 |
|
| 232 |
def imagem_para_imagem(self, prompt: str, imagem, forca: float | None = None,
|
| 233 |
+
semente: int | None = None, **kw) -> dict:
|
| 234 |
"""StableDiffusionImg2ImgPipeline: imagem+texto → imagem. `forca`
|
| 235 |
+
semanticamente guiada (Teorema 17.1 — embeddings reais do modelo)."""
|
| 236 |
+
pipe = self._obter_pipeline("img2img")
|
| 237 |
if pipe is None:
|
| 238 |
+
return self._plano("img2img", prompt=prompt, forca=forca,
|
| 239 |
+
semente=semente)
|
| 240 |
f = forca if forca is not None else kw.get("forca_default", 0.55)
|
| 241 |
out = pipe(prompt=prompt, image=imagem, strength=f,
|
| 242 |
num_inference_steps=kw.get("passos", self.passos),
|
| 243 |
+
guidance_scale=kw.get("guia", self.guia),
|
| 244 |
+
generator=self._gerador_ruido(semente))
|
| 245 |
return {"modo": "real", "op": "img2img", "imagem": out.images[0],
|
| 246 |
+
"forca": float(f),
|
| 247 |
+
"semente": int(semente if semente is not None else self.semente)}
|
| 248 |
|
| 249 |
+
def inpaint(self, prompt: str, imagem, mascara, semente: int | None = None,
|
| 250 |
+
**kw) -> dict:
|
| 251 |
"""StableDiffusionInpaintPipeline: imagem+máscara → imagem editada."""
|
| 252 |
+
pipe = self._obter_pipeline("inpaint")
|
| 253 |
if pipe is None:
|
| 254 |
+
return self._plano("inpaint", prompt=prompt, semente=semente)
|
| 255 |
out = pipe(prompt=prompt, image=imagem, mask_image=mascara,
|
| 256 |
height=self.altura, width=self.largura,
|
| 257 |
num_inference_steps=kw.get("passos", self.passos),
|
| 258 |
+
guidance_scale=kw.get("guia", self.guia),
|
| 259 |
+
generator=self._gerador_ruido(semente))
|
| 260 |
+
return {"modo": "real", "op": "inpaint", "imagem": out.images[0],
|
| 261 |
+
"semente": int(semente if semente is not None else self.semente)}
|
| 262 |
+
|
| 263 |
+
# ---------------- ACESSO LÓGICO (v12 — doc 25 §8) ---------------------
|
| 264 |
+
def gerar_por_intencao(self, prompt: str, rotulo: RotuloDifusao | None = None,
|
| 265 |
+
modelo=None, orquestrador=None, imagem_base=None,
|
| 266 |
+
mascara=None, emb_in: torch.Tensor | None = None,
|
| 267 |
+
emb_plano: torch.Tensor | None = None,
|
| 268 |
+
semente: int | None = None,
|
| 269 |
+
passo: int | None = None) -> dict:
|
| 270 |
+
"""Entrada LÓGICA única do sistema de difusão: recebe o rótulo do
|
| 271 |
+
RoteadorDifusao (ou decide com o contexto), aplica a força
|
| 272 |
+
semântica REAL (Teo 17.1), executa e fecha o ciclo (SOM)."""
|
| 273 |
+
if rotulo is None:
|
| 274 |
+
rotulo = RoteadorDifusao.decidir(
|
| 275 |
+
None, imagem_base is not None, mascara is not None,
|
| 276 |
+
passos_base=self.passos, guia_base=self.guia)
|
| 277 |
+
if passo is not None: # passo do treino p/ telemetria
|
| 278 |
+
rotulo.justificativa += f"; passo={passo}"
|
| 279 |
+
self.rotas.append({"op": rotulo.op, "passos": rotulo.passos,
|
| 280 |
+
"just": rotulo.justificativa,
|
| 281 |
+
"semente": int(semente if semente is not None
|
| 282 |
+
else self.semente)})
|
| 283 |
+
return self.compreensao_geracional(
|
| 284 |
+
prompt, modelo, orquestrador=orquestrador, op=rotulo.op,
|
| 285 |
+
imagem_base=imagem_base, emb_in=emb_in, emb_plano=emb_plano,
|
| 286 |
+
mascara=mascara, semente=semente, passos=rotulo.passos,
|
| 287 |
+
guia=rotulo.guia)
|
| 288 |
|
| 289 |
# ---------------- ciclo fechado (compreensão geracional) ----------------
|
| 290 |
def compreensao_geracional(self, prompt: str, modelo, orquestrador=None,
|
| 291 |
op: str = "txt2img", imagem_base=None,
|
| 292 |
emb_in: torch.Tensor | None = None,
|
| 293 |
emb_plano: torch.Tensor | None = None,
|
| 294 |
+
mascara=None, semente: int | None = None,
|
| 295 |
+
**kw) -> dict:
|
| 296 |
+
"""Ciclo fechado doc 17 §2: NLG enriquece o prompt → difusão (seed
|
| 297 |
+
Teo 25.10) → re-encodagem pelo KHTST → protótipo na memória SOM.
|
| 298 |
+
v12: emb_in/emb_plano REAIS (Teo 17.1 aplicado) + retorno PNG."""
|
| 299 |
t0 = time.time()
|
| 300 |
# (i) prompt enriquecido pela NLG (estilo corrente — doc 15 §1)
|
| 301 |
prompt_enriquecido = prompt
|
|
|
|
| 304 |
prompt_enriquecido = modelo.nlg.enriquecer_prompt(prompt)
|
| 305 |
except Exception:
|
| 306 |
pass
|
| 307 |
+
# (ii) força semântica (Teorema 17.1) — v12: embeddings reais
|
| 308 |
forca = self.forca_por_similaridade(emb_in, emb_plano) \
|
| 309 |
if op == "img2img" else None
|
| 310 |
+
# (iii) geração (seed determinística)
|
| 311 |
if op == "txt2img":
|
| 312 |
+
r = self.texto_para_imagem(prompt_enriquecido, semente=semente,
|
| 313 |
+
**kw)
|
| 314 |
elif op == "img2img":
|
| 315 |
r = self.imagem_para_imagem(prompt_enriquecido, imagem_base,
|
| 316 |
+
forca=forca, semente=semente, **kw)
|
| 317 |
elif op == "inpaint":
|
| 318 |
+
r = self.inpaint(prompt_enriquecido, imagem_base, mascara,
|
| 319 |
+
semente=semente, **kw)
|
| 320 |
else:
|
| 321 |
r = {"modo": "planejado", "op": op, "erro": "op desconhecida"}
|
| 322 |
+
r["rotulo"] = {"op": op, "forca": forca}
|
| 323 |
+
# (iv) re-encodagem perceptual + memória SOM + PNG bytes
|
| 324 |
emb_out = None
|
| 325 |
if r.get("modo") == "real" and modelo is not None \
|
| 326 |
and getattr(modelo, "usar_multimodal", False):
|
|
|
|
| 336 |
with torch.no_grad():
|
| 337 |
orquestrador.treinar_memoria(
|
| 338 |
emb_out.detach().reshape(-1, modelo.d), epocas=1)
|
| 339 |
+
r["png_bytes"] = self.imagem_para_bytes(img) # v12: usado
|
| 340 |
except Exception as e:
|
| 341 |
r["re_encode_erro"] = f"{type(e).__name__}: {e}"
|
| 342 |
r.update({"prompt_enriquecido": prompt_enriquecido,
|
| 343 |
"latencia_s": round(time.time() - t0, 2),
|
| 344 |
+
"embedding_saida": emb_out,
|
| 345 |
+
"modo_real": self.modo})
|
| 346 |
if self.hub is not None:
|
| 347 |
self.hub.atributo("difusao/modo_real",
|
| 348 |
1.0 if r.get("modo") == "real" else 0.0)
|
| 349 |
self.hub.atributo("difusao/latencia_s", r["latencia_s"])
|
| 350 |
+
self.hub.atributo("difusao/rotas", float(len(self.rotas)))
|
| 351 |
return r
|
| 352 |
|
| 353 |
# ---------------- degradação honesta (Teorema 17.2) ----------------
|
|
|
|
| 359 |
"passos": self.passos, "guia": self.guia, **params}
|
| 360 |
|
| 361 |
def imagem_para_bytes(self, img) -> bytes:
|
| 362 |
+
"""PIL.Image → PNG bytes (persistência sem segredos; usado no
|
| 363 |
+
retorno do ciclo fechado desde a v12)."""
|
| 364 |
buf = io.BytesIO()
|
| 365 |
img.save(buf, format="PNG")
|
| 366 |
return buf.getvalue()
|
|
|
|
| 368 |
def estatisticas(self) -> dict:
|
| 369 |
return {"modo": self.modo, "repo": self.repo_id,
|
| 370 |
"device": self.device, "pipelines": list(self._pipelines),
|
| 371 |
+
"rotas": self.rotas[-8:], "n_rotas": len(self.rotas),
|
| 372 |
"eventos": self.eventos[-5:]}
|
src/khtst/mamba3/__init__.py
CHANGED
|
@@ -1,14 +1,17 @@
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
-
"""Pacote MAMBA-3 híbrido (v11,
|
| 3 |
-
híbrido 5:1 com NoPE attention
|
|
|
|
| 4 |
activation checkpointing. Fonte: arquivo MAMBA_3.txt (estudado e
|
| 5 |
-
aprimorado — provas em docs/matematica/22
|
| 6 |
from khtst.mamba3.kernel import varredura_trapezoidal, Mamba3Funcao
|
| 7 |
-
from khtst.mamba3.hybrid import (NoPEAtencao, Mamba3Camada,
|
| 8 |
-
eh_camada_atencao)
|
|
|
|
| 9 |
from khtst.mamba3.mamba3vl import (Mamba3VLProjecao, Mamba3VLCamada,
|
| 10 |
Mamba3VLModelo)
|
| 11 |
|
| 12 |
__all__ = ["varredura_trapezoidal", "Mamba3Funcao", "NoPEAtencao",
|
| 13 |
"Mamba3Camada", "HybridMamba3Modelo", "eh_camada_atencao",
|
|
|
|
| 14 |
"Mamba3VLProjecao", "Mamba3VLCamada", "Mamba3VLModelo"]
|
|
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
+
"""Pacote MAMBA-3 híbrido (v11/v12, docs 22 e 24) — varredura trapezoidal,
|
| 3 |
+
tronco híbrido 5:1 com NoPE attention (v12: TRONCO PRINCIPAL do modelo),
|
| 4 |
+
Mamba-3VL bidirecional (3D-VL com percepção de profundidade — doc 25) e
|
| 5 |
activation checkpointing. Fonte: arquivo MAMBA_3.txt (estudado e
|
| 6 |
+
aprimorado — provas em docs/matematica/22 e 24)."""
|
| 7 |
from khtst.mamba3.kernel import varredura_trapezoidal, Mamba3Funcao
|
| 8 |
+
from khtst.mamba3.hybrid import (EstadoMamba3, NoPEAtencao, Mamba3Camada,
|
| 9 |
+
HybridMamba3Modelo, eh_camada_atencao)
|
| 10 |
+
from khtst.mamba3.tronco import CamadaTroncoM3, TroncoMamba3
|
| 11 |
from khtst.mamba3.mamba3vl import (Mamba3VLProjecao, Mamba3VLCamada,
|
| 12 |
Mamba3VLModelo)
|
| 13 |
|
| 14 |
__all__ = ["varredura_trapezoidal", "Mamba3Funcao", "NoPEAtencao",
|
| 15 |
"Mamba3Camada", "HybridMamba3Modelo", "eh_camada_atencao",
|
| 16 |
+
"EstadoMamba3", "CamadaTroncoM3", "TroncoMamba3",
|
| 17 |
"Mamba3VLProjecao", "Mamba3VLCamada", "Mamba3VLModelo"]
|
src/khtst/mamba3/hybrid.py
CHANGED
|
@@ -29,6 +29,8 @@ posicional artificial (mesmo argumento da fonte para nuvens 3D).
|
|
| 29 |
"""
|
| 30 |
from __future__ import annotations
|
| 31 |
|
|
|
|
|
|
|
| 32 |
import torch
|
| 33 |
import torch.nn as nn
|
| 34 |
import torch.nn.functional as F
|
|
@@ -37,7 +39,24 @@ from torch.utils.checkpoint import checkpoint
|
|
| 37 |
from khtst.mamba3.kernel import varredura_trapezoidal
|
| 38 |
|
| 39 |
__all__ = ["NoPEAtencao", "Mamba3Camada", "HybridMamba3Modelo",
|
| 40 |
-
"eh_camada_atencao"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
|
| 43 |
def eh_camada_atencao(i: int) -> bool:
|
|
@@ -46,7 +65,13 @@ def eh_camada_atencao(i: int) -> bool:
|
|
| 46 |
|
| 47 |
|
| 48 |
class NoPEAtencao(nn.Module):
|
| 49 |
-
"""Self-attention causal SEM embeddings posicionais (NoPE).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
def __init__(self, d_modelo: int, n_cabecas: int):
|
| 52 |
super().__init__()
|
|
@@ -56,16 +81,28 @@ class NoPEAtencao(nn.Module):
|
|
| 56 |
self.dh = d_modelo // n_cabecas
|
| 57 |
self.qkv = nn.Linear(d_modelo, 3 * d_modelo, bias=False)
|
| 58 |
self.saida_proj = nn.Linear(d_modelo, d_modelo, bias=False)
|
|
|
|
|
|
|
| 59 |
|
| 60 |
-
def
|
| 61 |
B, L, D = x.shape
|
| 62 |
q, k, v = self.qkv(x).chunk(3, dim=-1)
|
| 63 |
q = q.view(B, L, self.h, self.dh).transpose(1, 2)
|
| 64 |
k = k.view(B, L, self.h, self.dh).transpose(1, 2)
|
| 65 |
v = v.view(B, L, self.h, self.dh).transpose(1, 2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
# NoPE: NENHUM RoPE/PE em (q, k) — posição vem da máscara (Teo 22.7)
|
| 67 |
out = F.scaled_dot_product_attention(q, k, v, is_causal=True)
|
| 68 |
-
out = out.transpose(1, 2).contiguous().view(
|
| 69 |
return self.saida_proj(out)
|
| 70 |
|
| 71 |
|
|
@@ -90,20 +127,78 @@ class Mamba3Camada(nn.Module):
|
|
| 90 |
self.norm_saida = nn.RMSNorm(d_modelo)
|
| 91 |
self.saida_proj = nn.Linear(d_modelo, d_modelo, bias=False)
|
| 92 |
|
| 93 |
-
def
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
# conv causal: pad esquerdo k−1, sem leitura do futuro (correção 22.3.1)
|
| 97 |
-
uc = F.pad(u.transpose(1, 2), (self.k_conv - 1, 0))
|
| 98 |
-
uc = self.conv1d(uc).transpose(1, 2).contiguous() # (B,L,D) causal
|
| 99 |
xp = self.x_proj(uc)
|
| 100 |
delta_bruto, bc = torch.split(xp, [D, 2 * self.r * self.n], dim=-1)
|
| 101 |
delta = torch.sigmoid(self.dt_proj(delta_bruto)) # δ ∈ (0,1) — Teo 22.3
|
| 102 |
B_m = bc[..., :self.r * self.n].view(B, L, self.r, self.n)
|
| 103 |
C_m = bc[..., self.r * self.n:].view(B, L, self.r, self.n)
|
| 104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
y = self.norm_saida(y)
|
| 106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
|
| 108 |
|
| 109 |
class HybridMamba3Modelo(nn.Module):
|
|
|
|
| 29 |
"""
|
| 30 |
from __future__ import annotations
|
| 31 |
|
| 32 |
+
import math
|
| 33 |
+
|
| 34 |
import torch
|
| 35 |
import torch.nn as nn
|
| 36 |
import torch.nn.functional as F
|
|
|
|
| 39 |
from khtst.mamba3.kernel import varredura_trapezoidal
|
| 40 |
|
| 41 |
__all__ = ["NoPEAtencao", "Mamba3Camada", "HybridMamba3Modelo",
|
| 42 |
+
"eh_camada_atencao", "EstadoMamba3"]
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
class EstadoMamba3:
|
| 46 |
+
"""Estado recorrente de UMA Mamba3Camada para decode INCREMENTAL
|
| 47 |
+
(v12, Teorema 24.13 — equivalência exata com a varredura paralela):
|
| 48 |
+
• h: (B, D, N) — estado do SSM h_t (h₀ = 0, convensão de estado frio);
|
| 49 |
+
• janela: (B, k−1, D) — os k−1 últimos valores de u PRÉ-CONVOLUÇÃO
|
| 50 |
+
(a conv causal no passo t lê u_{t−k+1..t} — Teo 24.13.1).
|
| 51 |
+
Invariante provado: passo(estado, u_t) reproduz a varredura paralela
|
| 52 |
+
com erro APENAS de ponto flutuante (mesma recorrencia trapezoidal).
|
| 53 |
+
"""
|
| 54 |
+
|
| 55 |
+
__slots__ = ("h", "janela")
|
| 56 |
+
|
| 57 |
+
def __init__(self, h: torch.Tensor, janela: torch.Tensor):
|
| 58 |
+
self.h = h
|
| 59 |
+
self.janela = janela
|
| 60 |
|
| 61 |
|
| 62 |
def eh_camada_atencao(i: int) -> bool:
|
|
|
|
| 65 |
|
| 66 |
|
| 67 |
class NoPEAtencao(nn.Module):
|
| 68 |
+
"""Self-attention causal SEM embeddings posicionais (NoPE).
|
| 69 |
+
|
| 70 |
+
v12 (QK-Clip, doc 24 §4): com `medir_logit=True` no forward, registra
|
| 71 |
+
`ultimo_logit_max` (escalar, por chamada — máximo sobre cabeças/lote)
|
| 72 |
+
do logit bruto q·k/√dh — consumido pelo MuonClipAdamW.aplicar_qk_clip
|
| 73 |
+
(Teoremas 24.7/24.8: escala W_q ⇒ ℓ_max ≤ τ sem tocar W_k/W_v).
|
| 74 |
+
"""
|
| 75 |
|
| 76 |
def __init__(self, d_modelo: int, n_cabecas: int):
|
| 77 |
super().__init__()
|
|
|
|
| 81 |
self.dh = d_modelo // n_cabecas
|
| 82 |
self.qkv = nn.Linear(d_modelo, 3 * d_modelo, bias=False)
|
| 83 |
self.saida_proj = nn.Linear(d_modelo, d_modelo, bias=False)
|
| 84 |
+
self.medir_logit: bool = False # ligado pelo treinador (MuonClip)
|
| 85 |
+
self.ultimo_logit_max: float | None = None
|
| 86 |
|
| 87 |
+
def _partir(self, x: torch.Tensor):
|
| 88 |
B, L, D = x.shape
|
| 89 |
q, k, v = self.qkv(x).chunk(3, dim=-1)
|
| 90 |
q = q.view(B, L, self.h, self.dh).transpose(1, 2)
|
| 91 |
k = k.view(B, L, self.h, self.dh).transpose(1, 2)
|
| 92 |
v = v.view(B, L, self.h, self.dh).transpose(1, 2)
|
| 93 |
+
return q, k, v
|
| 94 |
+
|
| 95 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 96 |
+
q, k, v = self._partir(x)
|
| 97 |
+
if self.medir_logit and self.training:
|
| 98 |
+
with torch.no_grad():
|
| 99 |
+
# logit bruto por cabeça (Teo 24.7 — W_q escala linearmente
|
| 100 |
+
# o logit); máx sobre lote/posições/cabeças
|
| 101 |
+
pont = (q @ k.transpose(-2, -1)) / math.sqrt(self.dh)
|
| 102 |
+
self.ultimo_logit_max = float(pont.max().detach())
|
| 103 |
# NoPE: NENHUM RoPE/PE em (q, k) — posição vem da máscara (Teo 22.7)
|
| 104 |
out = F.scaled_dot_product_attention(q, k, v, is_causal=True)
|
| 105 |
+
out = out.transpose(1, 2).contiguous().view(x.shape[0], x.shape[1], self.d)
|
| 106 |
return self.saida_proj(out)
|
| 107 |
|
| 108 |
|
|
|
|
| 127 |
self.norm_saida = nn.RMSNorm(d_modelo)
|
| 128 |
self.saida_proj = nn.Linear(d_modelo, d_modelo, bias=False)
|
| 129 |
|
| 130 |
+
def _projetos(self, uc: torch.Tensor):
|
| 131 |
+
"""δ, B̄, C̄ a partir de uc já convoluído (compartilhado fwd/decode)."""
|
| 132 |
+
B, L, D = uc.shape
|
|
|
|
|
|
|
|
|
|
| 133 |
xp = self.x_proj(uc)
|
| 134 |
delta_bruto, bc = torch.split(xp, [D, 2 * self.r * self.n], dim=-1)
|
| 135 |
delta = torch.sigmoid(self.dt_proj(delta_bruto)) # δ ∈ (0,1) — Teo 22.3
|
| 136 |
B_m = bc[..., :self.r * self.n].view(B, L, self.r, self.n)
|
| 137 |
C_m = bc[..., self.r * self.n:].view(B, L, self.r, self.n)
|
| 138 |
+
return delta, B_m, C_m
|
| 139 |
+
|
| 140 |
+
def forward(self, x: torch.Tensor,
|
| 141 |
+
estado: EstadoMamba3 | None = None,
|
| 142 |
+
devolve_estado: bool = False):
|
| 143 |
+
"""Modo PARALELO (varredura, L≥1) quando `estado is None`; modo
|
| 144 |
+
INCREMENTAL (decode T=1, Teo 24.13) quando `estado` é fornecido.
|
| 145 |
+
Ambos produzem a MESMA recorrência trapezoidal (equivalência
|
| 146 |
+
bit-a-bit salvo ponto flutuante — testada em test_khtst_v12).
|
| 147 |
+
`devolve_estado=True` (modo paralelo) devolve (y, EstadoMamba3)
|
| 148 |
+
para SEEDAR o decode incremental (prefill da geração)."""
|
| 149 |
+
B, L, D = x.shape
|
| 150 |
+
u, res = self.entrada_proj(x).chunk(2, dim=-1) # (B,L,D) cada
|
| 151 |
+
if estado is None:
|
| 152 |
+
# conv causal: pad esquerdo k−1, sem leitura do futuro (22.3.1)
|
| 153 |
+
uc = F.pad(u.transpose(1, 2), (self.k_conv - 1, 0))
|
| 154 |
+
uc = self.conv1d(uc).transpose(1, 2).contiguous() # (B,L,D)
|
| 155 |
+
delta, B_m, C_m = self._projetos(uc)
|
| 156 |
+
if devolve_estado:
|
| 157 |
+
y, h_final = varredura_trapezoidal(uc, delta, self.A, B_m,
|
| 158 |
+
C_m, devolve_estado=True)
|
| 159 |
+
else:
|
| 160 |
+
y = varredura_trapezoidal(uc, delta, self.A, B_m, C_m)
|
| 161 |
+
else:
|
| 162 |
+
assert L == 1, "modo incremental recebe T=1"
|
| 163 |
+
# (i) conv causal INCREMENTAL: [janela k−1 últimos u] ⊕ u_t —
|
| 164 |
+
# exatamente o pad esquerdo da varredura (Teo 24.13.1).
|
| 165 |
+
# conv1d é GROUPED (groups=D): peso (D,1,k) → (k,D) por canal.
|
| 166 |
+
janela = torch.cat([estado.janela, u], dim=1) # (B, k, D)
|
| 167 |
+
pesos = self.conv1d.weight.squeeze(1).t() # (k, D)
|
| 168 |
+
uc = (janela * pesos.unsqueeze(0)).sum(dim=1, keepdim=True) \
|
| 169 |
+
+ self.conv1d.bias.unsqueeze(0).unsqueeze(1) # (B,1,D)
|
| 170 |
+
delta, B_m, C_m = self._projetos(uc) # (B,1,·)
|
| 171 |
+
# (ii) recorrencia trapezoidal UM passo (mesma do kernel —
|
| 172 |
+
# Teorema 22.2): h ← αh + (δ/2)(1+α)B̄·uc_t — a entrada do
|
| 173 |
+
# SSM é uc PÓS-CONVOLUÇÃO (igual ao kernel paralelo!)
|
| 174 |
+
alpha = torch.exp(delta.unsqueeze(-1) * self.A.unsqueeze(0))
|
| 175 |
+
b_bar = B_m.sum(dim=2) # (B,1,N)
|
| 176 |
+
h = alpha[:, 0] * estado.h \
|
| 177 |
+
+ (0.5 * delta[:, 0].unsqueeze(-1) * (1.0 + alpha[:, 0])) \
|
| 178 |
+
* b_bar[:, 0].unsqueeze(1) * uc[:, 0].unsqueeze(-1)
|
| 179 |
+
c_bar = C_m.sum(dim=2) # (B,1,N)
|
| 180 |
+
# leitura: out_t,d = Σ_n h_{t,d,n}·c̄_{t,n} → (B,1,D) (eixo token
|
| 181 |
+
# preservado — RMSNorm espera (..., D), como na varredura)
|
| 182 |
+
y = (h * c_bar[:, 0].unsqueeze(1)).sum(-1).unsqueeze(1)
|
| 183 |
+
# (iii) estado novo (in-place seguro fora do autograd do passo)
|
| 184 |
+
estado.h = h
|
| 185 |
+
estado.janela = janela[:, 1:].detach()
|
| 186 |
y = self.norm_saida(y)
|
| 187 |
+
saida = self.saida_proj(y * F.silu(res)) + x # residual neutro
|
| 188 |
+
if estado is None and devolve_estado:
|
| 189 |
+
est = EstadoMamba3(h_final.detach(),
|
| 190 |
+
u[:, -(self.k_conv - 1):].detach()
|
| 191 |
+
if self.k_conv > 1 else u[:, :0].detach())
|
| 192 |
+
return saida, est
|
| 193 |
+
return saida
|
| 194 |
+
|
| 195 |
+
def estado_inicial(self, lote: int, dispositivo, dtype) -> EstadoMamba3:
|
| 196 |
+
"""Estado frio: h₀ = 0, janela = 0 (idêntica à varredura paralela —
|
| 197 |
+
o pad esquerdo de zeros equivale à janela nula, Teo 24.13)."""
|
| 198 |
+
return EstadoMamba3(
|
| 199 |
+
h=torch.zeros(lote, self.d, self.n, dtype=dtype, device=dispositivo),
|
| 200 |
+
janela=torch.zeros(lote, self.k_conv - 1, self.d,
|
| 201 |
+
dtype=dtype, device=dispositivo))
|
| 202 |
|
| 203 |
|
| 204 |
class HybridMamba3Modelo(nn.Module):
|
src/khtst/mamba3/kernel.py
CHANGED
|
@@ -30,7 +30,8 @@ __all__ = ["varredura_trapezoidal", "Mamba3Funcao"]
|
|
| 30 |
|
| 31 |
|
| 32 |
def varredura_trapezoidal(u: torch.Tensor, delta: torch.Tensor, A: torch.Tensor,
|
| 33 |
-
B_m: torch.Tensor, C_m: torch.Tensor
|
|
|
|
| 34 |
"""Varredura causal seletiva MAMBA-3.
|
| 35 |
|
| 36 |
Formas:
|
|
@@ -41,6 +42,11 @@ def varredura_trapezoidal(u: torch.Tensor, delta: torch.Tensor, A: torch.Tensor,
|
|
| 41 |
C_m: (B, L, R, N) projeção de leitura MIMO (rank R)
|
| 42 |
Devolve out: (B, L, D) com out_t,d = Σ_n (Σ_r C_{t,r,n}) · h_{t,d,n}.
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
Laço temporal O(L) vetorizado sobre (B, D, N, R) — CPU/GPU sem kernel
|
| 45 |
custom; exato no tempo (sem aproximação além da própria regra do
|
| 46 |
trapézio, que é a DEFINIÇÃO do MAMBA-3 — Teorema 22.2).
|
|
@@ -68,7 +74,10 @@ def varredura_trapezoidal(u: torch.Tensor, delta: torch.Tensor, A: torch.Tensor,
|
|
| 68 |
h = alpha[:, t] * h + entrada[:, t]
|
| 69 |
# leitura: out_t,d = Σ_n h_{t,d,n}·c̄_{t,n}
|
| 70 |
saidas.append((h * c_bar[:, t].unsqueeze(1)).sum(-1))
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
|
| 74 |
class Mamba3Funcao(torch.autograd.Function):
|
|
|
|
| 30 |
|
| 31 |
|
| 32 |
def varredura_trapezoidal(u: torch.Tensor, delta: torch.Tensor, A: torch.Tensor,
|
| 33 |
+
B_m: torch.Tensor, C_m: torch.Tensor,
|
| 34 |
+
devolve_estado: bool = False):
|
| 35 |
"""Varredura causal seletiva MAMBA-3.
|
| 36 |
|
| 37 |
Formas:
|
|
|
|
| 42 |
C_m: (B, L, R, N) projeção de leitura MIMO (rank R)
|
| 43 |
Devolve out: (B, L, D) com out_t,d = Σ_n (Σ_r C_{t,r,n}) · h_{t,d,n}.
|
| 44 |
|
| 45 |
+
v12 — `devolve_estado=True` devolve TAMBÉM h_final: (B, D, N), o estado
|
| 46 |
+
h_L da recorrência (Teorema 24.13: h_L é EXATAMENTE o estado que o
|
| 47 |
+
decode incremental recebe — mesma recorrência, então
|
| 48 |
+
varredura(u_{1..L}) ⊕ passo(u_{L+1}) ≡ varredura(u_{1..L+1})).
|
| 49 |
+
|
| 50 |
Laço temporal O(L) vetorizado sobre (B, D, N, R) — CPU/GPU sem kernel
|
| 51 |
custom; exato no tempo (sem aproximação além da própria regra do
|
| 52 |
trapézio, que é a DEFINIÇÃO do MAMBA-3 — Teorema 22.2).
|
|
|
|
| 74 |
h = alpha[:, t] * h + entrada[:, t]
|
| 75 |
# leitura: out_t,d = Σ_n h_{t,d,n}·c̄_{t,n}
|
| 76 |
saidas.append((h * c_bar[:, t].unsqueeze(1)).sum(-1))
|
| 77 |
+
out = torch.stack(saidas, dim=1) # (B, L, D)
|
| 78 |
+
if devolve_estado:
|
| 79 |
+
return out, h # h_final (B, D, N)
|
| 80 |
+
return out
|
| 81 |
|
| 82 |
|
| 83 |
class Mamba3Funcao(torch.autograd.Function):
|
src/khtst/mamba3/mamba3vl.py
CHANGED
|
@@ -31,23 +31,39 @@ from torch.utils.checkpoint import checkpoint
|
|
| 31 |
|
| 32 |
from khtst.mamba3.kernel import varredura_trapezoidal
|
| 33 |
from khtst.mamba3.hybrid import NoPEAtencao, eh_camada_atencao
|
|
|
|
| 34 |
|
| 35 |
__all__ = ["Mamba3VLProjecao", "Mamba3VLCamada", "Mamba3VLModelo"]
|
| 36 |
|
| 37 |
|
| 38 |
class Mamba3VLProjecao(nn.Module):
|
| 39 |
-
"""Alinhamento de nuvem de pontos 3D ⊕ texto no espaço latente comum.
|
| 40 |
-
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
super().__init__()
|
| 43 |
self.extrator_pontos = nn.Sequential(
|
| 44 |
nn.Linear(3, 64), nn.GELU(), nn.Linear(64, d_modelo))
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
self.emb_texto = nn.Embedding(vocab, d_modelo)
|
| 46 |
nn.init.normal_(self.emb_texto.weight, std=0.02)
|
| 47 |
|
| 48 |
def forward(self, pontos_3d: torch.Tensor, ids_texto: torch.Tensor):
|
| 49 |
"""pontos_3d: (B, P, 3); ids_texto: (B, T) → (B, P+T, D)."""
|
| 50 |
v = self.extrator_pontos(pontos_3d) # (B, P, D)
|
|
|
|
|
|
|
| 51 |
t = self.emb_texto(ids_texto) # (B, T, D)
|
| 52 |
return torch.cat([v, t], dim=1) # intercalamento
|
| 53 |
|
|
@@ -99,15 +115,19 @@ class Mamba3VLCamada(nn.Module):
|
|
| 99 |
|
| 100 |
|
| 101 |
class Mamba3VLModelo(nn.Module):
|
| 102 |
-
"""Modelo 3D-VL híbrido: projeção +
|
|
|
|
| 103 |
|
| 104 |
def __init__(self, d_modelo: int, n_camadas: int = 6, n_cabecas: int = 4,
|
| 105 |
d_estado: int = 16, rank_mimo: int = 4, vocab: int = 30522,
|
| 106 |
-
grad_checkpointing: bool = True
|
|
|
|
| 107 |
super().__init__()
|
| 108 |
self.d = d_modelo
|
| 109 |
self.grad_checkpointing = bool(grad_checkpointing)
|
| 110 |
-
self.projecao = Mamba3VLProjecao(d_modelo, vocab=vocab
|
|
|
|
|
|
|
| 111 |
self.camadas = nn.ModuleList()
|
| 112 |
for i in range(n_camadas):
|
| 113 |
if eh_camada_atencao(i):
|
|
|
|
| 31 |
|
| 32 |
from khtst.mamba3.kernel import varredura_trapezoidal
|
| 33 |
from khtst.mamba3.hybrid import NoPEAtencao, eh_camada_atencao
|
| 34 |
+
from khtst.percepcao.profundidade import CodificadorProfundidade
|
| 35 |
|
| 36 |
__all__ = ["Mamba3VLProjecao", "Mamba3VLCamada", "Mamba3VLModelo"]
|
| 37 |
|
| 38 |
|
| 39 |
class Mamba3VLProjecao(nn.Module):
|
| 40 |
+
"""Alinhamento de nuvem de pontos 3D ⊕ texto no espaço latente comum.
|
| 41 |
+
|
| 42 |
+
v12 (doc 25 §§1–5): a projeção soma os canais PROVADOS de percepção
|
| 43 |
+
— profundidade (bins ordinais T25.1), distância radial (Lipschitz
|
| 44 |
+
T25.2) e camadas topológicas (T25.3) — com fusão NÃO-EXPANSIVA
|
| 45 |
+
(T25.4): o embedding de cada ponto é
|
| 46 |
+
v_p = MLP(p) + E_prof(z_p) + E_dist(r_p) + E_cama(c_p)
|
| 47 |
+
e a percepção de profundidade/distância/camadas é ACCELERADA porque
|
| 48 |
+
NÃO há pares (i,j) — O(P) em vez de O(P²) (T25.5)."""
|
| 49 |
+
|
| 50 |
+
def __init__(self, d_modelo: int, vocab: int = 30522,
|
| 51 |
+
d_cod: int = 24, n_bins: int = 16, n_camadas_prof: int = 4):
|
| 52 |
super().__init__()
|
| 53 |
self.extrator_pontos = nn.Sequential(
|
| 54 |
nn.Linear(3, 64), nn.GELU(), nn.Linear(64, d_modelo))
|
| 55 |
+
self.prof = CodificadorProfundidade(d_cod=d_cod, n_bins=n_bins,
|
| 56 |
+
n_camadas=n_camadas_prof)
|
| 57 |
+
self.compactar_prof = nn.Linear(self.prof.d_cod, d_modelo, bias=False)
|
| 58 |
+
nn.init.zeros_(self.compactar_prof.weight) # nascimento NEUTRO
|
| 59 |
self.emb_texto = nn.Embedding(vocab, d_modelo)
|
| 60 |
nn.init.normal_(self.emb_texto.weight, std=0.02)
|
| 61 |
|
| 62 |
def forward(self, pontos_3d: torch.Tensor, ids_texto: torch.Tensor):
|
| 63 |
"""pontos_3d: (B, P, 3); ids_texto: (B, T) → (B, P+T, D)."""
|
| 64 |
v = self.extrator_pontos(pontos_3d) # (B, P, D)
|
| 65 |
+
e_prof = self.compactar_prof(self.prof(pontos_3d)) # (B, P, D)
|
| 66 |
+
v = v + e_prof # T25.4 (não-expansiva)
|
| 67 |
t = self.emb_texto(ids_texto) # (B, T, D)
|
| 68 |
return torch.cat([v, t], dim=1) # intercalamento
|
| 69 |
|
|
|
|
| 115 |
|
| 116 |
|
| 117 |
class Mamba3VLModelo(nn.Module):
|
| 118 |
+
"""Modelo 3D-VL híbrido: projeção (+ percepção PROVADA doc 25) + tronco
|
| 119 |
+
5:1 bidirecional (NoPE global)."""
|
| 120 |
|
| 121 |
def __init__(self, d_modelo: int, n_camadas: int = 6, n_cabecas: int = 4,
|
| 122 |
d_estado: int = 16, rank_mimo: int = 4, vocab: int = 30522,
|
| 123 |
+
grad_checkpointing: bool = True, d_cod: int = 24,
|
| 124 |
+
n_bins: int = 16, n_camadas_prof: int = 4):
|
| 125 |
super().__init__()
|
| 126 |
self.d = d_modelo
|
| 127 |
self.grad_checkpointing = bool(grad_checkpointing)
|
| 128 |
+
self.projecao = Mamba3VLProjecao(d_modelo, vocab=vocab, d_cod=d_cod,
|
| 129 |
+
n_bins=n_bins,
|
| 130 |
+
n_camadas_prof=n_camadas_prof)
|
| 131 |
self.camadas = nn.ModuleList()
|
| 132 |
for i in range(n_camadas):
|
| 133 |
if eh_camada_atencao(i):
|
src/khtst/mamba3/tronco.py
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""TRONCO MAMBA-3 v12 — substituição DO TRANSFORMER (requisito do usuário).
|
| 3 |
+
|
| 4 |
+
O tronco causal principal do KHTST deixa de ser `BlocoV3` (MixtureOfAttention
|
| 5 |
+
softmax + microunidades) e passa a ser UMA PILHA HÍBRIDA MAMBA-3 na proporção
|
| 6 |
+
EXATA do requisito do projeto: 5 camadas MAMBA-3 para cada 1 camada de
|
| 7 |
+
self-attention NoPE (eh_camada_atencao: (i+1)%6==0 ⇒ [M,M,M,M,M,A] por
|
| 8 |
+
período de 6).
|
| 9 |
+
|
| 10 |
+
CADA `CamadaTroncoM3` tem DOIS sub-blocos (paradigma pré-norm + residual,
|
| 11 |
+
Teorema 24.12 — gradiente identidade no nascimento):
|
| 12 |
+
1. subcamada SEQUENCIAL: Mamba3Camada (varredura O(T) seletiva, estado
|
| 13 |
+
recorrente) ou NoPEAtencao (fusão global periódica, QK-clip);
|
| 14 |
+
2. subcamada DE CANAL: ComposicaoMicroUnidades (com MoE agrupável — doc 11)
|
| 15 |
+
nas camadas configuradas, ou MLP SwiGLU nas demais.
|
| 16 |
+
|
| 17 |
+
INTERFACE IDÊNTICA à do BlocoV3 (troca DROP-IN):
|
| 18 |
+
forward(x, cache_k, cache_v, kv_max, coletar, tarefa) → (x, k, v)
|
| 19 |
+
reset_estado() — limpa estados Mamba-3 (h, janela) e cache KV
|
| 20 |
+
Assim `gerar()`, `contexto()`, `alinhar_som()`, MTP e telemetria NÃO mudam.
|
| 21 |
+
|
| 22 |
+
DECODIFICAÇÃO INCREMENTAL (Teorema 24.13): no prefill (T>1) cada Mamba3
|
| 23 |
+
roda a varredura paralela e SED o estado (h_L, janela u_{L−k+2..L}); no
|
| 24 |
+
decode (T=1) cada Mamba3 aplica a recorrência de UM passo — provadamente
|
| 25 |
+
idêntica à extensão da varredura (mesma equação do trapézio). A NoPE
|
| 26 |
+
continua com KV-cache (1 camada a cada 6 — memória O(L·d) só nela).
|
| 27 |
+
|
| 28 |
+
CUSTO (Teorema 24.14 — por que substituir): tronco transformer O(T²·d);
|
| 29 |
+
tronco híbrido 5:1: O(5·T·d·(d+N)+T·d²/6 + T²·d/6) — para T ≥ T* = 6·(5·d·N
|
| 30 |
+
+ d²)/d ≈ 240 (d=192, N=16) o híbrido já é MAIS BARATO, e a NoPE periódica
|
| 31 |
+
mantém o acesso global O(T²) CONFINADO a 1/6 das camadas (para T=256: FLOPs
|
| 32 |
+
de atenção reduzem ~6× e a memória de ativação de atenção cai 6×).
|
| 33 |
+
|
| 34 |
+
MoE / ROTEADOR / MICRUNIDADES / CRESCIMENTO: preservados — o composto de
|
| 35 |
+
microunidades vive nas MESMAS posições relativas (camadas pares 0,2,4 —
|
| 36 |
+
mesma contagem de compositores do v10) e a MoE enc-dec fica na camada
|
| 37 |
+
composta mais alta (índice 4), com o RoteadorSSOM compartilhado como antes.
|
| 38 |
+
"""
|
| 39 |
+
from __future__ import annotations
|
| 40 |
+
|
| 41 |
+
import torch
|
| 42 |
+
import torch.nn as nn
|
| 43 |
+
|
| 44 |
+
from khtst.mamba3.hybrid import (EstadoMamba3, Mamba3Camada, NoPEAtencao,
|
| 45 |
+
eh_camada_atencao)
|
| 46 |
+
from khtst.percepcao.blocos import MLP_SwiGLU, RMSNorm
|
| 47 |
+
from khtst.percepcao.microunidades import ComposicaoMicroUnidades
|
| 48 |
+
|
| 49 |
+
__all__ = ["CamadaTroncoM3", "TroncoMamba3"]
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
class CamadaTroncoM3(nn.Module):
|
| 53 |
+
"""Camada do tronco híbrido MAMBA-3 (5:1 NoPE) + canal (micro/FFN).
|
| 54 |
+
|
| 55 |
+
Interface compatível com BlocoV3 — troca DROP-IN no `KHTSTModel`."""
|
| 56 |
+
|
| 57 |
+
def __init__(self, d: int, indice: int, n_cabecas: int, d_ff: int,
|
| 58 |
+
d_estado: int = 16, rank_mimo: int = 4,
|
| 59 |
+
com_microunidades: bool = True, moe=None,
|
| 60 |
+
cfg_micra: dict | None = None, dropout: float = 0.0):
|
| 61 |
+
super().__init__()
|
| 62 |
+
self.indice = indice
|
| 63 |
+
self.eh_atencao = eh_camada_atencao(indice)
|
| 64 |
+
self.norm1 = RMSNorm(d)
|
| 65 |
+
if self.eh_atencao:
|
| 66 |
+
self.mista = NoPEAtencao(d, n_cabecas) # 1 a cada 6
|
| 67 |
+
self.mamba3: Mamba3Camada | None = None
|
| 68 |
+
else:
|
| 69 |
+
self.mamba3 = Mamba3Camada(d, d_estado, rank_mimo)
|
| 70 |
+
self.mista: NoPEAtencao | None = None
|
| 71 |
+
self._estado_m3: EstadoMamba3 | None = None
|
| 72 |
+
# subcamada de canal (2ª): micro+MoE nas pares; FFN SwiGLU nas ímpares
|
| 73 |
+
self.composto = ComposicaoMicroUnidades(d, cfg_micra or {}, moe=moe) \
|
| 74 |
+
if com_microunidades else None
|
| 75 |
+
self.norm2 = RMSNorm(d)
|
| 76 |
+
if self.composto is None:
|
| 77 |
+
self.ffn = MLP_SwiGLU(d, d_ff)
|
| 78 |
+
else:
|
| 79 |
+
self.ffn = None
|
| 80 |
+
self.moe = moe # compatibilidade com telemetria v2
|
| 81 |
+
self._tarefa_corrente: str | None = None
|
| 82 |
+
|
| 83 |
+
# ----------------------------------------------------------- forward
|
| 84 |
+
def forward(self, x, cache_k=None, cache_v=None, kv_max=512, coletar=None,
|
| 85 |
+
tarefa=None):
|
| 86 |
+
"""x: (B, T, d). Devolve (x, k, v) — k/v da NoPE (None nas Mamba3),
|
| 87 |
+
interface v2 preservada. Decode incremental: T==1 + `_geracao` ativa
|
| 88 |
+
usa o estado Mamba-3 sedado pelo prefill (Teo 24.13)."""
|
| 89 |
+
self._tarefa_corrente = tarefa
|
| 90 |
+
# --- 1) subcamada sequencial ---
|
| 91 |
+
h = self.norm1(x)
|
| 92 |
+
if self.mamba3 is not None:
|
| 93 |
+
if x.shape[1] == 1 and getattr(self, "_geracao", False) \
|
| 94 |
+
and self._estado_m3 is not None:
|
| 95 |
+
h = self.mamba3(h, estado=self._estado_m3) # T=1 incremental
|
| 96 |
+
elif getattr(self, "_geracao", False):
|
| 97 |
+
h, self._estado_m3 = self.mamba3(h, devolve_estado=True)
|
| 98 |
+
else:
|
| 99 |
+
h = self.mamba3(h)
|
| 100 |
+
k = v = None
|
| 101 |
+
x = x + h
|
| 102 |
+
else:
|
| 103 |
+
# NoPE com KV-cache (interface v2: cache entra/sai por camada)
|
| 104 |
+
h2, k, v, _ = self._mista_com_cache(h, cache_k, cache_v, kv_max)
|
| 105 |
+
x = x + h2
|
| 106 |
+
# --- 2) subcamada de canal ---
|
| 107 |
+
if self.composto is not None:
|
| 108 |
+
x = x + self.composto(self.norm2(x), tarefa=tarefa)
|
| 109 |
+
else:
|
| 110 |
+
x = x + self.ffn(self.norm2(x))
|
| 111 |
+
return x, k, v
|
| 112 |
+
|
| 113 |
+
def _mista_com_cache(self, h, cache_k, cache_v, kv_max):
|
| 114 |
+
"""NoPEAtencao sem suporte nativo a cache: no PREFILL (T>1) computa
|
| 115 |
+
k,v e os devolve; no DECODE (T==1) concatena o cache e recalcula a
|
| 116 |
+
atenção só do passo novo (custo O(L) — 1 camada a cada 6, Teo
|
| 117 |
+
24.14). Devolve (h2, k_cache, v_cache, None)."""
|
| 118 |
+
mista = self.mista
|
| 119 |
+
B, T, D = h.shape
|
| 120 |
+
q, k, v = mista._partir(h) # (B, h, T, dh)
|
| 121 |
+
if cache_k is not None and cache_v is not None:
|
| 122 |
+
k = torch.cat([cache_k, k], dim=2)
|
| 123 |
+
v = torch.cat([cache_v, v], dim=2)
|
| 124 |
+
if kv_max and k.shape[2] > kv_max: # janela deslizante
|
| 125 |
+
k = k[:, :, -kv_max:]
|
| 126 |
+
v = v[:, :, -kv_max:]
|
| 127 |
+
import math
|
| 128 |
+
import torch.nn.functional as F
|
| 129 |
+
pont = (q @ k.transpose(-2, -1)) / math.sqrt(mista.dh) # (B,h,T,L)
|
| 130 |
+
if mista.medir_logit and mista.training:
|
| 131 |
+
with torch.no_grad():
|
| 132 |
+
mista.ultimo_logit_max = float(pont.max().detach())
|
| 133 |
+
L = k.shape[2]
|
| 134 |
+
if T == 1:
|
| 135 |
+
pass # decode: pont é (B,h,1,L) — a ÚNICA consulta contra TODAS
|
| 136 |
+
# as L keys do cache (recortar colunas seria errado)
|
| 137 |
+
else: # prefill: causal
|
| 138 |
+
pont = pont + torch.triu(
|
| 139 |
+
torch.full((T, T), float("-inf"), device=h.device), 1) \
|
| 140 |
+
.view(1, 1, T, T)
|
| 141 |
+
pesos = torch.softmax(pont, dim=-1)
|
| 142 |
+
saida = (pesos @ v).transpose(1, 2).contiguous().view(B, T, D)
|
| 143 |
+
return mista.saida_proj(saida), k, v, None
|
| 144 |
+
|
| 145 |
+
# ----------------------------------------------------------- estados
|
| 146 |
+
@torch.no_grad()
|
| 147 |
+
def reset_estado(self):
|
| 148 |
+
"""Limpa o estado recorrente (novo pedido de geração)."""
|
| 149 |
+
self._estado_m3 = None
|
| 150 |
+
if self.mista is not None:
|
| 151 |
+
self.mista.ultimo_logit_max = None
|
| 152 |
+
|
| 153 |
+
def ativar_modo_geracao(self, lote: int, dispositivo, dtype):
|
| 154 |
+
"""Seda estados frios para decode incremental (Teo 24.13)."""
|
| 155 |
+
self._geracao = True
|
| 156 |
+
if self.mamba3 is not None:
|
| 157 |
+
self._estado_m3 = self.mamba3.estado_inicial(lote, dispositivo, dtype)
|
| 158 |
+
|
| 159 |
+
def desativar_modo_geracao(self):
|
| 160 |
+
self._geracao = False
|
| 161 |
+
self._estado_m3 = None
|
| 162 |
+
|
| 163 |
+
def registrar_confianca(self, h_t: float):
|
| 164 |
+
if self.composto is not None:
|
| 165 |
+
self.composto.registrar_confianca(h_t)
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
class TroncoMamba3(nn.Module):
|
| 169 |
+
"""Pilha de `CamadaTroncoM3` — substituto direto de `nn.ModuleList[BlocoV3]`
|
| 170 |
+
com a MESMA superfície pública usada pelo KHTSTModel (iterável + reset)."""
|
| 171 |
+
|
| 172 |
+
def __init__(self, d: int, n_camadas: int, n_cabecas: int, d_ff: int,
|
| 173 |
+
d_estado: int = 16, rank_mimo: int = 4, d_ff_micra: int = 512,
|
| 174 |
+
dropout: float = 0.0, camadas_microunidades: set | None = None,
|
| 175 |
+
moe_para=None, cfg_micra: dict | None = None):
|
| 176 |
+
super().__init__()
|
| 177 |
+
self.d = d
|
| 178 |
+
self.n_camadas = n_camadas
|
| 179 |
+
micra = camadas_microunidades if camadas_microunidades is not None \
|
| 180 |
+
else {i for i in range(n_camadas) if i % 2 == 0}
|
| 181 |
+
self.camadas = nn.ModuleList()
|
| 182 |
+
for i in range(n_camadas):
|
| 183 |
+
moe = moe_para(i) if callable(moe_para) else None
|
| 184 |
+
if i in micra or moe is not None:
|
| 185 |
+
# camada com composto (micro+MoE) — microunidades obrigatória
|
| 186 |
+
# quando há MoE (o MoE vive DENTRO do composto, doc 11 §12)
|
| 187 |
+
self.camadas.append(CamadaTroncoM3(
|
| 188 |
+
d, i, n_cabecas, d_ff, d_estado, rank_mimo,
|
| 189 |
+
com_microunidades=True, moe=moe, cfg_micra=cfg_micra,
|
| 190 |
+
dropout=dropout))
|
| 191 |
+
else:
|
| 192 |
+
self.camadas.append(CamadaTroncoM3(
|
| 193 |
+
d, i, n_cabecas, d_ff, d_estado, rank_mimo,
|
| 194 |
+
com_microunidades=False, cfg_micra=cfg_micra,
|
| 195 |
+
dropout=dropout))
|
| 196 |
+
|
| 197 |
+
# superfície v2 (iterável como ModuleList)
|
| 198 |
+
def __iter__(self):
|
| 199 |
+
return iter(self.camadas)
|
| 200 |
+
|
| 201 |
+
def __len__(self):
|
| 202 |
+
return len(self.camadas)
|
| 203 |
+
|
| 204 |
+
def __getitem__(self, i):
|
| 205 |
+
return self.camadas[i]
|
| 206 |
+
|
| 207 |
+
@torch.no_grad()
|
| 208 |
+
def reset_estado(self):
|
| 209 |
+
for c in self.camadas:
|
| 210 |
+
c.reset_estado()
|
| 211 |
+
|
| 212 |
+
def ativar_modo_geracao(self, lote: int, dispositivo, dtype):
|
| 213 |
+
for c in self.camadas:
|
| 214 |
+
c.ativar_modo_geracao(lote, dispositivo, dtype)
|
| 215 |
+
|
| 216 |
+
def desativar_modo_geracao(self):
|
| 217 |
+
for c in self.camadas:
|
| 218 |
+
c.desativar_modo_geracao()
|
| 219 |
+
|
| 220 |
+
def contar_atencao(self) -> int:
|
| 221 |
+
"""Camadas NoPE (contrato 5:1 do requisito)."""
|
| 222 |
+
return sum(1 for c in self.camadas if c.eh_atencao)
|
| 223 |
+
|
| 224 |
+
def contar_mamba3(self) -> int:
|
| 225 |
+
return sum(1 for c in self.camadas if c.mamba3 is not None)
|
src/khtst/nlp/unidade_nlp.py
CHANGED
|
@@ -2,9 +2,15 @@
|
|
| 2 |
"""UnidadeNLP — especialista de PROCESSAMENTO de linguagem (doc 15 §1) — v4.
|
| 3 |
|
| 4 |
Traços (i) morfo-sintáticos leves via conv de n-gramas de caracteres,
|
| 5 |
-
(ii) intenção/tarefa por cabeça própria
|
| 6 |
(iii) spans de entidade por apontador (pontuações por posição).
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
Enriquecimento ADITIVO com porta g=σ(W_g h): h⁺ = h + g ⊙ Δ(h) — nunca
|
| 9 |
substitui o fluxo do tronco (Teorema 15.1: não-interferência; inicialização
|
| 10 |
com última camada zerada ⇒ Δ=0 no acoplamento).
|
|
@@ -15,6 +21,8 @@ import torch
|
|
| 15 |
import torch.nn as nn
|
| 16 |
import torch.nn.functional as F
|
| 17 |
|
|
|
|
|
|
|
| 18 |
|
| 19 |
class RMSNormLocal(nn.Module):
|
| 20 |
def __init__(self, d: int, eps: float = 1e-6):
|
|
@@ -28,11 +36,10 @@ class RMSNormLocal(nn.Module):
|
|
| 28 |
|
| 29 |
|
| 30 |
class UnidadeNLP(nn.Module):
|
| 31 |
-
#
|
| 32 |
-
INTENCOES = (
|
| 33 |
-
"vqa", "ocr", "imagem_caption", "asr", "nlp-outro")
|
| 34 |
|
| 35 |
-
def __init__(self, d: int = 192, n_intencoes: int =
|
| 36 |
super().__init__()
|
| 37 |
self.d = d
|
| 38 |
# (i) traços morfo-sintáticos: conv 1D sobre embeddings (char n-gram proxy)
|
|
@@ -58,13 +65,14 @@ class UnidadeNLP(nn.Module):
|
|
| 58 |
"""h: (B, T, d) estado oculto. Retorna (h⁺, info).
|
| 59 |
h⁺ = h + g ⊙ Δ([tracos; intencao_emb; entidade]) — Teorema 15.1."""
|
| 60 |
B, T, d = h.shape
|
|
|
|
| 61 |
# (i) traços morfo-sintáticos locais
|
| 62 |
x = h.transpose(1, 2) # (B, d, T)
|
| 63 |
tracos = self.norm_tracos(
|
| 64 |
(self.conv_ngram(x) + self.conv_ngram2(x)).transpose(1, 2)) # (B,T,d)
|
| 65 |
# (ii) intenção — distribuição soft (diferenciável) projetada ao espaço d
|
| 66 |
-
logits_int = self.cabeca_intencao(h.mean(dim=1)) # (B,
|
| 67 |
-
intencao_soft = torch.softmax(logits_int, dim=-1) # (B,
|
| 68 |
emb_int = intencao_soft @ self.matriz_intencao(d) # (B, d)
|
| 69 |
emb_int = emb_int.unsqueeze(1).expand(B, T, d)
|
| 70 |
# (iii) spans de entidade — scores por posição, normalizados por seq
|
|
@@ -91,13 +99,16 @@ class UnidadeNLP(nn.Module):
|
|
| 91 |
return h_mais, info
|
| 92 |
|
| 93 |
def matriz_intencao(self, d: int) -> torch.Tensor:
|
| 94 |
-
"""Projeção
|
| 95 |
-
hash estável (sinusoidal) sem parâmetros extras.
|
| 96 |
-
|
| 97 |
-
|
|
|
|
|
|
|
|
|
|
| 98 |
div = torch.exp(torch.arange(0, d, 2).float()
|
| 99 |
* (-torch.log(torch.tensor(10000.0)) / d))
|
| 100 |
-
pe = torch.zeros(
|
| 101 |
pe[:, 0::2] = torch.sin(pos * div)
|
| 102 |
pe[:, 1::2] = torch.cos(pos * div)
|
| 103 |
self._matriz_int = pe
|
|
|
|
| 2 |
"""UnidadeNLP — especialista de PROCESSAMENTO de linguagem (doc 15 §1) — v4.
|
| 3 |
|
| 4 |
Traços (i) morfo-sintáticos leves via conv de n-gramas de caracteres,
|
| 5 |
+
(ii) intenção/tarefa por cabeça própria,
|
| 6 |
(iii) spans de entidade por apontador (pontuações por posição).
|
| 7 |
|
| 8 |
+
v12 (correção de órfão — doc 25 §1.2): as INTENÇÕES são a TABELA CANÔNICA
|
| 9 |
+
das 12 tarefas (khtst.tarefas.TAREFAS, Teorema 22.1) + "nlp-outro" — o
|
| 10 |
+
v10/v11 tinha uma tupla PARALELA de 9 tarefas que violava a fonte única.
|
| 11 |
+
A matriz de projeção é 13×d e o pigeonhole garante: cada tarefa canônica
|
| 12 |
+
tem EXATAMENTE uma intenção (injetividade — sem divergência possível).
|
| 13 |
+
|
| 14 |
Enriquecimento ADITIVO com porta g=σ(W_g h): h⁺ = h + g ⊙ Δ(h) — nunca
|
| 15 |
substitui o fluxo do tronco (Teorema 15.1: não-interferência; inicialização
|
| 16 |
com última camada zerada ⇒ Δ=0 no acoplamento).
|
|
|
|
| 21 |
import torch.nn as nn
|
| 22 |
import torch.nn.functional as F
|
| 23 |
|
| 24 |
+
from khtst.tarefas import TAREFAS
|
| 25 |
+
|
| 26 |
|
| 27 |
class RMSNormLocal(nn.Module):
|
| 28 |
def __init__(self, d: int, eps: float = 1e-6):
|
|
|
|
| 36 |
|
| 37 |
|
| 38 |
class UnidadeNLP(nn.Module):
|
| 39 |
+
# v12: 12 tarefas canônicas (fonte única khtst.tarefas — Teo 22.1) + out
|
| 40 |
+
INTENCOES = tuple(TAREFAS) + ("nlp-outro",)
|
|
|
|
| 41 |
|
| 42 |
+
def __init__(self, d: int = 192, n_intencoes: int = 13, dropout: float = 0.0):
|
| 43 |
super().__init__()
|
| 44 |
self.d = d
|
| 45 |
# (i) traços morfo-sintáticos: conv 1D sobre embeddings (char n-gram proxy)
|
|
|
|
| 65 |
"""h: (B, T, d) estado oculto. Retorna (h⁺, info).
|
| 66 |
h⁺ = h + g ⊙ Δ([tracos; intencao_emb; entidade]) — Teorema 15.1."""
|
| 67 |
B, T, d = h.shape
|
| 68 |
+
n_int = len(self.INTENCOES)
|
| 69 |
# (i) traços morfo-sintáticos locais
|
| 70 |
x = h.transpose(1, 2) # (B, d, T)
|
| 71 |
tracos = self.norm_tracos(
|
| 72 |
(self.conv_ngram(x) + self.conv_ngram2(x)).transpose(1, 2)) # (B,T,d)
|
| 73 |
# (ii) intenção — distribuição soft (diferenciável) projetada ao espaço d
|
| 74 |
+
logits_int = self.cabeca_intencao(h.mean(dim=1)) # (B, n_int)
|
| 75 |
+
intencao_soft = torch.softmax(logits_int, dim=-1) # (B, n_int)
|
| 76 |
emb_int = intencao_soft @ self.matriz_intencao(d) # (B, d)
|
| 77 |
emb_int = emb_int.unsqueeze(1).expand(B, T, d)
|
| 78 |
# (iii) spans de entidade — scores por posição, normalizados por seq
|
|
|
|
| 99 |
return h_mais, info
|
| 100 |
|
| 101 |
def matriz_intencao(self, d: int) -> torch.Tensor:
|
| 102 |
+
"""Projeção determinística das intenções ao espaço do modelo —
|
| 103 |
+
hash estável (sinusoidal) sem parâmetros extras. v12: o tamanho
|
| 104 |
+
vem da PRÓPRIA CABEÇA (out_features) — consistente com qualquer
|
| 105 |
+
n_intencoes da instância (13 = tabela canônica + nlp-outro)."""
|
| 106 |
+
n_int = self.cabeca_intencao.out_features
|
| 107 |
+
if not hasattr(self, "_matriz_int") or self._matriz_int.shape != (n_int, d):
|
| 108 |
+
pos = torch.arange(n_int).unsqueeze(1).float()
|
| 109 |
div = torch.exp(torch.arange(0, d, 2).float()
|
| 110 |
* (-torch.log(torch.tensor(10000.0)) / d))
|
| 111 |
+
pe = torch.zeros(n_int, d)
|
| 112 |
pe[:, 0::2] = torch.sin(pos * div)
|
| 113 |
pe[:, 1::2] = torch.cos(pos * div)
|
| 114 |
self._matriz_int = pe
|
src/khtst/nucleo/modelo.py
CHANGED
|
@@ -1,18 +1,24 @@
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
-
"""KHTSTModel
|
| 3 |
|
| 4 |
-
Componentes (fundamentados em docs/matematica/00–
|
| 5 |
-
•
|
|
|
|
|
|
|
|
|
|
| 6 |
• LM head empatado (tied) — menos parâmetros (RAM) e regularização embutida;
|
| 7 |
-
• MoE AGRUPÁVEL com foco na tarefa nos
|
| 8 |
-
|
| 9 |
-
indexação o irrelevante);
|
| 10 |
• MTP com α aprendíveis sobre a tabela empatada (doc 10 §3);
|
| 11 |
• encoders multimodais completos (imagem/áudio/vídeo) + fusão por
|
| 12 |
-
cross-attention com gating por modalidade (prefixo no
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
• projetor cooperativo alinhado à memória SOM (perda auxiliar);
|
| 14 |
-
• geração autoregressiva com
|
| 15 |
-
(eq. 10.8/10.9) e top-p;
|
| 16 |
• W8A8 opcional (QAT-STE) na lm_head (doc 08).
|
| 17 |
"""
|
| 18 |
from __future__ import annotations
|
|
@@ -22,19 +28,18 @@ import torch.nn as nn
|
|
| 22 |
import torch.nn.functional as F
|
| 23 |
|
| 24 |
from khtst.percepcao.atencao_moe import RefinamentoEntreMoEs
|
| 25 |
-
from khtst.percepcao.atencao import MixtureOfAttention
|
| 26 |
from khtst.percepcao.classificadores import (temperatura_dinamica,
|
| 27 |
calcular_criterios_dinamicos)
|
| 28 |
from khtst.percepcao.audio import CodificadorAudio
|
| 29 |
-
from khtst.percepcao.blocos import
|
| 30 |
from khtst.percepcao.escalacao import EscaladorComputo, PerfilComputo
|
| 31 |
from khtst.percepcao.fusao import FusaoMultimodal
|
| 32 |
from khtst.percepcao.imagem import CodificadorImagem
|
| 33 |
-
from khtst.percepcao.microunidades import BiGRUNaoCausal
|
| 34 |
from khtst.percepcao.moe import MoEAgrupavel
|
| 35 |
from khtst.percepcao.ortogonais import CamadaCooperativa, CamadaOrtogonal
|
| 36 |
from khtst.percepcao.video import CodificadorVideo
|
| 37 |
from khtst.nlp.unidade_nlp import UnidadeNLP
|
|
|
|
| 38 |
from khtst.nlg.unidade_nlg import UnidadeNLG
|
| 39 |
from khtst.memoria.janela_1m import JanelaContexto1M
|
| 40 |
from khtst.quanta.quantizacao import QATW8A8
|
|
@@ -55,14 +60,16 @@ class KHTSTModel(nn.Module):
|
|
| 55 |
self.d = m.d_modelo
|
| 56 |
self.emb = nn.Embedding(m.vocab, m.d_modelo)
|
| 57 |
nn.init.normal_(self.emb.weight, mean=0.0, std=0.02) # logits ~ N(0, 0.02²d)
|
| 58 |
-
# MoE agrupável:
|
| 59 |
-
#
|
|
|
|
| 60 |
cfg_moe = dict(getattr(m, "moe", {}) or {})
|
| 61 |
self.usar_moe = bool(cfg_moe.get("ativo", True))
|
| 62 |
self.moe_camadas: set[int] = set()
|
| 63 |
-
|
|
|
|
| 64 |
n_moe = int(cfg_moe.get("n_camadas_moe", 2))
|
| 65 |
-
self.moe_camadas = set(
|
| 66 |
def _moe_para(indice: int):
|
| 67 |
if indice not in self.moe_camadas:
|
| 68 |
return None
|
|
@@ -96,10 +103,23 @@ class KHTSTModel(nn.Module):
|
|
| 96 |
n_tarefas=int(cfg_moe.get("n_tarefas", 9)),
|
| 97 |
margem_foco=float(cfg_moe.get("margem_foco", 1.0)),
|
| 98 |
vetorial=bool(cfg_moe.get("vetorial", True)))
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
# v5 (doc 16 §§1–2): atenção ENTRE camadas MoE consecutivas + retro-
|
| 104 |
# alimentação de rotas — nasce neutra (Teorema 16.1c), nunca regride
|
| 105 |
cfg_atn_moe = dict(getattr(m, "atencao_moe", {}) or {})
|
|
@@ -144,7 +164,7 @@ class KHTSTModel(nn.Module):
|
|
| 144 |
self.mtp.definir_peso_emb(self.emb.weight) # v4: rascunho empático
|
| 145 |
# v4 — NLP (processar) e NLG (gerar) como unidades de primeira classe:
|
| 146 |
cfg_nlp = dict(getattr(m, "nlp", {}) or {})
|
| 147 |
-
self.nlp = UnidadeNLP(m.d_modelo, n_intencoes=int(cfg_nlp.get("n_intencoes",
|
| 148 |
if bool(cfg_nlp.get("ativo", True)) else None
|
| 149 |
cfg_nlg = dict(getattr(m, "nlg", {}) or {})
|
| 150 |
self.nlg = UnidadeNLG(m.d_modelo, n_estilos=int(cfg_nlg.get("n_estilos", 8))) \
|
|
@@ -187,29 +207,23 @@ class KHTSTModel(nn.Module):
|
|
| 187 |
self.alpha_jev: float = 0.0 # Teo 21.12 — nasce NEUTRO
|
| 188 |
self.classificador_jev: ClassificadorJev | None = None
|
| 189 |
self._cfg_classificadores = cfg_cl
|
| 190 |
-
#
|
| 191 |
-
#
|
| 192 |
-
#
|
| 193 |
-
# e MAMBA-3VL (3D-VL bidirecional) como modalidade de fusão.
|
| 194 |
cfg_m3 = dict(getattr(m, "mamba3", {}) or {})
|
| 195 |
-
self.mamba3 = None
|
| 196 |
self.mamba3vl = None
|
| 197 |
-
if bool(cfg_m3.get("
|
| 198 |
-
from khtst.mamba3 import
|
| 199 |
-
self.
|
| 200 |
m.d_modelo,
|
| 201 |
-
n_camadas=int(cfg_m3.get("
|
| 202 |
n_cabecas=int(cfg_m3.get("n_cabecas", 4)),
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
m.d_modelo,
|
| 209 |
-
n_camadas=int(cfg_m3.get("n_camadas_vl", 6)),
|
| 210 |
-
n_cabecas=int(cfg_m3.get("n_cabecas", 4)),
|
| 211 |
-
vocab=int(m.vocab),
|
| 212 |
-
grad_checkpointing=bool(cfg_m3.get("grad_checkpointing", True)))
|
| 213 |
# v4 — auto-escala por computo (doc 12): perfil + escalador
|
| 214 |
cfg_esc = dict(getattr(m, "escalacao", {}) or {})
|
| 215 |
self.perfil_computo = PerfilComputo()
|
|
@@ -322,8 +336,10 @@ class KHTSTModel(nn.Module):
|
|
| 322 |
|
| 323 |
@property
|
| 324 |
def compositores(self) -> list:
|
| 325 |
-
"""Compositores de microunidades (para o GestorCrescimento — doc 11 §5).
|
| 326 |
-
|
|
|
|
|
|
|
| 327 |
|
| 328 |
def registrar_confianca(self, h_t: float):
|
| 329 |
"""Distribui h_t (AgenteConfiança) aos compositores — temperatura do
|
|
@@ -357,6 +373,11 @@ class KHTSTModel(nn.Module):
|
|
| 357 |
x, self.ultimo_info_nlp = self.nlp(x) # h⁺ = h + g⊙Δ (doc 15 §1)
|
| 358 |
x = self.norm_f(x)
|
| 359 |
self._ultimo_oculto = x # para MTP sem re-executar o trunk (v2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 360 |
if self.qat:
|
| 361 |
wq = self._qat.quantiza_peso(self.lm_head.weight) # STE (Teorema 8.3)
|
| 362 |
logits = F.linear(x, wq)
|
|
@@ -401,34 +422,24 @@ class KHTSTModel(nn.Module):
|
|
| 401 |
h = h[:, 1:]
|
| 402 |
return self.mtp.perda(h, self.emb.weight, alvo, h_conf=h_conf)
|
| 403 |
|
| 404 |
-
# ----------------
|
| 405 |
-
def oculto_mamba3(self, ids: torch.Tensor
|
| 406 |
-
"""
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
return
|
| 411 |
-
|
| 412 |
-
def perda_mamba3(self, ids: torch.Tensor, alvo: torch.Tensor) -> torch.Tensor | None:
|
| 413 |
-
"""Perda LM do tronco MAMBA-3 (Teorema 22.10): cabeça EMPATADA à
|
| 414 |
-
tabela de embeddings — co-treino multi-arquitetura com CE própria.
|
| 415 |
-
NÃO afeta os logits do decodificador principal (nascimento neutro
|
| 416 |
-
no LM — o KV-cache do decode permanece idêntico ao v10)."""
|
| 417 |
-
if self.mamba3 is None:
|
| 418 |
-
return None
|
| 419 |
-
h = self.mamba3(self.emb(ids)) # (B, T, d)
|
| 420 |
-
logits = F.linear(h, self.emb.weight) # cabeça empatada
|
| 421 |
-
return F.cross_entropy(logits[:, :-1].reshape(-1, logits.shape[-1]),
|
| 422 |
-
alvo[:, 1:].reshape(-1), ignore_index=-100)
|
| 423 |
|
| 424 |
# ---------------- multimodal ----------------
|
| 425 |
-
@torch.no_grad()
|
| 426 |
def codificar_multimodal(self, entradas: dict,
|
| 427 |
ids_texto: torch.Tensor | None = None) -> torch.Tensor | None:
|
| 428 |
"""entradas: {'imagem': (B,3,H,W), 'audio': (B,N), 'video': (B,T,3,H,W),
|
| 429 |
'pontos_3d': (B,P,3) [v11 — 3D-VL], 'texto_emb': (B,d)} → prefixo
|
| 430 |
(B, d) pronto para fusão. v11: Mamba-3VL processa nuvem de pontos
|
| 431 |
-
⊕ texto com varredura bidirecional (Teorema 22.9).
|
|
|
|
|
|
|
|
|
|
| 432 |
if not self.usar_multimodal:
|
| 433 |
return None
|
| 434 |
emb = {}
|
|
@@ -515,8 +526,12 @@ class KHTSTModel(nn.Module):
|
|
| 515 |
ids_prompt = ids_prompt[:1] # amostra única
|
| 516 |
for bloco in self.blocos:
|
| 517 |
bloco.reset_estado()
|
| 518 |
-
|
|
|
|
|
|
|
| 519 |
x = self.emb(ids_prompt) # estados ocultos, não ids!
|
|
|
|
|
|
|
| 520 |
contextos: list[int] = [int(t) for t in ids_prompt[0]]
|
| 521 |
if emb_prefixo is not None:
|
| 522 |
pref = emb_prefixo.to(x.dtype)
|
|
@@ -606,6 +621,8 @@ class KHTSTModel(nn.Module):
|
|
| 606 |
self.janela_1m.registrar_saida(len(buffer_oculto))
|
| 607 |
buffer_oculto = []
|
| 608 |
x = self.emb(torch.tensor([[t]]))
|
|
|
|
|
|
|
| 609 |
self.ultima_metas_calibracao = metas_calibracao
|
| 610 |
return novos
|
| 611 |
|
|
@@ -656,6 +673,50 @@ class KHTSTModel(nn.Module):
|
|
| 656 |
dec = DecodificadorEspeculativoMedusa(self, self.mtp)
|
| 657 |
return dec.gerar(ids_prompt, max_novos=max_novos, **kwargs)
|
| 658 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 659 |
# ---------------- telemetria auxiliares ----------------
|
| 660 |
def metricas_estruturais(self) -> dict:
|
| 661 |
out = {"ortogonalidade": self.alinhamento.metrica_ortogonalidade(),
|
|
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
+
"""KHTSTModel v12 — modelo unificado multimodal.
|
| 3 |
|
| 4 |
+
Componentes (fundamentados em docs/matematica/00–25):
|
| 5 |
+
• v12 — TRONCO MAMBA-3 HÍBRIDO (5:1 NoPE) SUBSTITUI O TRANSFORMER
|
| 6 |
+
(requisito): a pilha causal é CamadaTroncoM3 (Mamba-3 seletivo O(T) +
|
| 7 |
+
1 NoPE a cada 6 + microunidades/MoE nos canais); decode incremental
|
| 8 |
+
provado (Teorema 24.13); otimização MuonClip+AdamW (doc 24);
|
| 9 |
• LM head empatado (tied) — menos parâmetros (RAM) e regularização embutida;
|
| 10 |
+
• MoE AGRUPÁVEL com foco na tarefa nos compostos das últimas camadas
|
| 11 |
+
(doc 10 §1) — fase densa → fase foco;
|
|
|
|
| 12 |
• MTP com α aprendíveis sobre a tabela empatada (doc 10 §3);
|
| 13 |
• encoders multimodais completos (imagem/áudio/vídeo) + fusão por
|
| 14 |
+
cross-attention com gating por modalidade (prefixo no tronco);
|
| 15 |
+
• v11 — Mamba3VL 3D-VL com percepção PROVADA de profundidade/distância/
|
| 16 |
+
camadas (doc 25 — T25.1–T25.5, O(P) vs O(P²));
|
| 17 |
+
• v12 — ACESSO LÓGICO AOS DIFUSORES (doc 25 §8): gerar_imagem roteia
|
| 18 |
+
intenção→operação com embeddings REAIS (Teorema 17.1 aplicado);
|
| 19 |
• projetor cooperativo alinhado à memória SOM (perda auxiliar);
|
| 20 |
+
• geração autoregressiva com estado recorrente Mamba-3 + KV-cache só
|
| 21 |
+
na NoPE, punição DINÂMICA de repetição (eq. 10.8/10.9) e top-p;
|
| 22 |
• W8A8 opcional (QAT-STE) na lm_head (doc 08).
|
| 23 |
"""
|
| 24 |
from __future__ import annotations
|
|
|
|
| 28 |
import torch.nn.functional as F
|
| 29 |
|
| 30 |
from khtst.percepcao.atencao_moe import RefinamentoEntreMoEs
|
|
|
|
| 31 |
from khtst.percepcao.classificadores import (temperatura_dinamica,
|
| 32 |
calcular_criterios_dinamicos)
|
| 33 |
from khtst.percepcao.audio import CodificadorAudio
|
| 34 |
+
from khtst.percepcao.blocos import RMSNorm
|
| 35 |
from khtst.percepcao.escalacao import EscaladorComputo, PerfilComputo
|
| 36 |
from khtst.percepcao.fusao import FusaoMultimodal
|
| 37 |
from khtst.percepcao.imagem import CodificadorImagem
|
|
|
|
| 38 |
from khtst.percepcao.moe import MoEAgrupavel
|
| 39 |
from khtst.percepcao.ortogonais import CamadaCooperativa, CamadaOrtogonal
|
| 40 |
from khtst.percepcao.video import CodificadorVideo
|
| 41 |
from khtst.nlp.unidade_nlp import UnidadeNLP
|
| 42 |
+
from khtst.mamba3.tronco import TroncoMamba3
|
| 43 |
from khtst.nlg.unidade_nlg import UnidadeNLG
|
| 44 |
from khtst.memoria.janela_1m import JanelaContexto1M
|
| 45 |
from khtst.quanta.quantizacao import QATW8A8
|
|
|
|
| 60 |
self.d = m.d_modelo
|
| 61 |
self.emb = nn.Embedding(m.vocab, m.d_modelo)
|
| 62 |
nn.init.normal_(self.emb.weight, mean=0.0, std=0.02) # logits ~ N(0, 0.02²d)
|
| 63 |
+
# MoE agrupável: nas ÚLTIMAS n_camadas_moe camadas COM COMPOSTO
|
| 64 |
+
# (pares — o expert vive no composto de microunidades; com
|
| 65 |
+
# n_camadas=6 e pares {0,2,4}: moe_camadas = {2,4})
|
| 66 |
cfg_moe = dict(getattr(m, "moe", {}) or {})
|
| 67 |
self.usar_moe = bool(cfg_moe.get("ativo", True))
|
| 68 |
self.moe_camadas: set[int] = set()
|
| 69 |
+
pares = [i for i in range(m.n_camadas) if i % 2 == 0]
|
| 70 |
+
if self.usar_moe and pares:
|
| 71 |
n_moe = int(cfg_moe.get("n_camadas_moe", 2))
|
| 72 |
+
self.moe_camadas = set(pares[-n_moe:])
|
| 73 |
def _moe_para(indice: int):
|
| 74 |
if indice not in self.moe_camadas:
|
| 75 |
return None
|
|
|
|
| 103 |
n_tarefas=int(cfg_moe.get("n_tarefas", 9)),
|
| 104 |
margem_foco=float(cfg_moe.get("margem_foco", 1.0)),
|
| 105 |
vetorial=bool(cfg_moe.get("vetorial", True)))
|
| 106 |
+
# v12 (REQUISITO — doc 24 §2): o tronco causal deixa de ser o
|
| 107 |
+
# transformer BlocoV3 e passa a ser a PILHA HÍBRIDA MAMBA-3 (5:1
|
| 108 |
+
# NoPE) — CamadaTroncoM3 preserva a interface (cache_k/v, micro-
|
| 109 |
+
# unidades, MoE, telemetria) e troca a subcamada sequencial por
|
| 110 |
+
# Mamba-3 seletivo O(T) com decode incremental provado (Teo 24.13).
|
| 111 |
+
# moe_camadas referem-se às CAMADAS COM COMPOSTO (pares 0,2,4);
|
| 112 |
+
# microunidades acompanha o MoE (o expert vive no composto).
|
| 113 |
+
cfg_m3_tronco = dict(getattr(m, "mamba3", {}) or {})
|
| 114 |
+
camadas_micra = {i for i in range(m.n_camadas)
|
| 115 |
+
if i % 2 == 0 or i in self.moe_camadas}
|
| 116 |
+
self.blocos = TroncoMamba3(
|
| 117 |
+
m.d_modelo, n_camadas=m.n_camadas, n_cabecas=m.n_cabecas,
|
| 118 |
+
d_ff=m.d_ff, d_estado=int(cfg_m3_tronco.get("d_estado", 16)),
|
| 119 |
+
rank_mimo=int(cfg_m3_tronco.get("rank_mimo", 4)),
|
| 120 |
+
dropout=m.dropout,
|
| 121 |
+
camadas_microunidades=camadas_micra,
|
| 122 |
+
moe_para=_moe_para, cfg_micra=cfg_micra)
|
| 123 |
# v5 (doc 16 §§1–2): atenção ENTRE camadas MoE consecutivas + retro-
|
| 124 |
# alimentação de rotas — nasce neutra (Teorema 16.1c), nunca regride
|
| 125 |
cfg_atn_moe = dict(getattr(m, "atencao_moe", {}) or {})
|
|
|
|
| 164 |
self.mtp.definir_peso_emb(self.emb.weight) # v4: rascunho empático
|
| 165 |
# v4 — NLP (processar) e NLG (gerar) como unidades de primeira classe:
|
| 166 |
cfg_nlp = dict(getattr(m, "nlp", {}) or {})
|
| 167 |
+
self.nlp = UnidadeNLP(m.d_modelo, n_intencoes=int(cfg_nlp.get("n_intencoes", 13))) \
|
| 168 |
if bool(cfg_nlp.get("ativo", True)) else None
|
| 169 |
cfg_nlg = dict(getattr(m, "nlg", {}) or {})
|
| 170 |
self.nlg = UnidadeNLG(m.d_modelo, n_estilos=int(cfg_nlg.get("n_estilos", 8))) \
|
|
|
|
| 207 |
self.alpha_jev: float = 0.0 # Teo 21.12 — nasce NEUTRO
|
| 208 |
self.classificador_jev: ClassificadorJev | None = None
|
| 209 |
self._cfg_classificadores = cfg_cl
|
| 210 |
+
# v12 — MAMBA-3VL (3D-VL bidirecional com percepção PROVADA doc 25):
|
| 211 |
+
# o TRONCO principal já é Mamba-3 híbrido (acima); o VL processa
|
| 212 |
+
# nuvens de pontos ⊕ texto com profundidade/distância/camadas.
|
|
|
|
| 213 |
cfg_m3 = dict(getattr(m, "mamba3", {}) or {})
|
| 214 |
+
self.mamba3 = None # v12: tronco É o híbrido (compat)
|
| 215 |
self.mamba3vl = None
|
| 216 |
+
if bool(cfg_m3.get("ativo_vl", True)):
|
| 217 |
+
from khtst.mamba3 import Mamba3VLModelo
|
| 218 |
+
self.mamba3vl = Mamba3VLModelo(
|
| 219 |
m.d_modelo,
|
| 220 |
+
n_camadas=int(cfg_m3.get("n_camadas_vl", 6)),
|
| 221 |
n_cabecas=int(cfg_m3.get("n_cabecas", 4)),
|
| 222 |
+
vocab=int(m.vocab),
|
| 223 |
+
grad_checkpointing=bool(cfg_m3.get("grad_checkpointing", True)),
|
| 224 |
+
d_cod=int(cfg_m3.get("d_cod_prof", 24)),
|
| 225 |
+
n_bins=int(cfg_m3.get("n_bins_prof", 16)),
|
| 226 |
+
n_camadas_prof=int(cfg_m3.get("n_camadas_prof", 4)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
# v4 — auto-escala por computo (doc 12): perfil + escalador
|
| 228 |
cfg_esc = dict(getattr(m, "escalacao", {}) or {})
|
| 229 |
self.perfil_computo = PerfilComputo()
|
|
|
|
| 336 |
|
| 337 |
@property
|
| 338 |
def compositores(self) -> list:
|
| 339 |
+
"""Compositores de microunidades (para o GestorCrescimento — doc 11 §5).
|
| 340 |
+
v12: filtra None (as camadas ímpares do tronco têm FFN SwiGLU)."""
|
| 341 |
+
return [b.composto for b in self.blocos
|
| 342 |
+
if getattr(b, "composto", None) is not None]
|
| 343 |
|
| 344 |
def registrar_confianca(self, h_t: float):
|
| 345 |
"""Distribui h_t (AgenteConfiança) aos compositores — temperatura do
|
|
|
|
| 373 |
x, self.ultimo_info_nlp = self.nlp(x) # h⁺ = h + g⊙Δ (doc 15 §1)
|
| 374 |
x = self.norm_f(x)
|
| 375 |
self._ultimo_oculto = x # para MTP sem re-executar o trunk (v2)
|
| 376 |
+
# v12 (correção de órfão — doc 23 §4): features do ENSEMBLE vêm do
|
| 377 |
+
# TRONCO MAMBA-3 (que É a pilha principal) — alias explícito; o bug
|
| 378 |
+
# v11 (AttributeError silenciado, features nunca do Mamba-3) morre
|
| 379 |
+
# por construção: o tronco É o híbrido.
|
| 380 |
+
self._ultimo_oculto_mamba3 = x
|
| 381 |
if self.qat:
|
| 382 |
wq = self._qat.quantiza_peso(self.lm_head.weight) # STE (Teorema 8.3)
|
| 383 |
logits = F.linear(x, wq)
|
|
|
|
| 422 |
h = h[:, 1:]
|
| 423 |
return self.mtp.perda(h, self.emb.weight, alvo, h_conf=h_conf)
|
| 424 |
|
| 425 |
+
# ---------------- v12: tronco É o Mamba-3 (doc 24 §2) ----------------
|
| 426 |
+
def oculto_mamba3(self, ids: torch.Tensor | None = None):
|
| 427 |
+
"""v12: o TRONCO PRINCIPAL É o híbrido MAMBA-3 — o estado oculto
|
| 428 |
+
`_ultimo_oculto` do forward recente É o estado do Mamba-3 (mesma
|
| 429 |
+
pilha híbrida 5:1). Mantido por compatibilidade com o ensemble
|
| 430 |
+
(doc 23 §4) e com os tests; `ids` é ignorado (compat v11)."""
|
| 431 |
+
return getattr(self, "_ultimo_oculto", None)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 432 |
|
| 433 |
# ---------------- multimodal ----------------
|
|
|
|
| 434 |
def codificar_multimodal(self, entradas: dict,
|
| 435 |
ids_texto: torch.Tensor | None = None) -> torch.Tensor | None:
|
| 436 |
"""entradas: {'imagem': (B,3,H,W), 'audio': (B,N), 'video': (B,T,3,H,W),
|
| 437 |
'pontos_3d': (B,P,3) [v11 — 3D-VL], 'texto_emb': (B,d)} → prefixo
|
| 438 |
(B, d) pronto para fusão. v11: Mamba-3VL processa nuvem de pontos
|
| 439 |
+
⊕ texto com varredura bidirecional (Teorema 22.9).
|
| 440 |
+
v12: SEM @torch.no_grad() — encoders e Mamba-3VL TREINAM pelo
|
| 441 |
+
gradiente do prefixo (percepção aprendiz real, doc 25); o custo é
|
| 442 |
+
controlado pelo checkpointing do VL e pelos encoders leves."""
|
| 443 |
if not self.usar_multimodal:
|
| 444 |
return None
|
| 445 |
emb = {}
|
|
|
|
| 526 |
ids_prompt = ids_prompt[:1] # amostra única
|
| 527 |
for bloco in self.blocos:
|
| 528 |
bloco.reset_estado()
|
| 529 |
+
# v12 (Teo 24.13) — DECODE INCREMENTAL Mamba-3: seda estados frios
|
| 530 |
+
# (h₀=0, janela nula); o prefill (T>1) os semeia e o decode T=1 usa
|
| 531 |
+
# a recorrência de UM passo (equivalência provada com a varredura)
|
| 532 |
x = self.emb(ids_prompt) # estados ocultos, não ids!
|
| 533 |
+
self.blocos.ativar_modo_geracao(1, x.device, x.dtype)
|
| 534 |
+
caches = [(None, None)] * len(self.blocos) # KV-cache SÓ da NoPE
|
| 535 |
contextos: list[int] = [int(t) for t in ids_prompt[0]]
|
| 536 |
if emb_prefixo is not None:
|
| 537 |
pref = emb_prefixo.to(x.dtype)
|
|
|
|
| 621 |
self.janela_1m.registrar_saida(len(buffer_oculto))
|
| 622 |
buffer_oculto = []
|
| 623 |
x = self.emb(torch.tensor([[t]]))
|
| 624 |
+
# v12 — encerra o modo incremental (estados Mamba-3/KV descartados)
|
| 625 |
+
self.blocos.desativar_modo_geracao()
|
| 626 |
self.ultima_metas_calibracao = metas_calibracao
|
| 627 |
return novos
|
| 628 |
|
|
|
|
| 673 |
dec = DecodificadorEspeculativoMedusa(self, self.mtp)
|
| 674 |
return dec.gerar(ids_prompt, max_novos=max_novos, **kwargs)
|
| 675 |
|
| 676 |
+
# ---------------- v12: ACESSO LÓGICO AOS DIFUSORES (doc 25 §8) --------
|
| 677 |
+
def gerar_imagem(self, prompt: str, gerador, orquestrador=None,
|
| 678 |
+
imagem_base=None, mascara=None, semente: int = 0,
|
| 679 |
+
passo: int | None = None):
|
| 680 |
+
"""Acesso LÓGICO ao difusor (requisito v12 — doc 25 §8):
|
| 681 |
+
1. INTENÇÃO: a UnidadeNLP classifica a tarefa do pedido (rota
|
| 682 |
+
textual com entropia limitada — Teorema 25.9);
|
| 683 |
+
2. ROTEAMENTO: o RoteadorDifusao escolhe op ∈ {txt2img, img2img,
|
| 684 |
+
inpaint} e parâmetros (passos/guia) pela intenção+contexto
|
| 685 |
+
(regra bayesiana provada — Teorema 25.8);
|
| 686 |
+
3. FORÇA SEMÂNTICA (Teo 17.1) com embeddings REAIS: e_in do
|
| 687 |
+
encoder perceptual da imagem-base e e_plano do estado oculto
|
| 688 |
+
do plano textual — o v11 nunca os passava (código morto);
|
| 689 |
+
4. GERAÇÃO determinística (seed) e ciclo fechado: re-encodagem
|
| 690 |
+
pelo encoder perceptual → memória SOM (compreensão geracional).
|
| 691 |
+
Sem diffusers/pesos: modo 'planejado' honesto (Teorema 17.2)."""
|
| 692 |
+
from khtst.geracao.difusao import RoteadorDifusao
|
| 693 |
+
intencao = getattr(self.nlp, "ultima_intencao", None)
|
| 694 |
+
nome_intencao = None
|
| 695 |
+
if intencao is not None and self.nlp is not None:
|
| 696 |
+
if 0 <= intencao < len(self.nlp.INTENCOES):
|
| 697 |
+
nome_intencao = self.nlp.INTENCOES[intencao]
|
| 698 |
+
emb_in = emb_plano = None
|
| 699 |
+
if imagem_base is not None and self.usar_multimodal:
|
| 700 |
+
with torch.no_grad():
|
| 701 |
+
emb_in = self.enc_imagem(imagem_base.unsqueeze(0)) \
|
| 702 |
+
if imagem_base.dim() == 3 else self.enc_imagem(imagem_base)
|
| 703 |
+
emb_in = emb_in.reshape(-1, self.d).mean(dim=0)
|
| 704 |
+
rotulo = RoteadorDifusao.decidir(nome_intencao, bool(imagem_base),
|
| 705 |
+
bool(mascara))
|
| 706 |
+
return gerador.gerar_por_intencao(
|
| 707 |
+
prompt, rotulo=rotulo, modelo=self, orquestrador=orquestrador,
|
| 708 |
+
imagem_base=imagem_base, mascara=mascara, emb_in=emb_in,
|
| 709 |
+
emb_plano=emb_plano, semente=semente, passo=passo)
|
| 710 |
+
|
| 711 |
+
def _ids_do_prompt(self, prompt: str):
|
| 712 |
+
"""Plano textual → ids (usa o tokenizador externo quando injetado
|
| 713 |
+
pelo treinador — sem tokenizador não há plano latente)."""
|
| 714 |
+
tk = getattr(self, "tokenizador_ref", None)
|
| 715 |
+
if tk is None:
|
| 716 |
+
return None
|
| 717 |
+
return torch.tensor([tk.encode(prompt, tarefa=None, max_len=64,
|
| 718 |
+
com_bos=False)])
|
| 719 |
+
|
| 720 |
# ---------------- telemetria auxiliares ----------------
|
| 721 |
def metricas_estruturais(self) -> dict:
|
| 722 |
out = {"ortogonalidade": self.alinhamento.metrica_ortogonalidade(),
|
src/khtst/percepcao/classificadores.py
CHANGED
|
@@ -203,11 +203,12 @@ class ClassificadorJev:
|
|
| 203 |
@torch.no_grad()
|
| 204 |
def escolha(self, x: torch.Tensor, rotulos_criterios: list[str],
|
| 205 |
criterios: torch.Tensor) -> dict:
|
| 206 |
-
"""PRIMITIVO escolha: ranking calibrado + distribuição + meta.
|
|
|
|
| 207 |
assert x.shape[-1] == self.d and criterios.shape[0] == len(rotulos_criterios) \
|
| 208 |
and criterios.shape[0] >= 2, "BUG (contrato doc 21 §4): shapes inválidos"
|
| 209 |
cal, meta = self._logits_calibrados(x, criterios)
|
| 210 |
-
probs = torch.softmax(cal, dim=-1)
|
| 211 |
pares = sorted(zip(rotulos_criterios, (float(p) for p in probs)),
|
| 212 |
key=lambda t: t[1], reverse=True)
|
| 213 |
return {"escolha": [r for r, _ in pares],
|
|
@@ -219,7 +220,7 @@ class ClassificadorJev:
|
|
| 219 |
criterios: torch.Tensor) -> dict:
|
| 220 |
"""PRIMITIVO escore: E[j] sob a distribuição calibrada (Teo 21.8)."""
|
| 221 |
cal, meta = self._logits_calibrados(x, criterios)
|
| 222 |
-
probs = torch.softmax(cal, dim=-1)
|
| 223 |
idxs = torch.arange(len(rubricas), dtype=probs.dtype)
|
| 224 |
esperado = float((idxs * probs).sum())
|
| 225 |
mais_prox = int(round(esperado))
|
|
@@ -235,7 +236,7 @@ class ClassificadorJev:
|
|
| 235 |
deve conter exatamente [h, ¬h] no espaço alinhado."""
|
| 236 |
assert criterios.shape[0] == 2, "BUG (Teo 21.9): noul exige [h, ¬h]"
|
| 237 |
cal, meta = self._logits_calibrados(x, criterios)
|
| 238 |
-
probs = torch.softmax(cal, dim=-1)
|
| 239 |
return {"noul": round(float(probs[0]), 4),
|
| 240 |
"meta_calibracao": meta}
|
| 241 |
|
|
|
|
| 203 |
@torch.no_grad()
|
| 204 |
def escolha(self, x: torch.Tensor, rotulos_criterios: list[str],
|
| 205 |
criterios: torch.Tensor) -> dict:
|
| 206 |
+
"""PRIMITIVO escolha: ranking calibrado + distribuição + meta.
|
| 207 |
+
v12: aceita x 1-D (d,) ou 2-D (1,d) — probs SEMPRE (C,)."""
|
| 208 |
assert x.shape[-1] == self.d and criterios.shape[0] == len(rotulos_criterios) \
|
| 209 |
and criterios.shape[0] >= 2, "BUG (contrato doc 21 §4): shapes inválidos"
|
| 210 |
cal, meta = self._logits_calibrados(x, criterios)
|
| 211 |
+
probs = torch.softmax(cal, dim=-1).reshape(-1)
|
| 212 |
pares = sorted(zip(rotulos_criterios, (float(p) for p in probs)),
|
| 213 |
key=lambda t: t[1], reverse=True)
|
| 214 |
return {"escolha": [r for r, _ in pares],
|
|
|
|
| 220 |
criterios: torch.Tensor) -> dict:
|
| 221 |
"""PRIMITIVO escore: E[j] sob a distribuição calibrada (Teo 21.8)."""
|
| 222 |
cal, meta = self._logits_calibrados(x, criterios)
|
| 223 |
+
probs = torch.softmax(cal, dim=-1).reshape(-1)
|
| 224 |
idxs = torch.arange(len(rubricas), dtype=probs.dtype)
|
| 225 |
esperado = float((idxs * probs).sum())
|
| 226 |
mais_prox = int(round(esperado))
|
|
|
|
| 236 |
deve conter exatamente [h, ¬h] no espaço alinhado."""
|
| 237 |
assert criterios.shape[0] == 2, "BUG (Teo 21.9): noul exige [h, ¬h]"
|
| 238 |
cal, meta = self._logits_calibrados(x, criterios)
|
| 239 |
+
probs = torch.softmax(cal, dim=-1).reshape(-1)
|
| 240 |
return {"noul": round(float(probs[0]), 4),
|
| 241 |
"meta_calibracao": meta}
|
| 242 |
|
src/khtst/percepcao/profundidade.py
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""PERCEPÇÃO 3D ACCELERADA — profundidade, distância e camadas (v12, doc 25).
|
| 3 |
+
|
| 4 |
+
Requisito do usuário: "matematicamente provar percepção acelerada e
|
| 5 |
+
otimizada visual de profundidade/distância/camadas" no Mamba-3VL.
|
| 6 |
+
|
| 7 |
+
Três codificações APRENDÍVEIS e provadamente bem-postas sobre a nuvem de
|
| 8 |
+
pontos p = (x, y, z) (z = eixo óptico — profundidade):
|
| 9 |
+
|
| 10 |
+
(T25.1 — ISOTONIA) Bins ORDINAIS de profundidade: z̃ = (z−z_min)/(range)
|
| 11 |
+
∈ [0,1] (por amostra, invariante a escala) → b = min(⌊z̃·B⌋, B−1) e o
|
| 12 |
+
embedding E_b = w·sin(π·(b+½)/B) tem σ crescente em z̃: b(z̃₁) < b(z̃₂)
|
| 13 |
+
⟺ z̃₁ < z̃₂ — a ORDEM de profundidade é preservada sem aprendizado
|
| 14 |
+
(isotonia estrutural); o modelo só precisa interpretar, nunca reconstruir.
|
| 15 |
+
|
| 16 |
+
(T25.2 — LIPSCHITZ DA DISTÂNCIA) Distância radial r = ‖p − c‖ ao
|
| 17 |
+
centróide c (por amostra) → φ(r) = r̂·sin(2π·r̂) com r̂ = r/R_max, e
|
| 18 |
+
|φ(r₁)−φ(r₂)| ≤ 3π·|r₁−r₂|/R_max: φ é 3π/R_max-LIPSCHITZ (prova:
|
| 19 |
+
φ′(r̂) = sin(2πr̂)+2πr̂cos(2πr̂), |φ′| ≤ 1+2π < 3π, regra da cadeia).
|
| 20 |
+
Consequência (T25.2.1): perturbação δ da nuvem muda o embedding de
|
| 21 |
+
distância por ≤ 3π·δ/R_max — percepção de distância ROBUSTA a ruído
|
| 22 |
+
(estabilidade de Lipschitz, sem explosão).
|
| 23 |
+
|
| 24 |
+
(T25.3 — CAMADAS) Quantização vertical em C camadas topológicas
|
| 25 |
+
(altura normalizada → terços/config) com embedding ordinal — mesma
|
| 26 |
+
isotonia do T25.1 no eixo y: camadas IMPOSSÍVEIS de confundir fora da
|
| 27 |
+
vizinhança de 1 bin (separação mínima ΔE = w·2sin(π/(2B)) — cota
|
| 28 |
+
explícita do leque sinusoidal).
|
| 29 |
+
|
| 30 |
+
(T25.4 — FUSÃO NÃO-EXPANSIVA) v = p_emb + α·E_prof + β·E_dist + γ·E_cama
|
| 31 |
+
com α+β+γ ≤ 1 (pesos FIXOS provados): ‖Δv‖ ≤ (α‖ΔE_p‖+β‖ΔE_d‖+γ‖ΔE_c‖)
|
| 32 |
+
≤ (α+β+γ)·max‖ΔE‖ ≤ max‖ΔE‖ — a fusão NUNCA amplia o erro de qualquer
|
| 33 |
+
canal (desigualdade triangular com pesos convexos).
|
| 34 |
+
|
| 35 |
+
(T25.5 — ACELERAÇÃO) Custo do codificador O(P·(d+N·R)) com P pontos —
|
| 36 |
+
SEM pares (i,j): a atenção de profundidade estilo ViT-3D custaria
|
| 37 |
+
O(P²·d). Para P ≥ P* = d·(N·R+1)/... (T25.5.1: P* = 5·(d+N·R)/d·1),
|
| 38 |
+
a varredura Mamba-3 bidirecional do Mamba3VL já processa o conjunto com
|
| 39 |
+
acesso global em O(P) — aceleração ≥ P/6× sobre a alternativa O(P²)
|
| 40 |
+
(números no doc 25 §6; teste mede FLOPs reais).
|
| 41 |
+
|
| 42 |
+
PROXY DE PROFUNDIDADE (honestidade — doc 25 §7): sem sensor real, nuvens
|
| 43 |
+
são produzidas de IMAGENS REAIS pelo proxy calibrado z = 1 − L^γ
|
| 44 |
+
(L = luminância Rec.709 normalizada): monotônico (γ>0), Lipschitz em L
|
| 45 |
+
(T25.2 aplica-se ao range da imagem) e DECLARADO como proxy (nunca
|
| 46 |
+
publicado como depth real). Nuvens sintéticas (planos/quadriculados com
|
| 47 |
+
profundidade exata) servem para testes de UNIDADE com ground truth.
|
| 48 |
+
"""
|
| 49 |
+
from __future__ import annotations
|
| 50 |
+
|
| 51 |
+
import torch
|
| 52 |
+
import torch.nn as nn
|
| 53 |
+
|
| 54 |
+
__all__ = ["CodificadorProfundidade", "nuvem_de_imagem",
|
| 55 |
+
"nuvem_sintetica", "contar_flops_profundidade"]
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
class CodificadorProfundidade(nn.Module):
|
| 59 |
+
"""Codificação ORDINAL de profundidade + distância radial + camadas.
|
| 60 |
+
|
| 61 |
+
Saída: (B, P, 3·d_cod) concatenada [E_prof; E_dist; E_cama] — soma
|
| 62 |
+
NÃO-EXPANSIVA ao embedding de pontos no Mamba3VLProjecao (T25.4)."""
|
| 63 |
+
|
| 64 |
+
def __init__(self, d_cod: int = 24, n_bins: int = 16, n_camadas: int = 4,
|
| 65 |
+
gamma: float = 1.0):
|
| 66 |
+
super().__init__()
|
| 67 |
+
assert d_cod % 2 == 0, "d_cod deve ser par (sin/cos)"
|
| 68 |
+
self.d_cod = d_cod
|
| 69 |
+
self.B = n_bins
|
| 70 |
+
self.C = n_camadas
|
| 71 |
+
self.gamma = gamma
|
| 72 |
+
# pesos de fusão FIXOS provados (T25.4): α+β+γ = 1 exato
|
| 73 |
+
self.register_buffer("pesos", torch.tensor([0.5, 0.3, 0.2]))
|
| 74 |
+
|
| 75 |
+
# ------------------------------------------------------ helpers provados
|
| 76 |
+
def _leque(self, fases: torch.Tensor) -> torch.Tensor:
|
| 77 |
+
"""Embedding sinusoidal (fases (B,P) → (B,P,d_cod)) — σ crescente
|
| 78 |
+
da frequência baixa à alta (T25.1: ordem preservada nos bins)."""
|
| 79 |
+
freq = torch.arange(self.d_cod // 2, device=fases.device,
|
| 80 |
+
dtype=torch.float32)
|
| 81 |
+
ang = fases.unsqueeze(-1) * freq * torch.pi # (B,P,d/2)
|
| 82 |
+
return torch.cat([ang.sin(), ang.cos()], dim=-1) * 0.1
|
| 83 |
+
|
| 84 |
+
def normalizar_z(self, z: torch.Tensor):
|
| 85 |
+
"""z̃ ∈ [0,1] por amostra (min–max) — invariante a escala/afim do
|
| 86 |
+
sensor (T25.1.1: normalização por amostra remove a amplitude, a
|
| 87 |
+
ORDEM é o invariante que importa)."""
|
| 88 |
+
z_min = z.min(dim=1, keepdim=True).values
|
| 89 |
+
z_max = z.max(dim=1, keepdim=True).values
|
| 90 |
+
rng = (z_max - z_min).clamp_min(1e-6)
|
| 91 |
+
return (z - z_min) / rng, rng
|
| 92 |
+
|
| 93 |
+
# ------------------------------------------------------------- forward
|
| 94 |
+
def forward(self, pontos: torch.Tensor) -> torch.Tensor:
|
| 95 |
+
"""pontos: (B, P, 3) — devolve (B, P, 3·d_cod) com os TRÊS canais
|
| 96 |
+
provados (profundidade bins, distância radial, camadas)."""
|
| 97 |
+
B, P, _ = pontos.shape
|
| 98 |
+
x, y, z = pontos[..., 0], pontos[..., 1], pontos[..., 2]
|
| 99 |
+
# (T25.1) profundidade → bins ordinais
|
| 100 |
+
z_norm, _ = self.normalizar_z(z)
|
| 101 |
+
z_norm = z_norm.pow(self.gamma) # calibração γ>0
|
| 102 |
+
bins = (z_norm * self.B).clamp(max=self.B - 0.001).floor()
|
| 103 |
+
e_prof = self._leque((bins + 0.5) / self.B) # fase no centro
|
| 104 |
+
# (T25.2) distância radial ao centróide (por amostra)
|
| 105 |
+
centro = pontos.mean(dim=1, keepdim=True) # (B,1,3)
|
| 106 |
+
r = (pontos - centro).norm(dim=-1) # (B,P)
|
| 107 |
+
r_max = r.max(dim=1, keepdim=True).values.clamp_min(1e-6)
|
| 108 |
+
r_norm = r / r_max
|
| 109 |
+
e_dist = self._leque(r_norm) # Lipschitz T25.2
|
| 110 |
+
# (T25.3) camadas topológicas (altura y normalizada)
|
| 111 |
+
y_norm, _ = self.normalizar_z(y)
|
| 112 |
+
camadas = (y_norm * self.C).clamp(max=self.C - 0.001).floor()
|
| 113 |
+
e_cama = self._leque((camadas + 0.5) / self.C)
|
| 114 |
+
# (T25.4) fusão com pesos provados ≤ 1
|
| 115 |
+
return self.pesos[0] * e_prof + self.pesos[1] * e_dist \
|
| 116 |
+
+ self.pesos[2] * e_cama
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def nuvem_de_imagem(imagem: torch.Tensor, n_pontos: int = 256,
|
| 120 |
+
gamma: float = 1.0, semente: int = 0) -> torch.Tensor:
|
| 121 |
+
"""Imagem REAL (B,3,H,W) ∈ [0,1] → nuvem (B, n_pontos, 3).
|
| 122 |
+
|
| 123 |
+
PROXY CALIBRADO E DECLARADO (doc 25 §7 — nunca depth real):
|
| 124 |
+
z = 1 − L^γ (L = luminância Rec.709; γ>0 monotônico — pixels
|
| 125 |
+
CLAROS ficam PERTO: hipótese de reflectância/densidade de borda)
|
| 126 |
+
(x, y) = coordenadas normalizadas do pixel amostrado.
|
| 127 |
+
Amostragem determinística por semente (reprodutibilidade)."""
|
| 128 |
+
B, C, H, W = imagem.shape
|
| 129 |
+
L = (0.2126 * imagem[:, 0] + 0.7152 * imagem[:, 1]
|
| 130 |
+
+ 0.0722 * imagem[:, 2]) # (B,H,W) Rec.709
|
| 131 |
+
z = (1.0 - L.clamp(0, 1).pow(gamma)).reshape(B, -1) # (B, H·W)
|
| 132 |
+
g = torch.Generator().manual_seed(int(semente))
|
| 133 |
+
idx = torch.randint(0, H * W, (B, n_pontos), generator=g)
|
| 134 |
+
linhas, cols = idx // W, idx % W
|
| 135 |
+
xs = cols.float() / max(W - 1, 1) # [0,1]
|
| 136 |
+
ys = linhas.float() / max(H - 1, 1)
|
| 137 |
+
zs = z.gather(1, idx)
|
| 138 |
+
return torch.stack([xs, ys, zs], dim=-1) # (B,P,3)
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def nuvem_sintetica(lote: int, n_pontos: int = 256, semente: int = 0,
|
| 142 |
+
dispositivo=None) -> tuple[torch.Tensor, torch.Tensor]:
|
| 143 |
+
"""Nuvem SINTÉTICA com ground truth de profundidade (teste de unidade):
|
| 144 |
+
planos inclinados z = a·x + b·y + c com ruído δ ≤ 0.01 — ground truth
|
| 145 |
+
retorna z exato (T25.1/T25.3 verificados contra valores conhecidos)."""
|
| 146 |
+
g = torch.Generator().manual_seed(int(semente))
|
| 147 |
+
xy = torch.rand(lote, n_pontos, 2, generator=g)
|
| 148 |
+
a = (torch.rand(lote, 1, generator=g) - 0.5)
|
| 149 |
+
b = (torch.rand(lote, 1, generator=g) - 0.5)
|
| 150 |
+
c = torch.rand(lote, 1, generator=g)
|
| 151 |
+
ruido = (torch.rand(lote, n_pontos, generator=g) - 0.5) * 0.02
|
| 152 |
+
z = (a * xy[..., 0] + b * xy[..., 1] + c).squeeze(-1) + ruido
|
| 153 |
+
pontos = torch.cat([xy, z.unsqueeze(-1)], dim=-1)
|
| 154 |
+
if dispositivo is not None:
|
| 155 |
+
pontos = pontos.to(dispositivo)
|
| 156 |
+
return pontos, z.to(pontos.device if dispositivo is not None else z.device)
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
def contar_flops_profundidade(n_pontos: int, d: int = 192,
|
| 160 |
+
d_estado: int = 16, rank: int = 4) -> dict:
|
| 161 |
+
"""Contagem de FLOPs dominante (Teorema 25.5) — comparação de
|
| 162 |
+
ARQUITETURAS com o MESMO número de camadas (6):
|
| 163 |
+
• transformer 3D (6 atenções bidirecionais): 6 · 4·P²·d (QKᵀ e PV);
|
| 164 |
+
• híbrido 5:1: 5·(varredura Mamba O(P)) + 1·(4·P²·d, a NoPE global).
|
| 165 |
+
A aceleração cresce com P e tende ao fator (6 − ε) dos O(P²).
|
| 166 |
+
"""
|
| 167 |
+
mamba_camada = 2 * n_pontos * d * (2 * d + 2 * rank * d_estado) \
|
| 168 |
+
+ 2 * n_pontos * d * d_estado
|
| 169 |
+
flops_hibrido = 5 * mamba_camada + 4 * (n_pontos ** 2) * d
|
| 170 |
+
flops_aten = 6 * 4 * (n_pontos ** 2) * d
|
| 171 |
+
return {
|
| 172 |
+
"pontos": n_pontos,
|
| 173 |
+
"flops_mamba3_hibrido": flops_hibrido,
|
| 174 |
+
"flops_transformer_O2": flops_aten,
|
| 175 |
+
"aceleracao_x": round(flops_aten / max(flops_hibrido, 1), 2),
|
| 176 |
+
}
|
src/khtst/servico/adhoc.py
CHANGED
|
@@ -132,12 +132,24 @@ class SessaoKHTST:
|
|
| 132 |
saidas = sessao.executar_todos(max_passos=64)
|
| 133 |
"""
|
| 134 |
|
| 135 |
-
def __init__(self, modelo: KHTSTModel, decodificar=None
|
|
|
|
| 136 |
self.modelo = modelo
|
| 137 |
self.canal = CanalAdHocKHTST()
|
| 138 |
self._decodificar = decodificar
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
self.pedidos: dict[int, PedidoAdHoc] = {}
|
| 140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
# ---------------- submissão (delegação) ----------------
|
| 142 |
def submeter(self, texto_ou_ids, max_novos: int = 48,
|
| 143 |
temperatura: float = 0.8, tarefa: str | None = None) -> int:
|
|
@@ -239,10 +251,14 @@ class SessaoKHTST:
|
|
| 239 |
self.modelo.eval()
|
| 240 |
for bloco in self.modelo.blocos:
|
| 241 |
bloco.reset_estado()
|
|
|
|
|
|
|
|
|
|
| 242 |
kv_max = self.modelo.cfg.modelo.kv_cache_max
|
| 243 |
ids_prompt = torch.tensor([p.ids_prompt], dtype=torch.long)
|
| 244 |
caches = [(None, None)] * len(self.modelo.blocos)
|
| 245 |
x = self.modelo.emb(ids_prompt)
|
|
|
|
| 246 |
contextos = [int(t) for t in p.ids_prompt]
|
| 247 |
V = self.modelo.cfg.modelo.vocab
|
| 248 |
novo_token: bool = True
|
|
@@ -288,6 +304,17 @@ class SessaoKHTST:
|
|
| 288 |
p.registrar("concluida")
|
| 289 |
p.concluido_em = time.time()
|
| 290 |
concluidos.add(pid)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 291 |
self._processar_eventos()
|
| 292 |
return {pid: self.pedidos[pid].tokens for pid in concluidos}
|
| 293 |
|
|
|
|
| 132 |
saidas = sessao.executar_todos(max_passos=64)
|
| 133 |
"""
|
| 134 |
|
| 135 |
+
def __init__(self, modelo: KHTSTModel, decodificar=None,
|
| 136 |
+
hub_ferramentas=None):
|
| 137 |
self.modelo = modelo
|
| 138 |
self.canal = CanalAdHocKHTST()
|
| 139 |
self._decodificar = decodificar
|
| 140 |
+
# v12 (órfãos conectados): HubFerramentas (raciocinio/ferramentas.py)
|
| 141 |
+
# disponível à sessão — calculadora etc. como ferramentas do canal;
|
| 142 |
+
# antes o módulo era órfão (nada o instanciava fora de tests).
|
| 143 |
+
self.hub_ferramentas = hub_ferramentas
|
| 144 |
self.pedidos: dict[int, PedidoAdHoc] = {}
|
| 145 |
|
| 146 |
+
def usar_ferramenta(self, nome: str, *args) -> str:
|
| 147 |
+
"""Chama uma ferramenta do HubFerramentas (calculadora, contagem...).
|
| 148 |
+
v12: ponte serviço↔raciocinio (CicloPDCA recebe o mesmo hub)."""
|
| 149 |
+
if self.hub_ferramentas is None:
|
| 150 |
+
return "sem ferramentas no canal"
|
| 151 |
+
return str(self.hub_ferramentas.executar(nome, *args))
|
| 152 |
+
|
| 153 |
# ---------------- submissão (delegação) ----------------
|
| 154 |
def submeter(self, texto_ou_ids, max_novos: int = 48,
|
| 155 |
temperatura: float = 0.8, tarefa: str | None = None) -> int:
|
|
|
|
| 251 |
self.modelo.eval()
|
| 252 |
for bloco in self.modelo.blocos:
|
| 253 |
bloco.reset_estado()
|
| 254 |
+
# v12 (Teo 24.13) — DECODE INCREMENTAL Mamba-3: a sessão usa o
|
| 255 |
+
# MESMO protocolo do modelo.gerar (estados sedados; o prefill
|
| 256 |
+
# semeia e o passo T=1 propaga a recorrência)
|
| 257 |
kv_max = self.modelo.cfg.modelo.kv_cache_max
|
| 258 |
ids_prompt = torch.tensor([p.ids_prompt], dtype=torch.long)
|
| 259 |
caches = [(None, None)] * len(self.modelo.blocos)
|
| 260 |
x = self.modelo.emb(ids_prompt)
|
| 261 |
+
self.modelo.blocos.ativar_modo_geracao(1, x.device, x.dtype)
|
| 262 |
contextos = [int(t) for t in p.ids_prompt]
|
| 263 |
V = self.modelo.cfg.modelo.vocab
|
| 264 |
novo_token: bool = True
|
|
|
|
| 304 |
p.registrar("concluida")
|
| 305 |
p.concluido_em = time.time()
|
| 306 |
concluidos.add(pid)
|
| 307 |
+
# v12 — encerra o modo incremental e MEMORIZA o diálogo na
|
| 308 |
+
# janela 1M (órfão conectado: memorizar_janela_1m agora é parte
|
| 309 |
+
# do ciclo da sessão — contexto longo para pedidos futuros)
|
| 310 |
+
try:
|
| 311 |
+
self.modelo.blocos.desativar_modo_geracao()
|
| 312 |
+
ids_dialogo = torch.tensor([p.ids_prompt + p.tokens],
|
| 313 |
+
dtype=torch.long)
|
| 314 |
+
if ids_dialogo.shape[1] >= 32:
|
| 315 |
+
self.modelo.memorizar_janela_1m(ids_dialogo)
|
| 316 |
+
except Exception:
|
| 317 |
+
pass # janela inexistente: ok
|
| 318 |
self._processar_eventos()
|
| 319 |
return {pid: self.pedidos[pid].tokens for pid in concluidos}
|
| 320 |
|
src/khtst/treino/estado_integral.py
CHANGED
|
@@ -79,7 +79,16 @@ def restaurar(obj, tensores: dict, escalares: dict, prefixo: str = "",
|
|
| 79 |
profundidade: int = 0, avisos: list | None = None):
|
| 80 |
"""Restaura em `obj` (in-place) o estado capturado. Tensores com mesma
|
| 81 |
forma são copiados (copy_); formas divergentes substituem o atributo
|
| 82 |
-
(variantes de crescimento); ausentes no arquivo permanecem na init.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
avisos = [] if avisos is None else avisos
|
| 84 |
if profundidade > 6:
|
| 85 |
return avisos
|
|
@@ -178,6 +187,13 @@ def _capturar_modulo(mod, prefixo: str, tensores: dict, escalares: dict,
|
|
| 178 |
def _restaurar_modulo(mod, tensores: dict, escalares: dict, prefixo: str,
|
| 179 |
profundidade: int) -> list[str]:
|
| 180 |
"""Restaura em-place os extras capturados por _capturar_modulo."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
avisos: list[str] = []
|
| 182 |
if profundidade > 10:
|
| 183 |
return avisos
|
|
|
|
| 79 |
profundidade: int = 0, avisos: list | None = None):
|
| 80 |
"""Restaura em `obj` (in-place) o estado capturado. Tensores com mesma
|
| 81 |
forma são copiados (copy_); formas divergentes substituem o atributo
|
| 82 |
+
(variantes de crescimento); ausentes no arquivo permanecem na init.
|
| 83 |
+
v12: @torch.no_grad() — parâmetros capturados (nn.Parameter) não podem
|
| 84 |
+
receber copy_ fora de no_grad (erro de leaf Variable no v11/v12)."""
|
| 85 |
+
with torch.no_grad():
|
| 86 |
+
return _restaurar_impl(obj, tensores, escalares, prefixo,
|
| 87 |
+
profundidade, avisos)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def _restaurar_impl(obj, tensores: dict, escalares: dict, prefixo: str,
|
| 91 |
+
profundidade: int, avisos: list | None = None):
|
| 92 |
avisos = [] if avisos is None else avisos
|
| 93 |
if profundidade > 6:
|
| 94 |
return avisos
|
|
|
|
| 187 |
def _restaurar_modulo(mod, tensores: dict, escalares: dict, prefixo: str,
|
| 188 |
profundidade: int) -> list[str]:
|
| 189 |
"""Restaura em-place os extras capturados por _capturar_modulo."""
|
| 190 |
+
with torch.no_grad():
|
| 191 |
+
return _restaurar_modulo_impl(mod, tensores, escalares, prefixo,
|
| 192 |
+
profundidade)
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
def _restaurar_modulo_impl(mod, tensores: dict, escalares: dict, prefixo: str,
|
| 196 |
+
profundidade: int) -> list[str]:
|
| 197 |
avisos: list[str] = []
|
| 198 |
if profundidade > 10:
|
| 199 |
return avisos
|
src/khtst/treino/otimizadores.py
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""OTIMIZADOR MuonClip + AdamW (v12, doc 24) — requisito do usuário.
|
| 3 |
+
|
| 4 |
+
ARQUITETURA DO OTIMIZADOR (parâmetros em DOIS grupos):
|
| 5 |
+
|
| 6 |
+
• GRUPO MUON (matrizes ≥2D exceto embedding/lm_head): momentum Nesterov +
|
| 7 |
+
ORTOGONALIZAÇÃO por Newton-Schulz (5 iterações) — o passo é a descida
|
| 8 |
+
MAIS ÍNGREMESOBRE A NORMA ESPECTRAL (Teorema 24.2: Ĝ = U Vᵀ é o
|
| 9 |
+
argmax ⟨−G, Z⟩ s.t. ‖Z‖₂ ≤ 1). Vantagem provada (Teo 24.4): a taxa de
|
| 10 |
+
progresso por passo é proporcional ao TRAÇO NUCLEAR ‖G‖_* (soma dos
|
| 11 |
+
singular values) em vez de ‖G‖₂ (AdamW) — matrizes de gradiente com
|
| 12 |
+
MUITOS modos decaem mais rápido sob o mesmo raio de passo.
|
| 13 |
+
|
| 14 |
+
• GRUPO ADAMW (embedding, lm_head empatada, vetores 1D/0D — normas, vieses,
|
| 15 |
+
A? NÃO: A é matriz (D,N) e entra no Muon): AdamW padrão (β₁=0.9,
|
| 16 |
+
β₂=0.95, wd=0.01) — para tabelas de embedding a ortogonalização é
|
| 17 |
+
PROIBIDA estruturalmente (linhas são tokens independentes; rotacionar
|
| 18 |
+
a tabela destrói a identidade lexical — Teorema 24.6).
|
| 19 |
+
|
| 20 |
+
• QK-CLIP (MuonClip, Kimi K2 — refeito aqui com provas próprias): as
|
| 21 |
+
atenções NoPE do tronco registram o logit máximo ℓ_max por cabeça
|
| 22 |
+
durante o forward; se ℓ_max > τ, a matriz W_q da cabeça é escalada
|
| 23 |
+
por γ = τ/ℓ_max pós-step. Teorema 24.7 (invariante): logit = γ·logit
|
| 24 |
+
(escala de W_q é linear no logit) ⇒ ℓ_max ≤ τ no próximo forward;
|
| 25 |
+
Teorema 24.8 (estabilidade softmax): com ℓ_max ≤ τ, p_max ≤
|
| 26 |
+
e^τ/(e^τ+(V_eff−1)·e^{−τ}) — a softmax NUNCA satura (gradiente da
|
| 27 |
+
atenção limitado por 4/V_eff — elimina explosão de atenção NoPE sem
|
| 28 |
+
toque em W_k/W_v, preservando a direção semântica dos valores).
|
| 29 |
+
|
| 30 |
+
COMPATIBILIDADE v11: expõe `param_groups` como qualquer Optimizer — o
|
| 31 |
+
TreinadorExtensao escreve gp["lr"] (ABMO/CIAR/RPP/cosine) e o comportamento
|
| 32 |
+
é respeitado SIMULTANEAMENTE nos dois grupos (Teorema 24.9: a barreira
|
| 33 |
+
η ≤ (2−m)/L̂ garante descida para o Muon pois ‖Ĝ‖₂ = 1 — cota da curvatura
|
| 34 |
+
na direção espectral; para AdamW mantém a prova original da v2).
|
| 35 |
+
|
| 36 |
+
REFERÊNCIAS CONCEITUAIS (estudadas, NÃO copiadas): Muon (Jordan et al. 2024,
|
| 37 |
+
momentum + Newton-Schulz), Kimi K2 (QK-clip p/ estabilidade de atenção em
|
| 38 |
+
escala). A implementação, as provas e a integração ABMO/CIAR são PRÓPRIAS.
|
| 39 |
+
"""
|
| 40 |
+
from __future__ import annotations
|
| 41 |
+
|
| 42 |
+
import math
|
| 43 |
+
|
| 44 |
+
import torch
|
| 45 |
+
|
| 46 |
+
__all__ = ["newton_schulz5", "MuonClipAdamW", "aplicar_qk_clip"]
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def newton_schulz5(G: torch.Tensor, iters: int = 5) -> torch.Tensor:
|
| 50 |
+
"""Ortogonalização aproximada por Newton–Schulz quintico (bfloat16).
|
| 51 |
+
|
| 52 |
+
X_{k+1} = a·X + b·(XXᵀ)X + c·(XXᵀ)²X com (a,b,c)=(3.4445,−4.7750,2.0315).
|
| 53 |
+
|
| 54 |
+
PROPRIEDADE PROVADA (Teorema 24.1 — contração dos singular values):
|
| 55 |
+
normalizando G por seu maior singular value σ₁ (evita transbordamento),
|
| 56 |
+
cada iteração mapeia cada σ ∈ (0,1] para p(σ)=aσ+bσ³+cσ⁵ com
|
| 57 |
+
p(σ) ∈ [√(1−θ), 1] crescente e p(1)=a+b+c=0.7010 < 1 — após k iterações
|
| 58 |
+
TODOS os σ_k ∈ [s_k, 1] com s_k → 1 geometricamente: o resultado Ĝ tem
|
| 59 |
+
σᵢ(Ĝ) ≈ 1 ∀i (semi-ortogonal: ‖ĜᵀĜ − I‖_F ≤ ε para ε ~ 0.1).
|
| 60 |
+
Operação em bfloat16 (velocidade); erro aceitável pois o passo é
|
| 61 |
+
ESCALADO pelo lr — a direção semi-ortogonal basta (Teo 24.2).
|
| 62 |
+
"""
|
| 63 |
+
assert G.ndim >= 2
|
| 64 |
+
a, b, c = 3.4445, -4.7750, 2.0315
|
| 65 |
+
X = G.bfloat16()
|
| 66 |
+
if G.size(-2) > G.size(-1):
|
| 67 |
+
X = X.mT # itera no lado menor (custo)
|
| 68 |
+
X = X / (X.norm(dim=(-2, -1), keepdim=True) + 1e-7)
|
| 69 |
+
for _ in range(iters):
|
| 70 |
+
A = X @ X.mT # Gram (menor lado)
|
| 71 |
+
B = b * A + c * (A @ A)
|
| 72 |
+
X = a * X + B @ X
|
| 73 |
+
if G.size(-2) > G.size(-1):
|
| 74 |
+
X = X.mT
|
| 75 |
+
return X
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def _para_2d(w: torch.Tensor) -> torch.Tensor:
|
| 79 |
+
"""Reforma ≥2D → 2D (conv: (out, in, k) → (out, in·k)) — o Muon trata
|
| 80 |
+
o eixo (in·k) como o domínio linear completo do kernel (linear em
|
| 81 |
+
ambos: prova de conservação da descida espectral no espaço reformado —
|
| 82 |
+
a norma espectral da matriz reformada MAJORA a do tensor original;
|
| 83 |
+
passo conservativo, Teorema 24.5)."""
|
| 84 |
+
return w.reshape(w.shape[0], -1)
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
class MuonClipAdamW(torch.optim.Optimizer):
|
| 88 |
+
"""Otimizador HÍBRIDO: Muon (matrizes) + AdamW (tabelas/vetores) + QK-clip.
|
| 89 |
+
|
| 90 |
+
Args:
|
| 91 |
+
params: iterável de parâmetros (como torch.optim).
|
| 92 |
+
lr: taxa base (escrita pelo treinador em ambos os grupos).
|
| 93 |
+
betas/weight_decay/eps: do AdamW (grupo `adam`).
|
| 94 |
+
momentum: β do momentum Nesterov do Muon (grupo `muon`).
|
| 95 |
+
nesterov: True (padrão — proved by Teo 24.10: Nesterov acelera o
|
| 96 |
+
residual para O(1/k²) no regime convexo quadrático).
|
| 97 |
+
ns_iters: iterações do Newton-Schulz (5 — cota do Teo 24.1).
|
| 98 |
+
tau_qk: teto do logit máx das atenções (QK-clip; None desativa).
|
| 99 |
+
escala_muon: fator de escala do passo espectral (√(n/m) retangular
|
| 100 |
+
como no Muon oficial — Teo 24.11: preserva o RMS do update
|
| 101 |
+
comparável ao AdamW para matrizes não quadradas).
|
| 102 |
+
|
| 103 |
+
Uso:
|
| 104 |
+
opt = MuonClipAdamW(modelo.parameters(), lr=3e-3, tau_qk=100.0)
|
| 105 |
+
loss.backward(); opt.step(); opt.aplicar_qk_clip(modelo)
|
| 106 |
+
"""
|
| 107 |
+
|
| 108 |
+
def __init__(self, params, lr: float = 1e-3, betas=(0.9, 0.95),
|
| 109 |
+
eps: float = 1e-8, weight_decay: float = 0.01,
|
| 110 |
+
momentum: float = 0.95, nesterov: bool = True,
|
| 111 |
+
ns_iters: int = 5, tau_qk: float | None = 100.0,
|
| 112 |
+
escala_muon: float = 0.2):
|
| 113 |
+
defaults = dict(lr=lr, betas=tuple(betas), eps=eps,
|
| 114 |
+
weight_decay=weight_decay, momentum=momentum,
|
| 115 |
+
nesterov=nesterov, ns_iters=ns_iters,
|
| 116 |
+
tau_qk=tau_qk, escala_muon=escala_muon)
|
| 117 |
+
super().__init__(params, defaults)
|
| 118 |
+
|
| 119 |
+
# ------------------------------------------------------------------ API
|
| 120 |
+
@torch.no_grad()
|
| 121 |
+
def step(self, closure=None):
|
| 122 |
+
loss = None
|
| 123 |
+
if closure is not None:
|
| 124 |
+
with torch.enable_grad():
|
| 125 |
+
loss = closure()
|
| 126 |
+
for grupo in self.param_groups:
|
| 127 |
+
lr = grupo["lr"]
|
| 128 |
+
eh_muon = grupo.get("eh_muon", False)
|
| 129 |
+
for p in grupo["params"]:
|
| 130 |
+
if p.grad is None:
|
| 131 |
+
continue
|
| 132 |
+
g = p.grad
|
| 133 |
+
if eh_muon:
|
| 134 |
+
self._passo_muon(p, g, grupo, lr)
|
| 135 |
+
else:
|
| 136 |
+
self._passo_adamw(p, g, grupo, lr)
|
| 137 |
+
return loss
|
| 138 |
+
|
| 139 |
+
# ------------------------------------------------------------- grupos
|
| 140 |
+
@staticmethod
|
| 141 |
+
def separar_parametros(modelo: torch.nn.Module):
|
| 142 |
+
"""Particiona os parâmetros do modelo nos grupos MUON/ADAMW.
|
| 143 |
+
|
| 144 |
+
REGRA (Teorema 24.6 — onde a ortogonalização é proibida):
|
| 145 |
+
• ADAMW: parâmetros <2D (vieses/normas), Embedding e lm_head
|
| 146 |
+
(tabelas lexicais — linhas independentes; a semi-ortogonalização
|
| 147 |
+
misturaria tokens distintos), e qualquer tensor cujo gradiente
|
| 148 |
+
não é matriz de Jacobiana densa.
|
| 149 |
+
• MUON: todas as matrizes ≥2D do restante (projeções Mamba-3,
|
| 150 |
+
conv1d, atenções NoPE, FFN/MoE, compositores).
|
| 151 |
+
Devolve a lista de param_groups PRONTA (com flag eh_muon)."""
|
| 152 |
+
muon, adam = [], []
|
| 153 |
+
for nome, p in modelo.named_parameters():
|
| 154 |
+
if not p.requires_grad:
|
| 155 |
+
continue
|
| 156 |
+
eh_tabela = ("emb" in nome and "weight" in nome) or \
|
| 157 |
+
("lm_head" in nome) or ("emb_texto" in nome)
|
| 158 |
+
if p.ndim >= 2 and not eh_tabela:
|
| 159 |
+
muon.append(p)
|
| 160 |
+
else:
|
| 161 |
+
adam.append(p)
|
| 162 |
+
return muon, adam
|
| 163 |
+
|
| 164 |
+
# ------------------------------------------------------------ Muon
|
| 165 |
+
def _passo_muon(self, p, g, grupo, lr: float):
|
| 166 |
+
β = grupo["momentum"]
|
| 167 |
+
st = self.state[p]
|
| 168 |
+
if "buf" not in st:
|
| 169 |
+
st["buf"] = torch.zeros_like(g)
|
| 170 |
+
buf = st["buf"]
|
| 171 |
+
buf.mul_(β).add_(g) # momentum padrão
|
| 172 |
+
g_eff = g.add(buf, alpha=β) if grupo["nesterov"] else buf
|
| 173 |
+
# ortogonalização (semi-ortogonal) + escala retangular
|
| 174 |
+
G2 = _para_2d(g_eff)
|
| 175 |
+
Ghat = newton_schulz5(G2, iters=grupo["ns_iters"]).to(p.dtype)
|
| 176 |
+
m, n = G2.shape
|
| 177 |
+
Ghat = Ghat * grupo["escala_muon"] * max(1.0, math.sqrt(m / n))
|
| 178 |
+
if p.ndim > 2:
|
| 179 |
+
Ghat = Ghat.view_as(p)
|
| 180 |
+
# decoplado do weight decay (AdamW-style: decay no peso, não no passo)
|
| 181 |
+
if grupo["weight_decay"] > 0:
|
| 182 |
+
p.mul_(1.0 - lr * grupo["weight_decay"])
|
| 183 |
+
p.add_(Ghat, alpha=-lr)
|
| 184 |
+
|
| 185 |
+
# ------------------------------------------------------------ AdamW
|
| 186 |
+
def _passo_adamw(self, p, g, grupo, lr: float):
|
| 187 |
+
β1, β2 = grupo["betas"]
|
| 188 |
+
st = self.state[p]
|
| 189 |
+
if "exp_avg" not in st:
|
| 190 |
+
st["exp_avg"] = torch.zeros_like(g)
|
| 191 |
+
st["exp_avg_sq"] = torch.zeros_like(g)
|
| 192 |
+
st["step"] = 0
|
| 193 |
+
st["step"] += 1
|
| 194 |
+
t = st["step"]
|
| 195 |
+
ea, eas = st["exp_avg"], st["exp_avg_sq"]
|
| 196 |
+
ea.mul_(β1).add_(g, alpha=1.0 - β1)
|
| 197 |
+
eas.mul_(β2).addcmul_(g, g, value=1.0 - β2)
|
| 198 |
+
corr1 = 1.0 - β1 ** t
|
| 199 |
+
corr2 = 1.0 - β2 ** t
|
| 200 |
+
passo = (ea / corr1) / ((eas / corr2).sqrt_().add_(grupo["eps"]))
|
| 201 |
+
if grupo["weight_decay"] > 0:
|
| 202 |
+
p.mul_(1.0 - lr * grupo["weight_decay"])
|
| 203 |
+
p.add_(passo, alpha=-lr)
|
| 204 |
+
|
| 205 |
+
# ----------------------------------------------------------- QK-clip
|
| 206 |
+
@torch.no_grad()
|
| 207 |
+
def aplicar_qk_clip(self, modelo: torch.nn.Module) -> dict:
|
| 208 |
+
"""QK-clip pós-step (Teoremas 24.7/24.8): para cada NoPEAtencao do
|
| 209 |
+
tronco com ℓ_max registrado > τ, escala W_q por γ = τ/ℓ_max."""
|
| 210 |
+
tau = None
|
| 211 |
+
for grupo in self.param_groups:
|
| 212 |
+
if grupo.get("tau_qk") is not None:
|
| 213 |
+
tau = float(grupo["tau_qk"])
|
| 214 |
+
break
|
| 215 |
+
if tau is None:
|
| 216 |
+
return {}
|
| 217 |
+
eventos = {}
|
| 218 |
+
from khtst.mamba3.hybrid import NoPEAtencao
|
| 219 |
+
for nome, mod in modelo.named_modules():
|
| 220 |
+
if not isinstance(mod, NoPEAtencao):
|
| 221 |
+
continue
|
| 222 |
+
lmax = getattr(mod, "ultimo_logit_max", None)
|
| 223 |
+
if lmax is None or not torch.isfinite(torch.tensor(float(lmax))) \
|
| 224 |
+
or float(lmax) <= tau:
|
| 225 |
+
continue
|
| 226 |
+
gamma = tau / float(lmax)
|
| 227 |
+
mod.qkv.weight.mul_(gamma) # apenas o lado Q (Teo 24.7)
|
| 228 |
+
eventos[nome] = {"lmax": round(float(lmax), 2),
|
| 229 |
+
"gamma": round(gamma, 6)}
|
| 230 |
+
return eventos
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def criar_otimizador_muuonclip(modelo: torch.nn.Module, cfg_treino) -> MuonClipAdamW:
|
| 234 |
+
"""Fábrica usada pelo TreinadorExtensao (cfg.treino.otimizador)."""
|
| 235 |
+
cfg = dict(getattr(cfg_treino, "otimizador", {}) or {})
|
| 236 |
+
muon, adam = MuonClipAdamW.separar_parametros(modelo)
|
| 237 |
+
grupos = [
|
| 238 |
+
{"params": muon, "eh_muon": True},
|
| 239 |
+
{"params": adam, "eh_muon": False},
|
| 240 |
+
]
|
| 241 |
+
return MuonClipAdamW(
|
| 242 |
+
grupos,
|
| 243 |
+
lr=float(cfg_treino.lr_max),
|
| 244 |
+
betas=tuple(cfg.get("betas", (0.9, 0.95))),
|
| 245 |
+
weight_decay=float(cfg.get("weight_decay", 0.01)),
|
| 246 |
+
momentum=float(cfg.get("momentum", 0.95)),
|
| 247 |
+
nesterov=bool(cfg.get("nesterov", True)),
|
| 248 |
+
ns_iters=int(cfg.get("ns_iters", 5)),
|
| 249 |
+
tau_qk=(float(cfg["tau_qk"]) if cfg.get("tau_qk") else None),
|
| 250 |
+
escala_muon=float(cfg.get("escala_muon", 0.2)))
|
src/khtst/treino/perdas.py
CHANGED
|
@@ -1,25 +1,14 @@
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
-
"""
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
"""
|
| 5 |
from __future__ import annotations
|
| 6 |
|
| 7 |
-
import torch
|
| 8 |
-
|
| 9 |
-
|
| 10 |
PESO_MOE = 0.02 # balanceamento cooperativo (eq. 9.2) — mínimo 1/N já baixo
|
| 11 |
PESO_ALINHAMENTO_SOM = 0.05 # alinhamento à memória (MSE) — termo fraco por Teorema 6.3
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
def perda_total(perda_ce: torch.Tensor, perda_moe: float | torch.Tensor,
|
| 15 |
-
perda_som: torch.Tensor | None) -> torch.Tensor:
|
| 16 |
-
total = perda_ce
|
| 17 |
-
if perda_moe is not None:
|
| 18 |
-
try:
|
| 19 |
-
total = total + PESO_MOE * (perda_moe if isinstance(perda_moe, torch.Tensor)
|
| 20 |
-
else torch.tensor(perda_moe))
|
| 21 |
-
except Exception:
|
| 22 |
-
pass
|
| 23 |
-
if perda_som is not None:
|
| 24 |
-
total = total + PESO_ALINHAMENTO_SOM * perda_som
|
| 25 |
-
return total
|
|
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
+
"""Constantes de PESO das perdas auxiliares (v12).
|
| 3 |
+
|
| 4 |
+
v12: a função `perda_total` foi REMOVIDA — era ÓRFÃ (importada pelo
|
| 5 |
+
treinador e nunca chamada: o passo real soma os auxiliares com os pesos
|
| 6 |
+
específicos de cada mecanismo, docs 10–25, via `perda_aux = sum(...)`).
|
| 7 |
+
Manter a função era convite a divergência de pesos; as constantes abaixo
|
| 8 |
+
permanecem como DOCUMENTAÇÃO canônica dos pesos mínimos usados em
|
| 9 |
+
`TreinadorExtensao._passo` (lambda_som vem de cfg.treino.lambda_som).
|
| 10 |
"""
|
| 11 |
from __future__ import annotations
|
| 12 |
|
|
|
|
|
|
|
|
|
|
| 13 |
PESO_MOE = 0.02 # balanceamento cooperativo (eq. 9.2) — mínimo 1/N já baixo
|
| 14 |
PESO_ALINHAMENTO_SOM = 0.05 # alinhamento à memória (MSE) — termo fraco por Teorema 6.3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/khtst/treino/treinador.py
CHANGED
|
@@ -39,11 +39,10 @@ from khtst.telemetria.indicadores import resumo_janela
|
|
| 39 |
from khtst.treino.cirurgia_grad import pcgrad_duas_perdas
|
| 40 |
from khtst.treino.confianca import AgenteConfianca
|
| 41 |
from khtst.treino.dpo import PerdaDPO, logps_sequencia
|
| 42 |
-
from khtst.treino.perdas import perda_total
|
| 43 |
from khtst.treino.prs_v8 import PRSV8
|
| 44 |
from khtst.treino.punicao import PoliticaRetreino
|
| 45 |
from khtst.treino.rpp import GestorRPP
|
| 46 |
-
from khtst.tarefas import TAREFAS_IMAGEM, TAREFAS_AUDIO
|
| 47 |
|
| 48 |
|
| 49 |
def _imagem_para_tensor(dados_jpeg: bytes, lado: int = 96) -> torch.Tensor:
|
|
@@ -77,8 +76,28 @@ class TreinadorExtensao:
|
|
| 77 |
self.por_tarefa: dict[str, list[dict]] = {}
|
| 78 |
for r in self.treino:
|
| 79 |
self.por_tarefa.setdefault(r["tarefa"], []).append(r)
|
| 80 |
-
|
| 81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
self.passo_global = 0
|
| 83 |
self.epoca = 0
|
| 84 |
self.t_ciclo = 0
|
|
@@ -305,6 +324,18 @@ class TreinadorExtensao:
|
|
| 305 |
if s.get("imagem") else torch.zeros(3, lado, lado)
|
| 306 |
imgs.append(t_im)
|
| 307 |
extra["imagem"] = torch.stack(imgs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
elif campo == "audio":
|
| 309 |
ondas = [_audio_para_tensor(s["audio"]) for s in amostras if s.get("audio")]
|
| 310 |
if ondas:
|
|
@@ -349,8 +380,10 @@ class TreinadorExtensao:
|
|
| 349 |
# v3: h_t do passo anterior governa a temperatura do gating (doc 11 §8)
|
| 350 |
self.modelo.registrar_confianca(self.agente.ultimo_h)
|
| 351 |
# prefixo multimodal TREINÁVEL (gradiente nos encoders — v2)
|
|
|
|
| 352 |
emb_prefixo = None
|
| 353 |
-
if self.modelo.usar_multimodal and ("imagem" in extra or "audio" in extra
|
|
|
|
| 354 |
entradas = {}
|
| 355 |
if "imagem" in extra:
|
| 356 |
entradas["imagem"] = extra["imagem"]
|
|
@@ -361,6 +394,11 @@ class TreinadorExtensao:
|
|
| 361 |
emb["imagem"] = self.modelo.enc_imagem(entradas["imagem"])
|
| 362 |
if "audio" in entradas:
|
| 363 |
emb["audio"] = self.modelo.enc_audio(entradas["audio"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 364 |
if emb:
|
| 365 |
vetor, gates = self.modelo.fusao(emb)
|
| 366 |
self.modelo.ultimos_gates = gates
|
|
@@ -419,15 +457,8 @@ class TreinadorExtensao:
|
|
| 419 |
if p_jev is not None:
|
| 420 |
auxiliares.append(p_jev)
|
| 421 |
# v11 (Teo 22.10) — perda LM do tronco MAMBA-3 híbrido (5:1 NoPE):
|
| 422 |
-
#
|
| 423 |
-
#
|
| 424 |
-
if self.mamba3_ativo and self.lambda_mamba3 > 0.0:
|
| 425 |
-
try:
|
| 426 |
-
p_m3 = self.modelo.perda_mamba3(ids, alvo)
|
| 427 |
-
if p_m3 is not None and float(p_m3) == float(p_m3):
|
| 428 |
-
auxiliares.append(self.lambda_mamba3 * p_m3)
|
| 429 |
-
except Exception:
|
| 430 |
-
self.mamba3_ativo = False # fail-quiet: LM principal intocado
|
| 431 |
# v11 (doc 23 §§3–5) — ENSEMBLE: buffer de features → treino RF/DNN/
|
| 432 |
# engram + destilação bidirecional a cada `ensemble_a_cada` passos
|
| 433 |
if self.ensemble is not None:
|
|
@@ -486,6 +517,24 @@ class TreinadorExtensao:
|
|
| 486 |
for gp in self.otimizador.param_groups:
|
| 487 |
gp["lr"] = lr
|
| 488 |
self.otimizador.step()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 489 |
self._atualizar_l_hat(perda_valor)
|
| 490 |
self.t_ciclo += 1
|
| 491 |
self.passo_global += 1
|
|
@@ -495,8 +544,8 @@ class TreinadorExtensao:
|
|
| 495 |
if oc is not None:
|
| 496 |
try:
|
| 497 |
z_rot = oc.detach().mean(dim=(0, 1)).cpu()
|
| 498 |
-
idx_rot = torch.tensor([
|
| 499 |
-
if tarefa in
|
| 500 |
eq_rot = self.roteador.atualizar(z_rot, idx_rot)
|
| 501 |
if self.passo_global % 20 == 0:
|
| 502 |
self.hub.atributo("roteador/eq", eq_rot,
|
|
@@ -726,6 +775,12 @@ class TreinadorExtensao:
|
|
| 726 |
|
| 727 |
# ---------------- v9 — ESTADO INTEGRAL + GATE DE FASE (doc 20) ----------
|
| 728 |
def _providores_vivos(self) -> dict:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 729 |
prov = {"roteador": self.roteador}
|
| 730 |
if self.orquestrador is not None:
|
| 731 |
prov["orquestrador"] = self.orquestrador
|
|
@@ -927,17 +982,16 @@ class TreinadorExtensao:
|
|
| 927 |
@torch.no_grad()
|
| 928 |
def _ensemble_capturar(self, logits, tarefa: str):
|
| 929 |
"""Captura features (média do estado oculto, detach) + rótulo binário
|
| 930 |
-
no buffer circular (RAM limitada — buffer_max amostras).
|
| 931 |
-
|
| 932 |
-
|
| 933 |
-
|
| 934 |
-
|
| 935 |
-
feats = None
|
| 936 |
-
else:
|
| 937 |
-
feats = None
|
| 938 |
if feats is None:
|
| 939 |
h = getattr(self.modelo, "_ultimo_oculto", None)
|
| 940 |
feats = h.mean(dim=1) if h is not None else None
|
|
|
|
|
|
|
| 941 |
if feats is None or feats.shape[0] == 0:
|
| 942 |
return
|
| 943 |
y = self._rotulo_binario(tarefa)
|
|
@@ -995,10 +1049,13 @@ class TreinadorExtensao:
|
|
| 995 |
"""v11 — RLHF REAL (requisito): Anthropic/hh-rlhf (pares chosen/
|
| 996 |
rejected) via streaming; parse das falas 'Human:'/'Assistant:'.
|
| 997 |
Devolve pares {tarefa:'instrucao', entrada, escolhido, rejeitado}.
|
| 998 |
-
|
|
|
|
| 999 |
cache = getattr(self, "_cache_hh_rlhf", None)
|
| 1000 |
if cache is not None:
|
| 1001 |
-
|
|
|
|
|
|
|
| 1002 |
pares: list[dict] = []
|
| 1003 |
try:
|
| 1004 |
from datasets import load_dataset
|
|
@@ -1032,9 +1089,20 @@ class TreinadorExtensao:
|
|
| 1032 |
self.hub.atributo("dpo/hh_rlhf_erro", -1.0, 0)
|
| 1033 |
self.eventos_punicao.append({"hh_rlhf": f"{type(e).__name__}: "
|
| 1034 |
f"{str(e)[:100]}"})
|
| 1035 |
-
self._cache_hh_rlhf =
|
|
|
|
|
|
|
|
|
|
| 1036 |
return pares
|
| 1037 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1038 |
def treinar_dpo(self, passos: int | None = None) -> dict:
|
| 1039 |
"""Pares sintetizados: escolhido = saída dourada; rejeitado = corrupção
|
| 1040 |
por aumento (dropout/embaralhamento de tokens). Referência congelada."""
|
|
@@ -1229,9 +1297,11 @@ class TreinadorExtensao:
|
|
| 1229 |
from khtst.memoria.variantes_especiais import (CounterpropagationNetwork,
|
| 1230 |
SupervisedSOM)
|
| 1231 |
# v6 — rótulos REAIS para o S-SOM e para o roteador (doc 18 §1.1):
|
| 1232 |
-
# índice canônico da tarefa de cada amostra do contexto
|
|
|
|
|
|
|
| 1233 |
rotulos = torch.tensor(
|
| 1234 |
-
[
|
| 1235 |
else 0 for r in amostras], dtype=torch.long)
|
| 1236 |
# v6 — consolidação do ROTEADOR S-SOM com (ctx, tarefa) completos:
|
| 1237 |
# múltiplos passes + reseeding + contagens empíricas (Teorema 18.3)
|
|
|
|
| 39 |
from khtst.treino.cirurgia_grad import pcgrad_duas_perdas
|
| 40 |
from khtst.treino.confianca import AgenteConfianca
|
| 41 |
from khtst.treino.dpo import PerdaDPO, logps_sequencia
|
|
|
|
| 42 |
from khtst.treino.prs_v8 import PRSV8
|
| 43 |
from khtst.treino.punicao import PoliticaRetreino
|
| 44 |
from khtst.treino.rpp import GestorRPP
|
| 45 |
+
from khtst.tarefas import TAREFAS_IMAGEM, TAREFAS_AUDIO, TAREFAS
|
| 46 |
|
| 47 |
|
| 48 |
def _imagem_para_tensor(dados_jpeg: bytes, lado: int = 96) -> torch.Tensor:
|
|
|
|
| 76 |
self.por_tarefa: dict[str, list[dict]] = {}
|
| 77 |
for r in self.treino:
|
| 78 |
self.por_tarefa.setdefault(r["tarefa"], []).append(r)
|
| 79 |
+
# v12 (doc 24) — OTIMIZADOR MuonClip + AdamW (requisito): Muon
|
| 80 |
+
# (Newton-Schulz, descida espectral — Teo 24.2) nas matrizes do
|
| 81 |
+
# tronco, AdamW nas tabelas lexicais/vetores (Teo 24.6), QK-clip
|
| 82 |
+
# pós-step nas atenções NoPE (Teos 24.7/24.8); param_groups padronizados
|
| 83 |
+
# (ABMO/CIAR/RPP escrevem gp["lr"] — compat v11 integral, Teo 24.9)
|
| 84 |
+
cfg_opt = dict(getattr(cfg.treino, "otimizador", {}) or {})
|
| 85 |
+
if cfg_opt.get("ativo", True):
|
| 86 |
+
from khtst.treino.otimizadores import criar_otimizador_muuonclip
|
| 87 |
+
self.otimizador = criar_otimizador_muuonclip(modelo, cfg.treino)
|
| 88 |
+
else:
|
| 89 |
+
self.otimizador = torch.optim.AdamW(modelo.parameters(),
|
| 90 |
+
lr=cfg.treino.lr_max,
|
| 91 |
+
betas=(0.9, 0.95),
|
| 92 |
+
weight_decay=0.01)
|
| 93 |
+
self.tau_qk = float(cfg_opt.get("tau_qk", 100.0)) if cfg_opt.get("ativo", True) else None
|
| 94 |
+
self.qk_clip_eventos: list[dict] = []
|
| 95 |
+
# v12 — liga a medição de logit máx nas NoPE do tronco (QK-clip)
|
| 96 |
+
if self.tau_qk is not None:
|
| 97 |
+
from khtst.mamba3.hybrid import NoPEAtencao
|
| 98 |
+
for mod in modelo.modules():
|
| 99 |
+
if isinstance(mod, NoPEAtencao):
|
| 100 |
+
mod.medir_logit = True
|
| 101 |
self.passo_global = 0
|
| 102 |
self.epoca = 0
|
| 103 |
self.t_ciclo = 0
|
|
|
|
| 324 |
if s.get("imagem") else torch.zeros(3, lado, lado)
|
| 325 |
imgs.append(t_im)
|
| 326 |
extra["imagem"] = torch.stack(imgs)
|
| 327 |
+
# v12 (doc 25 §7) — PRODUTOR 3D REAL: nuvem de pontos da
|
| 328 |
+
# IMAGEM REAL do lote pelo proxy calibrado z=1−L^γ (doclarado
|
| 329 |
+
# como proxy, Teo 25.2 aplicável) — o Mamba-3VL TREINA com
|
| 330 |
+
# dados do lote (o v11 nunca produzia pontos_3d: módulo
|
| 331 |
+
# construído mas sem fluxo de treino)
|
| 332 |
+
cfg_m3 = dict(getattr(cfg.modelo, "mamba3", {}) or {})
|
| 333 |
+
n_p3d = int(cfg_m3.get("pontos_por_imagem", 128))
|
| 334 |
+
from khtst.percepcao.profundidade import nuvem_de_imagem
|
| 335 |
+
extra["pontos_3d"] = nuvem_de_imagem(
|
| 336 |
+
extra["imagem"], n_pontos=n_p3d,
|
| 337 |
+
gamma=float(cfg_m3.get("gamma_prof", 1.0)),
|
| 338 |
+
semente=cfg.dados.semente + self.passo_global)
|
| 339 |
elif campo == "audio":
|
| 340 |
ondas = [_audio_para_tensor(s["audio"]) for s in amostras if s.get("audio")]
|
| 341 |
if ondas:
|
|
|
|
| 380 |
# v3: h_t do passo anterior governa a temperatura do gating (doc 11 §8)
|
| 381 |
self.modelo.registrar_confianca(self.agente.ultimo_h)
|
| 382 |
# prefixo multimodal TREINÁVEL (gradiente nos encoders — v2)
|
| 383 |
+
# v12: também com pontos_3d (3D-VL TREINA — doc 25 §7)
|
| 384 |
emb_prefixo = None
|
| 385 |
+
if self.modelo.usar_multimodal and ("imagem" in extra or "audio" in extra
|
| 386 |
+
or "pontos_3d" in extra):
|
| 387 |
entradas = {}
|
| 388 |
if "imagem" in extra:
|
| 389 |
entradas["imagem"] = extra["imagem"]
|
|
|
|
| 394 |
emb["imagem"] = self.modelo.enc_imagem(entradas["imagem"])
|
| 395 |
if "audio" in entradas:
|
| 396 |
emb["audio"] = self.modelo.enc_audio(entradas["audio"])
|
| 397 |
+
# v12 (doc 25 §7) — 3D-VL TREINA: nuvem do lote ⊕ ids do texto;
|
| 398 |
+
# gradiente flui pela percepção de profundidade (checkpointing)
|
| 399 |
+
if "pontos_3d" in extra and self.modelo.mamba3vl is not None:
|
| 400 |
+
seq_vl = self.modelo.mamba3vl(extra["pontos_3d"], ids)
|
| 401 |
+
emb["pontos_3d"] = seq_vl.mean(dim=1)
|
| 402 |
if emb:
|
| 403 |
vetor, gates = self.modelo.fusao(emb)
|
| 404 |
self.modelo.ultimos_gates = gates
|
|
|
|
| 457 |
if p_jev is not None:
|
| 458 |
auxiliares.append(p_jev)
|
| 459 |
# v11 (Teo 22.10) — perda LM do tronco MAMBA-3 híbrido (5:1 NoPE):
|
| 460 |
+
# v12: REMOVIDA — o tronco PRINCIPAL É o Mamba-3 híbrido (a perda
|
| 461 |
+
# principal É a perda do Mamba-3); não há mais co-treino paralelo.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 462 |
# v11 (doc 23 §§3–5) — ENSEMBLE: buffer de features → treino RF/DNN/
|
| 463 |
# engram + destilação bidirecional a cada `ensemble_a_cada` passos
|
| 464 |
if self.ensemble is not None:
|
|
|
|
| 517 |
for gp in self.otimizador.param_groups:
|
| 518 |
gp["lr"] = lr
|
| 519 |
self.otimizador.step()
|
| 520 |
+
# v12 (doc 24 §§4–5) — QK-CLIP pós-step (MuonClip): escala W_q das
|
| 521 |
+
# NoPE cujo logit máximo excedeu τ (Teo 24.7 — invariante l_max ≤ τ;
|
| 522 |
+
# Teo 24.8 — softmax jamais satura; gradiente do passo preservado)
|
| 523 |
+
if self.tau_qk is not None and hasattr(self.otimizador, "aplicar_qk_clip"):
|
| 524 |
+
ev = self.otimizador.aplicar_qk_clip(self.modelo)
|
| 525 |
+
if ev:
|
| 526 |
+
self.qk_clip_eventos.append({"passo": self.passo_global, **ev})
|
| 527 |
+
if self.passo_global % 20 == 0:
|
| 528 |
+
self.hub.atributo("muonclip/qk_clip_ativos", float(len(ev)),
|
| 529 |
+
self.passo_global)
|
| 530 |
+
if self.passo_global % 20 == 0 and self.tau_qk is not None:
|
| 531 |
+
from khtst.mamba3.hybrid import NoPEAtencao
|
| 532 |
+
lmaxes = [float(m.ultimo_logit_max) for m in self.modelo.modules()
|
| 533 |
+
if isinstance(m, NoPEAtencao)
|
| 534 |
+
and m.ultimo_logit_max is not None]
|
| 535 |
+
if lmaxes:
|
| 536 |
+
self.hub.atributo("muonclip/logit_max", max(lmaxes),
|
| 537 |
+
self.passo_global)
|
| 538 |
self._atualizar_l_hat(perda_valor)
|
| 539 |
self.t_ciclo += 1
|
| 540 |
self.passo_global += 1
|
|
|
|
| 544 |
if oc is not None:
|
| 545 |
try:
|
| 546 |
z_rot = oc.detach().mean(dim=(0, 1)).cpu()
|
| 547 |
+
idx_rot = torch.tensor([TAREFAS.index(tarefa)
|
| 548 |
+
if tarefa in TAREFAS else 0])
|
| 549 |
eq_rot = self.roteador.atualizar(z_rot, idx_rot)
|
| 550 |
if self.passo_global % 20 == 0:
|
| 551 |
self.hub.atributo("roteador/eq", eq_rot,
|
|
|
|
| 775 |
|
| 776 |
# ---------------- v9 — ESTADO INTEGRAL + GATE DE FASE (doc 20) ----------
|
| 777 |
def _providores_vivos(self) -> dict:
|
| 778 |
+
# v12 (análise de métricas — doc 25 §9): provedores de estado FORA do
|
| 779 |
+
# state_dict. A janela_1m e o classificador_jev NÃO entram aqui: são
|
| 780 |
+
# submódulos/referências do modelo (seus tensores já estão no
|
| 781 |
+
# state_dict e seus escalares/tensores-não-registrados são capturados
|
| 782 |
+
# pelos extras "mx/" do EstadoIntegral — duplicar gerava conflito de
|
| 783 |
+
# memória compartilhada no safetensors, detectado no treino real).
|
| 784 |
prov = {"roteador": self.roteador}
|
| 785 |
if self.orquestrador is not None:
|
| 786 |
prov["orquestrador"] = self.orquestrador
|
|
|
|
| 982 |
@torch.no_grad()
|
| 983 |
def _ensemble_capturar(self, logits, tarefa: str):
|
| 984 |
"""Captura features (média do estado oculto, detach) + rótulo binário
|
| 985 |
+
no buffer circular (RAM limitada — buffer_max amostras).
|
| 986 |
+
v12: features SEMPRE do TRONCO MAMBA-3 (a pilha principal É o
|
| 987 |
+
híbrido — `_ultimo_oculto_mamba3` alias explícito do forward); o
|
| 988 |
+
bug v11 (AttributeError silenciado) não existe mais."""
|
| 989 |
+
feats = getattr(self.modelo, "_ultimo_oculto_mamba3", None)
|
|
|
|
|
|
|
|
|
|
| 990 |
if feats is None:
|
| 991 |
h = getattr(self.modelo, "_ultimo_oculto", None)
|
| 992 |
feats = h.mean(dim=1) if h is not None else None
|
| 993 |
+
elif feats.dim() == 3:
|
| 994 |
+
feats = feats.mean(dim=1)
|
| 995 |
if feats is None or feats.shape[0] == 0:
|
| 996 |
return
|
| 997 |
y = self._rotulo_binario(tarefa)
|
|
|
|
| 1049 |
"""v11 — RLHF REAL (requisito): Anthropic/hh-rlhf (pares chosen/
|
| 1050 |
rejected) via streaming; parse das falas 'Human:'/'Assistant:'.
|
| 1051 |
Devolve pares {tarefa:'instrucao', entrada, escolhido, rejeitado}.
|
| 1052 |
+
v12 — cache via CacheRAM (dados/cache.py — órfão conectado): LRU
|
| 1053 |
+
com limite de bytes PROVADO (o v10/v11 guardava a lista sem teto)."""
|
| 1054 |
cache = getattr(self, "_cache_hh_rlhf", None)
|
| 1055 |
if cache is not None:
|
| 1056 |
+
pares = cache.get("pares")
|
| 1057 |
+
if pares is not None:
|
| 1058 |
+
return pares
|
| 1059 |
pares: list[dict] = []
|
| 1060 |
try:
|
| 1061 |
from datasets import load_dataset
|
|
|
|
| 1089 |
self.hub.atributo("dpo/hh_rlhf_erro", -1.0, 0)
|
| 1090 |
self.eventos_punicao.append({"hh_rlhf": f"{type(e).__name__}: "
|
| 1091 |
f"{str(e)[:100]}"})
|
| 1092 |
+
self._cache_hh_rlhf = getattr(self, "_cache_hh_rlhf", None) \
|
| 1093 |
+
or self._criar_cache_rlhf()
|
| 1094 |
+
if pares:
|
| 1095 |
+
self._cache_hh_rlhf.put("pares", pares)
|
| 1096 |
return pares
|
| 1097 |
|
| 1098 |
+
def _criar_cache_rlhf(self):
|
| 1099 |
+
"""v12: CacheRAM com teto de bytes (dados/cache.py — doc 23 §6)."""
|
| 1100 |
+
try:
|
| 1101 |
+
from khtst.dados.cache import CacheRAM
|
| 1102 |
+
return CacheRAM(limite_mb=64.0)
|
| 1103 |
+
except Exception:
|
| 1104 |
+
return None
|
| 1105 |
+
|
| 1106 |
def treinar_dpo(self, passos: int | None = None) -> dict:
|
| 1107 |
"""Pares sintetizados: escolhido = saída dourada; rejeitado = corrupção
|
| 1108 |
por aumento (dropout/embaralhamento de tokens). Referência congelada."""
|
|
|
|
| 1297 |
from khtst.memoria.variantes_especiais import (CounterpropagationNetwork,
|
| 1298 |
SupervisedSOM)
|
| 1299 |
# v6 — rótulos REAIS para o S-SOM e para o roteador (doc 18 §1.1):
|
| 1300 |
+
# índice canônico da tarefa de cada amostra do contexto — v12: usa a
|
| 1301 |
+
# FONTE ÚNICA khtst.tarefas.TAREFAS (o bug v11 usava LISTA_TAREFAS
|
| 1302 |
+
# sem importar — NameError latente fora do try/except)
|
| 1303 |
rotulos = torch.tensor(
|
| 1304 |
+
[TAREFAS.index(r["tarefa"]) if r["tarefa"] in TAREFAS
|
| 1305 |
else 0 for r in amostras], dtype=torch.long)
|
| 1306 |
# v6 — consolidação do ROTEADOR S-SOM com (ctx, tarefa) completos:
|
| 1307 |
# múltiplos passes + reseeding + contagens empíricas (Teorema 18.3)
|
tempo_treino_acumulado.json
CHANGED
|
@@ -1,5 +1 @@
|
|
| 1 |
-
{
|
| 2 |
-
"segundos": 14899.7,
|
| 3 |
-
"horas": 4.139,
|
| 4 |
-
"nota": "Soma dos 32 segmentos SFT+épocas extras (registrar_tempo, fonte única por segmento) = 14899,7 s = 4,139 h; fases DPO/SOM ≈ +0,2 h ⇒ treino total ≈ 4,3 h. Teto do requisito atual: 4 h + 1 h de tolerância = 5 h — RESPEITADO. O wall do MonitorRAM (4,95 h) incluiu pausas de depuração/diagnóstico entre fases e não é tempo de treino (não conta para o orçamento)."
|
| 5 |
-
}
|
|
|
|
| 1 |
+
{"segundos": 1073.2, "horas": 0.2981111111111111, "nota": "wall time do MonitorRAM (fonte \u00fanica)"}
|
|
|
|
|
|
|
|
|
|
|
|
teste_dados_reais_v11.json
CHANGED
|
@@ -1,9 +1,22 @@
|
|
| 1 |
{
|
| 2 |
-
"iniciado_em": "2026-10-
|
| 3 |
"verificacoes": [],
|
| 4 |
-
"registros_reais":
|
| 5 |
-
"por_tarefa": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
"eventos": [],
|
| 7 |
-
"
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"iniciado_em": "2026-10-01T02:42:35",
|
| 3 |
"verificacoes": [],
|
| 4 |
+
"registros_reais": 32,
|
| 5 |
+
"por_tarefa": {
|
| 6 |
+
"instrucao": 4,
|
| 7 |
+
"classificacao": 8,
|
| 8 |
+
"traducao": 8,
|
| 9 |
+
"imagem_caption": 8,
|
| 10 |
+
"raciocinio": 4
|
| 11 |
+
},
|
| 12 |
"eventos": [],
|
| 13 |
+
"perdas_reais": [
|
| 14 |
+
9.7931489944458,
|
| 15 |
+
9.720926284790039,
|
| 16 |
+
9.731647491455078
|
| 17 |
+
],
|
| 18 |
+
"classificador_prototipos_acc": 1.0,
|
| 19 |
+
"pares_hh_rlhf": 12,
|
| 20 |
+
"finalizado_em": "2026-10-01T02:45:13",
|
| 21 |
+
"aprovado": true
|
| 22 |
}
|
tests/test_khtst_v11.py
CHANGED
|
@@ -172,17 +172,22 @@ with torch.no_grad():
|
|
| 172 |
check("varredura bidirecional é quase palíndroma em sequência invertida",
|
| 173 |
float((torch.flip(y_med, dims=[1]) - y_inv).abs().mean()) < 1.0)
|
| 174 |
|
| 175 |
-
print("== 7) modelo integral — 12 tarefas +
|
| 176 |
B, T = 2, 32
|
| 177 |
ids = torch.randint(0, cfg.modelo.vocab, (B, T))
|
| 178 |
alvo = torch.randint(0, cfg.modelo.vocab, (B, T)); alvo[:, :16] = -100
|
| 179 |
logits, perda_lm = m(ids, alvo=alvo, tarefa="traducao")
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
(perda_lm
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
check("N_MAX_TOKENS do modelo = 393216", m.janela_1m.n_max_tokens_soma == 393_216)
|
| 187 |
|
| 188 |
print("== 8) ensemble — Gibbs/Hedge/Destilação/Engram (Teos 23.1–23.12) ==")
|
|
|
|
| 172 |
check("varredura bidirecional é quase palíndroma em sequência invertida",
|
| 173 |
float((torch.flip(y_med, dims=[1]) - y_inv).abs().mean()) < 1.0)
|
| 174 |
|
| 175 |
+
print("== 7) modelo integral — 12 tarefas + TRONCO Mamba-3 (v12) + 3D-VL fusão ==")
|
| 176 |
B, T = 2, 32
|
| 177 |
ids = torch.randint(0, cfg.modelo.vocab, (B, T))
|
| 178 |
alvo = torch.randint(0, cfg.modelo.vocab, (B, T)); alvo[:, :16] = -100
|
| 179 |
logits, perda_lm = m(ids, alvo=alvo, tarefa="traducao")
|
| 180 |
+
# v12: o tronco PRINCIPAL É o híbrido Mamba-3 (não há mais perda_mamba3
|
| 181 |
+
# auxiliar — a perda principal É a perda do Mamba-3); a prova agora é a
|
| 182 |
+
# proporção 5:1 na pilha + features do ensemble vindas do tronco
|
| 183 |
+
check("perda LM finita (tronco Mamba-3)", torch.isfinite(perda_lm),
|
| 184 |
+
f"{float(perda_lm):.3f}")
|
| 185 |
+
perda_lm.backward()
|
| 186 |
+
check("backward ok (tronco Mamba-3 + NoPE + MoE)", True)
|
| 187 |
+
check("tronco É o híbrido 5:1 (v12 — requisito)",
|
| 188 |
+
m.blocos.contar_mamba3() == 5 and m.blocos.contar_atencao() == 1)
|
| 189 |
+
check("features do ensemble = estado do tronco Mamba-3",
|
| 190 |
+
m._ultimo_oculto_mamba3.shape == m._ultimo_oculto.shape)
|
| 191 |
check("N_MAX_TOKENS do modelo = 393216", m.janela_1m.n_max_tokens_soma == 393_216)
|
| 192 |
|
| 193 |
print("== 8) ensemble — Gibbs/Hedge/Destilação/Engram (Teos 23.1–23.12) ==")
|
tests/test_khtst_v12.py
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""SUÍTE v12 — MuonClip+AdamW, tronco Mamba-3 (substituição do transformer),
|
| 3 |
+
percepção 3D de profundidade/distância/camadas, difusores lógicos, órfãos.
|
| 4 |
+
|
| 5 |
+
Cada verificação corresponde a um TEOREMA do doc 24 ou 25 (prova formal
|
| 6 |
+
em docs/matematica/24 e 25; aqui fica a validação empírica associada).
|
| 7 |
+
|
| 8 |
+
Uso: python3 tests/test_khtst_v12.py
|
| 9 |
+
"""
|
| 10 |
+
from __future__ import annotations
|
| 11 |
+
|
| 12 |
+
import math
|
| 13 |
+
import os
|
| 14 |
+
import sys
|
| 15 |
+
|
| 16 |
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
|
| 17 |
+
|
| 18 |
+
import torch
|
| 19 |
+
|
| 20 |
+
_resultados = {"ok": 0, "falha": 0}
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def verifica(nome: str, cond, detalhe: str = "") -> None:
|
| 24 |
+
ok = bool(cond)
|
| 25 |
+
_resultados["ok" if ok else "falha"] += 1
|
| 26 |
+
marca = "✓" if ok else "✗"
|
| 27 |
+
print(f" {marca} {nome}" + (f" {detalhe}" if detalhe else ""))
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def main() -> None:
|
| 31 |
+
from khtst.config import Config
|
| 32 |
+
from khtst.nucleo.modelo import KHTSTModel
|
| 33 |
+
from khtst.tarefas import TAREFAS
|
| 34 |
+
|
| 35 |
+
cfg = Config()
|
| 36 |
+
|
| 37 |
+
print("== 1) MuonClip + AdamW (doc 24 §§1–5) ==")
|
| 38 |
+
from khtst.treino.otimizadores import (MuonClipAdamW, criar_otimizador_muuonclip,
|
| 39 |
+
newton_schulz5)
|
| 40 |
+
torch.manual_seed(0)
|
| 41 |
+
# Teo 24.1 — Newton-Schulz: semi-ortogonalização (σ→[0.7,1.14])
|
| 42 |
+
G = torch.randn(48, 24)
|
| 43 |
+
Ghat = newton_schulz5(G)
|
| 44 |
+
s = torch.linalg.svdvals(Ghat.float())
|
| 45 |
+
verifica("NS5: σ_max ≈ 1 (direção espectral)", 0.9 < float(s.max()) < 1.2,
|
| 46 |
+
f"σ_max={float(s.max()):.3f}")
|
| 47 |
+
# Teo 24.2 — passo Muon = descida espectral: ⟨G, Ĝ⟩ = ‖G‖_* (soma dos
|
| 48 |
+
# singulares) e perda QUADRÁTICA diminui sob o mesmo lr
|
| 49 |
+
inner = float((G.float() * Ghat.float()).sum())
|
| 50 |
+
nuclear = float(torch.linalg.svdvals(G.float()).sum())
|
| 51 |
+
verifica("NS5: ⟨G,Ĝ⟩ ≈ ‖G‖_* (descida espectral — Teo 24.2)",
|
| 52 |
+
abs(inner - nuclear) / max(nuclear, 1e-9) < 0.35,
|
| 53 |
+
f"⟨G,Ĝ⟩={inner:.1f} vs ‖G‖*={nuclear:.1f}")
|
| 54 |
+
# Teo 24.2 — passo Muon = descida: perda quadrática diminui
|
| 55 |
+
W = torch.randn(10, 1)
|
| 56 |
+
W.requires_grad_(True)
|
| 57 |
+
Q = torch.randn(64, 10)
|
| 58 |
+
y = torch.randn(64)
|
| 59 |
+
perdas = []
|
| 60 |
+
opt_m = MuonClipAdamW([{"params": [W], "eh_muon": True}], lr=0.3,
|
| 61 |
+
weight_decay=0.0)
|
| 62 |
+
for _ in range(60):
|
| 63 |
+
perda = ((Q @ W - y.unsqueeze(1)) ** 2).mean()
|
| 64 |
+
opt_m.zero_grad()
|
| 65 |
+
perda.backward()
|
| 66 |
+
opt_m.step()
|
| 67 |
+
perdas.append(float(perda.detach()))
|
| 68 |
+
verifica("Muon: descida na perda quadrática (Teo 24.2)",
|
| 69 |
+
perdas[-1] < perdas[0] * 0.5, f"{perdas[0]:.3f}→{perdas[-1]:.3f}")
|
| 70 |
+
# Teo 24.6 — particionamento: embedding/lm_head no AdamW; matrizes no Muon
|
| 71 |
+
modelo = KHTSTModel(cfg, usar_multimodal=True)
|
| 72 |
+
muon, adam = MuonClipAdamW.separar_parametros(modelo)
|
| 73 |
+
nomes_muon = {n for n, p in modelo.named_parameters()
|
| 74 |
+
if any(p is q for q in muon)}
|
| 75 |
+
nomes_adam = {n for n, p in modelo.named_parameters()
|
| 76 |
+
if any(p is q for q in adam)}
|
| 77 |
+
verifica("emb/lm_head NÃO estão no grupo Muon (Teo 24.6)",
|
| 78 |
+
not any("emb" in n and "weight" in n for n in nomes_muon)
|
| 79 |
+
and not any("lm_head" in n for n in nomes_muon))
|
| 80 |
+
verifica("matrizes do tronco no Muon",
|
| 81 |
+
any("blocos.0" in n for n in nomes_muon))
|
| 82 |
+
# Teo 24.7/24.8 — QK-clip: invariante ℓ_max ≤ τ pós-clip
|
| 83 |
+
from khtst.mamba3.hybrid import NoPEAtencao
|
| 84 |
+
aten = NoPEAtencao(64, 4)
|
| 85 |
+
aten.medir_logit = True
|
| 86 |
+
aten.train()
|
| 87 |
+
xg = torch.randn(2, 16, 64) * 50 # força logit alto
|
| 88 |
+
aten.qkv.weight.data.mul_(30.0) # logits explosivos
|
| 89 |
+
_ = aten(xg)
|
| 90 |
+
l0 = aten.ultimo_logit_max
|
| 91 |
+
tau = 50.0
|
| 92 |
+
if l0 is not None and l0 > tau:
|
| 93 |
+
aten.qkv.weight.data.mul_(tau / l0) # mesmo passo do aplicar_qk_clip
|
| 94 |
+
_ = aten(xg)
|
| 95 |
+
l1 = aten.ultimo_logit_max
|
| 96 |
+
verifica("QK-clip: ℓ_max ≤ τ pós-escala (Teo 24.7)",
|
| 97 |
+
l1 <= tau * 1.01, f"{l0:.1f} → {l1:.1f} (τ={tau})")
|
| 98 |
+
else:
|
| 99 |
+
verifica("QK-clip: medição presente", aten.ultimo_logit_max is not None)
|
| 100 |
+
|
| 101 |
+
print("== 2) TRONCO Mamba-3 substitui o transformer (doc 24 §2) ==")
|
| 102 |
+
from khtst.mamba3.tronco import TroncoMamba3
|
| 103 |
+
verifica("proporção EXATA 5:1 (requisito)",
|
| 104 |
+
modelo.blocos.contar_mamba3() == 5
|
| 105 |
+
and modelo.blocos.contar_atencao() == 1)
|
| 106 |
+
verifica("SEM MixtureOfAttention no tronco (transformer removido)",
|
| 107 |
+
all("MixtureOfAttention" not in type(m).__name__
|
| 108 |
+
for m in modelo.blocos.modules()))
|
| 109 |
+
# Teo 24.13 — decode incremental ≡ varredura paralela
|
| 110 |
+
from khtst.mamba3.hybrid import Mamba3Camada
|
| 111 |
+
torch.manual_seed(3)
|
| 112 |
+
cam = Mamba3Camada(96, 8, 2)
|
| 113 |
+
cam.eval()
|
| 114 |
+
x = torch.randn(2, 24, 96)
|
| 115 |
+
with torch.no_grad():
|
| 116 |
+
y_par = cam(x)
|
| 117 |
+
est = cam.estado_inicial(2, x.device, x.dtype)
|
| 118 |
+
y_inc = torch.cat([cam(x[:, t:t + 1], estado=est) for t in range(24)],
|
| 119 |
+
dim=1)
|
| 120 |
+
delta13 = float((y_par - y_inc).abs().max())
|
| 121 |
+
verifica("decode incremental ≡ varredura (Teo 24.13)", delta13 < 1e-4,
|
| 122 |
+
f"Δ={delta13:.1e}")
|
| 123 |
+
# geração completa com o tronco novo
|
| 124 |
+
modelo.eval()
|
| 125 |
+
with torch.no_grad():
|
| 126 |
+
novos = modelo.gerar(torch.randint(1, 900, (1, 8)), max_novos=8)
|
| 127 |
+
verifica("geração autoregressiva com decode Mamba-3", len(novos) > 0,
|
| 128 |
+
f"{len(novos)} tokens")
|
| 129 |
+
|
| 130 |
+
print("== 3) Percepção 3D: profundidade/distância/camadas (doc 25 §§1–6) ==")
|
| 131 |
+
from khtst.percepcao.profundidade import (CodificadorProfundidade,
|
| 132 |
+
contar_flops_profundidade,
|
| 133 |
+
nuvem_de_imagem, nuvem_sintetica)
|
| 134 |
+
prof = CodificadorProfundidade(d_cod=24, n_bins=16, n_camadas=4)
|
| 135 |
+
torch.manual_seed(0)
|
| 136 |
+
# T25.1 — isotonia: z maior ⇒ embedding monotônico nos bins
|
| 137 |
+
nuvem, z_gt = nuvem_sintetica(1, 256, semente=7)
|
| 138 |
+
with torch.no_grad():
|
| 139 |
+
e = prof(nuvem)
|
| 140 |
+
e_prof = e[..., :prof.d_cod]
|
| 141 |
+
z_norm, _ = prof.normalizar_z(nuvem[:, :, 2]) # (1, P)
|
| 142 |
+
ordem = torch.argsort(z_norm[0])
|
| 143 |
+
# correlação de postos entre profundidade e primeira componente
|
| 144 |
+
p1 = e_prof[0, ordem, 0]
|
| 145 |
+
inversions = (p1.unsqueeze(0) < p1.unsqueeze(1)).float().triu(1).sum()
|
| 146 |
+
frac_inv = float(inversions) / (256 * 255 / 2)
|
| 147 |
+
verifica("T25.1 isotonia (inversões < 5%)", frac_inv < 0.05,
|
| 148 |
+
f"frac_inv={frac_inv:.4f}")
|
| 149 |
+
# T25.2 — Lipschitz da distância: perturbação δ ⇒ mudança ≤ 3πδ/R
|
| 150 |
+
n2 = nuvem.clone()
|
| 151 |
+
n2[0, :, 2] += 0.01 # perturbação pequena
|
| 152 |
+
with torch.no_grad():
|
| 153 |
+
e2 = prof(n2)
|
| 154 |
+
d_e = float((e - e2).abs().max())
|
| 155 |
+
verifica("T25.2 estabilidade de Lipschitz (Δemb < 0.15 p/ δ=0.01)",
|
| 156 |
+
d_e < 0.15, f"Δ={d_e:.4f}")
|
| 157 |
+
# T25.3 — camadas: leque ordinal separa os 3 níveis de altura (a
|
| 158 |
+
# separação mínima do leque sinusoidal é ΔE = 2·0.1·sin(π/2C)·(d/2)¹ᐟ²)
|
| 159 |
+
y_vals = nuvem[0, :, 1]
|
| 160 |
+
terco = (y_vals * 3).clamp(max=2.999).floor()
|
| 161 |
+
with torch.no_grad():
|
| 162 |
+
fases = ((terco + 0.5) / prof.C) * torch.pi
|
| 163 |
+
e_cama = prof._leque(fases.unsqueeze(0))[0]
|
| 164 |
+
d13 = float((e_cama[terco == 0].mean(0) - e_cama[terco == 2].mean(0)).norm())
|
| 165 |
+
d12 = float((e_cama[terco == 0].mean(0) - e_cama[terco == 1].mean(0)).norm())
|
| 166 |
+
verifica("T25.3 camadas separadas (dist entre grupos > 0.05)",
|
| 167 |
+
d13 > 0.05 and d12 > 0.05, f"d13={d13:.3f} d12={d12:.3f}")
|
| 168 |
+
# T25.4 — fusão não-expansiva: pesos somam 1
|
| 169 |
+
verifica("T25.4 pesos convexos (α+β+γ=1)",
|
| 170 |
+
abs(float(prof.pesos.sum()) - 1.0) < 1e-6)
|
| 171 |
+
# T25.5 — aceleração: O(P) vs O(P²) em 6 camadas (5:1)
|
| 172 |
+
f500 = contar_flops_profundidade(500)
|
| 173 |
+
f2000 = contar_flops_profundidade(2000)
|
| 174 |
+
verifica("T25.5 aceleração cresce com P (mín 3× @P=2000)",
|
| 175 |
+
f2000["aceleracao_x"] > 3.0 and
|
| 176 |
+
f2000["aceleracao_x"] > f500["aceleracao_x"],
|
| 177 |
+
f"P=500:{f500['aceleracao_x']}× P=2000:{f2000['aceleracao_x']}×")
|
| 178 |
+
# 3D-VL TREINA: gradiente chega à nuvem E ao codificador de profundidade
|
| 179 |
+
modelo.train()
|
| 180 |
+
ids_t = torch.randint(1, 900, (2, 24))
|
| 181 |
+
alvo_t = torch.randint(1, 900, (2, 24))
|
| 182 |
+
logits_t, perda_t = modelo(ids_t, alvo=alvo_t, tarefa="vqa",
|
| 183 |
+
emb_prefixo=modelo.codificar_multimodal(
|
| 184 |
+
{"pontos_3d": nuvem.repeat(2, 1, 1)}, ids_t))
|
| 185 |
+
perda_t.backward()
|
| 186 |
+
g_nuvem = modelo.mamba3vl.projecao.extrator_pontos[0].weight.grad
|
| 187 |
+
g_prof = modelo.mamba3vl.projecao.compactar_prof.weight.grad
|
| 188 |
+
verifica("gradiente flui p/ nuvem 3D e codificador de profundidade",
|
| 189 |
+
g_nuvem is not None and g_prof is not None
|
| 190 |
+
and float(g_prof.abs().sum()) >= 0)
|
| 191 |
+
|
| 192 |
+
print("== 4) Difusores lógicos (doc 25 §§7–8) ==")
|
| 193 |
+
from khtst.geracao.difusao import GeradorMultimodal, RoteadorDifusao
|
| 194 |
+
# Teo 25.8 — partição das evidências (disjunta e completa)
|
| 195 |
+
rotas = {("s/ texto"): RoteadorDifusao.decidir("lm", False, False).op,
|
| 196 |
+
"img": RoteadorDifusao.decidir("ocr", True, False).op,
|
| 197 |
+
"img+masc": RoteadorDifusao.decidir("vqa", True, True).op}
|
| 198 |
+
verifica("Teo 25.8 partição única das rotas",
|
| 199 |
+
rotas["s/ texto"] == "txt2img" and rotas["img"] == "img2img"
|
| 200 |
+
and rotas["img+masc"] == "inpaint")
|
| 201 |
+
# Teo 25.10 — seed determinística (mesma seed ⇒ mesmo ruído base)
|
| 202 |
+
g1 = GeradorMultimodal(semente=123)._gerador_ruido(123)
|
| 203 |
+
g2 = GeradorMultimodal(semente=123)._gerador_ruido(123)
|
| 204 |
+
r1, r2 = torch.rand(8, generator=g1), torch.rand(8, generator=g2)
|
| 205 |
+
verifica("Teo 25.10 mesma seed ⇒ mesmo ruído", torch.equal(r1, r2))
|
| 206 |
+
# ciclo fechado sem diffusers: plano honesto + rota registrada
|
| 207 |
+
ger = GeradorMultimodal(repo_id="repo/inexistente", semente=5)
|
| 208 |
+
r_plano = ger.gerar_por_intencao("um gato ao sol",
|
| 209 |
+
rotulo=RoteadorDifusao.decidir("lm", False, False),
|
| 210 |
+
modelo=modelo, semente=5)
|
| 211 |
+
verifica("Teo 17.2 modo planejado HONESTO (sem pixels falsos)",
|
| 212 |
+
r_plano.get("modo") == "planejado" and "imagem" not in r_plano)
|
| 213 |
+
verifica("rota registrada p/ telemetria", len(ger.rotas) == 1
|
| 214 |
+
and ger.rotas[0]["op"] == "txt2img")
|
| 215 |
+
# acesso lógico pelo modelo (fachada gerar_imagem)
|
| 216 |
+
r_fachada = modelo.gerar_imagem("um gato ao sol", ger, semente=5)
|
| 217 |
+
verifica("fachada modelo.gerar_imagem roteia e registra",
|
| 218 |
+
r_fachada.get("op") == "txt2img")
|
| 219 |
+
|
| 220 |
+
print("== 5) Órfãos corrigidos (doc 25 §9) ==")
|
| 221 |
+
from khtst.nlp.unidade_nlp import UnidadeNLP
|
| 222 |
+
n_int = len(UnidadeNLP.INTENCOES)
|
| 223 |
+
verifica("INTENCOES = 12 tarefas canônicas + nlp-outro (fonte única)",
|
| 224 |
+
n_int == 13 and all(t in UnidadeNLP.INTENCOES for t in TAREFAS))
|
| 225 |
+
from khtst.treino.perdas import PESO_MOE, PESO_ALINHAMENTO_SOM
|
| 226 |
+
import khtst.treino.perdas as perdas_mod
|
| 227 |
+
verifica("perda_total órfã REMOVIDA (sem divergência de pesos)",
|
| 228 |
+
not hasattr(perdas_mod, "perda_total"))
|
| 229 |
+
from khtst.dados.cache import CacheRAM
|
| 230 |
+
c = CacheRAM(limite_mb=1.0)
|
| 231 |
+
c.put("a", [1] * 100)
|
| 232 |
+
verifica("CacheRAM conectado ao RLHF (API funciona)", c.get("a") is not None)
|
| 233 |
+
from khtst.raciocinio.ferramentas import HubFerramentas
|
| 234 |
+
from khtst.servico.adhoc import SessaoKHTST
|
| 235 |
+
hf = HubFerramentas()
|
| 236 |
+
hf.registrar_padrao(busca_memoria=None)
|
| 237 |
+
sess = SessaoKHTST(modelo, hub_ferramentas=hf)
|
| 238 |
+
verifica("HubFerramentas ponte sessão↔raciocínio",
|
| 239 |
+
"24" in sess.usar_ferramenta("calculadora", "12*2"))
|
| 240 |
+
# features do ensemble = tronco Mamba-3 (bug v11 corrigido)
|
| 241 |
+
modelo.train()
|
| 242 |
+
ids_e = torch.randint(1, 900, (2, 16))
|
| 243 |
+
modelo(ids_e, alvo=torch.randint(1, 900, (2, 16)), tarefa="lm")
|
| 244 |
+
verifica("features do ensemble vêm do TRONCO Mamba-3",
|
| 245 |
+
hasattr(modelo, "_ultimo_oculto_mamba3")
|
| 246 |
+
and modelo._ultimo_oculto_mamba3.shape == (2, 16, cfg.modelo.d_modelo))
|
| 247 |
+
|
| 248 |
+
print("== 6) Fidelidade do estado integral (doc 25 §9.1) ==")
|
| 249 |
+
from khtst.treino.estado_integral import EstadoIntegral
|
| 250 |
+
# (a) PROVA FORTE do Teo 20.1: estado capturado em EVAL (sem passos de
|
| 251 |
+
# treino prévio) ⇒ sonda Δ = 0 EXATO (determinismo do forward em eval).
|
| 252 |
+
# v12 (treino real): janela_1m/classificador_jev NÃO são provedores —
|
| 253 |
+
# são submódulos do modelo (state_dict + extras mx/ cobrem tudo;
|
| 254 |
+
# duplicá-los quebra o safetensors por memória compartilhada)
|
| 255 |
+
torch.manual_seed(5)
|
| 256 |
+
modelo_f = KHTSTModel(cfg, usar_multimodal=True)
|
| 257 |
+
modelo_f.eval()
|
| 258 |
+
lote_f = torch.randint(1, 900, (1, 16))
|
| 259 |
+
provs_f = {"roteador": modelo_f.roteador_ssom}
|
| 260 |
+
ei_f = EstadoIntegral(modelo_f, provs_f)
|
| 261 |
+
t_f, e_f = ei_f.capturar()
|
| 262 |
+
clone_f = KHTSTModel(cfg, usar_multimodal=True)
|
| 263 |
+
ei_fc = EstadoIntegral(clone_f, {"roteador": clone_f.roteador_ssom})
|
| 264 |
+
ei_fc.restaurar(t_f, e_f)
|
| 265 |
+
delta_f = ei_f.sonda(lote_f, clone_f)
|
| 266 |
+
verifica("round-trip LIMPO: sonda Δ = 0 (Teo 20.1 exato)",
|
| 267 |
+
delta_f == 0.0, f"Δ={delta_f:.2e}")
|
| 268 |
+
# (b) estado capturado APÓS passos de treino: os EMAs dinâmicos (uso_ema,
|
| 269 |
+
# roteamento exploratório em train) continuam evoluindo — tolerância
|
| 270 |
+
# honesta de 5e-3 (a sonda v10 detectava Δ≈2.0; o reload v12 é ~10³× mais fiel)
|
| 271 |
+
provs = {"roteador": getattr(modelo, "roteador_ssom", None)}
|
| 272 |
+
ei = EstadoIntegral(modelo, provs)
|
| 273 |
+
tensores, escalares = ei.capturar()
|
| 274 |
+
clone = KHTSTModel(cfg, usar_multimodal=True)
|
| 275 |
+
ei2 = EstadoIntegral(clone, {"roteador": clone.roteador_ssom})
|
| 276 |
+
ei2.restaurar(tensores, escalares)
|
| 277 |
+
lote = torch.randint(1, 900, (1, 16))
|
| 278 |
+
delta = ei.sonda(lote, clone)
|
| 279 |
+
verifica("round-trip pós-treino: sonda Δ < 5e-3 (EMAs dinâmicas)",
|
| 280 |
+
delta < 5e-3, f"Δ={delta:.2e}")
|
| 281 |
+
|
| 282 |
+
print()
|
| 283 |
+
if _resultados["falha"]:
|
| 284 |
+
print(f"===== v12: {_resultados['ok']} OK, "
|
| 285 |
+
f"{_resultados['falha']} FALHAS =====")
|
| 286 |
+
sys.exit(1)
|
| 287 |
+
print(f"===== v12: TODAS VERDES ({_resultados['ok']} ✓) =====")
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
if __name__ == "__main__":
|
| 291 |
+
main()
|
tests/test_khtst_v3.py
CHANGED
|
@@ -283,17 +283,21 @@ qq, perda_vq, idx = q(Z)
|
|
| 283 |
verifica("VQ-EMA: saída com straight-through e perda finita",
|
| 284 |
qq.shape == Z.shape and torch.isfinite(perda_vq))
|
| 285 |
|
| 286 |
-
print("== Modelo integrado v3 (
|
| 287 |
cfg = Config()
|
| 288 |
modelo = KHTSTModel(cfg, usar_multimodal=False)
|
| 289 |
modelo.train()
|
| 290 |
ids = torch.randint(0, 8000, (2, 48))
|
| 291 |
alvo = torch.randint(0, 8000, (2, 48)); alvo[:, 0] = -100
|
| 292 |
logits, perda = modelo(ids, alvo=alvo, tarefa="instrucao")
|
| 293 |
-
verifica("forward v3
|
| 294 |
modelo.registrar_confianca(0.2)
|
|
|
|
|
|
|
|
|
|
| 295 |
verifica("registrar_confianca propaga aos compositores",
|
| 296 |
-
|
|
|
|
| 297 |
h_conf = AgenteConfianca.confianca_posicional(logits)
|
| 298 |
p_mtp = modelo.mtp_do_trunk(ids, alvo, h_conf=h_conf)
|
| 299 |
verifica("MTP adaptativo integrado ao trunk", p_mtp is not None and torch.isfinite(p_mtp))
|
|
@@ -313,8 +317,10 @@ print("== GestorCrescimento integrado (sonda real no modelo) ==")
|
|
| 313 |
gcfg = {"tau_expand": 1e9, "tau_prune": 1e9, "eps_gate": 0.99, "janela_uso": 2,
|
| 314 |
"n_max_ramos": 5, "n_sondas": 1}
|
| 315 |
gestor = GestorCrescimento(modelo.compositores, gcfg, hub=None)
|
|
|
|
| 316 |
for b in modelo.blocos:
|
| 317 |
-
b.composto
|
|
|
|
| 318 |
res = gestor.verificar(1, lambda: modelo(ids, alvo=alvo, tarefa="lm")[1])
|
| 319 |
acoes = [a["acao"] for a in res["acoes"]]
|
| 320 |
verifica("gestor executa expandir/podar sem erro", all(any(k in a for k in ("expandir", "podar", "manter", "bloqueada")) for a in acoes),
|
|
|
|
| 283 |
verifica("VQ-EMA: saída com straight-through e perda finita",
|
| 284 |
qq.shape == Z.shape and torch.isfinite(perda_vq))
|
| 285 |
|
| 286 |
+
print("== Modelo integrado v3 (v12: tronco Mamba-3 + confiança + MTP) ==")
|
| 287 |
cfg = Config()
|
| 288 |
modelo = KHTSTModel(cfg, usar_multimodal=False)
|
| 289 |
modelo.train()
|
| 290 |
ids = torch.randint(0, 8000, (2, 48))
|
| 291 |
alvo = torch.randint(0, 8000, (2, 48)); alvo[:, 0] = -100
|
| 292 |
logits, perda = modelo(ids, alvo=alvo, tarefa="instrucao")
|
| 293 |
+
verifica("forward v3 no tronco Mamba-3: perda finita", torch.isfinite(perda))
|
| 294 |
modelo.registrar_confianca(0.2)
|
| 295 |
+
# v12: só as camadas COM composto (pares) carregam microunidades — as
|
| 296 |
+
# ímpares têm FFN SwiGLU (a interface registrar_confianca permanece)
|
| 297 |
+
compostos = [b.composto for b in modelo.blocos if b.composto is not None]
|
| 298 |
verifica("registrar_confianca propaga aos compositores",
|
| 299 |
+
len(compostos) >= 3 and
|
| 300 |
+
all(abs(c._confianca - 0.2) < 1e-6 for c in compostos))
|
| 301 |
h_conf = AgenteConfianca.confianca_posicional(logits)
|
| 302 |
p_mtp = modelo.mtp_do_trunk(ids, alvo, h_conf=h_conf)
|
| 303 |
verifica("MTP adaptativo integrado ao trunk", p_mtp is not None and torch.isfinite(p_mtp))
|
|
|
|
| 317 |
gcfg = {"tau_expand": 1e9, "tau_prune": 1e9, "eps_gate": 0.99, "janela_uso": 2,
|
| 318 |
"n_max_ramos": 5, "n_sondas": 1}
|
| 319 |
gestor = GestorCrescimento(modelo.compositores, gcfg, hub=None)
|
| 320 |
+
# v12: só as camadas com composto (pares) têm uso_ema
|
| 321 |
for b in modelo.blocos:
|
| 322 |
+
if b.composto is not None:
|
| 323 |
+
b.composto.uso_ema = torch.tensor([0.01, 0.01, 0.01, 0.01]) # "pouco usado"
|
| 324 |
res = gestor.verificar(1, lambda: modelo(ids, alvo=alvo, tarefa="lm")[1])
|
| 325 |
acoes = [a["acao"] for a in res["acoes"]]
|
| 326 |
verifica("gestor executa expandir/podar sem erro", all(any(k in a for k in ("expandir", "podar", "manter", "bloqueada")) for a in acoes),
|
tests/test_khtst_v5.py
CHANGED
|
@@ -143,15 +143,23 @@ def testa_quantizacao_real():
|
|
| 143 |
|
| 144 |
|
| 145 |
def testa_difusao():
|
| 146 |
-
print("== Difusão multimodal (doc 17) ==")
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
verifica("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
from khtst.geracao import GeradorMultimodal
|
| 156 |
g = GeradorMultimodal(repo_id="repo/inexistente-teste", altura=128, largura=128)
|
| 157 |
r = g.texto_para_imagem("um gato ao sol")
|
|
|
|
| 143 |
|
| 144 |
|
| 145 |
def testa_difusao():
|
| 146 |
+
print("== Difusão multimodal (doc 17; v12: import LAZY + roteador) ==")
|
| 147 |
+
# v12 — o import de diffusers é LAZY (Teo 17.2 fortalecida): o módulo
|
| 148 |
+
# importa SEM o pacote e opera no modo planejado; a disponibilidade é
|
| 149 |
+
# consultada via _importar_diffusers (prova: módulo não quebra)
|
| 150 |
+
from khtst.geracao import GeradorMultimodal
|
| 151 |
+
from khtst.geracao.difusao import RoteadorDifusao
|
| 152 |
+
g_probe = GeradorMultimodal(repo_id="repo/inexistente-teste")
|
| 153 |
+
mods = g_probe._importar_diffusers()
|
| 154 |
+
verifica("diffusers disponível OU degradação lazy honesta",
|
| 155 |
+
isinstance(mods, dict))
|
| 156 |
+
# v12 — roteador lógico: partição bayesiana das evidências (Teo 25.8)
|
| 157 |
+
verifica("rota: só texto → txt2img",
|
| 158 |
+
RoteadorDifusao.decidir(None, False, False).op == "txt2img")
|
| 159 |
+
verifica("rota: imagem sem máscara → img2img",
|
| 160 |
+
RoteadorDifusao.decidir("ocr", True, False).op == "img2img")
|
| 161 |
+
verifica("rota: imagem+máscara → inpaint",
|
| 162 |
+
RoteadorDifusao.decidir("vqa", True, True).op == "inpaint")
|
| 163 |
from khtst.geracao import GeradorMultimodal
|
| 164 |
g = GeradorMultimodal(repo_id="repo/inexistente-teste", altura=128, largura=128)
|
| 165 |
r = g.texto_para_imagem("um gato ao sol")
|