RU ▾
https://api.unrestrictedaiapi.com/v1uncensored2026-10-06
Получить API-ключ

Создайте бота Discord или Telegram на API ИИ без ограничений

Чат-бот — самый быстрый способ вывести модель без ограничений перед пользователями. Это руководство поможет создать бота на discord.py и бота на python-telegram-bot на базе общего модуля, который обрабатывает вызовы API, ведёт историю по каналам, ограничивает частоту запросов, обрабатывает повторные попытки и реализует проверку возраста. Всё это пишется один раз и используется повторно.

Обновлено

Ключевые моменты

  1. Изолируйте логику API в одном модуле и держите адаптеры платформ минимальными.
  2. Храните отдельную ограниченную историю для каждого канала или чата, чтобы разговоры никогда не смешивались.
  3. Ограничивайте частоту в три слоя: задержка для каждого пользователя, глобальное скользящее окно (менее 300 запросов в минуту) и ограничение параллельных запросов.
  4. Возрастная фильтрация: только каналы Discord с пометкой NSFW и явное подтверждение /adult в Telegram.

Что мы строим

Два небольших бота, один общий мозг. Файл llm.py содержит всё, что связано с API: роль, ограничитель частоты и логику повторных попыток. Боты Discord и Telegram лишь преобразуют события платформы в список сообщений и обратно. Если позже вы добавите третью платформу, вам нужно будет написать только адаптер.

Установите зависимости через pip install httpx discord.py python-telegram-bot. Экспортируйте API_KEY со вашей страницы аккаунта, а также DISCORD_TOKEN и/или TELEGRAM_TOKEN из настроек бота каждой платформы. Оба бота ниже предполагают Python 3.10 или новее.

Формат запроса соответствует стандартному формату OpenAI chat-completions, описанному в быстром старте на нескольких языках. Для работы здесь не нужен SDK.

Общее ядро: персона, лимитер и повторные попытки

Разместите опасную часть в одном месте. Приведённый модуль хранит скользящее окно временных меток запросов и ожидает, когда их количество приблизится к 240 в минуту, оставляя запас до лимита в 300 запросов в минуту на ключ. Семафор ограничивает параллельные запросы до четырёх, чтобы активный канал не отправлял двадцать запросов одновременно.

# llm.py - shared by both bots
import asyncio
import os
import time
from collections import deque

import httpx

URL = "https://api.unrestrictedaiapi.com/v1/chat/completions"
PERSONA = "You are Pip, a sardonic bar-room storyteller. Keep replies under 150 words."

_stamps = deque()            # timestamps of recent calls
_gate = asyncio.Semaphore(4) # at most 4 requests in flight
_client = httpx.AsyncClient(timeout=60.0)

async def _wait_for_slot(limit=240, window=60.0):
    # Stay below the 300 requests/minute per-key limit with headroom.
    while True:
        now = time.monotonic()
        while _stamps and now - _stamps[0] > window:
            _stamps.popleft()
        if len(_stamps) < limit:
            _stamps.append(now)
            return
        await asyncio.sleep(window - (now - _stamps[0]) + 0.05)

async def chat(history):
    """history: list of {"role","content"} dicts, oldest first."""
    messages = [{"role": "system", "content": PERSONA}] + list(history)
    async with _gate:
        for attempt in range(3):
            await _wait_for_slot()
            r = await _client.post(
                URL,
                headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
                json={"model": "uncensored", "messages": messages, "max_tokens": 400},
            )
            if r.status_code in (429, 503):
                await asyncio.sleep(2 ** attempt)
                continue
            if r.status_code == 403:
                return "I can't continue with that."
            r.raise_for_status()
            return r.json()["choices"][0]["message"]["content"]
    return "The service is busy. Try again in a moment."

Посмотрите на обработку статусов. При 429 или 503 бот делает паузу на 1, затем 2 и 4 секунды перед повторной попыткой. Код 403 означает срабатывание фильтра контента, поэтому бот отвечает нейтральной фразой, а не повторяет запрос. Любая другая ошибка вызывает исключение, которое ваша библиотека платформы запишет в лог. Если вы видите 402, значит, баланс пуст или закончился пробный период; пополните предоплаченный баланс.

Адаптер Discord

Ботам Discord необходимо включить разрешение на чтение содержимого сообщений в панели разработчика и в коде, иначе msg.content будет пустым. Бот отвечает только при упоминании, что позволяет ему не читать каждое сообщение в активном сервере.

# discord_bot.py
import os
import time
from collections import defaultdict, deque

import discord

from llm import chat

intents = discord.Intents.default()
intents.message_content = True      # also enable it in the developer portal
bot = discord.Client(intents=intents)

HISTORY_TURNS = 10                   # user+assistant messages kept per channel
history = defaultdict(lambda: deque(maxlen=HISTORY_TURNS))
last_use = {}                        # user id -> last request time
COOLDOWN = 5.0                       # seconds between requests per user

def chunks(text, size=1900):
    return [text[i:i + size] for i in range(0, len(text), size)] or [""]

@bot.event
async def on_message(msg: discord.Message):
    if msg.author.bot or bot.user not in msg.mentions:
        return
    # Age gate: guild text channels must be flagged NSFW. No DMs.
    if not isinstance(msg.channel, discord.TextChannel) or not msg.channel.is_nsfw():
        await msg.reply("I only chat in channels marked age-restricted (NSFW).")
        return
    now = time.monotonic()
    if now - last_use.get(msg.author.id, 0) < COOLDOWN:
        await msg.add_reaction("\u23f3")
        return
    last_use[msg.author.id] = now

    text = msg.clean_content.replace(f"@{bot.user.display_name}", "").strip()
    if not text:
        return
    h = history[msg.channel.id]
    h.append({"role": "user", "content": f"{msg.author.display_name}: {text}"})
    async with msg.channel.typing():
        answer = await chat(h)
    h.append({"role": "assistant", "content": answer})
    for part in chunks(answer):
        await msg.channel.send(part)

bot.run(os.environ["DISCORD_TOKEN"])

История хранится в deque с параметром maxlen=10, индексированном по ID канала, поэтому каждый канал — это отдельный диалог, а старые реплики автоматически удаляются. Префикс имени пользователя перед каждой репликой позволяет модели различать людей в общей комнате. Десять сообщений — консервативное значение по умолчанию; контекстное окно поддерживает 100 000 токенов, поэтому вы можете значительно увеличить это значение, прежде чем это станет проблемой.

Адаптер Telegram

Версия python-telegram-bot v20 и выше работает асинхронно, что естественно сочетается с общим модулем. chat_data — это словарь для каждого чата, который библиотека хранит для вас, поэтому история и состояние задержки не требуют дополнительного кода для хранения данных.

# telegram_bot.py  (python-telegram-bot v20+)
import os
import time
from collections import deque

from telegram import Update
from telegram.ext import (ApplicationBuilder, CommandHandler, ContextTypes,
                          MessageHandler, filters)

from llm import chat

async def adult(update: Update, context: ContextTypes.DEFAULT_TYPE):
    context.chat_data["adult"] = True
    await update.message.reply_text("Noted. Say something.")

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text(
        "This bot produces adult fiction. Send /adult only if you are 18 or older."
    )

async def talk(update: Update, context: ContextTypes.DEFAULT_TYPE):
    cd = context.chat_data
    if not cd.get("adult"):
        await update.message.reply_text("Send /adult to confirm you are 18+.")
        return
    if time.monotonic() - cd.get("last", 0) < 4:
        return                                   # per-chat cooldown
    cd["last"] = time.monotonic()

    h = cd.setdefault("history", deque(maxlen=10))
    h.append({"role": "user", "content": update.message.text})
    await context.bot.send_chat_action(update.effective_chat.id, "typing")
    answer = await chat(h)
    h.append({"role": "assistant", "content": answer})
    for i in range(0, len(answer), 4000):        # Telegram limit is 4096 chars
        await update.message.reply_text(answer[i:i + 4000])

app = ApplicationBuilder().token(os.environ["TELEGRAM_TOKEN"]).build()
app.add_handler(CommandHandler("start", start))
app.add_handler(CommandHandler("adult", adult))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, talk))
app.run_polling()

run_polling() — самый простой способ запуска, не требует публичного URL. Имейте в виду, что chat_data живёт в памяти, поэтому перезапуск очищает её. Если вам нужно, чтобы история сохранялась после перезапусков, сохраняйте содержимое deque самостоятельно в файл или базу данных.

Возрастная фильтрация и правило NSFW-каналов

Этот API только для взрослых, и всё, что вы на нём построите, наследует эту ответственность. Рассматривайте возрастную фильтрацию как функцию, а не как дополнение.

  • Discord: отвечайте только в каналах сервера с пометкой 18+. Проверка channel.is_nsfw() ничего не стоит, и бот откажется отвечать в других местах, включая личные сообщения.
  • Telegram: требуйте явное подтверждение /adult для каждого чата перед генерацией и укажите правило в приветственном тексте.
  • Оба: не предлагайте бота в пространствах для молодёжи и немедленно отключайте доступ, если узнаете, что пользователю меньше 18 лет.

Команда подтверждения — это пропускной барьер, а не доказательство возраста. Сексуальный контент с участием несовершеннолетних всегда блокируется API с кодом 403, включая художественную литературу и ролевые игры, и ваш бот не должен пытаться обойти эту блокировку.

Запуск и тестирование без толпы

Запустите каждый бот в отдельном терминале с помощью python discord_bot.py или python telegram_bot.py. Для первого запуска создайте приватный тестовый сервер или чат только с собой. Пройдите короткий чек-лист, и вы обнаружите почти все ошибки новичков.

  1. Упомяните бота в не-NSFW канале и подтвердите, что он отказывается отвечать. Это доказывает работу фильтра.
  2. Упомяните его в помеченном канале и отправьте два сообщения быстро. Второе должно получить реакцию с песочными часами, что доказывает работу кулдауна.
  3. Ведите четырёхрепличный разговор, затем сослайтесь на первое сообщение. Если бот помнит, история подключена правильно.
  4. Временно установите неверное значение API-ключа и подтвердите, что ошибка появляется в логах, а не исчезает бесследно.
  5. Вставьте длинный блок текста и наблюдайте, как ответ разбивается на несколько сообщений в пределах лимита длины платформы.

Если ответы кажутся шаблонными, обычно проблема в персоне, а не в коде. Измените одно предложение в PERSONA, перезапустите и сравните. Поскольку персона живёт в общем модуле, одно изменение меняет обоих ботов одновременно, что именно и оправдывает структуру с дополнительным файлом.

Когда будете готовы к развёртыванию, подойдёт любой менеджер процессов с постоянным запуском. Боты поддерживают постоянное соединение с платформой и делают короткие исходящие HTTPS-запросы к API, поэтому им не нужны входящие порты и почти не требуется память. Добавьте политику перезапуска, чтобы сбой не оставил ваше сообщество общаться с молчащим ботом.

Лимиты запросов, размер истории и стоимость

Три регулятора управляют поведением бота под нагрузкой. Задержка для каждого пользователя не позволяет одному человеку монополизировать ключ. Глобальное окно защищает потолок в 300 запросов в минуту. Семафор сглаживает пики. Если вы запускаете несколько процессов бота на одном ключе, они делят этот потолок, поэтому уменьшите значение limit для каждого процесса соответственно.

Оцените расходы перед приглашением толпы. Предположения: каждый вызов отправляет около 1 200 входных токенов (персона плюс десять реплик) и возвращает 250 токенов. Один вызов стоит 1 200 x $0,25 / 1 000 000 + 250 x $1,00 / 1 000 000 = $0,0003 + $0,00025 = $0,00055. Сервер, выдающий 2 000 ответов в день, потратит около $1,10 в день при этих предположениях. Ваши цифры будут отличаться, поэтому логируйте поле usage неделю и пересчитайте.

Чтобы настроить саму персону, прочитайте гайд по промптам. Цены указаны на странице тарифов.

Укрепление перед публикацией бота

Храните токены вне системы контроля версий; читайте их из окружения, как показано. Ограничьте длину сообщения перед отправкой в API, чтобы одно большое вставленное сообщение не сожгло ваш баланс. Логируйте ошибки, но не текст сообщений, так как пользователи справедливо ожидают конфиденциальности чатов. Добавьте команду /reset, которая очищает deque канала — это самое быстрое исправление, когда разговор уходит в сторону. Наконец, добавьте заметную запись в профиле бота, что он пишет взрослую художественную литературу и что его ответы генерируются.

Ещё один выбор дизайна заслуживает упоминания: боты ждут полного ответа, а не потоковой передачи. Редактирование сообщения токкен за токкеном упирается в лимиты редактирования платформы, а для ответов, ограниченных примерно 150 словами, ожидание короткое. Если позже захотите живую печать в своём веб-интерфейсе, включите stream: true там, где вы контролируете транспорт. До тех пор индикатор набора текста, который вы уже отправляете, — самый дешёвый способ показать, что бот работает, и это сохраняет код достаточно коротким, чтобы прочитать его за один присест и провести аудит перед приглашением кого-либо.

Вопросы и ответы

Можно ли использовать один API-ключ для нескольких ботов?

Да, но для этого ключа действует общий лимит в 300 запросов в минуту, поэтому распределите внутреннее ограничение частоты между процессами.

Запоминает ли бот разговоры после перезапуска?

В этих примерах нет; история хранится в памяти. Сохраните содержимое очереди в файл или базу данных, если вам нужна непрерывность.

Как не допустить доступ несовершеннолетних?

Ограничьте ответы в Discord каналами с пометкой 18+, потребуйте команду подтверждения в Telegram и избегайте молодёжных пространств. Это пропускной барьер, а не доказательство, поэтому реагируйте на любые жалобы быстро.

Что происходит, когда баланс исчерпан?

API возвращает 402 с кодом no_credit. Перехватите его в основном модуле и сообщите пользователям, что бот приостановлен.

Ваш ключ — в одной форме от вас

Создайте аккаунт, скопируйте ключ, измените базовый URL. Это вся настройка.

Получить API-ключ