SPEC — SPEC_MARTY_AMELIORATION_CONTINUE_VESPA_GPU_CLIENT
Périmètre : SPEC_MARTY_AMELIORATION_CONTINUE_VESPA_GPU_CLIENT
Références :
SPEC — Marty : amélioration continue par feedback (Vespa), calcul opportuniste sur GPU client, apprentissage fédéré et transport pair‑à‑pair (WebRTC / WebSocket / TURN / libp2p / Y.js)
Date : 2026-04-24 (v1.2.2 — intégration du modèle fédéré : contrat MartyFederatedModelV1, registre versionné, compatibilité client, artefacts signés, politique de promotion et audit par modèle ; v1.2.1 — granularité étendue : sous‑tiers HIGH+/HIGH/MID+/MID/LOW+/LOW/DEGRADED, curseur intensité 0–100 + 6 presets, toggles consentement par tâche × sous‑finalité, fenêtres horaires utilisateur, quotas L1–L7, score de sélection cohorte multi‑dimensionnel)
Statut : Spécification normative v1.2 — proposée à validation produit + DPO (le défaut « consentement on » est subordonné à validation DPO ; sinon fallback automatique opt‑in). Implémentation incrémentale par phases F0 → F9 ; chaque phase est désactivable par flag, et chaque flux respecte les invariants existants (le NLU propose, le serveur autorise, Baserow reste source de vérité métier).
Périmètre : Boucle d’amélioration continue de Marty via retours utilisateurs (explicites + implicites) exploités par Vespa (signaux de pertinence, reranking, embeddings), accélération des réponses (cache multi‑niveau, prefetch, edge inference, SSE), calcul opportuniste GPU client lorsque l’utilisateur est inactif (embeddings, indexation locale, distillation), apprentissage fédéré des composants légers (rerank cross‑encoder, calibration NLI, adaptateurs LoRA‑like, intent mini‑classifier) avec différentielle privée, agrégation sécurisée, robustesse byzantine, et transport pair‑à‑pair entre navigateurs via WebRTC DataChannels (signalisation WebSocket, NAT traversal STUN/TURN coturn, options avancées libp2p pour le routage distribué et Y.js pour la synchronisation collaborative CRDT).
Statut documentaire : cette spec est transverse. Elle s’appuie sur les SPECs existantes (Marty, Vespa, ONNX, cache IA, agent adaptatif, offline, accessibilité) sans casser leurs contrats. Elle introduit quatre contrats normatifs (MartyFeedbackEventV1, MartyContributionV1, MartyFederatedModelV1, MartyP2PFrameV1), un protocole * et un canal de signalisation p2p. La couche Baserow WebSocket existante (websocket service, Composant interface) n’est pas modifiée ; le canal P2P Marty est totalement séparé.
Références transverses :
- — contrat
MartyUnderstanding, contexte client, performance. - — schéma Vespa, rank profiles, BFF search.
- — pipeline serveur / worker client.
- — capacités, sélection modèle (HIGH/MID/LOW), WebGPU, Web Worker.
- — couches L1–L5 et clés.
- — IndexedDB, pending queue, sync.
- — UI réponses / actions.
- — annonces live region, focus management, contraste.
- — infrastructure cible (services Docker
marty-coordinator,marty-yjs,marty-redis,marty-postgres,coturn,libp2p-relay), routage Traefikapp.grainerie.netlib.re/marty.grainerie.netlib.re, secrets, monitoring, plan I0–I7. - — agent contextuel transparent et non intrusif (catalogue de `20 surfaces UI N0–N5, modalités d'intervention, pipeline de décision, anti-patterns, préférences granulaires, accessibilité, observabilité, plan AC0–AC8). Réutilise la gestion de consentement granulaire §5.6 et le sub-tier matériel §5.6.1 ci-dessous.
Schéma directeur : . Extraits techniques en anglais admis ; UI = i18n strict.
Suivi implémentation — salve IA/Marty (2026-05-09)
Synthèse jalons / chaîne cible alignés sur §3 (boucle feedback), §3.3–§3.4 (Vespa), §5 (GPU client idle) et §9 (F0–F2, F4–F5) — hors périmètre immédiat de cette salve : fédération F6+, transport P2P (§6.10+), tuning bundle NLU F3 (traiter en salve dédiée si besoin).
- Boucle d’amélioration continue (§3, §9.1 F0) — Bus télémétrie + schéma
MartyFeedbackEventV1(§3.2) ; signaux explicites / implicites §3.1 ; route feedback (§3.3.1, Zod, rate limit, flush collector) ; repliIndexedDB/pending_queue(clémarty_feedback, alignementSPEC_OFFLINE_FIRST, flushPendingChanges) ; consentementstelemetrygpuContributionfederatedTrainingdans le payload ; émetteurs cibles (§9.1) :MartyResponseBlock, recherche globale queryMartysearchGlobal, modale actions ; flagMARTY_FEEDBACK_ENABLED`. - Vespa — ingestion signaux et ranking (§3.3.2, §3.4, §9.2 F1) — Schéma document `
interaction_event; rétention / purgeMARTY_FEEDBACK_RETENTION_DAYS/ jobvespa:purge-interactions-older-than; champs docctr_30d,dwell_avg_ms_30d,top_roles,vote_balance_30d,last_signal_update_ms;rank-profile hybrid_with_feedback(CTR, dwell, affinité rôle, vote balance) ; script nightly marty:aggregate-feedback → partial updates ;vespa-precompute-popular; BFF existant search ; flagsMARTY_RANK_FEEDBACK_ENABLED, ABMARTY_RANK_FEEDBACK_AB_RATIO. - GPU client — idle, budgets, contributions (§5, §9.5 F4, §9.6 F5) — `
marty-idle-scheduler/marty-idle-worker(Web Worker),runtime-budget,device-capability-detector,intensity-policy(§5.2, §5.6) ; tâches locales §5.1 / §5.4 (embeddings, cache L_EMBED, distillation locale sans upload en F4) ; UI `MartyConsentPanel,MartyIdleIndicator,MartyConsentBanner; F5 : contributions +MartyContributionV1, agrégateur serveur, HMAC anti‑rejeu,MARTY_CONTRIBUTIONS_ENABLED/ rolloutMARTY_CONTRIBUTIONS_ROLLOUT_PCT; kill switchMARTY_GPU_CONTRIBUTIONS_DISABLED; invariant : budgets physiques (FPS, batterie, thermique, RAM, CPU) non désactivables §5.2.
1. Contexte et objectifs
1.1 Pourquoi
Marty produit aujourd’hui des réponses correctes pour la plupart des branches, mais :
- la pertinence dépend de jeux de règles, modèles NLI/NER et grilles vocabulaire statiques : les corrections terrain (un utilisateur reformule, un admin rejette une réponse, un utilisateur clique sur le 3ᵉ résultat) ne sont pas réinjectées ;
- la latence p95 reste sensible aux montées en charge (NLI/NER côté serveur) et aux cold starts ; aucune route SSE pour des réponses longues ; pas de spéculation ;
- la flotte de navigateurs des utilisateurs représente un parc GPU/CPU très largement sous‑utilisé pendant l’interaction. Cette ressource peut, à coût zéro pour l’hébergeur, contribuer à des tâches non bloquantes d’amélioration de la qualité (embeddings, indexation, distillation, rounds fédérés), avec consentement et dans le respect de la vie privée.
1.2 Objectifs (cibles chiffrées)
- Boucle d’amélioration continue : transformer chaque interaction Marty / recherche / Vespa en signal exploitable (clics, abandons, reformulations, votes, conversion vers action exécutée) ; cible +10 pts CTR top‑3 à 90 j vs baseline.
- Accélération : p95 ≤ 350 ms sur les requêtes répétitives (warm path), ≤ 1.2 s sur le cold path ; TTFB SSE ≤ 200 ms pour les réponses longues.
- Calcul opportuniste GPU client : déléguer aux navigateurs inactifs (idle, consenti par défaut, modulé par capacités matérielles + choix UI, budget énergétique non débrayable) des micro‑tâches d’embedding et d’indexation locale ; cible ≥ 60 % d’utilisateurs HIGH/MID contribuant au moins une fois / semaine (rendu atteignable par le défaut on combiné à la modulation matérielle), ≥ 20 % de tier MID/LOW dans les cohortes fédérées (équité matérielle), aucun appareil ne dépassant ses budgets physiques.
- Réseau fédéré : entraîner un rerank cross‑encoder distillé et un mini‑intent classifier par FedAvg différentielle privée + agrégation sécurisée, avec budget (ε ≤ 8, δ ≤ 1e‑5) sur l’horizon de vie du modèle, et promotion gated par golden set.
- Transport pair‑à‑pair : ≥ 70 % des messages d’agrégation fédérée échangés en WebRTC direct (sans relais TURN), TURN utilisé pour ≤ 25 % des connexions, ≤ 5 % des participants en mode dégradé HTTPS centralisé. Économie de bande passante coordinator ≥ 50 % vs mode étoile pur.
- Souveraineté : zéro corpus utilisateur ne sort de l’infrastructure ; signaux agrégés, anonymisés, bornés ; aucune PII brute. Le serveur de signalisation et le serveur TURN sont auto‑hébergés sur l’infra Grainerie (pas de service tiers type Twilio/Xirsys).
1.3 Hors‑périmètre (explicite)
- Entraînement de gros LLM ou d’embeddings « from scratch » (la spec couvre uniquement adaptateurs légers / distillation / calibration).
- Bypass des règles métier ou des permissions Baserow par les retours utilisateurs (le NLU propose, le serveur autorise).
- Re‑identification` d’utilisateurs à partir des signaux remontés (interdit par construction).
2. Vue d’ensemble (architecture cible)
┌──────────────────────────────────────────────────────────────────────────────┐
│ Navigateur (Qwik) │
│ ┌─────────────────┐ ┌─────────────────────┐ ┌──────────────────────┐ │
│ │ Marty UI │ │ Telemetry Bus │ │ Idle Compute Worker │ │
│ │ /recherche │─►│ (events feedback) │ │ (WebGPU / WASM) │ │
│ │ Header search │ │ - vue / clic │ │ - embeddings batch │ │
│ └────────┬────────┘ │ - reformulation │ │ - distillation │ │
│ │ │ - vote 👍/👎 │ │ - rerank précalculé │ │
│ ▼ │ - abandon │ │ - rounds fédérés │ │
│ ┌─────────────────┐ │ - exécution action │ └──────────┬───────────┘ │
│ │ Embed worker │ └──────────┬──────────┘ │ │
│ │ ONNX (q/doc) │ │ │ │
│ └────────┬────────┘ │ │ │
│ ▼ ▼ ▼ │
│ POST /api/vespa/search POST /api/ai/feedback POST /api/ai/contributions │
│ GET /api/ai/stream GET /api/ai/federated/round │
└────────────┬─────────────────────┼───────────────────────────┼───────────────┘
▼ ▼ ▼
┌──────────────────┐ ┌────────────────────┐ ┌────────────────────────────┐
│ BFF Qwik │ │ Feedback collector │ │ Federated coordinator │
│ /api/vespa/* │ │ (anonymisation, │ │ (manifest, secure agg, │
│ /api/ai/* │ │ rate limit, sign) │ │ DP noise, robust agg) │
└────────┬─────────┘ └─────────┬──────────┘ └──────────┬─────────────────┘
▼ ▼ ▼
┌──────────────────┐ ┌────────────────────┐ ┌────────────────────────────┐
│ Vespa cluster │ │ Vespa interactions │ │ Aggregator + Trainer │
│ docs / index │◄─│ (events stream) │ │ (offline batch, golden set, │
│ rank profiles │ │ → ranking signals │ │ distillation, promotion) │
└──────────────────┘ └────────────────────┘ └──────────────┬─────────────┘
▼
Bundle de modèles signé,
déployé via ai-models-config.json
Quatre flux principaux :
- Recherche / NLU (chaud) — search, query, stream (SSE).
- Feedback (asynchrone, fire‑and‑forget) — feedback.
- Contributions GPU client (best‑effort, batché, idle) — contributions.
- Réseau fédéré (rounds périodiques) — round, manifest, upload delta, sa share (secure aggregation).
3. Boucle d’amélioration continue (feedback)
3.1 Signaux capturés
3.1.1 Signaux explicites
| Signal | Déclencheur UI | Payload |
|---|---|---|
vote_up / vote_down | Boutons 👍 / 👎 sur réponse Marty | { requestId, branch, score, comment? } |
clarification_chosen | Puce de clarification cliquée | { requestId, clarificationId, optionKey } |
result_pinned | Épingle un résultat pertinent | { queryId, docId, rankShown } |
result_hidden | Masque/rejette un résultat | { queryId, docId, reason? } |
report_problem | Signalement libre (modale) | { requestId, category, freeText } |
correction_inline | Édition inline d’une entité reconnue (lieu, date) | { requestId, slot, beforeValue, afterValue } |
3.1.2 Signaux implicites
| Signal | Détection | Usage ranking |
|---|---|---|
result_clicked | Clic / navigation vers un résultat | CTR par (query_norm, docId, rank) |
result_dwell_time | Temps passé avant retour | Pertinence implicite (≥ 8 s = positif) |
query_reformulated | Nouvelle requête ≤ 30 s, similarité ≥ 0.6 | Marqueur de non‑satisfaction |
query_abandoned | Ouverture résultats puis fermeture sans interaction | Marqueur négatif léger |
action_executed | Marty propose action → confirmation et succès | Renforce branche / intent |
action_cancelled | Modale fermée sans confirmation | Pénalise mapping |
marty_response_replaced | Réponse spéculative remplacée par autoritaire (§16) | Marqueur de divergence client/serveur (debug) |
3.1.3 Données interdites (jamais collectées)
- Texte libre de descriptions privées d’événements (sauf consentement explicite via
report_problem). - Identifiants nominatifs Baserow (uniquement
userIdHashsalé par jour, non réversible). - Adresse IP brute (uniquement préfixe /16 v4 ou /48 v6, optionnel et désactivable).
- Champs marqués
sensibledans les métadonnées de table. - Audio brut ou image brute (§17 multi‑modal) — uniquement features intermédiaires.
3.2 Schéma d’événement MartyFeedbackEventV1
{
"eventVersion": "v1",
"eventId": "ulid",
"eventTimeMs": 1745500000000,
"eventType": "result_clicked",
"session": {
"sessionIdHash": "base32_8ch",
"userIdHash": "base32_8ch", // salé serveur, rotation quotidienne
"rolesHash": "base32_8ch",
"locale": "fr",
},
"context": {
"routeId": "/recherche",
"view": "calendar",
"embed": false,
"filtersFingerprint": "ctx1a2b3c4d",
"deviceTier": "MID",
},
"request": {
"requestId": "uuid",
"queryId": "uuid",
"branch": "where_event",
"intentKey": "where_event.lookup",
"structuredUnderstandingHash": "8ch",
"modelBundleVersion": "v3.2.1",
"rankProfile": "hybrid_with_feedback",
"alpha": 0.62,
},
"result": {
"docId": "calendar_event:558:42",
"tableId": 558,
"rowId": 42,
"rankShown": 3,
"scoreVespa": 0.81,
"scoreCrossEncoder": 0.62,
},
"outcome": {
"dwellMs": 12450,
"reformulatedAfter": false,
"actionExecuted": false,
"ttftMs": 187,
"ttfsMs": 220,
},
"consent": {
"telemetry": "granted",
---
*Synthèse PRISME — 3083 lignes dans la source complète.*
**Voir aussi PRISME :** IA fédérée Marty · Nœud IA Expérimental
{
"eventVersion": "v1",
"eventId": "ulid",
"eventTimeMs": 1745500000000,
"eventType": "result_clicked",
"session": {
"sessionIdHash": "base32_8ch",
"userIdHash": "base32_8ch", // salé serveur, rotation quotidienne
"rolesHash": "base32_8ch",
"locale": "fr",
},
"context": {
"routeId": "/recherche",
"view": "calendar",
"embed": false,
"filtersFingerprint": "ctx1a2b3c4d",
"deviceTier": "MID",
},
"request": {
"requestId": "uuid",
"queryId": "uuid",
"branch": "where_event",
"intentKey": "where_event.lookup",
"structuredUnderstandingHash": "8ch",
"modelBundleVersion": "v3.2.1",
"rankProfile": "hybrid_with_feedback",
"alpha": 0.62,
},
"result": {
"docId": "calendar_event:558:42",
"tableId": 558,
"rowId": 42,
"rankShown": 3,
"scoreVespa": 0.81,
"scoreCrossEncoder": 0.62,
},
"outcome": {
"dwellMs": 12450,
"reformulatedAfter": false,
"actionExecuted": false,
"ttftMs": 187,
"ttfsMs": 220,
},
"consent": {
"telemetry": "granted",
Synthèse PRISME — 3083 lignes dans la source complète.
Voir aussi PRISME : IA fédérée Marty · Nœud IA Expérimental