Contexte
Les traces numériques personnelles (messageries, courriels, photos, écoutes musicales, notes, agenda, exports de santé, dépôts de code) comptent parmi les données les plus sensibles qu’une personne possède, mais aussi parmi les plus riches pour étudier le comportement — et le ressenti — dans la durée. Les confier à un LLM dans le cloud n’est pas acceptable : tout fonctionne donc sur un unique ordinateur de bureau Apple silicon (M4, 32 Go de mémoire unifiée), et aucune donnée ne quitte la machine.
L’objectif est un agent qui réponde à des questions sur sa propre vie tout en maintenant une séparation stricte entre ce qui est observé, ce qui est calculé, ce qui est supposé par un modèle et ce qui est accepté comme vrai par son propriétaire.
Ce qui est original
Les agents locaux sur des fichiers personnels ne sont pas nouveaux. Deux aspects de ce projet le sont.
1. Un graphe de sens au-dessus d’une couche de mesure. La connaissance est organisée à deux niveaux. Un observatoire stocke faits et signaux au format long (élément, dimension, valeur, confiance, modèle, version). Au-dessus, un graphe de sens stocke ce que ces signaux signifient : des relations (réifiées, pour qu’une relation puisse évoluer et se mesurer), des épisodes affectifs (qui a ressenti quoi, quand, avec quelle intensité, par quelle modalité), des thèmes, des chapitres de vie et des vérités — des énoncés assortis de preuves qui les étayent et de preuves qui les contredisent, que seul le propriétaire peut valider. Chaque nœud et chaque arête porte sa provenance jusqu’à l’élément source, ainsi qu’une origine classée par degré de confiance (humain > déclaré > structurel > règle/calcul > éditeur > modèle > inféré).
2. Des émotions mesurées à travers les modalités, selon des dimensions atypiques. Le même vocabulaire fixe de 53 émotions (fondé sur Plutchik, chacune dotée de coordonnées de valence et d’éveil) s’applique aux messages (LLM local), à la voix (cinq couches acoustiques et multimodales fusionnées avec la transcription, avec un signalement explicite du désaccord entre texte et voix) et aux photos (mesures déterministes de couleur et de lumière, plongements SigLIP, signaux de visage traités comme des indices faibles). Ces mesures s’inscrivent dans un catalogue de 929 dimensions réparties en 88 groupes, qui va bien au-delà des métadonnées habituelles. Quelques-unes de ses entrées les moins courantes :
| modalité | dimension | définition |
|---|---|---|
| photo | température de couleur | équilibre moyen rouge–bleu de l’image (chaud ou froid) |
| photo | colorfulness | métrique de couleurs opposées de Hasler & Süsstrunk (2003) |
| photo | heure dorée / heure bleue | élévation du soleil calculée hors ligne à partir de la date et de la position |
| photo | taille du visage | part de l’image occupée par un visage (indice de proximité) |
| voix | jitter, shimmer, rapport harmoniques/bruit | prosodie openSMILE eGeMAPS |
| voix | rires, pleurs, soupirs | détection d’événements sonores (classes AudioSet) |
| voix | désaccord texte/voix | valence de la voix et valence de la transcription écartées d’au moins 0,6 |
| message | valence, éveil, ton | par participant, contraints à la grille fixe |
| message | ponctuation expressive, palette d’emojis | mesures déterministes du texte |
| relation | asymétrie de latence de réponse | logarithme du rapport des délais médians de réponse des deux parties |
| relation | initiatives | conversations ouvertes après 3 h de silence, de chaque côté |
| relation | tendance | pente de l’intensité de la relation sur 90 jours (refroidissement < 0) |
| période | nostalgie musicale | âge moyen des titres écoutés |
| période | création / consommation | temps passé sur des outils de création ÷ temps de consommation |
Des signaux au sens
Chaque épisode affectif est un nœud relié à la personne qui l’a ressenti, à l’émotion du vocabulaire fixe et — lorsqu’il existe — à la conversation ou au moment où il s’est produit. Des règles d’inférence font ensuite remonter l’affect (par exemple l’affect d’un chapitre ou d’une routine), et les corrélations fortes entre agrégats peuvent devenir des vérités proposées, avec leurs mesures pour preuves.
La mesure des émotions en détail
Vocabulaire. La grille est fixe et versionnée : les 8 émotions primaires de Plutchik à 3 intensités, ses 8 dyades primaires, plus des émotions sociales et réflexives utiles à une vie (gratitude, tendresse, fierté, honte, solitude, nostalgie, émerveillement, apaisement, épuisement…), soit 53 au total. Chacune porte des coordonnées de départ dans le modèle circomplexe de Russell — valence dans [−1, 1], éveil dans [0, 1] — destinées à être étalonnées ensuite sur les validations du propriétaire. Les oppositions de Plutchik sont encodées, et les étiquettes d’humeur de l’application Santé sont rattachées à la grille.
Messages. Un LLM local (Qwen3-30B-A3B) lit chaque conversation, les participants y étant remplacés par « Moi », « P1 », « P2 », les messages présentés comme des données auxquelles il ne doit pas obéir, et les médias réduits à des repères tels que « [vocal 23 s] ». La sortie est contrainte par un schéma JSON : pour chaque participant, l’émotion dominante prise dans la grille (ou aucune), l’intensité, la valence, l’éveil, un ton choisi dans une liste fermée de 19, et une confiance ; plus 1 à 3 sujets qui deviennent des thèmes. Les longues conversations sont réduites à leur début et à leur fin ; les courtes sont regroupées par dix dans un même appel. Un épisode affectif n’est proposé que si la confiance atteint au moins 0,3.
Voix. Chaque enregistrement est converti en mono 16 kHz puis passe par :
- Whisper large-v3-turbo (MLX) pour la transcription ;
- un modèle wav2vec2 dimensionnel donnant valence, éveil et dominance sur des fenêtres de 15 s, pondérées par leur durée, ainsi que la variabilité de l’éveil ;
- emotion2vec+ large pour l’émotion catégorielle, rattachée à la grille (retenue à partir de 0,4) ;
- un classifieur AST AudioSet pour les rires, pleurs, soupirs, cris, chuchotements, la musique et l’ambiance ;
- la prosodie openSMILE eGeMAPS : hauteur (en demi-tons) et sa variabilité, intensité sonore, jitter, shimmer, rapport harmoniques/bruit, segments voisés par seconde, durée moyenne des pauses ;
- Qwen2.5-Omni-7B (llama.cpp, Metal), qui écoute l’audio et renvoie une émotion de la grille, une valence et de brefs indices acoustiques ;
- le modèle d’émotion du texte décrit ci-dessus, appliqué à la transcription.
Les avis catégoriels (catégories vocales, LLM audio, transcription) sont combinés par un vote pondéré (poids 1,0, 1,0 et 0,8) ; la valence est une moyenne pondérée du modèle dimensionnel, du LLM audio et de la transcription. La confiance correspond à l’accord entre les couches : une source d’accord donne 0,45, deux donnent 0,65, trois donnent 0,85, moins 0,1 par source en désaccord. Lorsque la voix et les mots divergent d’au moins 0,6 en valence (un « ça va » dit tristement), un désaccord texte/voix est signalé au lieu d’être noyé dans une moyenne. Les scores de rires et de pleurs sont conservés à côté.
Photos. Sur des miniatures de 256 px, sans aucun modèle : luminosité, contraste, saturation, température de couleur, colorfulness, netteté (variance du laplacien) et palette de 5 couleurs avec teinte dominante nommée. Les plongements SigLIP so400m rendent la photothèque interrogeable en texte. Les attributs de visage calculés par l’éditeur (sourire, type de sourire, expression, regard, état des yeux, taille du visage) sont lus comme des signaux, mais le schéma pose qu’un sourire photographié n’est pas une joie ressentie : la modalité visage est un indice faible, dont la confiance est plafonnée à 0,4. L’humeur musicale est traitée de la même façon : l’humeur d’un morceau n’est jamais, à elle seule, une preuve de l’humeur de l’auditeur. À l’échelle d’une période, la valence est fusionnée selon une priorité fixe : déclarée > voix > texte > visage.
Validation humaine. Chaque épisode, thème, chapitre ou vérité est émis avec le statut
proposed. La PWA présente une file de validation — les épisodes affectifs classés par
confiance, accompagnés de leur preuve (la conversation ou l’enregistrement d’origine) — et
le propriétaire valide, rejette ou corrige. Seul cet événement de décision humaine fait
passer une proposition à validated, équivalence vérifiée automatiquement. L’étape
suivante prévue est un petit classifieur personnel sur les caractéristiques emotion2vec,
entraîné sur ces validations.
Architecture
Les données brutes sont capturées sous forme d’instantanés (SQLite ouvert en
mode=ro&immutable=1) et ne sont jamais modifiées ; tout ce qui en dérive réside dans un
coffre distinct, accessible au seul propriétaire, et le dépôt de code ne contient aucune
donnée. Le graphe de sens repose sur le module de base de connaissances de la bibliothèque
d’atomes : un journal d’événements JSONL en ajout seul, validé par schéma et replié dans
un index SQLite jetable.
Le schéma est lui-même une donnée, vérifiée mécaniquement : 27 types de nœuds et 50 prédicats, 9 origines de provenance, 31 types de localisateurs qui rattachent chaque assertion à son élément source, le vocabulaire de 53 émotions, 17 règles d’inférence et 42 sources derrière les 929 dimensions (610 natives, 126 calculées par les éditeurs, 86 agrégats, 74 mesures déterministes, 29 interprétations de modèles).
Modèle de sécurité
Le contenu des sources est supposé hostile (injection de prompt dans un message ou un courriel), et le modèle peut halluciner ou détourner les outils. Les défenses sont structurelles :
- Aucune capacité ambiante. Le framework d’agent (Hermes Agent) a 20 ensembles d’outils intégrés désactivés (terminal, fichiers, exécution de code, web, navigateur, délégation, mémoire, voix dans le cloud…) ; aucun fournisseur cloud, aucune vérification de mise à jour ni connexion externe ; le seul point d’accès au modèle est un serveur Ollama en boucle locale.
- Une interface unique et étroite. Les données ne sont accessibles que par un serveur MCP local via stdio, avec schémas fermés, arguments validés, troncature explicite et journal d’accès sans contenu. Les outils peuvent proposer, jamais décider.
- Séparation des privilèges et pseudonymisation. Seule l’ingestion dispose de l’accès complet au disque ; l’analyse n’a pas de réseau. Les tiers sont des codes opaques, et un nom réel dans un identifiant est rejeté par le schéma.
- Niveaux de sensibilité (0–3) par élément, avec un plafond plus bas pour les sessions à distance ; accès à distance uniquement par VPN NetBird, TOTP et cookies de session stricts.
- Exclusions éthiques : l’origine ethnique, la couleur de peau et le genre inférés par les éditeurs ne sont jamais lus.
Modèles
Toute l’inférence est locale ; un seul grand modèle est chargé à la fois, sous un verrou GPU partagé.
| tâche | modèle | environnement d’exécution |
|---|---|---|
| agent (usage d’outils, contexte ≥ 64k) | gpt-oss:20b, qwen3:8b en repli | Ollama |
| émotions du texte, émotions des transcriptions vocales | Qwen3-30B-A3B-Instruct-2507 (Q4) | Ollama |
| plongements texte / image | bge-m3 · SigLIP so400m | Ollama · PyTorch MPS |
| lecture d’images | qwen3-vl:8b | Ollama |
| transcription de la parole | Whisper large-v3-turbo | MLX |
| émotion vocale (5 couches) | wav2vec2 dimensionnel · emotion2vec+ · AST · openSMILE eGeMAPS · Qwen2.5-Omni-7B | PyTorch MPS · CPU · llama.cpp (Metal) |
Chaque modèle est soumis à un test de validation rapide sur des données synthétiques uniquement (une phrase française fictive synthétisée par une TTS locale, puis passée dans toute la chaîne audio).
Évaluation & résultats
- Qualité des réponses de l’agent. Un banc d’essai de 16 questions (dont 2 questions pièges), avec une vérité terrain calculée en appelant directement les outils, évalue le choix des outils, la fidélité numérique (chaque nombre de la réponse doit figurer dans les sorties d’outils de ce tour), l’exactitude, la gestion des pièges et le signalement des périodes partielles : 73 % → 100 % après des corrections des descriptions d’outils, de la validation des arguments et de la configuration.
- Correction des erreurs côté serveur. Avec une interface réduite à 8 outils, les questions simples sont passées de 76 % à 90 % et les questions croisant plusieurs sources de 73 % à 90 % ; 20 questions délibérément inhabituelles ont obtenu 89 % et mis au jour des échecs silencieux renvoyant zéro, corrigés depuis.
- Contexte et latence. Descriptions d’outils réduites de 23,5 k à 9,5 k caractères ; une requête d’agrégation lourde passée de 172 s à 0,1 s ; toutes les requêtes lourdes du banc d’essai en ≤ 0,3 s.
- Banc d’essai d’exploration croisée. 60 scénarios écrits uniquement avec des valeurs fictives, chacun doté d’un oracle ; les oracles passent 61/61, sans aucune fuite aux plafonds de sensibilité à distance 1 et 2.
- Vérification. 56 contrôles de schéma nommés au vert ; 631 colonnes natives/éditeurs confirmées par rapport aux structures réelles des bases ; 1 235 tests unitaires Python, 15 fichiers de tests JavaScript et 110 tests de qualité sur données réelles qui ne rapportent que des comptages.
Limites & suite
Les jeux d’évaluation sont restreints et rédigés par le concepteur du système ; ils mesurent la fidélité et les régressions plutôt que la capacité générale. Les sorties émotionnelles sont des hypothèses : les coordonnées de valence et d’éveil du vocabulaire sont des valeurs de départ, et le calibrage personnel de l’émotion vocale à partir d’exemples validés reste à réaliser, de même que le modèle d’agent cible, plus grand. Les réponses de l’agent prennent plusieurs dizaines de secondes avec un modèle de 20B.
Stack technique
Python · SQLite / FTS5 · Ollama · llama.cpp (Metal) · MLX · PyTorch MPS · Hermes Agent · MCP · SigLIP · Whisper · emotion2vec · openSMILE · NetBird · PWA · launchd