El complemento Discourse AI tiene muchas funciones que necesitan un LLM para estar habilitadas: resumen, Asistente de IA, búsqueda semántica, Bot de IA y sus agentes. Puede usar una API de terceros, como Configurar claves de API para OpenAI o Configurar claves de API para Anthropic, pero Discourse AI se diseñó desde el primer día para que no quede atado a ellas.
Esta guía cubre cómo ejecutar usted mismo un modelo de pesos abiertos y conectarlo a Discourse.
Modelo utilizado aquí: Qwen/Qwen3.8-27B — un modelo denso de 27B lanzado en agosto de 2026 con una ventana de contexto nativa de 256K, comprensión de imágenes/video, llamadas a herramientas y modo de pensamiento activado por defecto. Actualmente es el punto óptimo para el autoalojamiento: lo suficientemente potente para tareas reales de resumen/agentes, y lo bastante pequeño para una sola GPU. Sustitúyalo por cualquier otro modelo que prefiera; las banderas que cambian se indican a continuación.
Lo que Discourse necesita de su servidor de inferencia
- Un endpoint
POST /v1/chat/completionscompatible con OpenAI (con soporte para streaming). - Llamadas nativas a herramientas/funciones si desea que el Bot de IA, los agentes o la salida estructurada funcionen bien. Sin esto, Discourse recurre a llamadas a herramientas basadas en XML, que los modelos más débiles manejan mal.
- Una ventana de contexto real — apunte a un mínimo de 16K tokens, 32K+ preferiblemente. El tamaño de las indicaciones de Discourse para el resumen y RAG crece rápidamente.
- Opcional: entrada de imágenes, si desea que el modelo lea las imágenes adjuntas a las publicaciones.
Cualquier cosa que cumpla con los tres primeros requisitos funcionará, por lo que la elección a continuación depende realmente de su hardware.
| Configuración | Adecuado para |
|---|---|
| vLLM | Servidor GPU dedicado, ≥24GB de VRAM (cuantizado) / 80GB (precisión completa), tráfico sostenido, múltiples usuarios |
| llama.cpp | GPUs de consumo, Apple silicon, equipos solo con CPU, un foro pequeño único |
| Gestionado / nube | Desea tener el modelo fuera de su portátil pero no en su hardware: cualquier endpoint compatible con OpenAI |
Ejecución con vLLM
vLLM es el motor recomendado para servidores GPU: licencia Apache, servidor compatible con OpenAI listo para usar y soporte de primera clase para la familia 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"
Notas sobre las banderas:
--max-model-lenlimita el contexto de la indicación + salida y, por lo tanto, la caché KV. El modelo soporta 256K nativamente; 32K es suficiente para el trabajo de un foro y mantiene la VRAM predecible. Aumente el valor (o useauto) si tiene memoria.--reasoning-parser qwen3divide el pensamiento del modelo en un camporeasoningseparado en lugar de volcarlo en la respuesta. Debe reflejar esta elección en la configuración del LLM de Discourse (vea más abajo).--enable-auto-tool-choice --tool-call-parser ...activa las llamadas nativas a funciones. Los nombres de los analizadores cambian entre las versiones de vLLM: revisepython3 -m vllm.entrypoints.openai.api_server --helpdentro de su imagen si las llamadas a herramientas vuelven como texto sin formato.HF_TOKENsolo es necesario para modelos restringidos;--api-keyprotege su propio endpoint. Advertencia de los documentos de vLLM:--api-keyprotege solo las rutas/v1, por lo que debe mantener el servidor fuera de Internet público.- ¿VRAM ajustada? Intente
--quantization fp8(o un checkpoint AWQ pre-cuantizado) antes de reducir el contexto. Multi-GPU: añada--tensor-parallel-size N.
Pruébalo:
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
}'
Debería obtener un cuerpo JSON normal de chat-completions, con message.reasoning junto a message.content.
Ejecución con llama.cpp
llama.cpp es la herramienta adecuada cuando el modelo debe caber en menos VRAM de la que vLLM querría, o cuando está en Apple silicon, AMD, Vulkan o CPU. Su llama-server también expone una API compatible con OpenAI.
Extraiga y ejecute la compilación oficial de GGUF usando la imagen del contenedor para su backend (server-cuda aquí; también existen server, server-rocm, server-vulkan y otros):
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_Mtiene unos 16GB de pesos; se midieron alrededor de 18.4 GiB de VRAM con un contexto de 8K y ~20 GiB con 32K, por lo que una tarjeta de 24GB funciona con un--ctx-sizemodesto.unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_Mde Unsloth es una alternativa popular.--jinjausa la plantilla de chat del propio modelo — esto es lo que hace que las llamadas nativas a herramientas funcionen.--aliasestablece el nombre reportado por la API, por lo que el nombre del modelo que escribe en Discourse coincide.--reasoning autoreporta el pensamiento por separado, igualando el comportamiento de--reasoning-parserde vLLM.- La entrada de imágenes necesita el proyector multimodal; con
-hfgeneralmente se obtiene automáticamente, de lo contrario pase--mmproj /models/mmproj-...gguf(o--no-mmprojpara ahorrar VRAM para el servicio solo de texto).
Pruébalo:
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
}'
Ejecutando otra cosa
Cualquier servidor que hable completaciones de chat compatibles con OpenAI — SGLang, TensorRT-LLM, LM Studio, una puerta de enlace empresarial, un despliegue dedicado en la nube — funciona tal cual: configúrelo en Discourse con el proveedor vLLM, que es nuestro cliente genérico compatible con OpenAI con soporte nativo para herramientas.
Si prefiere no ejecutar la inferencia usted mismo pero aún desea evitar el bloqueo con las grandes APIs, Hugging Face Inference Endpoints (que ahora usan vLLM como motor por defecto) funcionan con el proveedor Hugging Face — apúntelo a la URL /v1/chat/completions del endpoint.
Hacerlo disponible para su instancia de Discourse
Normalmente ejecutará esto en una máquina dedicada debido al requisito de GPU. Cuando lo haga:
- Ponga un proxy inverso frente al servidor y termine TLS allí — Discourse hablará HTTPS con él felizmente.
- Restrinja el endpoint mediante firewall o certificado de cliente para que solo sus hosts de Discourse puedan conectarse. Una clave de API es autenticación, no un límite de red.
- Mantenga la caché del modelo en un volumen persistente para que los reinicios no vuelvan a descargar decenas de gigabytes.
Configurando Discourse AI
Las conexiones LLM se configuran a través de la interfaz de administración en lugar de los ajustes del sitio. Vaya a /admin/plugins/discourse-ai/ai-llms y añada un nuevo LLM:
- Nombre para mostrar — lo que verán sus administradores y usuarios.
- Nombre — enviado en la solicitud API; debe coincidir con lo que espera el servidor (
Qwen/Qwen3.8-27Bpara vLLM, su--aliaspara llama.cpp). - Proveedor — vLLM para vLLM, llama.cpp y cualquier otro servidor compatible con OpenAI; Hugging Face para endpoints alojados en HF.
- URL — la URL del endpoint completa, incluyendo la ruta, por ejemplo:
https://llm.example.com/v1/chat/completions. - Clave de API — escríbala, o haga referencia a una clave almacenada desde la página AI Secrets.
- Tokenizador — Qwen para Qwen3.8 (elija el tokenizador que coincida con la familia de su modelo).
- Tokens máximos de indicación / tokens máximos de salida — mantenga la suma en o por debajo del
--max-model-len/--ctx-sizede su servidor. Por ejemplo, con un servidor de 32768 tokens: 28000 de indicación y 4096 de salida. Los modelos de razonamiento gastan parte de ese presupuesto de salida en el pensamiento, así que no lo apriete demasiado. - Visión — habilite la visión nativa si entregó el modelo con soporte para imágenes y quiere que lea imágenes.
- Opciones de proveedor (vLLM): establezca el analizador de razonamiento de vLLM a
qwen3para que coincida con la bandera del servidor, y use los campos de anulación de pensamiento / esfuerzo de razonamiento / presupuesto de tokens de pensamiento si desea que Discourse dirija el pensamiento por solicitud. Deje “desactivar herramientas nativas” sin marcar a menos que las llamadas a funciones del modelo estén rotas.
Haga clic en Ejecutar prueba antes de guardar: dispara tanto una solicitud con streaming como una sin streaming y le dice cuál falló.
Una vez guardado, hágalo el valor predeterminado del sitio con el ajuste del sitio ai_default_llm_model, o asígnelo por función en /admin/plugins/discourse-ai/ai-features. Los agentes individuales se configuran en la página de Agentes.
Una advertencia: las incrustaciones de búsqueda semántica no provienen de este modelo. Las incrustaciones usan su propio modelo de incrustación, configurado por separado (un modelo de incrustación API, o un servidor Text Embeddings Inference autoalojado mediante los ajustes ai_hugging_face_tei_endpoint). Si desea que la Búsqueda IA esté totalmente autoalojada, ejecute un pequeño modelo de incrustación como bge-m3 junto a su LLM.
Solución de problemas
| Síntoma | Causa probable |
|---|---|
404 desde el endpoint |
Falta /v1/chat/completions en la URL |
model not found |
El Nombre no coincide con el ID del modelo servido / --alias |
401 / 403 |
Incompatibilidad de la clave de API entre --api-key y el registro LLM |
| Las llamadas a herramientas aparecen como texto JSON en la publicación | El servidor se inició sin análisis de llamadas a herramientas; Discourse recurrió a las herramientas XML |
| El texto de pensamiento se filtra en la respuesta | Falta --reasoning-parser en el servidor, o el ajuste de analizador de razonamiento de Discourse no coincide |
| CUDA se quedó sin memoria | Reduzca --max-model-len, añada --quantization fp8, o reduzca --gpu-memory-utilization |
| Las solicitudes agotan el tiempo de espera en resúmenes largos | Los modelos de razonamiento son lentos; nuestro tiempo de espera HTTP es de 6 minutos — reduzca el contexto, baje el esfuerzo de pensamiento o deshabilite el pensamiento |
| Respuestas truncadas | Los tokens máximos de salida en Discourse son demasiado pequeños una vez que se cuentan los tokens de pensamiento |