Journal
IngénieriePublié le 2026-04-08·9 min de lecture

Concevoir Flux Engine : un seul runtime pour tous les produits

Un coup d'œil sur les choix d'architecture derrière notre runtime d'inférence embarquée partagé — et les contraintes qui l'ont façonné.

Un runtime, pas un wrapper

Faire tourner une app sur l'appareil est difficile. En faire tourner cinq l'est davantage. En faire tourner cinq qui partagent une fondation technique cohérente, sortent leurs mises à jour en même temps et ne régressent jamais en autonomie — c'est un problème de runtime.

Flux Engine est notre réponse. C'est une couche fine et tranchée par-dessus les meilleurs runtimes open source de chaque voie — voix (whisper.cpp / faster-whisper), vision (llama.cpp / mlx-vlm), langage (llama.cpp / MLC-LLM, executorch sur Android) — coordonnée par un unique scheduler qui sait ce qui est en mémoire, ce que l'utilisateur fait et ce que l'appareil peut soutenir.

Les trois contraintes

1. Latence de démarrage à froid

Les modèles vivent sur disque la plupart du temps. L'utilisateur, non. Flux Engine préchauffe le modèle le plus probable en s'appuyant sur les usages de l'app et un petit classifieur embarqué. Le classifieur lui-même est un MLP de 50 Ko — assez léger pour tourner à chaque réveil.

2. Débit soutenu sur les petites NPU

Nous ne lançons jamais de charges parallèles qui se disputent le même accélérateur. Le scheduler est en file, conscient des priorités, et cède de force la place à l'app au premier plan. Le flux ASR passe avant un résumé en arrière-plan ; le tap-to-translate passe avant une passe d'indexation.

3. Dégradation gracieuse quand la mémoire est rare

Si l'utilisateur monte une vidéo 4K, nous n'allons pas faire OOM son téléphone pour exécuter un résumé. Le moteur publie un signal souple de "capacité restante" que les produits respectent — ils peuvent retomber sur un modèle plus petit, différer au fond, ou afficher "prêt quand le téléphone aura refroidi".

Ce que Flux Engine expose réellement

Une poignée d'abstractions C++ et un binding fin Swift / Kotlin / Rust :

  • FluxSession — session d'inférence longue durée liée à un modèle + appareil.
  • FluxStream — sortie incrémentale, annulable au milieu d'un token.
  • FluxBudget — rapport de capacité conscient de l'appareil.
  • FluxRouter — choisit le bon modèle selon la gamme de l'appareil, la batterie, l'état thermique et la préférence produit.

Voilà tout. Cinq primitives. Chaque produit Flux* se construit dessus.

Ce que cela nous apporte

Un bug fix, un gain de perf, une amélioration de quantification — cinq produits s'améliorent en même temps. Un correctif de régression du scheduler — cinq produits arrêtent en même temps de faire spike la batterie. L'équation économique d'un runtime partagé, pour une équipe de notre taille, est écrasante.

Ce que nous avons raté

  • Nous avons surinvesti dans un compilateur de graphes les six premiers mois. Les loaders réglés à la main ont gagné.
  • Nous avons sous-investi dans le profilage. Nous l'avons réécrit au neuvième mois.
  • Nous avons supposé un schéma de quantification unique pour tous les produits. Nous embarquons aujourd'hui des mix par produit.

Recevez les nouveaux articles

Nous vous préviendrons dès qu'un nouvel article paraît.

S'abonner