Почему ваш Discord-бот не должен зависеть от OpenAI
Вы хотите добавить в Discord-бота "интеллект", но ChatGPT API стоит денег, а бесплатные лимиты кончаются на втором сообщении. Альтернатива? Локальная LLM на вашем сервере. Проблема в том, что все гайды начинаются с "возьмите RTX 4090", а у вас — старый ноутбук, Raspberry Pi или VPS за 5$ в месяц с 4 ГБ оперативки.
Я запускал ботов на слабом железе десятки раз. Сегодня покажу, как сделать это без нервного тика и перезагрузок каждые 5 минут.
Реальность, о которой молчат: Многие модели из Hugging Face не запустятся на 4 ГБ RAM даже в самом агрессивном квантовании. Нужно знать конкретные версии и параметры.
Что на самом деле ест память
Прежде чем выбирать модель, нужно понять, куда уходят ваши 4-6 ГБ. Это не только веса модели:
- Веса модели: Основной потребитель. 7B модель в INT4 — около 4 ГБ
- Контекст (prompt + ответ): Каждый токен требует памяти для вычислений
- Система (ОС, Discord бот, Ollama): 500 МБ - 1 ГБ в спокойном состоянии
- Буферы и временные данные: Ещё 300-500 МБ
Итого: даже если модель занимает 3.5 ГБ, свободных 500 МБ на контекст может не хватить. Бот упадёт в середине ответа.
Модели, которые реально работают на 4 ГБ RAM
Не все маленькие модели одинаково полезны. Некоторые дают осмысленные ответы, другие — рандомный набор слов. Вот проверенные варианты:
| Модель | Размер (INT4) | Качество | Скорость | Для чего подходит |
|---|---|---|---|---|
| TinyLlama 1.1B | 0.7 ГБ | Базовая логика, простые ответы | Очень быстро | Боты-помощники, простые команды |
| Phi-2 2.7B | 1.6 ГБ | Удивляет качеством для своего размера | Быстро | Общие вопросы, программирование |
| Qwen2.5 0.5B | 0.3 ГБ | Хорошо для китайского/английского | Молниеносно | Многоязычные боты |
| Mistral 7B (q4_K_M) | 4.1 ГБ | Лучшее качество из возможных | Медленно на CPU | Если есть 6 ГБ RAM |
Квантование: магия, которая всё меняет
Квантование — это сжатие модели за счёт уменьшения точности чисел. Вместо 32-битных чисел (FP32) используем 4-битные (INT4). Памяти нужно в 8 раз меньше. Качество падает, но не катастрофически.
Важно: Не все квантования одинаковы. q4_0 быстрее, q4_K_M качественнее. Для Discord-бота скорость часто важнее.
1 Ставим Ollama — мастхэв для локальных LLM
Ollama — это не просто удобная обёртка. Это система, которая автоматически загружает предварительно квантованные модели и запускает их с оптимальными параметрами. Без Ollama вам пришлось бы вручную качать файлы на 10+ ГБ и настраивать трансформеры.
curl -fsSL https://ollama.com/install.sh | sh
После установки проверяем:
ollama --version
# Должно показать версию, например: ollama version 0.5.2
2 Качаем и тестируем модель
Начнём с Phi-2 — лучший баланс размера и качества для наших ограничений:
ollama pull phi2:2.7b-q4_K_M
Почему именно q4_K_M? Этот вариант квантования сохраняет больше качества, чем базовый q4_0, но почти не увеличивает размер. Для Discord-бота, где ответы короткие, разница заметна.
Тестируем модель в консоли:
ollama run phi2:2.7b-q4_K_M
>>> Напиши приветственное сообщение для Discord-бота
Если модель отвечает в течение 5-10 секунд — всё работает. Если ждёте 30 секунд — возможно, не хватает RAM.
3 Пишем Discord-бота на Node.js
Ollama предоставляет REST API на порту 11434. Наш бот будет отправлять туда запросы. Вот минимальная рабочая версия:
const { Client, GatewayIntentBits } = require('discord.js');
const axios = require('axios');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
]
});
const OLLAMA_URL = 'http://localhost:11434';
const MODEL = 'phi2:2.7b-q4_K_M';
client.on('ready', () => {
console.log(`Бот ${client.user.tag} запущен!`);
});
client.on('messageCreate', async message => {
// Игнорируем сообщения от ботов и не начинающиеся с !ai
if (message.author.bot || !message.content.startsWith('!ai ')) return;
const prompt = message.content.slice(4); // Убираем "!ai "
// Отправляем "печатает..."
const typingMessage = await message.channel.send('*печатает...*');
try {
const response = await axios.post(`${OLLAMA_URL}/api/generate`, {
model: MODEL,
prompt: `Ты полезный Discord-бот. Отвечай кратко и по делу.\n\nВопрос: ${prompt}\nОтвет:`,
stream: false,
options: {
temperature: 0.7,
num_predict: 256 // Ограничиваем длину ответа
}
});
await typingMessage.edit(response.data.response);
} catch (error) {
console.error('Ошибка:', error);
await typingMessage.edit('Ошибка при генерации ответа');
}
});
client.login('YOUR_BOT_TOKEN_HERE');
4 Оптимизируем под слабое железо
Стандартные настройки могут убить ваш сервер. Вот что нужно изменить в конфигурации Ollama:
# Создаём или редактируем конфиг
sudo nano /etc/systemd/system/ollama.service.d/override.conf
[Service]
Environment="OLLAMA_NUM_PARALLEL=1" # Только один запрос одновременно
Environment="OLLAMA_MAX_LOADED_MODELS=1" # Загружаем только одну модель
Environment="OLLAMA_HOST=127.0.0.1:11434" # Локальный хост для безопасности
LimitMEMLOCK=infinity # Разрешаем блокировку памяти
LimitNOFILE=65536 # Увеличиваем лимит файлов
Перезапускаем Ollama:
sudo systemctl daemon-reload
sudo systemctl restart ollama
Ошибки, которые сломают ваш бот
Я видел эти ошибки десятки раз. Вот как их избежать:
1. Out of memory после 5 минут работы
Проблема: Бот работает, потом падает с ошибкой памяти.
Решение: Установите лимит контекста в настройках Ollama:
ollama run phi2:2.7b-q4_K_M
/set parameter num_ctx 512 # Вместо 2048 по умолчанию
2. Модель отвечает по 30 секунд
Проблема: Каждое сообщение обрабатывается вечность.
Решение: Уменьшите num_predict до 128 и temperature до 0.3. Модель будет отвечать быстрее и менее креативно, но для большинства команд Discord этого достаточно.
3. Discord блокирует бота за спам
Проблема: API Discord имеет лимиты. Если модель генерирует длинные ответы, бот может превысить лимит сообщений.
Решение: Разбивайте длинные ответы на части по 2000 символов (лимит Discord):
function splitMessage(text, limit = 2000) {
const parts = [];
for (let i = 0; i < text.length; i += limit) {
parts.push(text.slice(i, i + limit));
}
return parts;
}
// В обработчике сообщений:
const responseParts = splitMessage(llmResponse);
for (const part of responseParts) {
await message.channel.send(part);
await new Promise(resolve => setTimeout(resolve, 500)); // Задержка между сообщениями
}
А если хочется больше качества?
У вас есть 6 ГБ RAM или готовы мириться с медленной работой? Попробуйте Mistral 7B. Это уже серьёзная модель, которая справится с сложными диалогами.
ollama pull mistral:7b-q4_K_M
# Занимает ~4.1 ГБ
Но предупреждаю: на слабом CPU (например, Raspberry Pi 4) ответ будет генерироваться 15-30 секунд. Для Discord это много.
--verbose и посмотрите логи. Там будет видно, где происходит торможение: загрузка модели, генерация первых токенов или что-то ещё.Что делать, когда бот популярен?
Если в вашем Discord-сервере больше 100 активных пользователей, один экземпляр модели не справится. Решения:
- Очередь запросов: Самый простой вариант. Пользователи ждут своей очереди.
- Кэширование ответов: Если вопросы повторяются ("как настроить бота?"), сохраняйте ответы в Redis.
- Облачный инференс как fallback: Когда очередь слишком длинная, отправляйте запрос в OpenAI API (платно).
Вот пример простой очереди на Node.js:
class RequestQueue {
constructor() {
this.queue = [];
this.processing = false;
}
async add(prompt) {
return new Promise((resolve) => {
this.queue.push({ prompt, resolve });
this.process();
});
}
async process() {
if (this.processing || this.queue.length === 0) return;
this.processing = true;
const { prompt, resolve } = this.queue.shift();
try {
const response = await axios.post('http://localhost:11434/api/generate', {
model: MODEL,
prompt,
stream: false
});
resolve(response.data.response);
} catch (error) {
resolve('Ошибка при обработке запроса');
} finally {
this.processing = false;
setTimeout(() => this.process(), 100); // Небольшая пауза между запросами
}
}
}
const queue = new RequestQueue();
// В обработчике сообщений:
const response = await queue.add(prompt);
Когда это всё-таки не сработает
Бывают случаи, когда даже TinyLlama не влезет в 4 ГБ RAM. Обычно это происходит, когда:
- На сервере уже работает что-то тяжёлое (база данных, веб-сервер)
- Система использует swap, который медленнее в 1000 раз
- У вас ARM-процессор без оптимизаций под Ollama
В этом случае посмотрите мою статью про запуск LLM на Raspberry Pi — там есть специфичные для ARM оптимизации.
Итог: что выбрать для своего бота
Если нужно прямо сейчас запустить что-то работающее — берите Phi-2. Если есть время на эксперименты — попробуйте Mistral 7B. Если нужна максимальная скорость — TinyLlama.
Главное — не пытайтесь запустить 13B модель на 4 ГБ RAM. Она либо не загрузится, либо будет работать так медленно, что пользователи сбегут.
И последний совет: прежде чем разворачивать бота на продакшн, протестируйте его с реальными пользователями. Однажды я сделал бота с Mistral 7B для сервера на 500 человек. Он работал идеально... пока одновременно не написали 10 человек. Очередь выросла до 5 минут ожидания. Пришлось срочно ставить ограничение в 1 запрос в минуту на пользователя.
Локальные LLM на слабом железе — это не про производительность. Это про независимость от API, приватность и полный контроль. И иногда этого достаточно.