Bot de Discord de código aberto com LLM sem censura
Um bot de Discord de código aberto que conversa por meio de um LLM tem cerca de oitenta linhas de Python. Este guia fornece o código, os limites que você deve respeitar e o custo por resposta, usando uma API compatível com OpenAI com um modelo que não recusa solicitações adultas legais.

Pontos principais
- discord.py mais o SDK da OpenAI é suficiente; aponte o SDK para https://api.openrouternsfw.com/v1 e use o modelo uncensored.
- Ative a intenção de Conteúdo de Mensagem no portal do desenvolvedor do Discord ou o bot verá mensagens vazias.
- Use um semáforo abaixo de 8 para permanecer dentro do limite de concorrência e mantenha o conteúdo adulto em canais marcados como restritos por idade.
- Uma resposta com 1.500 tokens de entrada e 300 de saída custa $0,000375, ou seja, cerca de $3,75 por 10.000 respostas.
Sem necessidade de cartão. Após o cadastro, reivindique $0,50 de crédito de teste grátis com um clique (uma vez por pessoa).
Obter chave de APIO que você está construindo
O bot abaixo responde quando alguém o menciona. Ele mantém um histórico curto por canal, envia-o para o endpoint de conclusões de chat e publica a resposta. É Python puro, compatível com MIT e não tem banco de dados. Você pode ler tudo de uma vez, que é o ponto de um projeto de código aberto: alguém pode bifurcá-lo e entendê-lo.
O modelo por trás disso é um único modelo de texto de pesos abertos, executado por um provedor independente e ajustado para responder sem recusas de conteúdo para uso adulto legal. Isso se adequa a comunidades do Discord construídas em torno de ficção, roleplay ou conversas adultas. Duas regras se aplicam desde o início. Primeiro, conteúdo sexual envolvendo menores de idade não é permitido pela API e não deve fazer parte do design do seu bot. Segundo, o Discord tem suas próprias regras e configurações de canais restritos por idade, e você é responsável por segui-las. Mantenha o conteúdo adulto em canais que são marcados como tal e em servidores onde os membros são adultos.
Configurar o Discord e suas chaves
- Abra o portal do desenvolvedor do Discord e crie um aplicativo, depois adicione um bot a ele.
- Nas configurações do bot, ative a Intenção de Conteúdo de Mensagem. Sem isso, o bot recebe mensagens com texto vazio.
- Copie o token do bot. Trate-o como uma senha.
- Use o gerador de URL OAuth2 para convidar o bot com permissão para ler e enviar mensagens nos canais que você escolher.
- Obtenha uma chave de API na página de chaves. Novos usuários podem resgatar $0,50 de crédito de teste com um clique, sem necessidade de detalhes de pagamento, válido por 7 dias.
Armazene ambos os segredos como variáveis de ambiente, nunca no repositório. Para um projeto de código aberto, isso é mais importante do que o habitual, porque o código é público.
pip install discord.py openai python-dotenv
printf 'DISCORD_TOKEN=your-discord-token
API_KEY=your-api-key
' > .env
echo ".env" >> .gitignore
O código do bot
Salve isso como bot.py. Os comentários explicam as decisões que não são óbvias.
import asyncio
import os
from collections import defaultdict, deque
import discord
from dotenv import load_dotenv
from openai import AsyncOpenAI
load_dotenv()
ai = AsyncOpenAI(
base_url="https://api.openrouternsfw.com/v1",
api_key=os.environ["API_KEY"],
max_retries=4, # the SDK retries 429 and honors Retry-After
)
SYSTEM = (
"You are Vex, a sharp-tongued storyteller in a Discord server for adults. "
"Stay in character, keep replies under 150 words, and never write "
"anything sexual involving minors."
)
intents = discord.Intents.default()
intents.message_content = True
bot = discord.Client(intents=intents)
slots = asyncio.Semaphore(6) # stay under 8 concurrent
history = defaultdict(lambda: deque(maxlen=12)) # last 12 turns per channel
async def ask(channel_id, user_text):
turns = history[channel_id]
turns.append({"role": "user", "content": user_text})
messages = [{"role": "system", "content": SYSTEM}] + list(turns)
async with slots:
resp = await ai.chat.completions.create(
model="uncensored",
messages=messages,
temperature=0.9,
max_tokens=400,
)
reply = resp.choices[0].message.content or ""
turns.append({"role": "assistant", "content": reply})
return reply
@bot.event
async def on_ready():
print(f"Logged in as {bot.user}")
@bot.event
async def on_message(message):
if message.author.bot or bot.user not in message.mentions:
return
text = message.clean_content.replace(f"@{bot.user.display_name}", "").strip()
if not text:
return
async with message.channel.typing():
try:
reply = await ask(message.channel.id, f"{message.author.display_name}: {text}")
except Exception as exc:
print("API error:", exc)
await message.reply("The model is busy. Try again in a few seconds.")
return
for i in range(0, len(reply), 1900): # Discord caps messages at 2000 chars
await message.reply(reply[i:i + 1900])
bot.run(os.environ["DISCORD_TOKEN"])
Execute-o com python bot.py, depois mencione o bot em um canal que ele possa ler. A primeira resposta deve chegar em alguns segundos.
Se nada acontecer, verifique três coisas na ordem. O bot deve estar online na lista de membros, então o token é válido. Ele deve ter permissão para ler e enviar mensagens nesse canal. E a menção deve ser uma menção real do Discord, selecionada da lista de autocompletar, porque texto simples com o nome do bot não aparece em message.mentions. O terminal imprime erros da API, então uma chave errada aparece lá como uma falha de autenticação.
Por que o código é estruturado assim
O histórico é pequeno propositalmente
A janela de contexto tem 100.000 tokens, então você poderia enviar muito. Mas cada token de entrada é cobrado em cada chamada, e o chat do Discord é principalmente linhas curtas. Doze turnos mantêm as respostas coerentes sem transformar cada mensagem em uma conta grande. Aumente maxlen para canais de história onde a continuidade importa.
O semáforo protege sua chave
Uma chave completa permite 8 requisições simultâneas e 300 requisições por minuto. Uma chave de teste permite apenas 2 e 60. Se dez pessoas mencionarem o bot ao mesmo tempo e você enviar dez requisições, as extras retornarão HTTP 429 com o código de erro concurrency. O semáforo as enfileira no seu próprio processo. Defina como 2 enquanto estiver na chave de teste. Se você ativar o streaming, lembre-se de que uma requisição em streaming mantém seu slot até que o streaming termine.
As retentativas vêm do SDK
O SDK Python da OpenAI tenta novamente em 429 e respeita o cabeçalho Retry-After, que o serviço envia como Retry-After: 5 em sobrecarga temporária. Definir max_retries para 4 cobre picos curtos. Solicitações falhas ou recusadas não são cobradas, então as retentativas não custam tokens quando falham.
Uma persona compartilhada
O prompt do sistema fica primeiro em toda chamada. Personas por canal são uma pequena extensão: mantenha um dicionário de ID do canal para prompt e procure-o em ask.
Torne-o um bom projeto de código aberto
O código funciona, mas um repositório público precisa de alguns extras antes que estranhos possam usá-lo.
- Uma licença. MIT ou Apache 2.0 são as escolhas usuais para bots pequenos. Adicione o arquivo na raiz do repositório.
- Um .env.example. Liste
DISCORD_TOKENeAPI_KEYcom valores falsos para que as pessoas saibam o que definir. - Uma URL base configurável. Leia
BASE_URLeMODELdo ambiente, assumindo os valores acima como padrão. Qualquer pessoa que bifurcá-lo pode então usar qualquer servidor compatível com OpenAI. - Um Dockerfile. Um arquivo curto baseado em uma imagem slim do Python, copiando
bot.py, instalando os três pacotes e executando o script, permite que as pessoas o hospedem em qualquer lugar. - Um README com o aviso de intenções. A intenção de Conteúdo de Mensagem ausente é a principal pergunta de suporte para cada bot do Discord.
Mantenha seu próprio token e chave fora do histórico do Git. Se um vazar, revogue-o no portal do Discord ou na página da chave de API e emita um novo.
Hospedagem e o que custa
O bot é um único processo de longa execução com uso leve de CPU. Uma pequena VPS, uma máquina sobressalente ou uma plataforma de contêiner é suficiente. Não há servidor web para expor, porque o bot se conecta ao Discord.
O custo da API é fácil de calcular. Uma resposta típica aqui usa 1.500 tokens de entrada (prompt do sistema mais doze turnos curtos) e 300 tokens de saída.
- Entrada: 1.500 x $0,15 / 1M = $0,000225
- Saída: 300 x $0,50 / 1M = $0,00015
- Por resposta: $0,000375
Isso faz 1.000 respostas custarem $0,375 e 10.000 respostas custarem $3,75. O crédito de teste de $0,50 cobre cerca de 1.333 respostas. Uma recarga de $20 cobre mais de 53.000. Recargas variam de $20 a $500, com +5% de $50, +10% de $100 e +15% de $200. O crédito nunca expira e não há assinatura, então um servidor silencioso custa quase nada. Veja a página de preços para os detalhes. O pagamento é apenas cripto, usando USDT em TRC20 ou USDC na Base.
Para onde ir a seguir
Três melhorias valem o esforço. Adicione streaming editando uma única mensagem conforme os chunks chegam, mas observe os limites de taxa de edição do Discord. Adicione um comando slash que redefine o histórico do canal. Adicione chamada de funções para que o bot possa rolar dados ou consultar uma ficha de personagem; a API suporta tools, tool_choice e resultados role: "tool" no formato OpenAI.
A documentação da API lista todos os parâmetros suportados, e o artigo da API Hermes cobre como os modelos sem censura se comportam dentro de um projeto. Prompts enviados para a API não são usados para treinamento, o que vale a pena dizer nas regras do seu servidor se seus membros perguntarem.
Mais guias
Perguntas e respostas
O bot precisa da intenção de Conteúdo de Mensagem?
Sim. Ative-a no portal do desenvolvedor do Discord e no código com intents.message_content definido como true. Caso contrário, o bot vê mensagens vazias.
Quantas respostas o bot pode processar ao mesmo tempo?
Uma chave completa permite 8 requisições simultâneas e 300 por minuto; uma chave de teste permite 2 e 60. Um semáforo no bot mantém você abaixo do limite.
Posso publicar o código do bot?
Sim, desde que o token do Discord e a chave de API fiquem fora do repositório. Leia-os a partir de variáveis de ambiente e inclua um arquivo .env.example.
É permitido usar temas adultos?
Apenas para uso adulto legal, em conformidade com as regras do Discord e suas configurações de canais restritos por idade. Conteúdo sexual envolvendo menores de idade nunca é permitido.
Qual é o custo para executar?
Uma resposta com 1.500 tokens de entrada e 300 tokens de saída custa $0,000375, ou seja, cerca de $3,75 por 10.000 respostas, mais o custo de hospedar o processo.
Sua chave está a um formulário de distância
Crie uma conta, copie a chave e altere a URL base. Essa é toda a configuração.
Obter chave de API