PowerMachine commited on
Commit
bfe7b2e
·
verified ·
1 Parent(s): 3c2b90f

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 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 (v11: MAMBA-3 HÍBRIDO 5:1 + NoPE · Mamba-3VL 3D-VL · CHECKPOINTING DE ATIVAÇÃO · ENSEMBLE RF×DNN×DESTILAÇÃO BIDIRECIONAL×ENGRAEM · 12 TAREFAS · RLHF REAL)
45
 
46
  KHTST é um modelo multimodal compacto para PT-BR com roteamento por S-SOM,
47
- punição SGDR, RPP, janela PARALELA de contexto (entrada 256K + saída 128K
48
- = **N_MAX_TOKENS 393.216**), classificadores Jev auto-calibrados e —
49
- **novidade v11** — tronco **MAMBA-3 híbrido (1 NoPE-attention para cada 5
50
- Mamba-3)** com **Mamba-3VL bidirecional para visão 3D + linguagem-visão
51
- (3D-VL)**, **activation checkpointing**, **ensemble Random Forest × DNN
52
- com Destilação de Conhecimento BIDIRECIONAL e Engram Embeddings** (pesos
53
- dinâmicos Hedge/Gibbs), **12 tarefas** com fonte única de verdade,
54
- **9 datasets novos do requisito** (SFT AMALIA classlangcode, BLUEX-v2,
55
- intel-image, opus_books en-pt, flickr30k-pt-br, orion translations,
56
- Fable-5.1 reasoning, LLaVA-OneVision mid-training) e **RLHF REAL**
57
- (Anthropic/hh-rlhf) no DPO. Provas em `docs/matematica/22–23`.
58
-
59
- > ✅ **TESTE COM DADOS REAIS: APROVADO** (requisito: testar antes de
60
- > treinos longos) — 40 registros REAIS de 5 famílias (instrucao,
61
- > classificacao, traducao, imagem_caption, raciocinio), passos de treino
62
- > reais com perdas finitas e estáveis, DPO com pares REAIS do hh-rlhf
63
- > (acc 1,0), estado integral 84,8 MB (< 900 MB) com RELOAD bit-exato
64
- > (sonda δ\* = 0). Relatório: `telemetria_out/teste_dados_reais_v11.json`.
65
  >
66
- > 🧹 **Estados do treino anterior APAGADOS** (requisito) — o repositório
67
- > publica o código v11 sem pesos antigos; o novo treino usa orçamento de
68
- > **8 h + tolerância de 1 h** (teto rígido 9 h) e envia os estados
69
- > safetensors ao Hub **ANTES de 900 MB locais** (limiar 900 MB,
70
- > anti-bloqueio ≥ 10 min entre uploads, limpeza local verificada e
71
- > retomada real do Hub — Teorema 23.13).
 
72
 
73
- ## O que há de novo no v11 (provas em `docs/matematica/22` e `23`)
74
 
75
  | inovação | onde | prova |
76
  |---|---|---|
77
- | **N_MAX_TOKENS = ENTRADA + SAÍDA = 393.216** (constante órfã 1M do v10 corrigida e CONECTADA à classe); 5 campos de config mortos agora VIVOS (l_fino, w_segmento, s_passo, k_recall, viz_r) | `memoria/janela_1m.py` | Teo 22.1.1 |
78
- | **Fonte ÚNICA de tarefas** (12): fim da triplicação TAREFAS/LISTA_TAREFAS/GRUPOS_TAREFA | `tarefas.py` (novo) | Teo 22.1 |
79
- | **DESCRICOES_TAREFAS REMOVIDA** — critérios Jev DINÂMICOS: protótipos de contextos de exemplares REAIS por tarefa + refresh EMA não-expansivo | `percepcao/classificadores.py` | Teos 22.2.1–22.2.2 |
80
- | **MAMBA-3 híbrido 5:1** (1 NoPE attention / 5 Mamba-3): discretização TRAPETZOIDAL h_t = αh_{t−1} + (δ/2)(1+α)Bu com A por (d,n) — correção do bug `A[b,d,0]` da fonte; α ∈ (0,1) ⇒ CONTRAÇÃO (estabilidade BIBO); gradiente EXATO (erro 1,9e-10 vs diferença central); conv causal com pad esquerdo (fase corrigida) | `mamba3/` (novo) | Teos 22.2–22.7 |
81
- | **CHECKPOINTING DE ATIVAÇÃO** exato: memória O(√L), Δ(ckpt, sem-ckpt) = 0 medido; decode/KV-cache intocados | `mamba3/hybrid.py` | Teo 22.8 |
82
- | **Mamba-3VL (3D-VL)**: varredura bidirecional com fusão NÃO-EXPANSIVA ½(y⁺+y⁻) (a fonte somava — variância 2×); índice reverso exato; nuvem de pontos ⊕ texto intercalados, NoPE global sem viés geométrico | `mamba3/mamba3vl.py` | Teo 22.9 |
83
- | **Co-treino multi-arquitetura**: perda LM do Mamba-3 com cabeça EMPATADA — nascimento neutro no LM principal (decode idêntico ao v10) | `nucleo/modelo.py` | Teo 22.10 |
84
- | **Ensemble RF × DNN × Engram**: peso local GIBBS (positivo, normalizado — elimina o clip ad-hoc da fonte) + global HEDGE com regreto O(√(T ln M)) vs o melhor especialista; RF warm_start incremental com pesos por árvore | `ensemble/` (novo) | Teos 23.1–23.7 |
85
- | **Destilação de Conhecimento BIDIRECIONAL** (co-distilação): L = λ_T·KL(p_T‖p_S) + λ_S·KL(p_S‖p_T) — mode-covering + mode-seeking simultâneos; λ dinâmicos por HEDGE | `ensemble/destilacao.py` | Teos 23.8–23.9 |
86
- | **Engram Embeddings** (k-WTA Hebbiano): capacidade Hopfield M/(4 ln M) com esparsificação k/M; esquecimento exponencial (meia-vida ≈ 139 lotes); 3º especialista não-paramétrico da votação | `ensemble/engram.py` | Teos 23.10–23.12 |
87
- | **9 datasets do requisito** com adaptadores de schema REAL (validados por download): AMALIA classlangcode (parquet dirigido, filtro language=pt, score ≥ 0,5), BLUEX-v2 (question_text+subject), intel-image (label 0–5 → PT), opus_books + orion (traducao), flickr30k-pt-br (caption), Fable-5.1 (raciocinio, split lite), LLaVA-OneVision (caption VL) | `dados/streaming.py` | doc 23 §6 |
88
- | **RLHF REAL**: fração 0,4 dos passos DPO com pares (chosen, rejected) do Anthropic/hh-rlhf (streaming + cache limitado) | `treino/treinador.py` | doc 23 §6 |
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/02_coletar_corpus.py # inclui os 9 datasets do requisito
99
- python3 scripts/03_treinar_tokenizador.py # prefixos [trad]/[racio]/[class] novos
 
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 (estados antigos APAGADOS)
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 v11 (12 tarefas, ~20,6M parâmetros)
117
 
118
- `src/khtst/` — núcleo (decoder MoE + janela 393K), **mamba3/** (kernel
119
- trapezoidal + híbrido 5:1 NoPE + 3D-VL bidirecional + checkpointing),
120
- **ensemble/** (RF + DNN + destilação bidirecional + engram + votação
121
- Hedge/Gibbs), percepção (atenção árvore/MoE/ViT-LRA), memória (S-SOM +
122
- 8 variantes), treino (4 fases + PCGrad + CIAR + gates + DPO com RLHF
123
- real), servico (adhoc stop/continue), quanta (W8A8), telemetria,
124
- qualidade (Agente Engenheiro), acelerado (Cython+C).
 
 
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 | decoder causal 3 camadas, MoE enc-dec (2+4), MTP, atenção árvore |
132
- | **tronco Mamba-3** | híbrido 5:1 (6 camadas: 5 Mamba-3 + 1 NoPE), d=192, N=16, rank MIMO 4, checkpointing ON |
133
- | **Mamba-3VL** | 3D-VL bidirecional (6 camadas), nuvem (B,P,3) ⊕ texto → fusão `pontos_3d` |
134
- | **ensemble** | RF 32 árvores (warm_start) × DNN 96-48 × engram 256×8-vencedores; KD simétrica τ=2 |
 
 
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 com metacalibração térmica + critérios DINÂMICOS |
137
 
138
  ## Verificações (verdes)
139
 
140
- - **Suíte v11 (nova)**: 66 ✓ — Teos 22.1–22.9, 23.1–23.13, adaptadores
141
- dos 9 datasets com schemas reais, parse hh-rlhf, limiar 900 MB,
142
- checkpointing Δ=0, gradiente do kernel vs diferença central (1,9e-10).
143
- - Suítes v2–v10: **263 ✓ / 0 ✗** (v5 requer `diffusers` — ambiente sem
144
- GPU; teste executável em ambiente completo).
 
 
 
145
 
146
  ## Histórico
147
 
148
- - **v10** — janela paralela 256K→128K, classificadores Jev, fail-fast
149
- Cython (gate APROVADO: ppl_lm 2,58 vs AURORA 17,09; 4,14 h ≤ 4h+1h).
150
- - **v9** — estado integral + gates de rollback + CIAR. **v8** — itens
151
- a–j (atenção árvore, MoE enc-dec, anti-vanishing). Docs 00–23 com as
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": "v10-khtst-estado-integral-autorregulacao",
3
- "versao_anterior": "aurora-v7-baseline-publicado",
4
  "test_khtst_v6": {
5
- "ok": 48,
6
- "falhou": 0
7
  },
8
  "ram": {
9
- "amostras": 8398,
10
- "rss_min_mb": 421.1,
11
- "rss_med_mb": 2623.2,
12
- "rss_max_mb": 3445.3,
13
- "disponivel_min_mb": 197.1,
14
- "duracao_s": 17807.5
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": -0.1604,
106
- "clip_controle": -0.1702,
107
- "ppl_mm": 9.41,
108
- "ppl_visual": 1.16,
109
- "itm_acc": 0.5
110
  },
111
  "atual": {
112
- "clip_real": -0.0785,
113
- "clip_controle": -0.0819,
114
- "ppl_mm": 1.67,
115
- "ppl_visual": 1.96,
116
- "itm_acc": 0.5
117
  }
118
  },
119
  "ppl_lm": {
120
- "anterior": 17.088452564794597,
121
- "atual": 2.5771306062625214,
122
- "delta_pct": -84.92
123
  },
124
  "nao_regressao": {
125
- "antes": {
126
- "ppl_lm": 17.088452564794597,
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": 17.088452564794597,
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": 2.5771306062625214,
157
- "perdas_tarefa": {
158
- "lm": 0.9466766119003296,
159
- "noticia": 0.8249871333440145,
160
- "instrucao": 0.5357708881298701,
161
- "pontuacao": 1.0137320359547932,
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": null,
 
 
 
 
 
 
 
 
174
  "som": {
175
  "fase": "som",
176
  "tag_pre": "pre-som",
177
  "tag_pos": "fase-som",
178
- "ppl_pre": 11.485505113237048,
179
- "ppl_pos": 12.953695336481905,
180
- "sonda_max_delta": 1.9613137245178223,
181
- "acao": "ROLLBACK (regressão além da tolerância)"
182
  },
183
  "eventos": [
184
  {
185
- "acao": "rollback",
186
- "tag": "pre-som",
187
- "passo": 4788
 
 
 
 
188
  },
189
  {
190
  "fase": "som",
191
  "tag_pre": "pre-som",
192
  "tag_pos": "fase-som",
193
- "ppl_pre": 11.485505113237048,
194
- "ppl_pos": 12.953695336481905,
195
- "sonda_max_delta": 1.9613137245178223,
196
- "acao": "ROLLBACK (regressão além da tolerância)"
197
  }
198
  ]
199
  },
200
  "ciar": {
201
- "kappa": 0.781386,
202
- "integral": 1.655914,
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": true,
211
- "perdas_tarefa <= AURORA (todas)": true,
212
- "tempo < 3.98h (reduzir o último registrado)": false,
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

  • SHA256: 5ab4ab843c89883856c5876388f693d69714313c501b6779e08daee4ac107101
  • Pointer size: 128 Bytes
  • Size of remote file: 131 Bytes

Git LFS Details

  • SHA256: 260c8df91913db959da342f10f6fc557eafde35c00a34737a769d23253b35f97
  • Pointer size: 131 Bytes
  • Size of remote file: 145 kB
relatorio_agente_engenheiro.json CHANGED
@@ -1,5 +1,5 @@
1
  {
2
- "t": 1789892922.82,
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": "v10-khtst-estado-integral-autorregulacao",
3
- "teto_horas": 5.0,
4
- "tempo_acumulado_h": 4.139,
5
  "memoria_v8": {
6
- "rss_mb": 558.9,
7
- "pico_rss_mb": 558.9,
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": 0.781386,
16
- "integral": 1.655914,
17
  "kappa_min": 0.5,
18
  "kappa_max": 1.5,
19
  "ganho": 0.3,
20
  "vazamento": 0.98
21
  },
22
  "gate_fase": {
23
- "dpo": null,
 
 
 
 
 
 
 
 
24
  "som": {
25
  "fase": "som",
26
  "tag_pre": "pre-som",
27
  "tag_pos": "fase-som",
28
- "ppl_pre": 11.485505113237048,
29
- "ppl_pos": 12.953695336481905,
30
- "sonda_max_delta": 1.9613137245178223,
31
- "acao": "ROLLBACK (regressão além da tolerância)"
32
  },
33
  "eventos": [
34
  {
35
- "acao": "rollback",
36
- "tag": "pre-som",
37
- "passo": 4788
 
 
 
 
38
  },
39
  {
40
  "fase": "som",
41
  "tag_pre": "pre-som",
42
  "tag_pos": "fase-som",
43
- "ppl_pre": 11.485505113237048,
44
- "ppl_pos": 12.953695336481905,
45
- "sonda_max_delta": 1.9613137245178223,
46
- "acao": "ROLLBACK (regressão além da tolerância)"
47
  }
48
  ]
49
  },
50
  "avaliacao_recarregada_honesta": {
51
- "vqa": 1.3110978603363037,
52
- "pontuacao": 2.4990692734718323,
53
- "instrucao": 1.845857948064804,
54
- "tts": 2.519872546195984,
55
- "lm": 2.713647186756134,
56
- "imagem_caption": 1.9055586755275726,
57
- "ocr": 3.0294827222824097,
58
- "noticia": 2.4793878197669983,
59
- "asr": 2.4136089086532593,
60
- "ppl_lm": 15.084190170617365,
61
- "sonda_max_delta": 1.9985218048095703
 
 
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.39099937677383423,
664
- 0.1590317189693451,
665
- 0.04730470851063728,
666
- 0.25277379155158997
667
  ],
668
  "passos_rec": 2
669
  },
@@ -681,19 +147,23 @@
681
  1.0
682
  ],
683
  "uso_ema": [
684
- 0.022895572707057,
685
- 0.40639346837997437,
686
- 0.39755943417549133,
687
- 0.023261096328496933
688
  ],
689
  "passos_rec": 2
690
  }
691
  ],
692
  "dpo": {
693
- "pulado": true
 
 
 
 
694
  },
695
  "som": {
696
- "variante_ativa": "cpn",
697
  "variantes": {
698
  "som": {
699
  "k": 24,
@@ -712,7 +182,7 @@
712
  "gcs": {
713
  "k": 3,
714
  "arestas": 3,
715
- "eq_treino": 78938.59375,
716
  "atingiu_alvo": true
717
  },
718
  "gsom": {
@@ -737,22 +207,23 @@
737
  "ssom": {
738
  "k": 24,
739
  "taxa_ativos": 1.0,
740
- "resemeados": 23,
741
  "usos": 0,
742
  "atingiu_alvo": true
743
  }
744
  },
745
  "roteador": {
746
- "amostras": 3930,
747
  "pronto": true,
748
  "lambda_rota": 0.35,
749
  "gamma_empate": 0.15,
750
- "drift_codebook": 0.009764,
751
- "conf_media": 0.6561,
752
- "frac_rotas_ativas": 0.5312,
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
- "vqa": 1.5314274728298187,
806
- "pontuacao": 2.563664436340332,
807
- "instrucao": 1.82451793551445,
808
- "tts": 2.5394134521484375,
809
- "lm": 2.5076587200164795,
810
- "imagem_caption": 1.9724642932415009,
811
- "ocr": 3.667245090007782,
812
- "noticia": 2.373363494873047,
813
- "asr": 2.1272042989730835,
814
- "ppl_lm": 12.276154473059243
 
 
815
  },
816
  "metricas_completas": {
817
  "neuronios_ativos": {
818
- "ativos/som": 0.0,
819
  "k/som": 24,
820
- "ativos/gg": 0.0,
821
  "k/gg": 4,
822
- "ativos/gcs": 0.0,
823
  "k/gcs": 3,
824
- "ativos/gsom": 0.0,
825
  "k/gsom": 4,
826
- "ativos/hsom": 0.0,
827
  "k/hsom": 12,
828
- "ativos/tkm": 0.0,
829
  "k/tkm": 32,
830
- "ativos/rsom": 0.0,
831
  "k/rsom": 32,
832
  "ativos/cpn": 1.0,
833
  "k/cpn": 24,
834
- "ativos/ssom": 0.0,
835
  "k/ssom": 24,
836
- "A_global": 0.1111
837
  },
838
  "estruturais": {
839
- "ortogonalidade": 9.5367431640625e-07,
840
  "balanceamento_moe": 0.0,
841
- "gate_global": 0.3510807156562805,
842
- "gate_janela": 0.3591609001159668,
843
- "gate_linear": 0.2897583544254303,
844
- "moe1/experts_ativos": 6.0,
845
- "moe1/uso_max": 0.17338751256465912,
846
- "moe1/perda_lb": 0.05571587756276131,
847
- "moe1/perda_ort": 0.02825321815907955,
848
- "moe1/fase": 0.0,
849
- "moe1/beta_feedback": 0.0,
850
- "moe1/entropia_atn": 0.0,
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": 3,
857
- "micra0/ramos_ativos": 3,
858
  "micra0/passos_rec": 2,
859
- "micra0/alpha0": 6.553096909556189e-08,
860
- "micra0/alpha1": 0.9999998807907104,
861
- "micra0/alpha2": 4.121223219459569e-13,
862
- "micra0/uso0": 0.03092869557440281,
863
- "micra0/uso1": 0.7914800047874451,
864
- "micra0/uso2": 0.027701063081622124,
865
- "micra1/n_ramos": 4,
866
- "micra1/ramos_ativos": 4,
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.0033912688959389925,
880
- "micra2/alpha1": 0.7294881939888,
881
- "micra2/alpha2": 0.25933098793029785,
882
- "micra2/alpha3": 0.007789500057697296,
883
- "micra2/uso0": 0.022895572707057,
884
- "micra2/uso1": 0.40639346837997437,
885
- "micra2/uso2": 0.39755943417549133,
886
- "micra2/uso3": 0.023261096328496933,
887
- "nlp/gate_medio": 0.45893731713294983,
888
- "nlp/intencao_id": 7,
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": 2394,
904
  "roteador/pronto": 1.0,
905
  "roteador/frac_rotas": 0.0,
906
- "roteador/conf_media": 0.1111,
907
- "roteador/drift": 0.009764
908
  },
909
  "escala": {},
910
  "regime": {
@@ -921,43 +390,58 @@
921
  "kappa_rotas_mortas": 0.01
922
  },
923
  "roteador_ssom": {
924
- "amostras": 2394,
925
  "pronto": true,
926
  "lambda_rota": 0.35,
927
  "gamma_empate": 0.15,
928
- "drift_codebook": 0.009764,
929
- "conf_media": 0.1111,
930
  "frac_rotas_ativas": 0.0,
931
  "k": 24,
932
- "taxa_ativos": 0.2917
933
  },
934
  "inferencia_agente": {
935
- "latencia_s": 0.499,
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": false
945
  },
946
  "checkpoints_eventos": [
947
- "checkpoint fase-dpo: 571 tensores do modelo + 55 de provedores, 135 escalares",
948
- "checkpoint pre-som: local (62.5 MB, 626 tensores integrais)",
949
- "checkpoint fase-som: local (62.5 MB, 649 tensores integrais)",
950
- "checkpoint fase-som: 571 tensores do modelo + 78 de provedores, 194 escalares",
951
- "checkpoint pre-som: 571 tensores do modelo + 55 de provedores, 136 escalares",
952
- "checkpoint fase-som: 571 tensores do modelo + 78 de provedores, 194 escalares"
 
 
 
953
  ],
954
  "ram": {
955
- "amostras": 8398,
956
- "rss_min_mb": 421.1,
957
- "rss_med_mb": 2623.2,
958
- "rss_max_mb": 3445.3,
959
- "disponivel_min_mb": 197.1,
960
- "duracao_s": 17807.5
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": "v10-khtst-estado-integral-autorregulacao",
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 v11 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–23: + Mamba-3 híbrido/NoPE/3D-VL/
7
- checkpointing e ensemble RF×DNN×KD×Engram) · tests/ · evidências ·
8
- estados/fase-v11/ (pesos finais + meta SHA-256 + estado integral)
 
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-v11" # ÚNICO estado publicado (pesos + integral)
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 v11 — MAMBA-3 HÍBRIDO + NoPE (5:1) + MAMBA-3VL 3D-VL + "
158
- "CHECKPOINTING DE ATIVAÇÃO + ENSEMBLE RF×DNN×DESTILAÇÃO "
159
- "BIDIRECIONAL×ENGRAEM + 9 DATASETS DO REQUISITO + RLHF REAL: "
160
- "12 tarefas com FONTE ÚNICA (Teo 22.1); N_MAX_TOKENS = "
161
- "entrada 256K + saída 128K = 393216 (Teo 22.1.1); critérios "
162
- "Jev DINÂMICOS de dados reais (DESCRICOES_TAREFAS removida, "
163
- "Teo 22.2); kernel trapezoidal estável com gradiente exato "
164
- "(Teos 22.2–22.5); checkpointing de ativação exato (Teo "
165
- "22.8, Δ=0 medido); Hedge com regreto O(√(T ln M)) e Gibbs "
166
- "local (Teos 23.1–23.4); KD simétrica mode-covering+seeking "
167
- "(Teo 23.8); engram k-WTA (Teo 23.10); estados no Hub antes "
168
- "de 900MB com retomada real (Teo 23.13); orçamento 8h+1h; "
169
- "teste com DADOS REAIS APROVADO antes de treinos longos",
 
 
 
 
 
 
 
 
 
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-v11" not in f]
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": (atu_r or {}).get("epocas", [{}])[-1]
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 (v11) — 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 v11 (tronco + Mamba-3 híbrido +
10
- ensemble + critérios Jev dinâmicos) verificando perdas finitas e
11
- decrescíveis;
12
- 4. roda DPO com pares REAIS do Anthropic/hh-rlhf;
13
- 5. valida o GestorEstadosHF (serializa um estado e confere o limiar);
14
- 6. grava o relatório JSON (aprovado/reprovado por verificação).
 
 
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 + mamba3 + 3D-VL)",
86
- len(modelo.TAREFAS) == 12 and modelo.mamba3 is not None
87
- and modelo.mamba3vl is not None)
 
 
 
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-v11", {"passo_global": 1})
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-v11")
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
- n_camadas: int = 3
 
 
 
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 — TRONCO MAMBA-3 HÍBRIDO + MAMBA-3VL (doc 22): proporção 5:1
98
- # (1 NoPE attention para cada 5 Mamba-3), activation checkpointing,
99
- # perda LM própria (co-treino — Teo 22.10) e 3D-VL bidirecional
 
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, "lambda_mamba3": 0.25,
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
- nlp: dict = field(default_factory=lambda: {"ativo": True, "n_intencoes": 10})
 
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 — v5 (doc 17).
3
-
4
- Compreensão geracional multimodal (pedido explícito): os três pipelines
5
- StableDiffusion do diffusers são integrados ao ciclo de KHTST:
6
-
7
- texto → imagem (StableDiffusionPipeline)
8
- imagem → imagem (StableDiffusionImg2ImgPipeline — força guiada pela
9
- SIMILARIDADE semântica medida pelo encoder perceptual)
10
- imagem → inpaint (StableDiffusionInpaintPipeline — máscara guiada pela
11
- saliência de atenção)
12
-
13
- CICLO FECHADO DE COMPREENSÃO GERACIONAL (doc 17 §2):
14
- NLG enriquece o prompt (PT-BR) → difusão gera → encoder de imagem do
15
- KHTST re-encoda o resultado → protótipo entra na memória SOM → gerações
16
- futuras condicionam na memória. A geração passa a ser PERCEBIDA pelo
17
- próprio modelo — compreensão geracional, não só síntese.
18
-
19
- TEOREMA 17.1 (força de edição semanticamente guiada). Seja s = cos(e_in,
20
- e_plano) a similaridade entre o embedding da imagem de entrada e do plano
21
- gerado. A força de re-edição strength = clip(1 − s, 0,35, 0,80) satisfaz:
22
- s=1 (idêntico) ⇒ strength=0,35 (edição leve, preserva conteúdo); s=0 ⇒ 0,80
23
- (recriação forte). Monotonia: ∂strength/∂s ≤ 0.
24
-
25
- TEOREMA 17.2 (degradação honesta). Sem GPU/diffusers/pesos, o gerador opera
26
- em modo "planejado": devolve um PLANO estruturado (prompt enriquecido,
27
- parâmetros, força calculados) — NUNCA pixels falsos. Toda telemetria registra
28
- o modo real (`real` | `planejado`).
 
 
 
 
 
 
 
 
 
 
 
 
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 e ciclo fechado.
 
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 _obter_pipeline(self, classe, chave: str):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 texto_para_imagem(self, prompt: str, **kw) -> dict:
 
 
 
 
 
 
 
 
116
  """StableDiffusionPipeline: texto → imagem."""
117
- pipe = self._obter_pipeline(StableDiffusionPipeline, "txt2img")
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
- return {"modo": "real", "op": "txt2img", "imagem": out.images[0]}
 
 
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(StableDiffusionImg2ImgPipeline, "img2img")
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, **kw) -> dict:
 
140
  """StableDiffusionInpaintPipeline: imagem+máscara → imagem editada."""
141
- pipe = self._obter_pipeline(StableDiffusionInpaintPipeline, "inpaint")
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
- return {"modo": "real", "op": "inpaint", "imagem": out.images[0]}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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) -> dict:
156
- """Ciclo fechado doc 17 §2: NLG enriquece o prompt → difusão →
157
- re-encodagem pelo KHTST → protótipo na memória SOM."""
 
 
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
- # (iv) re-encodagem perceptual + memória SOM
 
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, doc 22) — varredura trapezoidal, tronco
3
- híbrido 5:1 com NoPE attention, Mamba-3VL bidirecional (3D-VL) e
 
4
  activation checkpointing. Fonte: arquivo MAMBA_3.txt (estudado e
5
- aprimorado — provas em docs/matematica/22-mamba3-hibrido.md)."""
6
  from khtst.mamba3.kernel import varredura_trapezoidal, Mamba3Funcao
7
- from khtst.mamba3.hybrid import (NoPEAtencao, Mamba3Camada, HybridMamba3Modelo,
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 forward(self, x: torch.Tensor) -> torch.Tensor:
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(B, L, D)
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 forward(self, x: torch.Tensor) -> torch.Tensor:
94
- B, L, D = x.shape
95
- u, res = self.entrada_proj(x).chunk(2, dim=-1) # (B,L,D) cada
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
- y = varredura_trapezoidal(uc, delta, self.A, B_m, C_m)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  y = self.norm_saida(y)
106
- return self.saida_proj(y * F.silu(res)) + x # residual neutro
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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) -> 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
- return torch.stack(saidas, dim=1) # (B, L, D)
 
 
 
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
- def __init__(self, d_modelo: int, vocab: int = 30522):
 
 
 
 
 
 
 
 
 
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 + tronco 5:1 bidirecional (NoPE global)."""
 
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 (10 classes),
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
- # 9 tarefas canônicas + "nlp-outro"
32
- INTENCOES = ("lm", "noticia", "pontuacao", "instrucao", "tts",
33
- "vqa", "ocr", "imagem_caption", "asr", "nlp-outro")
34
 
35
- def __init__(self, d: int = 192, n_intencoes: int = 10, dropout: float = 0.0):
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, 10)
67
- intencao_soft = torch.softmax(logits_int, dim=-1) # (B, 10)
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 (10, d) determinística das intenções ao espaço do modelo —
95
- hash estável (sinusoidal) sem parâmetros extras."""
96
- if not hasattr(self, "_matriz_int") or self._matriz_int.shape != (10, d):
97
- pos = torch.arange(10).unsqueeze(1).float()
 
 
 
98
  div = torch.exp(torch.arange(0, d, 2).float()
99
  * (-torch.log(torch.tensor(10000.0)) / d))
100
- pe = torch.zeros(10, d)
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 v2 — modelo unificado multimodal.
3
 
4
- Componentes (fundamentados em docs/matematica/00–10):
5
- • decoder causal com MixtureOfAttention (global+janela+linear) e RoPE;
 
 
 
6
  • LM head empatado (tied) — menos parâmetros (RAM) e regularização embutida;
7
- • MoE AGRUPÁVEL com foco na tarefa nos últimos blocos (doc 10 §1) — fase
8
- densa (todos os experts, máx conexões) → fase foco (top-k, ignora por
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 decoder);
 
 
 
 
13
  • projetor cooperativo alinhado à memória SOM (perda auxiliar);
14
- • geração autoregressiva com KV-cache, punição DINÂMICA de repetição
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 Bloco, BlocoV3, RMSNorm
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: nos ÚLTIMOS n_camadas_moe blocos (capacidade abstrata
59
- # no topo da pilha; blocos iniciais ficam densos — custo controlado)
 
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
- if self.usar_moe:
 
64
  n_moe = int(cfg_moe.get("n_camadas_moe", 2))
65
- self.moe_camadas = set(range(max(0, m.n_camadas - n_moe), m.n_camadas))
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
- self.blocos = nn.ModuleList([
100
- BlocoV3(m.d_modelo, m.n_cabecas, m.d_ff, m.janela_sliding, m.dropout,
101
- moe=_moe_para(i), cfg_micra=cfg_micra)
102
- for i in range(m.n_camadas)])
 
 
 
 
 
 
 
 
 
 
 
 
 
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", 10))) \
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
- # v11 (doc 22 §3/§4) — TRONCO MAMBA-3 HÍBRIDO (5:1 NoPE) como cabeca
191
- # auxiliar co-treinada (nascimento NEUTRO no LM: NÃO altera os logits
192
- # do decodificador com KV-cache — perda própria λ_mamba3, Teo 22.10)
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("ativo", True)):
198
- from khtst.mamba3 import HybridMamba3Modelo, Mamba3VLModelo
199
- self.mamba3 = HybridMamba3Modelo(
200
  m.d_modelo,
201
- n_camadas=int(cfg_m3.get("n_camadas", 6)),
202
  n_cabecas=int(cfg_m3.get("n_cabecas", 4)),
203
- d_estado=int(cfg_m3.get("d_estado", 16)),
204
- rank_mimo=int(cfg_m3.get("rank_mimo", 4)),
205
- grad_checkpointing=bool(cfg_m3.get("grad_checkpointing", True)))
206
- if bool(cfg_m3.get("ativo_vl", True)):
207
- self.mamba3vl = Mamba3VLModelo(
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
- return [b.composto for b in self.blocos if hasattr(b, "composto")]
 
 
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
- # ---------------- v11: tronco Mamba-3 híbrido (doc 22 §3) ----------------
405
- def oculto_mamba3(self, ids: torch.Tensor) -> torch.Tensor | None:
406
- """Estado oculto do tronco MAMBA-3 HÍBRIDO (5:1 NoPE) — usado pela
407
- perda auxiliar e pelo ensemble (features para RF/DNN/engram)."""
408
- if self.mamba3 is None:
409
- return None
410
- return self.mamba3(self.emb(ids))
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
- caches = [(None, None)] * len(self.blocos)
 
 
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)[0]
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)[0]
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)[0]
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
- """Perdas multi-tarefa (item 6): CE principal + auxiliares com pesos
3
- fundamentados (Teorema 6.2 p/ normalização de escalas de gradiente).
 
 
 
 
 
 
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
- self.otimizador = torch.optim.AdamW(modelo.parameters(), lr=cfg.treino.lr_max,
81
- betas=(0.9, 0.95), weight_decay=0.01)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- # co-treino multi-arquitetura com cabeça empatada; não altera os
423
- # logits do decodificador (nascimento neutro no LM — Teo 22.10)
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([LISTA_TAREFAS.index(tarefa)
499
- if tarefa in LISTA_TAREFAS else 0])
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
- if self.modelo.mamba3 is not None:
932
- try:
933
- feats = self.modelo._ultimo_oculto_mamba3
934
- except AttributeError:
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
- Cache em RAM limitado (limite — orçamento do projeto)."""
 
999
  cache = getattr(self, "_cache_hh_rlhf", None)
1000
  if cache is not None:
1001
- return cache
 
 
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 = pares
 
 
 
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
- [LISTA_TAREFAS.index(r["tarefa"]) if r["tarefa"] in LISTA_TAREFAS
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-01T00:31:09",
3
  "verificacoes": [],
4
- "registros_reais": 0,
5
- "por_tarefa": {},
 
 
 
 
 
 
6
  "eventos": [],
7
- "finalizado_em": "2026-10-01T00:31:09",
8
- "aprovado": false
 
 
 
 
 
 
 
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 + perda Mamba-3 + 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
- p_m3 = m.perda_mamba3(ids, alvo)
181
- check("perda LM e perda Mamba-3 finitas",
182
- torch.isfinite(perda_lm) and torch.isfinite(p_m3),
183
- f"{float(perda_lm):.3f} / {float(p_m3):.3f}")
184
- (perda_lm + p_m3).backward()
185
- check("backward combinado ok", True)
 
 
 
 
 
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 (BlocoV3 + confiança + MTP adaptativo) ==")
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 com BlocoV3: perda finita", torch.isfinite(perda))
294
  modelo.registrar_confianca(0.2)
 
 
 
295
  verifica("registrar_confianca propaga aos compositores",
296
- all(abs(b.composto._confianca - 0.2) < 1e-6 for b in modelo.blocos))
 
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.uso_ema = torch.tensor([0.01, 0.01, 0.01, 0.01]) # tudo "pouco usado"
 
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
- try:
148
- from diffusers import (StableDiffusionImg2ImgPipeline,
149
- StableDiffusionInpaintPipeline,
150
- StableDiffusionPipeline)
151
- ok_import = True
152
- except Exception:
153
- ok_import = False
154
- verifica("import EXATO dos 3 pipelines SD", ok_import)
 
 
 
 
 
 
 
 
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")