Un concierge qui a lu tout ce que nous avons jamais publié
Chaque site d'agence a sa bulle de chat. La plupart sont un formulaire en costume. La nôtre devait connaître le travail, l'endroit où habitent les prix, les frontières du fondateur et les vingt et un essais de ce Journal — alors nous l'avons construite comme nous construisons tout le reste, et nous avons noté ce que cela a coûté.
Sur cette page
Il y a une petite pastille au coin de cette page qui dit interrogez le studio. Derrière elle se trouve la chose que chaque site de conseil promet depuis 2016 et que presque aucun n'a livrée : une boîte de dialogue qui connaît vraiment l'entreprise qu'elle représente. Demandez-lui ce que comprend une mission de plateforme web et elle récite les livrables réels. Demandez-lui ce que nous pensons du code généré et elle cite l'essai. Demandez-lui où habite Edward et elle décline poliment, parce que nous lui avons appris les manières en même temps que les faits.
Nous aurions pu coller un widget tiers au-dessus du pied de page et passer à autre chose. Mais nous avons imprimé nous conjurons chaque ligne de code & chaque pixel sous notre propre nom, et une bulle de chat louée, diffusant la marque de quelqu'un d'autre dans notre coin d'écran, aurait plaidé contre chaque page au-dessus de laquelle elle flottait. Le concierge est donc à nous de bout en bout : une Edge Function Supabase, un modèle OpenAI, un client de la taille d'une carte de visite, et une couche de connaissance avec une histoire que nous ne pensions pas raconter.
Une identité sans compte
La première décision de conception, c'était qui est le visiteur. L'historique du chat doit survivre à un rechargement de page — perdre la conversation parce qu'on a consulté la page des tarifs, c'est de l'amateurisme — mais personne ne veut créer un compte pour poser une question, et nous ne voulions pas faire tourner une authentification anonyme pour ce qui est, structurellement, un livre d'or avec des opinions.
L'identité est donc un jeton : le widget frappe un identifiant de fil aléatoire et un secret dans le stockage de votre navigateur, et le serveur ne garde qu'un hachage du secret. Présentez la paire et la conversation continue ; perdez-la et vous repartez simplement de zéro. Les tables de fils sont verrouillées sur le rôle de service — aucune politique de lecture publique n'existe, il n'y a donc rien à mal configurer. C'est la même forme que les jetons de partage que nos pages de devis utilisent depuis le premier jour, et c'est exactement pour cela que nous lui avons fait confiance.
Toujours 200
Les réponses arrivent token par token en server-sent events, et le transport a une règle héritée du générateur /blueprint : la réponse est toujours un flux d'événements HTTP 200, même quand c'est une mauvaise nouvelle. Limité en débit ? C'est un événement error. Jeton de fil invalide ? Un événement error. L'alternative — un 4xx nu après que le préflight CORS a déjà réussi — est un échec que le navigateur voit mais que votre JavaScript ne peut pas lire, le pire des deux mondes.
Le flux transporte aussi plus que du texte. Quand le modèle termine, un événement done livre l'identifiant de la réponse enregistrée, et c'est lui qui fait fonctionner les petits pouces sous la réponse. Quand un lead est capté en pleine conversation, un événement lead prévient la page pour que nos analytics puissent le compter. Le protocole fait trois verbes de large, et nous comptons bien qu'il y reste.
L'abus est borné par l'arithmétique plutôt que par l'optimisme : dix requêtes par minute et par adresse via le même limiteur de débit durable que les formulaires de contact, deux mille caractères par message, une fenêtre de contexte de vingt messages, mille tokens de réponse. Un bot qui veut dépenser notre budget d'inférence doit faire la queue derrière les curl de tout le monde.
Le fichier que nous avons écrit pour les autres robots
Le problème intéressant, c'était la connaissance. Un concierge qui répond depuis l'entraînement général d'un modèle est un passif en beau costume : il inventera des services que nous ne vendons pas et des prix que nous n'avons jamais annoncés. Tout ce qu'il dit du studio doit venir du studio.
Voici la partie que nous n'avions pas planifiée. Il y a des mois, nous avons publié /llms-full.txt — un condensé lisible par machine du site entier, maintenu automatiquement depuis le même contenu que rendent les pages, pour que les assistants IA des autres nous décrivent avec exactitude. Quand nous sommes allés chercher un corpus d'ancrage pour notre propre concierge, il était déjà là : à jour, complet, et testé depuis six mois par les robots d'inconnus. La fonction le récupère, le met brièvement en cache et le tend au modèle avec chaque question. Le fichier que nous avions écrit pour les autres robots s'est révélé être le cerveau du nôtre.
Au-dessus du condensé se tiennent deux niveaux de plus. Un canon court, écrit à la main, porte les règles qui ne doivent jamais dériver : les mots bannis de la marque, le refus d'inventer des chiffres, et un profil du fondateur avec une frontière explicite — tout ce que le concierge peut dire d'Edward personnellement tient en six puces, et il a pour instruction de refuser la septième. Non que le modèle se mettrait autrement à colporter, mais parce que les limites d'un bot public doivent être une décision de conception, écrite noir sur blanc, pas une propriété émergente.
Lui apprendre le Journal
Le troisième niveau, c'est ce Journal. Vingt et un essais sur notre façon de construire, c'est exactement la matière que réclament les questions les plus dures d'un visiteur — comment avez-vous rendu Safari rapide, qu'est-ce qui a cassé dans le musée, pourquoi publier des prix du tout — mais à quelque soixante mille mots, il ne peut pas voyager dans chaque requête.
Les essais sont donc découpés en passages et plongés dans des vecteurs, et chaque question entrante est plongée de la même manière puis confrontée à eux. Les quatre passages les plus proches, au-dessus d'un plancher de similarité, voyagent avec le prompt ; le modèle a pour instruction de citer librement et de lier la source. Demandez comment nous avons rendu Mobile Safari rapide et le concierge répond avec les chiffres réels de /articles/making-mobile-safari-fast — le TTFB de 250 à 950 millisecondes passé à un seul chiffre, les 91 kilooctets de JavaScript sortis du bundle initial — parce qu'il lit les mêmes paragraphes que vous.
L'index se reconstruit automatiquement au déploiement. Ce qui produit une phrase que nous prenons plaisir à taper : au moment où vous lisez ceci, le concierge l'a lu aussi. Les articles sur la machine deviennent une partie de la machine — demandez-lui comment il fonctionne et il vous citera cette page même.
Quand quelqu'un veut nous engager
Une boîte de chat de studio a un seul travail commercial : remarquer le moment où une conversation cesse d'être de la curiosité et commence à être un projet. Le modèle porte un seul outil pour cela — il peut déposer un lead avec un nom, un e-mail et un brief d'une ligne, et il a pour instruction de ne l'utiliser qu'une fois au plus, uniquement avec des détails que le visiteur a réellement tapés, et de ne jamais demander deux fois. Le lead atterrit dans la même table que ceux du formulaire de contact, le studio est prévenu, et le visiteur reçoit une phrase de confirmation au lieu d'une séquence de relance.
Mécaniquement, c'est la partie la moins spectaculaire du chantier et la plus instructive : en plein flux, le modèle suspend sa propre réponse, appelle l'outil, reçoit le résultat et reprend la parole — deux requêtes amont cousues sur une seule connexion vers le navigateur, invisibles à moins de regarder passer les octets. Le visiteur, lui, vit une phrase. Cette asymétrie, c'est l'essentiel de ce qu'est l'ingénierie.
Des chiffres que nous pouvons imprimer
- ~5,800
- tokens de prompt qui voyagent avec chaque question
- 130
- passages du Journal dans l'index vectoriel
- 6
- langues dans lesquelles le concierge vous accueille
- 10/min
- requêtes par visiteur avant que le limiteur ne proteste
Mesuré le jour de la mise en ligne, pas estimé — la réponse qui a produit le compte de tokens disait, en tout et pour tout, « OK ».
Chaque réponse écrit ses propres reçus de tokens dans la base, si bien que le coût mensuel du concierge est une requête, pas une estimation. Nous voyons aussi quelles réponses gagnent le pouce levé sous elles et lesquelles non — les notes atterrissent à côté des reçus. Une fonctionnalité qu'on ne peut pas mesurer est une fonctionnalité qu'on ne peut pas défendre ; celle-ci est livrée avec son propre registre.
Les limites, dites à voix haute
- L'index du Journal est pour l'instant en anglais seulement. La correspondance entre langues fonctionne plus souvent qu'elle ne le devrait, mais une question en russe rencontre des passages en anglais ; plonger les essais traduits dans l'index est le correctif honnête, et il est sur la liste.
- Le modèle voit les vingt derniers messages d'un fil. Le début d'une longue conversation finit par sortir du champ ; un résumé glissant est conçu mais pas construit.
- La limitation de débit est par adresse, si bien qu'un bureau derrière un seul routeur partage une allocation. Personne ne l'a encore atteinte ; le jour où quelqu'un y arrivera, la clé deviendra plus fine.
- Le concierge parle au nom du studio, mais il reste un modèle de langage. Il est ancré, borné et mesuré — et s'il dit un jour quelque chose que le site ne dit pas, c'est le site qui gagne.
Savoir si une boîte de chat a sa place sur le site d'un studio est une question légitime — nous avons écrit tout un essai sur les outils qui vous respectent, et un mauvais concierge en est le contraire. Notre réponse a été de le tenir à la même barre que tout le reste ici : il streame parce qu'attendre est impoli, il refuse parce que les frontières sont un contenu, il cite parce qu'il a lu les sources, et il s'efface quand vous êtes sur une page qui a son propre mobilier. Le musée garde son propre chat ; le nôtre reste hors du cadre.