Soixante conteneurs sur un seul serveur
Une seule machine bare-metal fait tourner des dizaines à des centaines de conteneurs Hoody. La déduplication KSM et BTRFS rend le coût marginal quasi nul.
vous faites tourner un modèle 70B sur une seule machine GPU. Cinquante conteneurs en aval dans votre flotte ont besoin de la même réponse pour la même requête — ils scorent le même catalogue, génèrent les mêmes embeddings, évaluent la même expérience. Ne payez pas cinquante inférences. Lancez le modèle une fois, broadcastez les tokens.
# génère une fois, pipe vers le hautllama.cpp -m llama3-70b.gguf \ -p "$PROMPT" --stream \ | curl -T - \ /pipe/llm?n=50pipe/llm?n=50UN CHEMIN · CINQUANTE LECTEURSle modèle tourne une fois · le pipe broadcast · les workers lents ne ralentissent qu'eux-mêmes
La réponse naïve est un serveur HTTP avec une queue, du request batching et de la contention de lock. La réponse moins chère pour cette forme : chaque requête va sur un chemin pipe avec ?n=50. Le modèle tourne une fois. Cinquante conteneurs consommateurs GET le même chemin et streament les mêmes tokens en même temps, fan-outés par le pipe. Un worker lent applique de la backpressure à sa propre connexion — les autres restent à pleine vitesse.
# 1× GPU box — run the model once and pipe its tokens upward.
llama.cpp -m llama3-70b.gguf -p "$PROMPT" --stream \
| curl -T - https://pipe.hoody.com/api/v1/pipe/llm?n=50
# 50 consumer containers — same path, ?n=50, fanned out by the pipe.
for i in $(seq 1 50); do
curl https://pipe.hoody.com/api/v1/pipe/llm?n=50 \
| jq -c .delta \
| ./score.py --worker $i &
done
# Sender blocks until 50 readers have connected, then bytes flow.
# Slow workers backpressure their own connection — others stay at line speed.PUT envoie les bytes vers le haut. GET les tire vers le bas. Le paramètre ?n=50 dit combien de lecteurs attendre ; le pipe garde la connexion jusqu'à ce que ce nombre se connecte, puis fan-out le stream simultanément vers tous. Pas de queue, pas de couche de batching, pas d'inference-server-with-load-balancer.
cinquante conteneurs en aval veulent la même réponse ; vous la générez sur le GPU une fois. Le pipe gère la livraison. Pas de framework de request-batching, pas de couche de cache de tokens, pas de coordination « s'il vous plaît ne le relancez pas ».
le pipe bloque jusqu'à ce que cinquante receivers se connectent, puis streame les bytes du producer vers chacun en parallèle. Copies identiques, livraison à pleine vitesse, zéro stockage côté serveur. Jusqu'à 256 receivers par chemin.
si un conteneur consommateur fait du GC ou que son disque est occupé, sa connexion lag. Le pipe applique de la backpressure à ce receiver — les 49 autres continuent à streamer à pleine vitesse. Pas de head-of-line blocking, pas de tuning de profondeur de queue.
Quand cinquante conteneurs veulent la même réponse, les alternatives facturent à l'appel, au token, ou par serveur d'inférence. Le pipe facture pour un seul transfert HTTP. Lancez le modèle sur une machine que vous louez déjà.
ce n'est pas chaque charge — c'est la forme où N conteneurs veulent la même réponse. Quand c'est votre forme, le pipe est le fan-out le moins cher que vous câblerez. Les charges avec des prompts qui divergent veulent toujours un vrai serveur d'inférence ; ce pattern brille quand la question est identique et que la flotte est large.
Un GPU, un pipe, cinquante conteneurs qui goûtent les mêmes tokens.
Chaque stack « donne à ma flotte accès à un modèle » que vous attrapez quand une requête doit alimenter plusieurs consommateurs. Chacune facture à l'appel, héberge vos weights, ou vous demande de faire tourner un load balancer devant vLLM. Le pipe broadcast une fois.
Arrêtez de payer cinquante factures d'inférence pour une réponse. Lancez le modèle là où vous louez déjà le silicium. Ouvrez un pipe. Laissez la flotte lire.