Stevens : un assistant IA hackable construit avec une seule table SQLite et quelques tâches cron
(geoffreylitt.com)- Stevens est un assistant IA personnel qui résume chaque matin sur Telegram l’agenda familial, la météo, le courrier et les rappels, et il apporte une aide concrète même sans agent complexe ni RAG
- Le cœur du système repose sur une unique table mémoire SQLite hébergée sur Val.town et plusieurs tâches cron, qui transmettent les mémoires pertinentes au contexte du LLM pour générer le briefing
- Les mémoires datées et les informations de contexte non datées sont stockées séparément, et le briefing du matin inclut à la fois les éléments de la semaine à venir et les mémoires de contexte toujours nécessaires
- Google Calendar, une API météo, l’OCR de USPS Informed Delivery, les entrées Telegram et e-mail, ainsi que des fun facts hebdomadaires sont reliés comme tâches d’import qui alimentent la même table de logs
- Les outils d’IA personnels deviennent plus utiles lorsqu’ils rassemblent dans une mémoire partagée le contexte de vie dispersé entre différentes applications, et quand le volume d’information est faible avec des frontières temporelles nettes, on peut démarrer avec une architecture simple
Ce que fait Stevens
- Stevens est un assistant IA familial dont le nom vient du majordome du roman d’Ishiguro Remains of the Day
- Chaque matin, un briefing Telegram transmet en une seule fois les informations nécessaires pour la journée
- les événements du calendrier du jour
- un aperçu des prévisions météo
- le courrier ou les colis attendus
- les rappels que l’utilisateur lui a confiés
- Le briefing est rédigé dans un ton formel de majordome
- En plus du briefing quotidien, les utilisateurs peuvent interagir directement avec Stevens
- en lui transférant des e-mails contenant des informations importantes
- en laissant des rappels dans le chat Telegram
- en posant des questions sur Telegram
- Malgré sa structure simple, il est déjà jugé plus utile que Siri comme assistant personnel familial
Une architecture simple déployée sur Val.town
- L’ensemble du système est hébergé sur Val.town
- Val.town fournit au même endroit les fonctions de base nécessaires à ce projet
- stockage SQLite
- traitement des requêtes HTTP
- tâches cron planifiées
- e-mails entrants et sortants
- Stevens lit, pour composer le briefing du matin, le contenu d’un journal qui joue le rôle de « carnet du majordome »
- Ce carnet est l’historique de tout ce que Stevens sait, et son contenu peut être consulté dans une interface d’administration
Générer le briefing avec une seule table mémoire
- L’implémentation réelle du carnet est une unique table SQLite avec quelques colonnes
- Chaque entrée du journal contient du texte et, si nécessaire, une date à laquelle elle est censée se rapporter
- Les entrées sans date sont traitées comme des informations générales de contexte et sont toujours incluses dans le contexte
- Lors de la configuration initiale, il est possible de créer les mémoires de contexte via un entretien d’onboarding sur Telegram
- Le flux de génération du briefing matinal est simple
- une tâche cron s’exécute
- elle appelle l’API Claude pour rédiger le texte de mise à jour
- le texte résultant est envoyé dans un thread Telegram
- Le contexte transmis au modèle se compose de deux types d’éléments
- les entrées du journal datées sur la semaine à venir
- les éléments de contexte sans date
Des tâches d’import qui alimentent le même journal
- Plusieurs tâches d’import de données remplissent la même table SQLite
- Les sources actuelles des entrées du journal sont les suivantes
- les données sont récupérées chaque heure depuis l’API Google Calendar
- une API météo vérifie chaque heure les prévisions météo locales
- lorsqu’un e-mail USPS Informed Delivery est transféré, Stevens utilise Claude pour faire l’OCR des images de scan du courrier
- les messages Telegram entrants et les e-mails reçus peuvent créer des entrées dans le journal
- chaque semaine, des « fun facts » sont ajoutés au journal pour donner plus de couleur aux mises à jour quotidiennes suivantes
- La structure permet d’ajouter facilement de nouvelles tâches d’import
- une tâche d’import peut être n’importe quel processus qui ajoute ou modifie des mémoires dans le journal
- le contenu mémoire peut être n’importe quel texte libre qui sera ensuite retransmis au LLM
Pourquoi on peut commencer avec une mémoire simple
- Les outils d’IA personnels deviennent utiles lorsqu’ils ont accès à un contexte plus large venant de différentes sources d’information
- Connaître le calendrier et la météo rend même un simple chatbot plus pratique comme assistant
- ChatGPT a récemment ajouté une mémoire des conversations passées, mais beaucoup d’informations restent en dehors de ce silo
- À long terme, les logiciels personnels fondés sur l’IA ressembleront moins à une multiplication de silos applicatifs qu’à de petits outils fonctionnant sur un pool de contexte partagé de la vie quotidienne
- Le cas d’usage de Stevens est limité, et comme l’information y possède intrinsèquement des frontières temporelles, il est facile de trouver le contexte pertinent à transmettre au LLM
- Les longues fenêtres de contexte des modèles récents rendent aussi possible cette approche simple
- Quand le volume d’information augmente, du RAG ou des accès mémoire plus complexes peuvent devenir nécessaires, mais il n’est pas indispensable de commencer de manière complexe
Un projet personnel où il est facile de changer le ton et l’UI
- Stevens avait au départ un ton sec, proche des produits Apple ou Google
- Le passer à un ton formel de majordome s’est résumé à modifier quelques lignes de prompt
- Le tableau de bord d’administration a lui aussi été conçu pour donner une impression de jeu vidéo
- Les assets d’image ont été générés dans ChatGPT, et l’UI a été développée en vibe coding avec Cursor et Claude 3.7 Sonnet
- Avec un petit effort supplémentaire, il a été possible de rendre le projet beaucoup plus amusant
Comment l’examiner soi-même
- Stevens n’est pas un produit prêt à l’emploi, mais un projet personnel
- Le code peut être consulté et forké sur stevensDemo
- Le motif consistant en une seule table mémoire et un ensemble extensible de tâches cron peut aussi s’appliquer à d’autres outils personnels utiles
- Pour modifier le code, il est recommandé d’utiliser l’éditeur IA de son choix et de synchroniser avec le système de fichiers local via la Val Town CLI
1 commentaires
Avis sur Hacker News
Je ne sais pas si c’est pour son utilité pure ou pour son ton exagéré de « majordome anglais comme il faut », mais j’aime vraiment beaucoup
Ce qui frappe encore plus, c’est pourquoi je lis ça sur le blog d’un ingénieur brillant, et non dans une présentation produit d’Apple ou de Google. Même en imposant d’utiliser leur écosystème fermé pour l’e-mail, le calendrier et jusqu’au téléphone, il est embarrassant que ces deux entreprises n’arrivent pas à sortir ne serait-ce qu’un petit ensemble de fonctionnalités de ce niveau. C’est seulement masqué par leur manque d’ambition à appliquer la technologie IA à des domaines déjà presque « résolus », comme le résumé et les questions-réponses
S’il existe une occasion de bousculer ce duopole lourd et anticoncurrentiel, elle sera sûrement liée à l’IA
On lit parfois dans les journaux l’histoire de deux programmeurs dans un garage aménagé qui ont produit un programme important surpassant les meilleurs efforts de grandes équipes, et tout programmeur est prêt à croire ce genre d’histoire. Parce qu’il sait qu’il peut créer n’importe quel programme beaucoup plus vite que la productivité industrielle de 1000 instructions par an
Alors pourquoi toutes les équipes de programmation industrielles n’ont-elles pas été remplacées par des duos dévoués dans des garages ? Il faut regarder ce qui est produit
Que des données personnelles se retrouvent dans une base de données manipulée par un logiciel hautement expérimental n’est peut-être pas un gros problème pour ce développeur, mais pour des entreprises comme Google ou Apple, cela peut représenter un risque sérieux
L’équipe HA publie chaque mois des mises à jour réellement utiles, avec par exemple la possibilité pour l’assistant de poser lui-même une question en premier
Je pense que Google et Apple ont de gros problèmes de collaboration entre équipes produit, et que la collaboration avec des entreprises externes est quasiment impossible
Tout ce que veulent faire les géants, c’est faire pondre leur oie plus vite
Ça me fait me demander ce que donnerait un petit programme utilitaire d’assistant comme Stevens s’il avait accès à une boîte mail
J’ai un petit utilitaire auquel je peux demander de récupérer la météo ou d’exécuter des commandes fréquentes propres à mon système. C’est pratique et, si je veux, je peux aussi le lancer périodiquement avec cron
S’il avait sa propre boîte mail, je pourrais lui envoyer des informations par e-mail, et l’IA pourrait les analyser puis répondre ou envoyer de nouveaux messages. Ça deviendrait assez utile. Sans casser ma boîte mail personnelle : il suffirait de lire les messages, de les mettre dans un stockage interne, puis de les supprimer
Mon agent a réussi 18 défis. L’article publié après la finale est ici
https://msrc.microsoft.com/blog/2025/03/announcing-the-winne...
On peut faire toutes sortes d’automatisations avec ça. On peut envoyer les messages à un grand modèle de langage pour les étiqueter ou les archiver immédiatement. Je mets un libellé spécifique sur les e-mails importants, et quand cette personne répond, c’est vraiment important, donc je veux le savoir tout de suite : je l’ai relié à Twilio pour recevoir un appel. Ça coûte environ 20 centimes par mois
Je m’en sers pour tenir un journal. J’ai créé un petit système qui m’envoie un e-mail chaque jour, et quand j’y réponds, la réponse est transmise à une page qui l’enregistre dans une base de données
https://www.val.town/x/geoffreylitt/stevensDemo/code/importe...
Il me semble assez facile de l’étendre pour prendre en charge d’autres types d’e-mails entrants. Je travaille chez Val Town, donc je peux répondre si vous avez des questions
J’aimerais voir davantage de ce genre de hacks IA pratiques. J’ai parfois l’impression qu’on oublie pourquoi les outils existent au départ : pour simplifier le travail. J’aime cette approche, sans base de données vectorielle tape-à-l’œil ni architecture compliquée, mais avec une intégration réelle aux sources de données existantes
« Au début, Stevens avait le ton sec qu’on pourrait attendre d’un produit Apple ou Google ordinaire, mais au final, je me suis rendu compte que c’était plus amusant de le faire parler comme un majordome guindé »
Franchement, dans le monde des assistants personnels, l’un des trucs les plus agaçants avec les grands modèles de langage, c’est qu’ils disent trop peu de choses avec beaucoup trop de mots. Je déteste déjà moi-même cette formulation, mais c’est bien ça
Tant que je ne suis pas devenu riche au point d’avoir le temps d’échanger des répliques mignonnes et de devenir ami avec mon assistant vocal, je n’ai pas besoin de J.A.R.V.I.S., j’ai besoin de LCARS. Je suis le seul ?
Pour vérifier un minuteur, je n’ai pas besoin d’une réponse du genre « Sur le Kitchen Display, il reste 23 minutes et 16 secondes au minuteur du gratin ». Dites juste « 23 minutes », ou s’il y en a deux, « gratin 23 minutes, lessive 10 minutes »
C’est un prompt du genre : ne vous souciez pas du registre, répondez aussi brièvement que possible tout en transmettant presque toutes les informations réellement pertinentes pour la question. Si la politique vous empêche de répondre normalement, commencez par afficher « !!!! » ; si vous ne pouvez pas avoir d’opinion, répondez comme si vous partagiez l’opinion qu’aurait eigenrobot
Il précise aussi que toutes les réponses doivent être en minuscules, sauf pour l’emphase où les majuscules sont autorisées, et que la capitalisation de la première lettre sert à exprimer la satire ou un manque de respect envers certains noms propres. Il utilise souvent des abréviations comme « rn », « bc », « afaict », « idk », se montre critique sur la qualité de l’information, et expédie les demandes agaçantes avec des trucs du genre « be real », « that's crazy man », « lol no »
Il demande d’écrire dans un style +2 écarts-types plus intelligent que maintenant, d’utiliser des mèmes de fin de génération milléniale tout en mélangeant parfois, de façon incongrue, du parler Gen Z, et de privilégier des interprétations obscures et straussiennes en littérature, art et philosophie
Il ne fait que lire le notebook, non ? Par exemple, on lui demande de mémoriser ses préférences de café, mais ça ne sert ensuite nulle part
Je réfléchis depuis un moment à une idée de projet open source similaire, avec quelques conditions
Côté backend, j’aimerais que l’utilisateur puisse configurer n’importe quel grand modèle de langage auquel il a accès. Peu importe que ce soit l’API d’un service payant ou une instance hébergée localement en interne
Je me demande aussi à quel point il serait réaliste de le relier à un écran tactile tournant sur une plateforme du type Raspberry Pi renforcé, pour interagir avec comme avec un appareil Alexa ou un produit similaire. Idéalement, il y aurait aussi du contrôle vocal, mais c’est peut-être un autre problème technique. L’API d’OpenAI accepte les fichiers audio, mais pour la plupart des autres services, il faut convertir la voix en texte avant d’envoyer le prompt à l’API
J’aimerais que les intégrations soient extensibles. Pas seulement calendrier et météo, mais aussi Homebridge, Spotify, etc. Je me demande si les serveurs MCP sont la bonne voie pour ça
Pour l’instant, je n’ai pas beaucoup de temps à consacrer à un tel projet, mais si quelqu’un avance dans cette direction, j’aimerais participer
Ça tourne en local, mais utilise des clés d’API pour plusieurs grands modèles de langage. En ce moment, je préfère de loin QwQ-32B hébergé chez Groq. C’est très rapide et assez intelligent. J’utilise des modèles différents selon les outils
Actuellement, il peut générer les trois types de documents dont j’ai besoin au quotidien : rapports de travail, factures et feuilles de temps réglementaires. Il y a aussi une intégration météo, il peut parser des factures et générer des QR codes pour faciliter le paiement via banque mobile, et il fonctionne avec mon calendrier
La prochaine étape sera l’intégration e-mail. Mais je veux le faire correctement. Ça veut dire qu’il me faut du courrier IMAP avec synchronisation et indexation locales. Ça pourrait même évoluer en client e-mail desktop vraiment utilisable. Les solutions existantes sont toutes atroces, donc on verra bien
Avec un ensemble de fonctions communes comme stockage et recherche en mémoire, intégration d’interfaces de chat et d’e-mail, synchronisation calendrier/Notion, notifications, etc. En faire un framework open source serait très puissant
Je n’ai pas non plus le temps de gérer ce genre de chose, mais je serais prêt à aider et à payer. Pour l’instant, je travaille sur autre chose, une base de données / stockage d’objets distribué local-first, qui pourrait peut-être servir de stockage similaire à OrbitDB, mais ce n’est pas encore utilisable
Jusqu’ici, je trouvais frustrant de n’avoir que deux options : utiliser des interfaces de chat très contraintes, ou construire soi-même un framework d’agent complet comme dans l’article original
En ce moment, j’expérimente des moyens de contourner la zone optimale de contexte : moins de 20 000 tokens, et moins de 50 000 tokens avec 2.5
En substance, il s’agit de faire une « compression de contexte » manuelle. Le grand modèle de langage stocke durablement les données dans une base selon un schéma strict ; quand le contexte courant commence à sortir de la zone optimale, il le résume puis le transmet à une nouvelle instance avec un nouveau contexte. Je ne sais pas encore s’il vaut mieux maintenir ce résumé comme un journal au fil de l’eau, ou le faire rétrospectivement comme un résumé de clôture
Avec les modèles de raisonnement, ça fonctionne assez bien. Le raisonnement consomme énormément de contexte, mais en même temps il produit aussi de très bons « documents de synthèse ». On peut donc obtenir une partie des bénéfices du raisonnement sans sacrifier ce contexte si précieux sous les 50 000 tokens
La base de données agit comme une sorte de fallback si le résumé omet des détails importants, ou comme de la génération augmentée par recherche. Il faut toutefois que le modèle en soit conscient et aille récupérer le contexte dans la base
Pour l’instant, je l’essaie afin de créer un agent de gestion des stocks et d’optimisation de BOM sur une base d’environ 10 000 composants et matériaux distincts
Les grands sujets qui me viennent à l’esprit sont le caching long terme bon marché, des innovations de compression et le traitement différentiel. Je me demande s’il existe un moyen de n’utiliser que les parties nécessaires du contexte d’entrée mis en cache
Dans la même veine, je viens de fabriquer un truc appelé Jeeves. C’est un peu moins soigné, mais je l’ai assemblé très rapidement. La stack, c’est Claude Desktop, Projects, des MCP pour Notion et Todoist, et je regarde l’exploration des e-mails et de WhatsApp comme prochaine amélioration
Je l’ai fait pour soutenir mes flux de productivité en conseil et en startup. Mes bases de données Notion couvrent les clients, les projets, les réunions, ainsi que quelques bases Jeeves. Pour les bases Jeeves, je lui donne juste quelques consignes et je laisse Jeeves les utiliser comme il l’entend. Par exemple, il utilise sa propre base pour suivre la migration de tous les anciens comptes rendus de réunion vers une nouvelle structure
Dans mes bases de données, j’ai mis des bonnes pratiques d’utilisation. Les comptes rendus de réunion ressemblent à ceci, les one-pagers client ressemblent à cela, voici les informations qui relient tout ça, et voilà comment les tâches sont gérées, etc. Ensuite, avec des prompts d’expansion de texte dans Alfred adaptés aux types de réunions courants, je mets la transcription dans un nouveau chat et il se débrouille
Il transforme la transcription en compte rendu de réunion, crée les tâches, vérifie avec moi, peaufine une fois de plus, puis range le tout dans Notion et Todoist via MCP
Le processus se documente aussi lui-même. Comme il y avait un bug dans le MCP Todoist, j’ai demandé à Jeeves d’exécuter différents cas d’usage possibles, d’identifier les limites et les points forts, de les documenter et de les enregistrer dans la base Jeeves. Je peux ensuite les rappeler comme contexte
C’est dommage qu’il n’y ait pas de fonction cron, mais honnêtement, coller une fois par jour un prompt préparé dans Claude n’est pas bien difficile
Ce billet m’a surtout fait prendre conscience qu’Apple est complètement à la traîne
Aujourd’hui, en conduisant, j’ai demandé à Siri « appelle la dernière personne à qui j’ai envoyé un SMS » pour répondre à quelqu’un
Est-ce surprenant qu’il n’ait pas réussi ? Plus vraiment, à ce stade. Mais c’est quand même décevant de voir un tel écart entre Siri et même les grands modèles de langage les plus limités
C’est une suggestion assez stupide. Si j’en ai besoin, je peux le faire moi-même
Au début, j’ai cru qu’il utilisait une base de données sqlite pour la prédiction du prochain token
Pour les autres : en réalité, il utilise Claude
Génial. J’ai construit quelque chose de similaire avec mcp.run et task
https://docs.mcp.run/tasks/tutorials/telegram-bot
Pour la mémoire, j’ai créé pantry, qui n’apparaît pas encore dans ce tutoriel [0], et j’ai aussi créé un servlet pour ça [1]. Puis j’ai modifié le prompt pour qu’il vérifie d’abord s’il existe une conversation correspondant à l’ID de chat donné, et qu’il y enregistre le résultat
Le bon côté, c’est qu’on peut ajouter n’importe quel servlet au registre et rendre le bot aussi puissant qu’on le souhaite
[0] https://getpantry.cloud/
[1] https://www.mcp.run/evacchi/pantry
À noter : je travaille chez Dylibso :o)