Le plugin Discourse AI propose de nombreuses fonctionnalités qui nécessitent un LLM pour être activées — résumé, AI Helper, recherche sémantique, robot IA et ses agents. Vous pouvez utiliser une API tierce, comme Configurer les clés d’API pour OpenAI ou Configurer les clés d’API pour Anthropic, mais Discourse AI a été conçu dès le départ pour que vous ne soyez pas prisonnier de ces solutions.
Ce guide explique comment exécuter vous-même un modèle à poids ouverts et le connecter à Discourse.
Modèle utilisé ici : Qwen/Qwen3.8-27B — un modèle dense de 27B sorti en août 2026 avec une fenêtre de contexte native de 256K, la compréhension d’images/vidéos, l’appel d’outils et le mode de réflexion activé par défaut. C’est actuellement le point d’équilibre idéal pour l’auto-hébergement : assez performant pour des tâches réelles de résumé/d’agent, mais assez petit pour tenir sur un seul GPU. Vous pouvez remplacer par n’importe quel autre modèle ; les indicateurs à modifier sont mentionnés ci-dessous.
Ce que Discourse attend de votre serveur d’inférence
- Un point de terminaison
POST /v1/chat/completionscompatible OpenAI (avec prise en charge du streaming). - L’appel d’outils/fonctions natif si vous souhaitez que le robot IA, les agents ou la sortie structurée fonctionnent bien. Sans cela, Discourse revient aux appels d’outils basés sur XML, que les modèles moins performants gèrent mal.
- Une véritable fenêtre de contexte — visez un minimum de 16K tokens, idéalement 32K et plus. La taille des invites de Discourse pour le résumé et le RAG augmente rapidement.
- Optionnel : entrée d’image, si vous souhaitez que le modèle lise les images jointes aux messages.
Tout serveur respectant les trois premiers points fonctionne, donc le choix ci-dessous dépend réellement de votre matériel.
| Configuration | Convient bien à |
|---|---|
| vLLM | Serveur GPU dédié, ≥24 Go de VRAM (quantifié) / 80 Go (pleine précision), trafic soutenu, utilisateurs multiples |
| llama.cpp | GPU grand public, puces Apple silicon, machines uniquement CPU, petits forums |
| Géré / cloud | Vous voulez que le modèle ne soit pas sur votre ordinateur portable, mais pas sur votre matériel : tout point de terminaison compatible OpenAI |
Exécution avec vLLM
vLLM est le moteur recommandé pour les serveurs GPU : licence Apache, serveur compatible OpenAI inclus, et prise en charge de premier plan de la famille Qwen.
mkdir -p /opt/vllm-cache
export VLLM_API_KEY="$(openssl rand -hex 24)"
docker run -d --name vllm \
--runtime nvidia --gpus all \
-v /opt/vllm-cache:/root/.cache/huggingface \
-e HF_HOME=/root/.cache/huggingface \
-e "HF_TOKEN=${HF_TOKEN}" \
-p 8080:8000 \
--ipc=host \
vllm/vllm-openai:latest \
Qwen/Qwen3.8-27B \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 32768 \
--reasoning-parser qwen3 \
--enable-auto-tool-choice \
--tool-call-parser qwen3_xml \
--api-key "$VLLM_API_KEY"
Notes sur les indicateurs :
--max-model-lendéfinit la limite de contexte invite+sortie, et donc du cache KV. Le modèle prend en charge nativement 256K ; 32K est largement suffisant pour les besoins d’un forum et garantit une VRAM prévisible. Augmentez-la (ou utilisezauto) si vous avez la mémoire.--reasoning-parser qwen3sépare la réflexion du modèle dans un champreasoningdistinct au lieu de l’injecter dans la réponse. Vous devez refléter ce choix dans les paramètres LLM de Discourse (voir ci-dessous).--enable-auto-tool-choice --tool-call-parser ...active l’appel de fonctions natif. Les noms des parseurs changent entre les versions de vLLM — vérifiezpython3 -m vllm.entrypoints.openai.api_server --helpdans votre image si les appels d’outils reviennent sous forme de texte brut.HF_TOKENn’est nécessaire que pour les modèles protégés ;--api-keyprotège votre propre point de terminaison. Mise en garde de la documentation vLLM :--api-keyne protège que les itinéraires/v1, alors gardez toujours le serveur hors d’internet public.- Contraint en VRAM ? Essayez
--quantization fp8(ou un point de contrôle pré-quantifié AWQ) avant de réduire le contexte. Multi-GPU : ajoutez--tensor-parallel-size N.
Testez-le :
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $VLLM_API_KEY" \
-d '{
"model": "Qwen/Qwen3.8-27B",
"messages": [{"role": "user", "content": "What is Discourse?"}],
"max_tokens": 200
}'
Vous devriez recevoir un corps JSON de complétion de chat classique, avec message.reasoning à côté de message.content.
Exécution avec llama.cpp
llama.cpp est l’outil adéquat lorsque le modèle doit tenir dans moins de VRAM que ce que vLLM souhaite, ou si vous êtes sur Apple silicon, AMD, Vulkan ou CPU. Son llama-server expose également une API compatible OpenAI.
Téléchargez et exécutez la build GGUF officielle en utilisant l’image de conteneur pour votre backend (server-cuda ici ; server, server-rocm, server-vulkan et d’autres existent également) :
export LLAMA_API_KEY="$(openssl rand -hex 24)"
docker run -d --name llama-server \
--gpus all \
-p 8080:8080 \
-v /opt/llama-models:/models \
ghcr.io/ggml-org/llama.cpp:server-cuda \
-hf ggml-org/Qwen3.8-27B-GGUF:Q4_K_M \
--host 0.0.0.0 \
--port 8080 \
--alias qwen3.8-27b \
--api-key "$LLAMA_API_KEY" \
--ctx-size 16384 \
--n-gpu-layers auto \
--flash-attn auto \
--jinja \
--reasoning auto
Q4_K_Mreprésente environ 16 Go de poids ; environ 18,4 GiB de VRAM mesurés avec un contexte de 8K et ~20 GiB à 32K, donc une carte de 24 Go fonctionne avec un--ctx-sizemodeste.unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_Md’Unsloth est une alternative populaire.--jinjautilise le modèle de chat propre au modèle — c’est ce qui permet à l’appel d’outils natif de fonctionner.--aliasdéfinit le nom renvoyé par l’API, afin que le nom du modèle que vous saisissez dans Discourse corresponde.--reasoning autosignale la réflexion séparément, correspondant au comportement du--reasoning-parserde vLLM.- L’entrée d’image nécessite le projecteur multimodal ; avec
-hf, il est généralement récupéré automatiquement, sinon passez--mmproj /models/mmproj-...gguf(ou--no-mmprojpour économiser de la VRAM en ne servant que du texte).
Testez-le :
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $LLAMA_API_KEY" \
-d '{
"model": "qwen3.8-27b",
"messages": [{"role": "user", "content": "What is Discourse?"}],
"max_tokens": 200
}'
Exécution d’autre chose
Tout serveur qui parle les complétions de chat OpenAI — SGLang, TensorRT-LLM, LM Studio, une passerelle d’entreprise, un déploiement dédié dans le cloud — fonctionne tel quel : configurez-le dans Discourse avec le fournisseur vLLM, qui est notre client compatible OpenAI générique avec prise en charge native des outils.
Si vous préférez ne pas exécuter l’inférence vous-même mais souhaitez tout de même éviter le verrouillage des grandes API, les points de terminaison d’inférence Hugging Face (qui utilisent désormais vLLM par défaut comme moteur) fonctionnent avec le fournisseur Hugging Face — indiquez-lui l’URL /v1/chat/completions du point de terminaison.
Le rendre disponible à votre instance Discourse
Vous l’exécuterez normalement sur une machine dédiée en raison de l’exigence GPU. Lorsque vous le faites :
- Placez un proxy inverse devant le serveur et terminez le TLS là — Discourse parlera joyeusement en HTTPS avec lui.
- Restreignez le point de terminaison par pare-feu ou certificat client afin que seules vos hôtes Discourse puissent se connecter. Une clé d’API est une authentification, pas une limite réseau.
- Gardez le cache du modèle sur un volume persistant afin que les redémarrages ne retéléchargent pas des dizaines de gigaoctets.
Configuration de Discourse AI
Les connexions LLM sont configurées via l’interface d’administration plutôt que via les paramètres du site. Allez sur /admin/plugins/discourse-ai/ai-llms et ajoutez un nouveau LLM :
- Nom d’affichage — ce que vos administrateurs et utilisateurs voient.
- Nom — envoyé dans la requête API ; il doit correspondre à ce que le serveur attend (
Qwen/Qwen3.8-27Bpour vLLM, votre--aliaspour llama.cpp). - Fournisseur — vLLM pour vLLM, llama.cpp et tout autre serveur compatible OpenAI ; Hugging Face pour les points de terminaison hébergés sur HF.
- URL — l’URL complète du point de terminaison incluant le chemin, par ex.
https://llm.example.com/v1/chat/completions. - Clé d’API — tapez-la, ou référez une clé stockée depuis la page des Secrets IA.
- Tokeniseur — Qwen pour Qwen3.8 (choisissez le tokeniseur correspondant à la famille de votre modèle).
- Max prompt tokens / max output tokens — gardez la somme égale ou inférieure au
--max-model-len/--ctx-sizede votre serveur. Par exemple, avec un serveur de 32768 tokens : 28000 pour l’invite et 4096 pour la sortie. Les modèles de réflexion consomment une partie de ce budget de sortie pour la réflexion, donc ne serrez pas trop. - Vision — activez la vision native si vous avez servi le modèle avec prise en charge des images et souhaitez qu’il les lise.
- Options du fournisseur (vLLM) : définissez vLLM reasoning parser sur
qwen3afin que cela corresponde à l’indicateur du serveur, et utilisez les champs de substitution de la réflexion / effort de réflexion / budget de tokens de réflexion si vous souhaitez que Discourse pilote la réflexion par requête. Laissez « disable native tools » décoché sauf si l’appel de fonctions du modèle est cassé.
Cliquez sur Exécuter le test avant d’enregistrer : il envoie une requête en streaming et une non-streaming et vous indique laquelle a échoué.
Une fois enregistré, définissez-le comme défaut du site avec le paramètre ai_default_llm_model, ou attribuez-le par fonctionnalité dans /admin/plugins/discourse-ai/ai-features. Les agents individuels sont configurés sur la page Agents.
Une mise en garde : les embeddings de recherche sémantique ne proviennent pas de ce modèle. Les embeddings utilisent leur propre modèle d’embedding, configuré séparément (un modèle d’embedding API, ou un serveur Text Embeddings Inference auto-hébergé via les paramètres ai_hugging_face_tei_endpoint). Si vous souhaitez que la Recherche IA soit entièrement auto-hébergée, exécutez un petit modèle d’embedding tel que bge-m3 à côté de votre LLM.
Dépannage
| Symptôme | Cause probable |
|---|---|
404 depuis le point de terminaison |
L’URL manque /v1/chat/completions |
model not found |
Le Nom ne correspond pas à l’ID du modèle servi / --alias |
401 / 403 |
Clé d’API non concordante entre --api-key et l’enregistrement LLM |
| Les appels d’outils apparaissent sous forme de texte JSON dans le message | Le serveur a été lancé sans analyse d’appels d’outils ; Discourse est revenu aux outils XML |
| Du texte de réflexion fuit dans la réponse | --reasoning-parser manquant sur le serveur, ou le paramètre reasoning parser de Discourse ne correspond pas |
| Erreur de mémoire CUDA | Diminuez --max-model-len, ajoutez --quantization fp8, ou diminuez --gpu-memory-utilization |
| Les requêtes expirent lors de longs résumés | Les modèles de réflexion sont lents ; notre délai HTTP est de 6 minutes — réduisez le contexte, diminuez l’effort de réflexion, ou désactivez la réflexion |
| Réponses tronquées | Le max output tokens dans Discourse est trop petit une fois les tokens de réflexion comptés |