Intermédiaire 16 minSupport

Support client multilingue avec LLM local : 6 langues sans cloud

Vous gérez un support client qui reçoit des tickets en français, anglais, espagnol, allemand, italien et arabe. Envoyer chaque message à une API cloud, c'est exposer des emails, des numéros de commande et parfois des données personnelles à un tiers — et payer au token. Ce guide monte un chatbot de support client multilingue 100% local avec Qwen3-30B-A3B, détection de langue automatique, ton adapté à chaque culture, et intégration directe Zendesk ou Freshdesk via webhook.

Par Marie L.·Màj 2026-06-16·Testé sur Windows, macOS, Linux

#Pourquoi un LLM local pour le support multilingue

Les API cloud (GPT-4o, Claude, Gemini) facturent par token et imposent un transfert hors-UE des messages clients. Pour un support B2C qui traite 5 000 tickets par jour, la facture mensuelle dépasse vite 1 500 € et la conformité RGPD devient acrobatique dès qu'un client envoie un IBAN ou un numéro de sécurité sociale dans le corps du ticket.

Un LLM local résout les deux problèmes d'un coup. Qwen3-30B-A3B (Alibaba) est multilingue natif sur 119 langues, gère les six langues européennes du brief avec une qualité comparable à GPT-4o-mini, et tourne sur une seule RTX 4090 ou un Mac M4 Max. Coût marginal par ticket : zéro.

i
Pourquoi Qwen3-30B-A3B précisément
C'est un MoE (Mixture of Experts) : 30 milliards de paramètres total, 3 milliards activés à chaque token. Vous obtenez la qualité d'un dense 30B avec la vitesse d'un 3B. Pour du support client où la latence compte, c'est le bon compromis.

#Prérequis

GPU 24 Go VRAM minimum
RTX 3090, 4090, 5090, ou Mac M3/M4 Max avec 32 Go de mémoire unifiée. Qwen3-30B-A3B en Q4_K_M occupe environ 18 Go.
Ollama installé
Version 0.5 ou supérieure pour le support natif des MoE Qwen3.
Un compte Zendesk ou Freshdesk
Avec les droits admin pour créer une intégration webhook et un trigger.
Un endpoint HTTPS accessible
Soit un VPS qui reverse-proxy vers votre Ollama, soit ngrok / Cloudflare Tunnel pour exposer le serveur local.
Python 3.11+
Pour la couche de détection de langue et le routeur de webhooks. FastAPI + langdetect suffisent.

#1. Installer Qwen3-30B-A3B avec Ollama

Le modèle est disponible directement dans la bibliothèque Ollama. Lancez le téléchargement et un test rapide :

Terminal
ollama pull qwen3:30b-a3b
ollama run qwen3:30b-a3b "Réponds en une phrase : qu'est-ce qu'un MoE ?"

Le pull télécharge environ 18 Go. Sur une RTX 4090, la première inférence se fait à 80–110 tokens/seconde — largement assez pour générer une réponse de support en moins de 3 secondes.

Tester le multilingue tout de suite
Posez la même question en 6 langues à la suite avec ollama run. Qwen3 ne fait pas de transition latente entre les langues, contrairement à Llama 3 qui glisse parfois vers l'anglais. C'est exactement ce qu'on veut pour du support.

Exposez Ollama sur le réseau pour que votre webhook puisse l'atteindre :

systemd override
sudo systemctl edit ollama
# Ajoutez :
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_KEEP_ALIVE=30m"

sudo systemctl restart ollama

OLLAMA_KEEP_ALIVE=30m garde le modèle en VRAM pendant 30 minutes après la dernière requête, ce qui évite un cold start à chaque ticket pendant les heures creuses.

#2. Détection automatique de la langue

Avant d'envoyer un message à Qwen3, on identifie sa langue pour choisir le bon system prompt. La librairie fast-langdetect (basée sur fastText de Meta) détecte 176 langues en moins de 5 ms par requête, avec une précision supérieure à 99 % sur des messages de plus de 50 caractères.

Installation
pip install fast-langdetect fastapi uvicorn httpx
detector.py
from fast_langdetect import detect

SUPPORTED = {"fr", "en", "es", "de", "it", "ar"}

def detect_language(text: str) -> str:
    text = text.replace("\n", " ").strip()
    if len(text) < 10:
        return "en"  # message trop court, fallback raisonnable
    result = detect(text, low_memory=False)
    lang = result["lang"]
    return lang if lang in SUPPORTED else "en"
!
Piège des messages mixtes
Un client français qui colle un message d'erreur en anglais peut faire basculer le détecteur. Détectez sur le premier paragraphe seulement (avant la première ligne vide), pas sur le message entier. Sinon vous répondez en anglais à un client francophone.

#3. System prompts par langue et ton adapté

Un bon support multilingue ne traduit pas un prompt français en anglais — il adapte le registre. Le français professionnel utilise le vouvoiement, l'anglais business reste plus direct, l'allemand attend une politesse formelle marquée, l'espagnol latin accepte plus de chaleur, l'italien est plus expressif, l'arabe demande des formules de politesse en début et fin de message.

prompts.py
SYSTEM_PROMPTS = {
    "fr": (
        "Tu es un agent de support client professionnel. "
        "Réponds en français, avec vouvoiement systématique. "
        "Sois concis, empathique, factuel. Ne promets jamais de remboursement "
        "sans validation. Si tu ne sais pas, propose une escalade humaine."
    ),
    "en": (
        "You are a professional customer support agent. "
        "Reply in English, business-friendly tone, direct and concise. "
        "Never commit to a refund without confirmation. "
        "Escalate to a human if uncertain."
    ),
    "es": (
        "Eres un agente de soporte profesional. Responde en español, "
        "trato de usted, tono cálido pero conciso. Nunca prometas reembolsos "
        "sin confirmación. Escala a un humano en caso de duda."
    ),
    "de": (
        "Du bist ein professioneller Kundensupport-Agent. Antworte auf Deutsch "
        "mit Sie-Form, höflich-formell, präzise und sachlich. Versprich nie eine "
        "Rückerstattung ohne Bestätigung. Eskaliere im Zweifel an einen Menschen."
    ),
    "it": (
        "Sei un agente di assistenza clienti professionale. Rispondi in italiano, "
        "forma di cortesia (Lei), tono cordiale e conciso. Mai promettere rimborsi "
        "senza conferma. Scala a un umano in caso di dubbio."
    ),
    "ar": (
        "أنت موظف دعم عملاء محترف. أجب باللغة العربية الفصحى، "
        "بأسلوب رسمي ومهذب يبدأ بتحية وينتهي بعبارة لطيفة. "
        "لا تعد بأي استرداد دون تأكيد. إذا لم تكن متأكدًا، اطلب تدخل موظف بشري."
    ),
}
Garde-fous métier dans le prompt
Les trois lignes "ne promets jamais de remboursement", "escalade si tu ne sais pas", "ne donne pas de remise" sont les seules qui empêchent un LLM de causer de vrais dégâts en support. Mettez-les dans toutes les langues. Le ton change, les règles métier non.

#4. Intégrer un webhook Zendesk ou Freshdesk

Zendesk et Freshdesk déclenchent un webhook HTTP POST à chaque nouveau ticket. On expose un endpoint FastAPI qui détecte la langue, choisit le prompt, appelle Ollama, et renvoie la réponse à l'API du support pour qu'elle soit ajoutée en commentaire interne (l'agent humain valide avant envoi).

webhook_server.py
from fastapi import FastAPI, Request
import httpx
from detector import detect_language
from prompts import SYSTEM_PROMPTS

app = FastAPI()
OLLAMA_URL = "http://localhost:11434/api/chat"

@app.post("/webhook/zendesk")
async def handle_ticket(req: Request):
    payload = await req.json()
    ticket_id = payload["ticket"]["id"]
    message = payload["ticket"]["description"]

    lang = detect_language(message)
    system = SYSTEM_PROMPTS[lang]

    async with httpx.AsyncClient(timeout=60) as client:
        r = await client.post(OLLAMA_URL, json={
            "model": "qwen3:30b-a3b",
            "messages": [
                {"role": "system", "content": system},
                {"role": "user", "content": message},
            ],
            "stream": False,
            "options": {"temperature": 0.3, "num_ctx": 8192},
        })
    draft = r.json()["message"]["content"]

    # Ajoute la réponse en note interne sur le ticket
    await post_internal_note(ticket_id, lang, draft)
    return {"status": "ok", "lang": lang}

La fonction post_internal_note pousse le brouillon en commentaire privé via l'API Zendesk (PUT /api/v2/tickets/{id}.json) ou Freshdesk (POST /api/v2/tickets/{id}/notes). L'agent humain relit, ajuste et clique "Envoyer". Vous gagnez environ 60 % du temps de rédaction sans jamais laisser le bot répondre seul.

  1. 01
    Exposer l'endpoint
    Cloudflare Tunnel ou ngrok pointe vers http://localhost:8000. Notez l'URL publique HTTPS.
  2. 02
    Créer la cible webhook
    Dans Zendesk Admin → Apps & intégrations → Webhooks, créez une cible avec votre URL et la méthode POST.
  3. 03
    Brancher un déclencheur
    Dans Triggers, condition "Ticket Created", action "Notify webhook" avec un payload JSON contenant {ticket: {id, description, requester}}.
  4. 04
    Tester avec un ticket factice
    Créez un ticket en allemand. L'endpoint doit recevoir l'event, détecter "de", et publier un brouillon en allemand dans les notes internes.
  5. 05
    Activer en production progressivement
    Démarrez avec une seule file (par exemple la file espagnole). Mesurez la qualité une semaine. Étendez file par file.
!
Ne répondez jamais au client en direct
Le LLM rédige, l'humain valide. C'est la règle. Un Qwen3 qui hallucine un numéro de commande ou invente une politique de remboursement, ça finit en avis Trustpilot 1 étoile. Tant que vous n'avez pas 6 mois de mesure de qualité par langue, restez en mode brouillon.

#5. Mesurer la qualité par langue

Qwen3 n'a pas la même qualité dans les six langues. Le français et l'anglais sont excellents, l'espagnol et l'italien très bons, l'allemand correct, l'arabe variable selon le dialecte (le standard MSA passe bien, les dialectes maghrébins moins). Il faut mesurer pour piloter.

Trois indicateurs à logger par langue, dès le premier jour :

Taux de validation sans édition
Pourcentage de brouillons que l'agent envoie tel quel. C'est l'indicateur le plus simple et le plus parlant. Cible : 40–60 % à 3 mois.
Édition rate (mots changés / mots générés)
Mesurez avec un diff sur la réponse finale vs. le brouillon. Une langue où l'édition dépasse 30 %, c'est un prompt à retravailler.
CSAT par langue
L'enquête de satisfaction post-résolution, croisée avec la langue du ticket. Si l'allemand chute à 3,5/5 alors que le français reste à 4,5, vous avez un problème de ton.
i
Cas concret d'ajustement
Sur un déploiement réel chez un e-commerce français étendu à l'Allemagne, le taux de validation allemande stagnait à 18 %. Cause identifiée : le prompt traduit littéralement disait "sois empathique". En allemand business, "empathisch" sonne thérapeute. Remplacé par "verbindlich und lösungsorientiert" (engageant et orienté solution) → 45 % en deux semaines.

#Pièges courants

Le bot répond dans la mauvaise langue
C'est presque toujours un message mixte (signature en anglais sous un ticket français). Détectez sur le premier paragraphe, ou forcez la langue du brouillon avec une instruction explicite "Reply in {lang}" en plus du system prompt.
Latence > 10 secondes
Vérifiez que OLLAMA_KEEP_ALIVE est actif et que le modèle reste en VRAM. ollama ps doit montrer 100 % GPU. Si non, baissez num_ctx à 4096 pour les tickets courts.
Réponses arabes mal formatées (RTL)
Qwen3 génère bien l'arabe, mais certaines interfaces de support n'affichent pas le RTL automatiquement. Ajoutez dir="rtl" lang="ar" sur le bloc de réponse côté Zendesk/Freshdesk.
Hallucination de promotions inexistantes
Réduisez la temperature à 0.2, et précisez dans le prompt "ne mentionne aucune promotion ou code de réduction sauf si présent dans le ticket". Le LLM aime offrir des cadeaux qui n'existent pas.
Webhook qui rejoue plusieurs fois
Zendesk peut retenter en cas de timeout. Stockez ticket_id dans Redis avec un TTL de 10 minutes pour idempotence — sinon vous générez 3 brouillons pour le même ticket.

#Pour aller plus loin

Une fois la base stable, deux extensions augmentent fortement le taux de validation : brancher un RAG local sur votre base de connaissances (FAQ, politique de retour, conditions de garantie) pour ancrer les réponses sur des faits, et ajouter une couche fine-tuning LoRA sur quelques milliers de tickets résolus pour caler le ton maison. Pour la mise en production multi-poste, le déploiement en intranet derrière Nginx couvre l'aspect réseau et authentification.

Ce guide vous a aidé ?

Un retour, une erreur, une précision ? Faites-nous signe, ça améliore le guide pour tout le monde.