O plugin Discourse AI possui muitos recursos que precisam de um LLM para serem ativados — resumização, AI Helper, busca semântica, AI Bot e seus agentes. Você pode usar uma API de terceiros, como Configure API Keys for OpenAI ou Configure API Keys for Anthropic, mas o Discourse AI foi criado desde o primeiro dia para que você não fique preso a essas opções.
Este guia aborda a execução de um modelo de pesos abertos por conta própria e sua conexão ao Discourse.
Modelo utilizado aqui: Qwen/Qwen3.8-27B — um modelo denso de 27B lançado em agosto de 2026 com uma janela de contexto nativa de 256K, compreensão de imagem/vídeo, chamadas de ferramentas e modo de raciocínio ativado por padrão. Atualmente, é o ponto ideal para auto-hospedagem: forte o suficiente para resumização/agentes reais, pequeno o suficiente para uma única GPU. Substitua por qualquer outro modelo que preferir; os sinalizadores que mudam estão indicados abaixo.
O que o Discourse precisa do seu servidor de inferência
- Um endpoint
POST /v1/chat/completionscompatível com a OpenAI (com suporte a streaming). - Chamada de ferramentas/funções nativa se você quiser que o AI Bot, agentes ou saída estruturada funcionem bem. Sem isso, o Discourse recorre a chamadas de ferramentas baseadas em XML, que modelos mais fracos tratam mal.
- Uma janela de contexto real — mire em no mínimo 16K tokens, preferencialmente 32K+. O tamanho dos prompts do Discourse para resumização e RAG cresce rapidamente.
- Opcional: entrada de imagem, se você quiser que o modelo leia imagens anexadas às postagens.
Qualquer coisa que satisfaça os três primeiros requisitos funciona, então a escolha abaixo depende realmente do seu hardware.
| Configuração | Bom para |
|---|---|
| vLLM | Servidor GPU dedicado, ≥24GB de VRAM (quantizado) / 80GB (precisão completa), tráfego sustentado, múltiplos usuários |
| llama.cpp | GPUs de consumo, Apple Silicon, máquinas apenas com CPU, fóruns pequenos únicos |
| Gerenciado / nuvem | Você quer o modelo fora do seu laptop, mas não no seu hardware: qualquer endpoint compatível com OpenAI |
Executando com vLLM
O vLLM é o motor recomendado para servidores GPU: licença Apache, servidor compatível com OpenAI pronto para uso e suporte de primeira classe para a família 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"
Observações sobre os sinalizadores:
--max-model-lenlimita o contexto de prompt+saída e, portanto, o cache KV. O modelo suporta 256K nativamente; 32K é suficiente para trabalhos em fórum e mantém a VRAM previsível. Aumente-o (ou useauto) se você tiver memória.--reasoning-parser qwen3separa o raciocínio do modelo em um camporeasoningseparado, em vez de despejá-lo na resposta. Você deve espelhar essa escolha nas configurações de LLM do Discourse (veja abaixo).--enable-auto-tool-choice --tool-call-parser ...ativa a chamada de função nativa. Os nomes dos analisadores mudam entre as versões do vLLM — verifiquepython3 -m vllm.entrypoints.openai.api_server --helpdentro da sua imagem se as chamadas de ferramentas retornarem como texto simples.HF_TOKENsó é necessário para modelos restritos;--api-keyprotege seu próprio endpoint. Ressalva da documentação do vLLM:--api-keyprotege apenas as rotas/v1, então mantenha o servidor fora da internet pública.- Apertado em VRAM? Tente
--quantization fp8(ou um checkpoint pré-quantizado AWQ) antes de reduzir o contexto. Multi-GPU: adicione--tensor-parallel-size N.
Teste-o:
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
}'
Você deve receber um corpo JSON normal de conclusão de chat de volta, com message.reasoning ao lado de message.content.
Executando com llama.cpp
O llama.cpp é a ferramenta certa quando o modelo precisa caber em menos VRAM do que o vLLM gostaria, ou quando você está em Apple Silicon, AMD, Vulkan ou CPU. Seu llama-server também expõe uma API compatível com a OpenAI.
Baixe e execute a versão oficial GGUF usando a imagem do container para seu backend (server-cuda aqui; server, server-rocm, server-vulkan e outros também existem):
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_Mtem cerca de 16GB de pesos; medido em torno de 18,4 GiB de VRAM em contexto 8K e ~20 GiB em 32K, então uma placa de 24GB funciona com um--ctx-sizemodesto.unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_Mda Unsloth é uma alternativa popular.--jinjausa o template de chat do próprio modelo — isso é o que faz a chamada de ferramentas nativa funcionar.--aliasdefine o nome reportado pela API, para que o nome do modelo que você digita no Discourse corresponda.--reasoning autoreporta o raciocínio separadamente, correspondendo ao comportamento--reasoning-parserdo vLLM.- A entrada de imagem precisa do projetor multimodal; com
-hfgeralmente é buscado automaticamente, caso contrário passe--mmproj /models/mmproj-...gguf(ou--no-mmprojpara economizar VRAM para serviço apenas de texto).
Teste-o:
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
}'
Executando algo diferente
Qualquer servidor que fale conclusões de chat compatíveis com OpenAI — SGLang, TensorRT-LLM, LM Studio, um gateway empresarial, uma implantação dedicada na nuvem — funciona como está: configure-o no Discourse com o provedor vLLM, que é nosso cliente genérico compatível com OpenAI com suporte a ferramentas nativo.
Se você preferir não executar a inferência por conta própria, mas ainda quiser ficar fora da dependência das grandes APIs, os Hugging Face Inference Endpoints (que agora têm o vLLM como motor padrão) funcionam com o provedor Hugging Face — aponte-o para a URL /v1/chat/completions do endpoint.
Tornando-o disponível para sua instância do Discourse
Normalmente, você executará isso em uma máquina dedicada devido ao requisito de GPU. Quando fizer isso:
- Coloque um proxy reverso na frente do servidor e finalize o TLS lá — o Discourse falará HTTPS com ele sem problemas.
- Restrinja o endpoint por firewall ou certificado de cliente para que apenas seus hosts Discourse possam se conectar. Uma chave API é autenticação, não uma fronteira de rede.
- Mantenha o cache do modelo em um volume persistente para que reinicializações não baixem novamente dezenas de gigabytes.
Configurando o Discourse AI
As conexões de LLM são configuradas através da interface administrativa, e não nas configurações do site. Vá para /admin/plugins/discourse-ai/ai-llms e adicione um novo LLM:
- Nome de exibição — o que seus administradores e usuários veem.
- Nome — enviado na solicitação da API; deve corresponder ao que o servidor espera (
Qwen/Qwen3.8-27Bpara vLLM, seu--aliaspara llama.cpp). - Provedor — vLLM para vLLM, llama.cpp e qualquer outro servidor compatível com OpenAI; Hugging Face para endpoints hospedados na HF.
- URL — a URL completa do endpoint incluindo o caminho, por exemplo,
https://llm.example.com/v1/chat/completions. - Chave API — digite-a, ou referencie uma chave armazenada na página de Segredos de IA.
- Tokenizer — Qwen para Qwen3.8 (escolha o tokenizer correspondente à família do seu modelo).
- Tokens máximos de prompt / tokens máximos de saída — mantenha a soma igual ou abaixo do
--max-model-len/--ctx-sizedo seu servidor. Por exemplo, com um servidor de 32768 tokens: 28000 de prompt e 4096 de saída. Modelos de raciocínio gastam parte desse orçamento de saída pensando, então não aperte demais. - Visão — ative a visão nativa se você serviu o modelo com suporte a imagens e quiser que ele leia imagens.
- Opções do provedor (vLLM): defina analisador de raciocínio vLLM como
qwen3para corresponder ao sinalizador do servidor, e use os campos de substituição de pensamento / esforço de raciocínio / orçamento de tokens de pensamento se você quiser que o Discourse guie o pensamento por solicitação. Deixe “desativar ferramentas nativas” desmarcado, a menos que a chamada de função do modelo esteja quebrada.
Clique em Executar teste antes de salvar: ele dispara uma solicitação com streaming e outra sem streaming e informa qual delas falhou.
Uma vez salvo, torne-o o padrão do site com a configuração do site ai_default_llm_model, ou atribua-o por recurso em /admin/plugins/discourse-ai/ai-features. Agentes individuais são configurados na página de Agentes.
Uma ressalva: as incorporações de busca semântica não vêm deste modelo. As incorporações usam seu próprio modelo de incorporação, configurado separadamente (um modelo de incorporação via API, ou um servidor Text Embeddings Inference auto-hospedado via configurações ai_hugging_face_tei_endpoint). Se você quiser a Busca por IA totalmente auto-hospedada, execute um pequeno modelo de incorporação como bge-m3 ao lado do seu LLM.
Solução de problemas
| Sintoma | Causa provável |
|---|---|
404 do endpoint |
URL está sem /v1/chat/completions |
model not found |
O Nome não corresponde ao ID do modelo servido / --alias |
401 / 403 |
Incompatibilidade de chave API entre --api-key e o registro do LLM |
| Chamadas de ferramentas aparecem como texto JSON na postagem | Servidor iniciado sem análise de chamada de ferramentas; o Discourse recorreu a ferramentas XML |
| Texto de raciocínio vazando na resposta | --reasoning-parser ausente no servidor, ou a configuração de analisador de raciocínio do Discourse não corresponde a ele |
| Memória insuficiente da CUDA | Reduza --max-model-len, adicione --quantization fp8 ou reduza --gpu-memory-utilization |
| Solicitações expiram em resumizações longas | Modelos de raciocínio são lentos; nosso tempo limite HTTP é de 6 minutos — reduza o contexto, diminua o esforço de raciocínio ou desative o raciocínio |
| Respostas truncadas | max output tokens no Discourse é muito pequeno quando os tokens de raciocínio são contados |