Source: https://aiprimetech.io/fr/blog/lemonade-by-amd-a-fast-and-open-source-local-llm-server-using-gpu-and-/ Juin 14, 2026 · 5 min · Ingénierie # Lemonade par AMD : un serveur LLM local rapide et open source utilisant le GPU ... A Par [AI Prime Tech](https://aiprimetech.io/fr/) · Avec l’aide de l’IA ## Lemonade d’AMD : un serveur LLM local rapide et open source utilisant le GPU et le NPU Un serveur LLM local pratique cesse d’être « local » dès qu’il lui faut 18 secondes pour répondre à un prompt de 20 tokens. J’ai observé ce phénomène à maintes reprises sur des ordinateurs portables de développeurs : le modèle s’exécute techniquement, l’utilisation du CPU reste bloquée à 700 %, les ventilateurs s’emballent et le premier token arrive alors que l’utilisateur a déjà perdu le fil. C’est le problème d’ingénierie que Lemonade cherche à résoudre : faire en sorte que l’inférence locale se comporte comme un véritable service, et non comme un script de démonstration. Lemonade d’AMD est un serveur LLM local open source conçu pour exécuter des modèles de langage sur du matériel client, en particulier sur des systèmes AMD avec accélération GPU et NPU Ryzen AI. L’intérêt ne se limite pas à « exécuter un modèle localement ». Nous disposons déjà de plusieurs moyens de le faire. Ce qui est intéressant, c’est l’architecture du serveur : exposer les modèles locaux via une API, acheminer l’inférence vers les accélérateurs disponibles et la rendre exploitable depuis du code applicatif classique. Pour les ingénieurs qui développent des copilotes locaux, des assistants documentaires privés, des environnements isolés pour agents ou des workflows d’inférence hors ligne, c’est la bonne abstraction. Vous ne voulez pas que chaque application doive savoir charger un modèle, quantifier les poids, choisir les fournisseurs d’exécution, verrouiller la mémoire, diffuser les tokens en continu et gérer les sessions. Vous voulez un service d’inférence local. ## À quoi sert réellement Lemonade Dans les grandes lignes, Lemonade est un serveur de modèles local. Il se place entre votre application et le matériel. Au lieu d’intégrer la logique d’inférence directement dans votre application, vous exécutez un démon local : ``` lemonade-server serve ``` Votre application communique ensuite avec lui via HTTP, souvent au moyen d’une API de complétion de conversations de type OpenAI : ``` from openai import OpenAI client = OpenAI( base_url="http://localhost:8000/api/v1", api_key="not-needed-for-local" ) response = client.chat.completions.create( model="llama-3.1-8b-instruct", messages=[ {"role": "system", "content": "You are a concise coding assistant."}, {"role": "user", "content": "Write a Python function to chunk text by tokens."} ], temperature=0.2, stream=True, ) for chunk in response: delta = chunk.choices[0].delta.content if delta: print(delta, end="", flush=True) ``` La structure de l’API compte. Si votre backend prend déjà en charge GPT-5.5, Claude Sonnet 4.6, Gemini 3 ou un point de terminaison de modèle ouvert, vous pouvez souvent diriger la même abstraction client vers Lemonade pour une exécution locale. Cela vous permet de tester le routage des modèles, les fonctionnalités sensibles en matière de confidentialité et les workflows hors ligne sans réécrire votre application autour d’un nouveau SDK. En pratique, je considère un serveur LLM local comme un composant d’infrastructure : ``` App / IDE / Agent Runtime | | HTTP streaming chat API v Lemonade local server | | model loader + scheduler v Execution backend | | GPU / NPU / CPU fallback v AMD client hardware ``` Cette séparation nette est ce qui rend cette approche exploitable dans des systèmes réels. ## Pourquoi le GPU et le NPU sont tous deux importants La plupart des ingénieurs comprennent déjà pourquoi l’accélération GPU est importante pour l’inférence LLM : les multiplications matricielles dominent le temps d’exécution, et les GPU sont conçus pour le calcul parallèle. Le rôle du NPU est plus récent et plus facile à mal comprendre. Un NPU n’est pas « un GPU plus petit ». C’est un accélérateur spécialisé, optimisé pour les opérations de réseaux neuronaux sous de fortes contraintes énergétiques et thermiques. Sur un ordinateur portable, cela compte. La meilleure pile d’inférence locale n’est pas toujours celle qui atteint le plus grand nombre de tokens par seconde en pointe lors d’un benchmark de 30 secondes. C’est souvent celle qui reste réactive lorsque l’utilisateur fait tourner Slack, un navigateur, VS Code et Docker. Le modèle mental utile : - GPU : mieux adapté aux modèles plus volumineux, à un débit plus élevé et à des calculs parallèles plus lourds. - NPU : intéressant pour les modèles à faible consommation, fonctionnant en continu, plus petits ou optimisés. - CPU : solution de repli fiable, mais généralement peu performante en matière de latence pour une utilisation interactive des LLM. - Systèmes hybrides : utiles pour acheminer le travail en fonction de la taille du modèle, de la quantification et de la disponibilité. Par exemple, un assistant local pourrait utiliser : ``` { "routes": { "autocomplete": { "model": "small-code-model", "device": "npu", "max_tokens": 64 }, "chat": { "model": "llama-3.1-8b-instruct-q4", "device": "gpu", "max_tokens": 1024 }, "summarization": { "model": "compact-instruct", "device": "auto", "max_tokens": 512 } } } ``` C’est l’approche que je privilégie : ne choisissez pas un accélérateur par dogmatisme. Choisissez la bonne cible d’exécution pour chaque charge de travail. ## La place de Lemonade parmi les serveurs LLM locaux Il existe désormais plusieurs solutions d’inférence locale matures. Lemonade se distingue par son approche de l’accélération locale axée sur AMD, en particulier pour les systèmes où le GPU et le NPU font tous deux partie de la plateforme cliente. | Outil | Usage le plus adapté | Style d’API | Matériel ciblé | Compromis courant | Lemonade | Service d’inférence local sur GPU/NPU AMD | HTTP local / utilisation similaire à OpenAI | Matériel client AMD | Écosystème moins mature que celui des serveurs plus anciens | Ollama | Gestion simple des modèles locaux | API REST | Large prise en charge des CPU/GPU | Moins de contrôle sur l’exécution de bas niveau | Serveur llama.cpp | Inférence quantifiée portable | REST / modes compatibles avec OpenAI | CPU, Metal, CUDA, Vulkan et autres | Le réglage du backend peut être manuel | vLLM | Service d’inférence à haut débit | Compatible avec OpenAI | GPU de serveur | Empreinte de déploiement plus importante | LM Studio | Expérimentation locale sur ordinateur | Interface graphique + serveur local | Machines grand public | Moins adapté à l’automatisation de l’infrastructure Lemonade ne peut pas remplacer directement toutes les piles d’inférence. Si vous servez des centaines d’utilisateurs simultanés depuis des GPU de centre de données, le traitement continu par lots de type vLLM constitue généralement l’architecture la plus pertinente. Si vous recherchez la portabilité la plus large possible sur des machines de toutes sortes, llama.cpp reste difficile à égaler. Lemonade devient intéressant lorsque la machine cible est un ordinateur portable AMD, une station de travail AMD ou un boîtier AMD en périphérie, et que vous privilégiez un serveur local à part entière plutôt qu’un script Python ponctuel. ## Une architecture locale pratique Voici une approche qui fonctionne bien pour les applications d’IA locales : ``` ┌──────────────────────────────┐ │ Desktop App / Backend Service │ └───────────────┬──────────────┘ │ OpenAI-compatible client v ┌──────────────────────────────┐ │ Local Model Gateway │ │ - retries │ │ - model routing │ │ - prompt templates │ │ - telemetry │ └───────────────┬──────────────┘ │ localhost HTTP v ┌──────────────────────────────┐ │ Lemonade Server │ │ - model loading │ │ - streaming responses │ │ - device selection │ │ - accelerator backend │ └───────────────┬──────────────┘ │ ┌────────┴────────┐ v v AMD GPU Ryzen AI NPU ``` J’ajoute généralement une passerelle légère, même lorsque le serveur local expose déjà une API bien conçue. Cette passerelle fournit un contrat interne stable et permet de basculer entre les modèles locaux et distants. Par exemple : ``` import os from openai import OpenAI def build_llm_client(): if os.getenv("LLM_MODE") == "local": return OpenAI( base_url="http://localhost:8000/api/v1", api_key="local" ) return OpenAI( base_url=os.environ["REMOTE_LLM_BASE_URL"], api_key=os.environ["REMOTE_LLM_API_KEY"] ) client = build_llm_client() ``` Ainsi, la logique de votre application n’a pas à se soucier de savoir si la requête est envoyée à Lemonade, GPT-5.5, Claude Opus 4.8, Gemini 3 ou à un modèle ouvert hébergé. Cette souplesse est précieuse lorsque vous évaluez la qualité, la latence, la confidentialité et le coût. Si votre équipe utilise un fournisseur d’API multimodèle tel qu’AI Prime Tech comme solution de repli dans le cloud, conservez les voies locale et distante derrière la même interface. ## Choix du modèle : un petit modèle vaut mieux qu’une intelligence théorique L’erreur la plus courante avec les serveurs LLM locaux consiste à choisir un modèle parce qu’il est bien classé, plutôt que parce qu’il convient à la machine. Pour l’inférence locale, l’adéquation du modèle est essentielle : - Le modèle quantifié tient-il dans la mémoire disponible de l’accélérateur ? - La longueur de contexte est-elle réaliste pour la charge de travail ? - Quel est le délai avant le premier token ? - La diffusion en continu reste-t-elle fluide dans les conditions thermiques normales d’un ordinateur portable ? - L’application peut-elle tolérer un repli occasionnel sur le CPU ? - La qualité est-elle suffisante pour la tâche ? Un modèle 7B ou 8B entraîné à suivre des instructions et quantifié sur 4 bits est souvent plus utile en local qu’un modèle bien plus volumineux qui déborde constamment de la mémoire disponible, se bloque ou impose une réduction drastique du contexte. Pour les tâches de programmation, les modèles ouverts dérivés de Qwen, DeepSeek, Llama, MiniMax et Kimi peuvent tous être des candidats raisonnables, selon leur licence, les formats pris en charge et leur compatibilité avec le backend. La bonne méthode est empirique : ``` # Example benchmark flow; adapt names to installed Lemonade commands/models. lemonade-server pull llama-3.1-8b-instruct-q4 lemonade-server serve --host 127.0.0.1 --port 8000 ``` Exécutez ensuite un prompt reproductible : ``` import time from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/api/v1", api_key="local") prompt = "Explain how an LRU cache works, then implement one in Python." start = time.perf_counter() first_token_at = None tokens = 0 stream = client.chat.completions.create( model="llama-3.1-8b-instruct-q4", messages=[{"role": "user", "content": prompt}], stream=True, temperature=0.1, max_tokens=400, ) for chunk in stream: text = chunk.choices[0].delta.content or "" if text and first_token_at is None: first_token_at = time.perf_counter() tokens += len(text.split()) end = time.perf_counter() print({ "time_to_first_token_s": round(first_token_at - start, 3), "total_time_s": round(end - start, 3), "rough_word_rate_per_s": round(tokens / (end - start), 2) }) ``` Ce n’est pas un benchmark scientifiquement parfait. C’est un test de bon fonctionnement pratique. Il vous indique ce que votre utilisateur ressentira. ## Sélection des périphériques et solutions de repli Un bon serveur local doit rendre le choix du périphérique suffisamment explicite pour permettre aux ingénieurs d’analyser les défaillances. Le mode « Auto » est pratique jusqu’à ce qu’un modèle passe silencieusement du GPU au CPU et que votre latence augmente de 8x. Dans les déploiements locaux proches de la production, je préfère une configuration sans surprise et facile à inspecter : ``` { "server": { "host": "127.0.0.1", "port": 8000 }, "models": [ { "name": "local-chat", "path": "./models/llama-3.1-8b-instruct-q4", "device": "gpu", "context_length": 8192 }, { "name": "fast-draft", "path": "./models/small-instruct-npu", "device": "npu", "context_length": 4096 } ], "fallback": { "allow_cpu": false, "on_failure": "return_error" } } ``` Les options exactes de configuration de Lemonade peuvent varier selon la version, mais le principe reste le même : évitez toute dégradation invisible. Si la voie GPU échoue, je veux que l’application le sache. Pour les applications interactives, renvoyer une erreur claire est souvent préférable à faire attendre l’utilisateur 90 secondes pour une réponse du CPU. Un piège courant : les pilotes et les bibliothèques d’exécution comptent autant que le modèle. Lorsque l’accélération GPU ou NPU ne s’active pas, le serveur peut continuer à « fonctionner », mais lentement. Vérifiez toujours le fournisseur d’exécution actif dans les journaux au démarrage. Vérifications utiles au démarrage : ``` lemonade-server serve --log-level debug ``` Recherchez : ``` loaded model: local-chat selected device: gpu execution provider: context length: 8192 quantization: q4 ``` Si les journaux ne montrent pas clairement la voie d’accélération, considérez que vous n’avez pas encore validé l’accélération. ## La diffusion en continu n’est pas facultative Pour l’expérience utilisateur des LLM locaux, la diffusion en continu est indispensable. Même lorsque le temps total de génération reste inchangé, elle donne l’impression d’une application nettement plus rapide, car l’utilisateur voit la progression. Votre serveur doit prendre en charge la diffusion des tokens en continu, et votre client doit la consommer correctement : ``` def stream_answer(client, model, messages): stream = client.chat.completions.create( model=model, messages=messages, stream=True, temperature=0.2, max_tokens=700, ) for event in stream: piece = event.choices[0].delta.content if piece: yield piece ``` En pratique, la diffusion en continu facilite aussi le débogage. Si la latence du premier token est élevée mais que la génération est ensuite rapide, le goulot d’étranglement peut être le chargement du modèle, le traitement du prompt ou la longueur du contexte. Si le premier token arrive rapidement mais que la génération est très lente, vous pouvez être limité par la bande passante mémoire, la réduction de fréquence liée à la chaleur ou un repli sur le CPU. Mesurez ces éléments séparément : - Temps de démarrage à froid : du démarrage du serveur jusqu’à ce que le modèle soit prêt. - Temps de traitement du prompt : de la réception de la requête au premier token. - Vitesse de décodage : du premier token au dernier token. - Latence de bout en bout : de la requête de l’application à la réponse complète. - Stabilité thermique : le même test après cinq minutes d’utilisation. Ce dernier point est facile à négliger et pose de sérieux problèmes dans les produits réels. ## Longueur du contexte : le multiplicateur silencieux de latence Les longues fenêtres de contexte sont utiles, mais elles ont un coût. Un modèle qui prend en charge un contexte de 8192 tokens ou de 32768 tokens peut malgré tout devenir pénible à utiliser si vous remplissez chaque requête de journaux, de documents et d’historique de conversation. Pour les systèmes locaux, j’impose généralement des budgets de contexte au niveau de la passerelle : ``` MAX_PROMPT_CHARS = 18_000 def trim_context(system_prompt, history, new_user_message): packed = [ {"role": "system", "content": system_prompt}, *history[-8:], {"role": "user", "content": new_user_message}, ] total = sum(len(m["content"]) for m in packed) while total > MAX_PROMPT_CHARS and len(packed) > 2: removed = packed.pop(1) total -= len(removed["content"]) return packed ``` Cette approche est rudimentaire, mais efficace. Une version plus aboutie utilise le comptage des tokens, la compression sémantique et la recherche d’informations. L’essentiel est que la gestion du contexte relève de la couche applicative, plutôt que d’un vague espoir que le serveur restera rapide. Si vous utilisez un modèle à grand contexte tel que Fable 5 avec un contexte de 1M dans le cloud, cela modifie les contraintes de conception. Sur un système GPU/NPU local, vous devez partir du principe que le contexte coûte cher, sauf si vos mesures démontrent le contraire. ## Bonnes pratiques pour un service d’inférence local de type Lemonade ### Gardez le serveur prêt Le chargement à froid du modèle est l’un des principaux facteurs qui dégradent l’expérience utilisateur. Démarrez le serveur avec l’application, chargez immédiatement le modèle par défaut et exposez son état de disponibilité séparément de l’état de santé du processus. ``` curl http://127.0.0.1:8000/health curl http://127.0.0.1:8000/models ``` Votre application doit distinguer les états suivants : - le processus du serveur est en cours d’exécution - le modèle est chargé - l’accélérateur est actif - le chemin de traitement des requêtes fonctionne correctement ### Figez les versions des modèles Ne laissez pas les modèles « latest » changer silencieusement dans une application de bureau. Figez les noms des modèles, leur quantification et la longueur de contexte attendue. ``` { "model": "llama-3.1-8b-instruct-q4", "revision": "2025-02-local-tested", "expected_device": "gpu" } ``` Même de petites modifications du tokenizer, du modèle de conversation ou de la quantification peuvent modifier le comportement. ### Séparez les tests de qualité des tests de vitesse Pour de nombreux usages, un modèle local rapide qui donne des réponses subtilement erronées est pire qu’un modèle plus lent. J’aime maintenir deux jeux de tests : ``` evals/ latency_prompts.jsonl task_quality_prompts.jsonl ``` Exemple de cas de test de qualité : ``` { "id": "python_exception_summary_01", "messages": [ { "role": "user", "content": "Summarize this stack trace and identify the likely bug: ..." } ], "must_include": ["None", "attribute", "guard"], "must_not_include": ["database outage"] } ``` Cela ne remplace pas une évaluation formelle, mais permet de détecter les régressions lorsque vous changez de modèle, de quantification ou de voie d’exécution sur un périphérique. ### Prévoyez un repli vers un service distant L’inférence locale échoue pour des raisons banales : mode économie de batterie d’un ordinateur portable, mises à jour de pilotes, fichiers de modèle manquants, quantification non prise en charge, réduction de fréquence liée à la chaleur. Si la tâche est importante, prévoyez une solution de repli. ``` try: answer = call_local_model(messages, timeout_s=20) except Exception: answer = call_remote_model(messages, timeout_s=30) ``` Définissez explicitement les règles de confidentialité. Certains prompts ne doivent jamais quitter la machine. Pour ceux-ci, bloquez le traitement en cas d’échec. ## Limites et compromis La promesse de Lemonade est la plus convaincante sur les systèmes AMD compatibles disposant de la bonne pile d’exécution. Cela signifie aussi que les aspects opérationnels englobent les capacités du matériel, l’état des pilotes, la prise en charge des formats de modèles et la maturité des backends d’accélération. Les principaux compromis : - Portabilité : l’accélération centrée sur AMD est précieuse, mais les parcs hétérogènes peuvent nécessiter plusieurs backends. - Disponibilité des modèles : tous les modèles ouverts ne seront pas distribués sous une forme prête à l’emploi ou optimisés pour chaque voie d’exécution. - Contraintes des NPU: les NPU excellent dans l’inférence économe en ressources, mais toutes les configurations de modèles et longueurs de contexte ne leur conviennent pas naturellement. - Observabilité: les serveurs locaux ont besoin de journaux et de métriques, tout comme les services cloud. - Concurrence: l’ordinateur portable d’un développeur n’est pas un cluster d’inférence mutualisé. Pour voir les choses avec lucidité : Lemonade ne fournit pas une capacité magique. Il offre une meilleure couche de service locale sur un matériel client aux ressources limitées. Le gain de performances vient du choix du bon modèle, de la bonne quantification, du bon accélérateur et d’une API serveur qui masque ces détails à votre application. ## Conseils pratiques - Utilisez Lemonade lorsque vous souhaitez un serveur LLM local accéléré par AMD plutôt que d’intégrer directement l’inférence dans votre application. - Considérez le GPU, le NPU et le CPU comme des cibles d’exécution distinctes, avec des profils différents en matière de latence, de consommation électrique et d’adéquation aux modèles. - Privilégiez les petits modèles quantifiés qui offrent une latence fiable pour les interactions plutôt que les modèles plus volumineux qui tiennent tout juste en mémoire. - Vérifiez l’accélération dans les journaux ; un serveur « fonctionnel » peut malgré tout s’exécuter sur le CPU. - Diffusez les réponses en continu, mesurez le délai avant le premier token et testez sous une charge thermique prolongée. - Placez le routage, les mécanismes de repli, la réduction des prompts et la politique de confidentialité dans la passerelle de votre application. - Fixez les versions des modèles et conservez de petits jeux d’évaluation de la latence et de la qualité avant de livrer des fonctionnalités d’IA locale. [Inférence](/fr/blog/tag/inference/)[Open source](/fr/blog/tag/open-source/) A [AI Prime Tech](https://aiprimetech.io/fr/) Ce blog est publié par AI Prime Tech. Les articles sont rédigés avec l’aide de l’IA ; vérifiez les détails propres à chaque version, tels que les identifiants de modèles, les prix et les limites, dans la documentation officielle avant de vous y fier. Accédez à l’API Claude à moindre coût Une seule clé API pour Claude Opus 5.5, Sonnet 5, Haiku 4.5 et Fable 5.1, ainsi que GPT-6 modèles. Paiement à l’usage, sans abonnement. [Obtenir votre clé API →](/register) AI Prime Tech est une passerelle API tierce indépendante. Claude™ et Anthropic® sont des marques d’Anthropic, PBC. Aucune affiliation ni approbation n’est sous-entendue.