Разработка AI-бота для Discord на базе LLM
Discord Bot с LLM популярен для игровых и developer-сообществ. Discord поддерживает Slash Commands, Thread-based диалоги, Voice Channel транскрипцию. Discord.py и discord.js — основные фреймворки.
Базовый AI-бот на discord.py
import discord
from discord.ext import commands
from discord import app_commands
from anthropic import AsyncAnthropic
import asyncio
class AIBot(commands.Bot):
def __init__(self):
intents = discord.Intents.default()
intents.message_content = True
super().__init__(command_prefix='!', intents=intents)
self.anthropic = AsyncAnthropic(api_key="ANTHROPIC_API_KEY")
self.conversations: dict[int, list] = {} # channel_id -> history
async def setup_hook(self):
await self.tree.sync()
bot = AIBot()
@bot.tree.command(name="ask", description="Задать вопрос AI-ассистенту")
@app_commands.describe(question="Ваш вопрос")
async def ask(interaction: discord.Interaction, question: str):
await interaction.response.defer()
response = await bot.anthropic.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": question}]
)
answer = response.content[0].text
# Discord лимит 2000 символов
if len(answer) > 1900:
answer = answer[:1900] + "..."
await interaction.followup.send(answer)
@bot.tree.command(name="chat", description="Начать AI-диалог в треде")
async def start_chat(interaction: discord.Interaction):
# Создаём приватный тред
thread = await interaction.channel.create_thread(
name=f"AI Chat с {interaction.user.display_name}",
type=discord.ChannelType.private_thread,
)
await thread.add_user(interaction.user)
bot.conversations[thread.id] = []
await interaction.response.send_message(
f"Открыл для вас приватный AI-чат: {thread.mention}"
)
await thread.send("Привет! Я AI-ассистент. Задайте любой вопрос.")
@bot.event
async def on_message(message: discord.Message):
if message.author == bot.user:
return
# Отвечаем в тредах, где ведётся диалог
if message.channel.id in bot.conversations:
history = bot.conversations[message.channel.id]
history.append({"role": "user", "content": message.content})
async with message.channel.typing():
response = await bot.anthropic.messages.create(
model="claude-haiku-4-5",
max_tokens=2048,
messages=history[-10:],
)
answer = response.content[0].text
history.append({"role": "assistant", "content": answer})
bot.conversations[message.channel.id] = history[-20:]
# Разбиваем длинные ответы на части
for chunk in [answer[i:i+1900] for i in range(0, len(answer), 1900)]:
await message.reply(chunk)
await bot.process_commands(message)
Модерация контента через AI
@bot.event
async def on_message(message: discord.Message):
if message.author.bot:
return
# Проверяем на токсичность
if await is_toxic(message.content):
await message.delete()
await message.channel.send(
f"{message.author.mention}, это сообщение нарушает правила сообщества.",
delete_after=10,
)
return
async def is_toxic(text: str) -> bool:
response = await bot.anthropic.messages.create(
model="claude-haiku-4-5",
max_tokens=10,
messages=[{
"role": "user",
"content": f"Is this message toxic/harmful? Reply only 'yes' or 'no': {text}"
}],
temperature=0,
)
return "yes" in response.content[0].text.lower()
Обработка изображений
import aiohttp
import base64
@bot.tree.command(name="analyze", description="Анализировать изображение")
@app_commands.describe(image="Прикрепите изображение")
async def analyze_image(interaction: discord.Interaction, image: discord.Attachment):
if not image.content_type.startswith("image/"):
await interaction.response.send_message("Нужно изображение!")
return
await interaction.response.defer()
async with aiohttp.ClientSession() as session:
async with session.get(image.url) as resp:
image_data = base64.b64encode(await resp.read()).decode()
response = await bot.anthropic.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
messages=[{
"role": "user",
"content": [
{
"type": "image",
"source": {"type": "base64", "media_type": "image/jpeg", "data": image_data}
},
{"type": "text", "text": "Опиши что на изображении."}
]
}]
)
await interaction.followup.send(response.content[0].text)
Запуск
bot.run("DISCORD_BOT_TOKEN")
Сроки
- Базовый бот со slash commands: 2–3 дня
- Thread-based диалог + история: 2–3 дня
- Модерация + image analysis: 2–3 дня
- Публикация в Discord Developer Portal: 1 день







