VI ▾
https://api.unrestrictedaiapi.com/v1uncensored2026-10-06
Lấy khóa API

Xây dựng bot Discord hoặc Telegram trên API AI không giới hạn

Bot chat là cách nhanh nhất để đưa mô hình không kiểm duyệt ra trước công chúng. Hướng dẫn này xây dựng cả bot discord.py và bot python-telegram-bot trên một mô-đun chia sẻ xử lý lệnh gọi API, vì vậy lịch sử theo kênh, giới hạn tốc độ, thử lại và cổng kiểm soát độ tuổi được viết một lần và tái sử dụng.

Cập nhật

Điểm chính

  1. Cô lập logic API trong một mô-đun và giữ cho bộ điều hợp mỗi nền tảng thật nhỏ gọn.
  2. Giữ lịch sử giới hạn riêng biệt cho mỗi kênh hoặc cuộc trò chuyện để các cuộc hội thoại không bao giờ trộn lẫn.
  3. Giảm tải theo ba lớp: thời gian chờ theo người dùng, cửa sổ trượt toàn cầu dưới 300 yêu cầu mỗi phút và giới hạn độ đồng thời.
  4. Cổng kiểm soát người trưởng thành: chỉ kênh Discord được đánh dấu NSFW và xác nhận rõ ràng /adult trên Telegram.

Những gì chúng tôi đang xây dựng

Hai bot nhỏ, một bộ não chia sẻ. Một tệp có tên llm.py chịu trách nhiệm mọi thứ liên quan đến API: nhân vật, trình giới hạn tốc độ, logic thử lại. Bot Discord và bot Telegram sau đó chỉ làm nhiệm vụ chuyển đổi sự kiện nền tảng thành danh sách tin nhắn và ngược lại. Thêm nền tảng thứ ba sau này và bạn chỉ cần viết trình kết nối.

Cài đặt các phụ thuộc với pip install httpx discord.py python-telegram-bot. Xuất API_KEY từ trang tài khoản của bạn, cùng với DISCORD_TOKEN và/hoặc TELEGRAM_TOKEN từ thiết lập bot của từng nền tảng. Cả hai bot bên dưới đều giả định Python 3.10 trở lên.

Định dạng yêu cầu là dạng chat-completions thuần của OpenAI, được trình bày trong hướng dẫn nhanh đa ngôn ngữ. Không có gì ở đây cần đến SDK.

Lõi chia sẻ: nhân vật, bộ giới hạn và thử lại

Đặt phần nguy hiểm vào một nơi. Mô-đun bên dưới duy trì cửa sổ trượt của dấu thời gian yêu cầu và chờ đợi khi nó gần đạt 240 lệnh gọi mỗi phút, một biên độ cố định dưới mức 300 yêu cầu mỗi phút cho phép cho mỗi khóa. Một semaphore giới hạn độ đồng thời ở mức bốn để một kênh bận rộn không thể kích hoạt hai mươi yêu cầu cùng một lúc.

# 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."

Xem cách xử lý trạng thái. Mã 429 hoặc 503 sẽ chờ 1, 2 rồi 4 giây và thử lại. Mã 403 có nghĩa là bộ lọc nội dung đã kích hoạt, vì vậy bot sẽ trả lời bằng một dòng trung tính thay vì thử lại. Bất kỳ lỗi nào khác sẽ được ném ra, thư viện nền tảng của bạn sẽ ghi nhật ký lỗi đó. Nếu bạn thấy mã 402, số dư của bạn đã hết hoặc thời gian dùng thử đã kết thúc; hãy nạp tiền vào số dư trả trước.

Bộ điều hợp Discord

Bot Discord cần bật ý định message-content trong cổng dành cho nhà phát triển cũng như trong mã, nếu không msg.content sẽ đến trống rỗng. Bot chỉ trả lời khi được đề cập, điều này giữ cho bot không đọc mọi tin nhắn trong một máy chủ bận rộn.

# 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"])

Lịch sử là một deque với maxlen=10 được đánh dấu theo id kênh, vì vậy mỗi kênh là một cuộc trò chuyện riêng và các lượt tin nhắn cũ sẽ tự động bị loại bỏ. Tiền tố mỗi dòng người dùng với tên hiển thị của người nói cho phép mô hình phân biệt mọi người trong một phòng chia sẻ. Mười tin nhắn là mặc định bảo thủ; cửa sổ ngữ cảnh là 100.000 token, vì vậy bạn có thể tăng nó lên rất nhiều trước khi nó trở nên quan trọng.

Bộ điều hợp Telegram

python-telegram-bot v20 trở lên là bất đồng bộ, phù hợp tự nhiên với lõi chia sẻ. chat_data là một từ điển theo cuộc trò chuyện mà thư viện duy trì cho bạn, vì vậy lịch sử và trạng thái thời gian chờ không cần mã lưu trữ bổ sung.

# 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() là cách đơn giản nhất để bắt đầu và không cần URL công khai. Hãy nhớ rằng chat_data tồn tại trong bộ nhớ, vì vậy một lần khởi động lại sẽ xóa nó. Nếu bạn cần lịch sử tồn tại sau khi khởi động lại, hãy lưu nội dung deque của riêng bạn vào tệp hoặc cơ sở dữ liệu.

Kiểm soát độ tuổi và quy tắc kênh NSFW

API này chỉ dành cho người trưởng thành, và mọi thứ bạn xây dựng trên đó đều thừa hưởng trách nhiệm đó. Hãy xem kiểm soát độ tuổi là một tính năng, không phải suy nghĩ sau.

  • Discord: chỉ trả lời trong các kênh guild được đánh dấu là giới hạn độ tuổi. Kiểm tra channel.is_nsfw() không tốn gì và bot từ chối ở những nơi khác, bao gồm cả tin nhắn trực tiếp.
  • Telegram: yêu cầu xác nhận rõ ràng /adult cho mỗi cuộc trò chuyện trước khi tạo nội dung, và nêu rõ quy tắc trong văn bản chào mừng.
  • Cả hai: không cung cấp bot trong các không gian hướng đến giới trẻ và thu hồi quyền truy cập ngay lập tức nếu bạn biết người dùng dưới 18 tuổi.

Lệnh xác nhận là một cổng kiểm soát, không phải bằng chứng về độ tuổi. Nội dung khiêu dâm liên quan đến trẻ vị thành niên luôn bị API chặn bằng mã 403, bao gồm cả tiểu thuyết và nhập vai, và bot của bạn không bao giờ nên cố gắng vượt qua phản hồi đó.

Chạy và kiểm tra mà không cần đám đông

Khởi động mỗi bot trong một terminal riêng với python discord_bot.py hoặc python telegram_bot.py. Đối với lần chạy đầu tiên, hãy tạo máy chủ kiểm tra riêng hoặc một cuộc trò chuyện chỉ có bạn. Đi qua một danh sách kiểm tra ngắn và bạn sẽ bắt được hầu hết các lỗi cơ bản.

  1. Đề cập đến bot trong một kênh không phải NSFW và xác nhận rằng nó từ chối. Điều này chứng minh cổng hoạt động.
  2. Đề cập đến nó trong một kênh được đánh dấu và gửi hai tin nhắn nhanh chóng. Tin nhắn thứ hai nên nhận được phản ứng đồng hồ cát, điều này chứng minh thời gian chờ hoạt động.
  3. Hãy giữ một cuộc trò chuyện bốn tin nhắn, sau đó tham khảo lại tin nhắn đầu tiên. Nếu bot ghi nhớ, lịch sử đã được kết nối đúng cách.
  4. Tạm thời đặt khóa API thành một giá trị sai và xác nhận lỗi xuất hiện trong nhật ký của bạn thay vì biến mất một cách im lặng.
  5. Dán một khối văn bản dài và xem phản hồi được chia thành nhiều tin nhắn dưới giới hạn độ dài của nền tảng.

Nếu các phản hồi có vẻ chung chung, nhân vật thường là vấn đề chứ không phải mã. Thay đổi một câu của PERSONA, khởi động lại và so sánh. Vì nhân vật sống trong mô-đun chia sẻ, một lần chỉnh sửa sẽ thay đổi cả hai bot cùng lúc, đó chính là lý do tại sao cấu trúc này đáng giá hơn một tệp bổ sung.

Khi bạn sẵn sàng triển khai, bất kỳ trình quản lý tiến trình luôn chạy nào cũng được. Các bot giữ kết nối dài hạn với nền tảng của chúng và thực hiện các lệnh gọi HTTPS ngắn đến API, vì vậy chúng không cần cổng vào và hầu như không tốn bộ nhớ. Thêm chính sách khởi động lại để một lần sập không khiến cộng đồng của bạn nói chuyện với một bot im lặng.

Giới hạn tốc độ, kích thước lịch sử và chi phí

Ba nút điều khiển cách bot hoạt động dưới tải. Thời gian chờ theo người dùng ngăn một người chiếm độc quyền khóa. Cửa sổ toàn bộ bảo vệ trần 300 yêu cầu mỗi phút. Semaphore làm mượt các đợt bùng nổ. Nếu bạn chạy nhiều tiến trình bot trên một khóa, chúng chia sẻ trần đó, vì vậy hãy giảm limit của mỗi tiến trình tương ứng.

Ước tính chi tiêu trước khi mời đám đông. Giả định: mỗi lệnh gọi gửi khoảng 1.200 token đầu vào (nhân vật cộng mười lượt) và trả về 250 token. Một lệnh gọi tốn 1.200 x $0,25 / 1.000.000 + 250 x $1,00 / 1.000.000 = $0,0003 + $0,00025 = $0,00055. Máy chủ tạo ra 2.000 phản hồi mỗi ngày sẽ chi khoảng $1,10 mỗi ngày theo những giả định đó. Số liệu của bạn sẽ khác, vì vậy hãy ghi nhật ký trường usage trong một tuần và tính toán lại.

Để tinh chỉnh chính nhân vật, hãy đọc hướng dẫn prompt. Giá được liệt kê trên trang giá cả.

Tăng cường độ cứng trước khi chia sẻ bot

Giữ token ra khỏi kiểm soát nguồn; đọc chúng từ môi trường như đã hiển thị. Giới hạn độ dài tin nhắn trước khi gửi nó đến API để một bản dán khổng lồ không thể đốt cháy số dư của bạn. Ghi nhật ký lỗi nhưng không ghi văn bản tin nhắn, vì người dùng của bạn sẽ mong đợi hợp lý rằng các cuộc trò chuyện của họ sẽ được giữ bí mật. Thêm lệnh /reset xóa deque của kênh, đây là cách sửa chữa nhanh nhất khi một cuộc trò chuyện đi chệch hướng. Cuối cùng, đặt một ghi chú rõ ràng trong hồ sơ bot nói rằng nó viết tiểu thuyết người lớn và các phản hồi của nó được tạo ra.

Một lựa chọn thiết kế khác xứng đáng một câu: các bot chờ phản hồi đầy đủ thay vì truyền phát nó. Chỉnh sửa tin nhắn trò chuyện từng token chạy thẳng vào giới hạn chỉnh sửa nền tảng và đối với các phản ứng được giới hạn gần 150 từ, thời gian chờ là ngắn. Nếu sau này bạn muốn gõ trực tiếp trong giao diện web của riêng mình, hãy bật stream: true ở đó, nơi bạn kiểm soát phương tiện truyền tải. Cho đến lúc đó, chỉ báo đang nhập bạn đã gửi là cách rẻ nhất để cho bot hoạt động và nó giữ cho mã ngắn đủ để đọc trong một lần và kiểm toán trước khi mời bất cứ ai vào.

Hỏi đáp

Một khóa API có thể dùng cho nhiều bot không?

Có, nhưng chúng chia sẻ giới hạn 300 yêu cầu mỗi phút cho khóa đó, vì vậy bạn hãy chia sẻ bộ điều tiết nội bộ giữa các tiến trình.

Bot có nhớ cuộc hội thoại sau khi khởi động lại không?

Không trong các ví dụ này; lịch sử được lưu trong bộ nhớ. Bạn hãy lưu nội dung deque vào tệp hoặc cơ sở dữ liệu nếu cần tính liên tục.

Làm thế nào để ngăn trẻ vị thành niên truy cập?

Bạn hãy hạn chế phản hồi Discord chỉ ở các kênh dành cho người trưởng thành, yêu cầu lệnh xác nhận trên Telegram và tránh các không gian hướng đến giới trẻ. Đây là các cổng kiểm soát, không phải bằng chứng chắc chắn, vì vậy bạn hãy xử lý nhanh bất kỳ báo cáo nào.

Điều gì xảy ra khi số dư hết?

API trả về 402 với mã no_credit. Bạn hãy bắt lỗi này trong mô-đun cốt lõi và thông báo cho người dùng rằng bot đang tạm dừng.

Khóa của bạn chỉ cách một biểu mẫu

Tạo tài khoản, sao chép khóa, thay đổi base URL. Đó là toàn bộ quá trình thiết lập.

Lấy khóa API