Tous les articles

IA8 min de lecture

Ce que nous avons appris en connectant un LLM local à une ligne téléphonique

L'IA vocale gérée facture à la minute ; ainsi, plus un agent est performant, plus la facture est élevée. Le développement de Vocale pour qu'il fonctionne soit sur une API hébergée, soit sur un GPU privé nous a appris quatre choses sur les véritables difficultés rencontrées lorsque les modèles sont déployés en interne.

Diagramme de séquence d'un tour de parole dans Vocale : le flux audio WebRTC parvient à un serveur LiveKit et à un agent, la détection d’activité vocale Silero identifie la parole, Faster-Whisper renvoie une transcription, l’échange est enregistré dans PostgreSQL, le contexte de chat est transmis à Qwen3-8B hébergé par vLLM, les tokens transmis en continu sont normalisés et agrégés en phrases, XTTS-v2 les convertit en audio, et le flux audio est renvoyé à l'appelant.

Toutes les plateformes d’IA vocale gérées facturent à la minute. Cela semble raisonnable jusqu’à ce que vous en installiez une sur une ligne d’assistance et qu’elle commence à fonctionner, car la récompense pour un bon agent, c’est un plus grand nombre d’appels traités, et la récompense pour un plus grand nombre d’appels traités, c’est une facture plus élevée. Plus le système s’améliore, plus il coûte cher. Sur une ligne d’assistance, qui existe précisément pour absorber le volume d’appels, ce n’est pas le bon type d’incitation.

Nous avons développé Vocale pour répondre au standard téléphonique d’une entreprise : il décroche dès la première sonnerie, répond en s’appuyant sur les manuels et les politiques de l’entreprise, et ouvre un ticket d’assistance lorsque la réponse honnête est qu’un intervenant doit se pencher sur le sujet. Très tôt, nous avons pris une décision qui a façonné tout ce qui a suivi. La plateforme intègre deux moteurs derrière un seul produit. Sur l’offre hébergée, la reconnaissance vocale, le raisonnement et la synthèse vocale proviennent d’une API tierce et chaque minute est facturée à la minute. Dans la version auto-hébergée, ces trois fonctions s’exécutent sur un GPU contrôlé par l’entreprise ; aucun fichier audio ni document ne quitte les locaux, et un appel ne coûte que de l’électricité.

Les deux versions se comportent de manière identique du point de vue de l’appelant. Le plus intéressant a été de parvenir à ce résultat, et voici ce que nous en avons tiré comme enseignements.

Ce qui se passe réellement dans la boucle

Un agent vocal n’est pas un chatbot auquel on aurait simplement ajouté un microphone. Chaque tour de conversation forme une chaîne, et chaque maillon ajoute un délai perceptible par l’oreille humaine.

Le flux audio arrive via WebRTC dans une salle LiveKit. La détection d’activité vocale (nous utilisons Silero) détermine quand l’appelant a réellement commencé et cessé de parler. L’audio mis en mémoire tampon est envoyé à Faster-Whisper et revient sous forme de transcription. Ce tour de conversation est enregistré dans Postgres, puis le contexte et l’historique de la conversation sont transmis au modèle linguistique, qui, sur notre infrastructure auto-hébergée, est Qwen3-8B géré par vLLM. Les tokens sont renvoyés en flux continu, normalisés et agrégés en phrases complètes, puis seulement à ce moment-là, ils atteignent XTTS-v2, qui les convertit en trames audio renvoyées via WebRTC.

Quatre modèles, une écriture dans la base de données et un aller-retour, le tout dans la pause qu’un interlocuteur tolérera avant de dire « Allô ? » dans le silence.

Exécuter cette chaîne localement n’est pas le plus difficile. L’exécuter localement à la vitesse d’une conversation, sur du matériel qu’une entreprise de taille moyenne achèterait réellement, voilà où réside tout le défi technique.

Leçon n° 1 : l’interruption est une fonctionnalité du produit, pas un cas marginal

Les appelants parlent en même temps que l’agent. Ils le font constamment, et ils le font dès qu’ils en ont assez entendu, c’est-à-dire généralement au bout de six mots sur une réponse de vingt. Un agent qui continue à parler donne l’impression de ne pas fonctionner correctement, d’une manière dont il est difficile de se remettre, car l’instinct humain est de parler plus fort, et les deux interlocuteurs se retrouvent alors à parler en même temps dans un système qui n’écoute ni l’un ni l’autre.

Couper le son sortant est la partie évidente. La partie qu’il est facile de négliger, c’est la transcription. Si l’enregistrement de l’agent contient toujours la phrase complète qu’il avait l’intention de prononcer, la conversation reprend à partir d’un appel qui n’a jamais eu lieu. Posez une question de suivi sur « la deuxième option que vous avez mentionnée » et l’agent répondra avec assurance à propos de quelque chose que l’appelant n’a jamais entendu.

Ainsi, lorsque la parole est détectée, nous interrompons le son, puis nous tronquons la réponse enregistrée de l’agent pour ne conserver que ce qui a réellement été dit à voix haute. La conversation se poursuit à partir de l’appel tel que l’appelant l’a vécu, et non de celui que le système avait prévu.

Leçon n° 2 : on ne peut pas supprimer la latence, il faut donc la combler

Lorsqu’une question nécessite une information factuelle, l’agent effectue une recherche dans les documents indexés avant de répondre. Cette recherche prend suffisamment de temps pour être perçue comme une coupure de ligne. Le silence lors d’un appel téléphonique n’est pas neutre. Il est inquiétant.

Nous diffusons une brève phrase de remplissage naturelle au bout d’environ une demi-seconde, et nous l’annulons si la recherche aboutit avant. C’est un petit détail qui a un effet considérable : il donne à la recherche le temps dont elle a besoin, sans que ce temps ne soit perçu par l’appelant comme un silence gênant.

Cela compte d’autant plus sur l’offre auto-hébergée, et non l’inverse. Un modèle local sur un seul GPU présente des caractéristiques de latence différentes de celles de l’API d’un hyperscaler, et elles ne sont pas systématiquement moins bonnes. Elles sont simplement réparties différemment. Concevoir la conversation pour tolérer une latence variable nous a permis de changer l’endroit où les modèles s’exécutent sans modifier la perception de l’agent.

Leçon n° 3 : le texte écrit ne se lit pas à voix haute

Les montants en argent, les dates sous forme de chiffres, les heures, les acronymes, les codes produit. Tout cela convient à l’écran, mais ne passe pas à l’oral. Donnez à un modèle de synthèse vocale « 1 250,00 au 15/03 » et vous entendrez quelque chose qu’aucune personne n’a jamais prononcé à voix haute.

Nous avons intégré une couche de normalisation entre le modèle linguistique et le modèle vocal qui réécrit les montants, les dates, les heures et les abréviations sous leur forme orale, langue par langue, avant qu’ils n’atteignent la synthèse. Vocale fonctionne en six langues, et cette couche est spécifique à chaque langue car les règles diffèrent réellement. Il n’existe pas de raccourci consistant à l’écrire une seule fois en anglais puis à le traduire.

C’est la composante la moins prestigieuse du système, mais l’une de celles qui ont le plus d’impact sur le fait que l’agent ait la voix d’une personne ou celle d’un menu téléphonique.

Leçon n° 4 : c’est la VRAM qui constitue la limite, pas la puissance de calcul

Voici ce qui nous a le plus surpris, et ce qui change le plus la façon dont vous dimensionnez le matériel.

Une session vocale en direct conserve ses modèles en mémoire vidéo pendant toute la durée de l’appel. La concurrence est donc limitée par la VRAM, et non par le débit brut. Vous pouvez disposer d’une carte avec de la puissance de calcul inutilisée qui ne peut pas prendre un autre appel, car il n’y a nulle part où stocker les modèles.

Pire encore, si vous laissez le framework regrouper les GPU par défaut, les tâches de reconnaissance vocale et de traitement du langage se retrouvent sur la même carte et se privent mutuellement de ressources. Le symptôme n’est pas une erreur. Il s’agit d’une conversation qui ralentit sous la charge, d’une manière qui n’est imputable à aucun composant en particulier. Nous répartissons désormais les sessions par carte et répartissons explicitement la charge de travail entre les cartes.

Si vous prévoyez un déploiement auto-hébergé, évaluez d’abord le nombre d’appels simultanés en fonction de la mémoire vidéo. Tout le reste découle de ce chiffre.

Ce qui ne change pas

Le principe de base reste inchangé. Sur les deux niveaux, l’agent répond à partir des documents mis en ligne par l’entreprise plutôt qu’à partir de la mémoire du modèle : une question nécessitant un fait déclenche une recherche, et la réponse est construite à partir des résultats obtenus. Lorsque rien de pertinent n’est trouvé, indiquer ce fait et proposer d’ouvrir un ticket constitue la réponse correcte, et c’est celle qu’il fournit. Un modèle local plus petit ne justifie pas davantage d’hallucinations, car le modèle n’est pas la source de vérité en soi. C’est la recherche qui l’est.

Le transfert d’appel ne change pas non plus. Lorsque l’agent ne peut pas aider, il recueille l’objet, les coordonnées et la priorité pendant que l’appelant est encore en ligne, crée le ticket et y joint la transcription.

C’est là tout l’intérêt de construire les deux niveaux autour d’un même comportement. Passer de l’un à l’autre relève de la configuration, et non d’une refonte.

Alors, lequel devriez-vous utiliser ?

Honnêtement : commencez par la version hébergée.

Le niveau hébergé est le moyen le plus rapide de déterminer si un agent sur votre ligne est réellement utile, et il s’agit là d’une question de produit, pas d’infrastructure. Notre propre console l’a chiffré à environ six centimes par minute d’appel. Pour une entreprise qui reçoit quelques dizaines d’appels par jour, ce n’est pas le poste budgétaire qu’il convient d’optimiser en premier lieu.

L’auto-hébergement prend tout son sens à partir de deux seuils, qui sont d’ailleurs différents.

Le premier est le volume. Le coût facturé évolue proportionnellement à l’adoption, contrairement au coût matériel ; il existe donc un point de basculement où le GPU revient tout simplement moins cher. La position de ce point dépend de votre volume d’appels, et vous devriez le mesurer plutôt que de le supposer. C’est précisément pour cette raison que Vocale calcule les coûts par modèle et par organisation : le choix entre une API et une carte doit reposer sur des chiffres concrets, et non sur des arguments.

Le deuxième seuil n’a rien à voir avec l’argent. Certaines entreprises ne peuvent pas transmettre l’audio des appels, les transcriptions ou les documents internes à un tiers, en raison d’une réglementation, d’un contrat client ou d’une politique interne. Pour elles, l’offre locale ne constitue pas une optimisation. C’est la seule version de ce produit dont l’existence est autorisée, et l’absence de tarif à la minute ne rend pas l’offre hébergée acceptable.

Il est important de distinguer ces deux seuils lorsque vous évaluez un fournisseur d’IA vocale. Une plateforme qui ne propose que l’inférence facturée à la minute a discrètement décidé que le deuxième seuil ne s’applique pas à vous.

En bref

L’inférence locale sur une ligne d’assistance est aujourd’hui tout à fait viable. Les modèles sont suffisamment performants et les outils (vLLM, Faster-Whisper, XTTS-v2, LiveKit) sont suffisamment aboutis pour que le pipeline ne constitue pas un risque.

Les risques sont ceux que personne ne montre en démonstration : être interrompu, donner l’impression d’être présent pendant que l’on réfléchit, lire des chiffres à voix haute comme un humain, et savoir combien de conversations tiennent réellement sur une carte. Si vous maîtrisez ces aspects, le choix entre une API hébergée et votre propre GPU redevient ce qu’il aurait dû être depuis le début, à savoir une ligne budgétaire plutôt qu’une limite à ce que vous êtes autorisé à développer.

  • Local LLM
  • Voice AI
  • Self-hosted
  • RAG
  • vLLM
  • LiveKit
  • Support automation