explanation/isoler-l-inference.md

Pourquoi isoler l'inférence dans un service dédié

Le calcul des embeddings — transformer un texte en vecteur comparable — est une brique d'inférence. On pourrait l'embarquer directement dans l'application qui en a besoin. Le choix retenu est l'inverse : cette brique vit dans un microservice HTTP séparé, appelé par contrat réseau.

Cette pièce explique pourquoi cette frontière a été tracée, ce qu'elle fait gagner, et ce qu'elle coûte. Elle ne décrit pas le contrat du service ni ses formats : cela vit dans la référence du service d'embeddings. Pour construire un tel service pas à pas, voir le tutoriel dédié. Ici, on raisonne le choix d'architecture.

Le problème : deux mondes qui n'ont pas les mêmes exigences

Une application de recherche sémantique doit faire deux choses de nature très différentes.

D'un côté, produire des vecteurs : charger un modèle d'inférence, l'exécuter, manipuler des tenseurs. C'est un travail coûteux en calcul, gourmand en mémoire, et ancré dans un écosystème logiciel précis — celui des bibliothèques d'inférence, mûres et confortables dans un langage donné.

De l'autre, exploiter ces vecteurs : les stocker, les indexer, les comparer, répondre à des requêtes, appliquer une logique métier. C'est le travail de l'application, qui a son propre langage, son propre cycle de vie, ses propres contraintes.

Embarquer l'inférence dans l'application, c'est forcer ces deux mondes à cohabiter dans le même processus, le même langage, le même cycle de déploiement. La question de conception est donc : faut-il les coudre ensemble, ou tracer une frontière entre eux ?

La réponse : une frontière réseau explicite

Le choix est de séparer les deux par un contrat HTTP stable. L'inférence devient un service autonome : on lui envoie du texte, il rend des vecteurs, et c'est tout ce qu'il fait. L'application ne connaît de lui que son contrat, pas son implémentation.

Le service est délibérément stateless : il ne stocke rien, n'indexe rien, ne cherche rien. Toute la mémoire du système — index, stockage vectoriel, logique de recherche — appartient au consommateur. La frontière n'est pas seulement technique (deux processus), elle est conceptuelle : chaque côté a une responsabilité nette et n'empiète pas sur l'autre.

Ce choix s'inscrit dans une décision d'architecture plus large, où un cœur de recherche mutualisé délègue lui aussi cette brique à un service externe plutôt que de la porter — voir Un cœur, trois surfaces.

Pourquoi cette frontière plutôt qu'un tout intégré

Frontière de langage : chaque brique dans son écosystème

L'inférence est confortable dans l'écosystème qui l'a fait mûrir — modèles, bibliothèques de vectorisation, outillage. L'application, elle, vit dans le sien. Les coudre dans un même processus, c'est imposer à l'un les contraintes de l'autre : dépendances lourdes tirées dans l'application, ou logique métier contorsionnée pour tenir dans l'écosystème d'inférence.

La frontière réseau laisse chaque brique dans son monde. Le service parle le langage de l'inférence ; l'application parle le sien. Ils ne se rencontrent qu'à la frontière, en JSON sur HTTP — un terrain neutre qu'aucun des deux n'impose à l'autre.

Isolement de la partie coûteuse

Charger un modèle prend du temps et de la mémoire ; l'exécuter consomme du calcul. Isoler cette charge dans un service dédié a deux vertus. D'abord, le modèle est chargé une seule fois, au démarrage du service, et réutilisé pour toutes les requêtes — le coût d'initialisation est payé une fois, pas à chaque appel. Ensuite, cette consommation reste circonscrite : elle ne pèse pas sur le processus applicatif, qui garde son propre profil de ressources. Un pic de vectorisation ne fait pas vaciller l'application, et inversement.

Substituabilité : changer de modèle sans toucher l'application

C'est sans doute le bénéfice le plus structurant. Parce que l'application ne connaît le service que par son contrat — pas par le modèle qu'il sert —, on peut remplacer le modèle d'inférence sans modifier une ligne côté application, tant que le contrat tient. Le service peut même exposer des métadonnées (le modèle servi, la dimension des vecteurs) pour que le consommateur s'adapte sans présumer de valeurs codées en dur.

Un détail de conception illustre bien cette substituabilité : certaines familles de modèles exigent une préparation particulière du texte selon son usage (distinguer un document à indexer d'une requête à chercher). Le service absorbe cette convention côté serveur — le consommateur envoie du texte brut et indique seulement le rôle. Si l'on change de modèle avec d'autres exigences, c'est le service qui s'adapte ; l'application ne voit rien passer. La convention détaillée est décrite dans la référence.

Scalabilité indépendante

Deux mondes aux profils de charge différents peuvent grandir séparément. Si la demande de vectorisation augmente, on dimensionne le service d'inférence sans retoucher l'application ; si c'est le trafic applicatif qui monte, on fait l'inverse. Un tout intégré force à scaler le bloc entier, même quand un seul de ses deux visages est sous pression. La frontière rend chaque côté dimensionnable pour ce qui le contraint vraiment.

Les arbitrages assumés

Une frontière ne se paie pas gratuitement. Ces coûts ont été acceptés en connaissance de cause.

  • Une dĂ©pendance rĂ©seau en plus. LĂ  oĂą un appel de fonction en mĂ©moire est immĂ©diat et infaillible, un appel rĂ©seau peut Ă©chouer, ralentir, ou tomber. Le consommateur doit traiter ces cas comme une partie normale de son travail : latence, indisponibilitĂ©, rejet d'une entrĂ©e invalide. On Ă©change la simplicitĂ© d'un appel local contre les vertus de la sĂ©paration — un Ă©change jugĂ© favorable, mais rĂ©el.

  • Un contrat Ă  tenir stable. Toute la valeur de la substituabilitĂ© repose sur la stabilitĂ© du contrat. C'est un engagement, pas une gratuitĂ© : chaque cĂ´tĂ© peut Ă©voluer librement Ă  condition que le contrat ne bouge pas sous les pieds de l'autre. Faire Ă©voluer le contrat demande de la discipline — versionner, prĂ©server la compatibilitĂ©, coordonner les deux cĂ´tĂ©s.

  • Une brique de plus Ă  opĂ©rer. Un service sĂ©parĂ©, c'est un composant supplĂ©mentaire Ă  dĂ©ployer, surveiller et sĂ©curiser. Sa posture d'exposition devient une responsabilitĂ© Ă  part entière : la frontière rĂ©seau qui l'isole doit ĂŞtre tenue, faute de quoi on a créé une surface nouvelle plutĂ´t qu'une sĂ©paration propre.

Aucun de ces coûts n'est anodin. Ce qui en fait un bon choix, c'est qu'ils vont tous dans le même sens : concentrer la complexité de l'inférence derrière une frontière nette, et garder de part et d'autre des composants qu'on peut raisonner, tester et faire évoluer indépendamment.

En une phrase

L'inférence et son exploitation n'ont ni le même écosystème, ni le même profil de charge, ni le même rythme d'évolution : on les sépare donc par un contrat réseau stable, en acceptant une dépendance de plus pour gagner la liberté de faire évoluer chaque côté sans toucher à l'autre.

Pour aller plus loin

Assistant documentaire

Posez une question sur la documentation. Les réponses citent leurs sources — un clic ouvre le document à gauche.