File size: 5,158 Bytes
7dcbd04
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# Architecture

## Flux de bout en bout

```
USER ──TASK_SUBMISSION──▶ KERNEL ──ROUTE_REQUEST──▶ ROUTER ──ROUTE_DECISION──▶ KERNEL
                            │
                            └──CODE_PROPOSAL──▶ VERIFIER ──TOOL_CALL × n──▶ SKILL_EXECUTOR
                                                   ▲                              │
                                                   └────────TOOL_RESULT × n───────┘
                            VERIFIER ──VERIFICATION_RESULT──▶ CORRECTOR
                                         certifié ? ──oui──▶ FINAL_ANSWER ──▶ USER   (certificat)
                                                    └─non──▶ CORRECTION_REQUEST ──▶ KERNEL ──(CODE_PROPOSAL, tentative+1)
                                                    └─budget épuisé──▶ SESSION_ABORT ──▶ USER   (aucune sortie)
```

Chaque flèche est un `JevMessage` validé par le `JevBus` (schéma strict, aucun champ inconnu) puis journalisé dans le
registre d'audit. Les composants n'ont aucune référence directe les uns vers les autres : ils ne communiquent que par
abonnement `(type, destinataire)`. `mouh/verification/loop.py` est l'unique endroit où ce câblage est déclaré.

## Noyau séquentiel hybride (`mouh/model/layers.py`)

- 24 blocs pour le défaut : motif `SSSSSA` × 4 (5 blocs Gated-SSM pour 1 bloc d'attention, imposé par validation de config).
- **Gated-SSM** : `in_proj` → convolution causale depthwise → récurrence d'espace d'état sélective (dt, B, C dépendants de
  l'entrée) évaluée par l'algorithme **SSD par blocs** (complexité linéaire en longueur) → porte `silu(z)·y` + RMSNorm → `out_proj`.
  Au décodage, un pas de récurrence met à jour un état de taille constante (`ssm_step`). Les deux chemins sont équivalents
  à 1e-4 près (tests).
- **Attention** : multi-têtes causale, RoPE (avec mise à l'échelle NTK optionnelle `rope_scaling_factor`), cache KV.
- **Pré-normalisation** `LayerNorm` avant chaque transformation ; activations SiLU (Swish).
- **Portes de rétroaction** : `g = 2·σ(W2·silu(W1·h))` (bas rang) module la sortie du mélangeur avant l'ajout résiduel ;
  `g ≈ 1` à l'initialisation.
- **Initialisation SSM** : `A ∈ [1,16]` (log), `dt` log-uniforme dans [1e-3, 0,1] (softplus inverse), sorties résiduelles
  mises à l'échelle `1/√(2L)`.
- **Noyaux Triton** (`triton_kernels.py`) : porte `silu(a)·b` fusionnée (avant et arrière) pour les experts et la porte SSM.
  Les projections linéaires restent sur cuBLAS. Repli PyTorch automatique hors GPU.

## MoE déterministe (`mouh/model/moe.py`)

- 8 experts SwiGLU par couche (`syntax_repair`, `formal_logic`, `code_generation`, `data_schema`, `refactor_optimize`,
  `docs_formatting`, `test_diagnostics`, `arbiter`), correspondant aux experts n°1 à n°8 de la spécification.
- **Score** = routeur linéaire + **prior du type de message** (table JEV précompilée) + biais d'équilibrage.
  **Sélection** : tri stable décroissant (égalité → plus petit indice), 4 premiers. **Coefficients** : σ(score) renormalisé
  sur les experts retenus. Aucun softmax, aucun bruit, aucun aléa : même entrée, même routage (testé bit à bit).
- **Contrôle de charge** : capacité par expert `⌈capacity_factor·N·k/E⌉` appliquée dans l'ordre des tokens (causal) en
  entraînement ; perte auxiliaire `E·Σ fᵢPᵢ` ; règle d'équilibrage sans perte (`step_routing_bias`) qui abaisse le biais des
  experts sur-chargés. L'historique de charge est un tampon persistant (`load_ema`). En inférence, le routage est sans
  abandon par défaut pour que préremplissage et décodage incrémental donnent les mêmes logits (`enforce_capacity_at_inference`).
- **Experts déchargeables** : `offload_experts` / `load_experts`.
- **Sortie validée** : aucune valeur non finie ne quitte la couche ; la trace discrète du routage est exportable sur le bus
  (`routing_messages`).

## Têtes de contrôle typées

`type_head` et `tool_head` produisent des logits sur `JevMessageType` et sur les skills. `MouhForCausalLM.decide()` renvoie
des `JevChoice` (alternatives bornées, `JevScore` normalisé, argmax déterministe). Elles se supervisent avec
`type_labels` / `tool_labels`.

## Boucle de vérification (`mouh/verification`)

Score = moyenne pondérée de composantes (analyse statique 1, exécution 2, tests 4, preuves 3). Un certificat est délivré
si et seulement si **score ≥ 0,85 et toutes les barrières dures valent 1** (syntaxe/politique, exécution sans erreur, tous
les tests, toutes les obligations prouvées) **et** au moins un oracle (tests ou preuves) existe. Sinon : demande de
correction, routée vers les experts de refactoring en tête (n°5, 1, 7, 3), avec les diagnostics typés et les indices tirés des
corrections déjà réussies (`CorrectionStore`, exportables en JSONL d'affinage). La boucle s'arrête sur certificat,
épuisement du budget, absence de progrès (même code proposé deux fois) ou renoncement du générateur.