TH ▾
https://api.unrestrictedaiapi.com/v1uncensored2026-10-06
รับคีย์ API

สร้างบอท Discord หรือ Telegram บน API AI แบบไม่มีข้อจำกัด

แชทบอทคือวิธีที่เร็วที่สุดในการนำโมเดลแบบไม่มีข้อจำกัดไปไว้ต่อหน้าผู้คน คู่มือนี้จะสร้างทั้งบอท discord.py และ python-telegram-bot บนโมดูลร่วมกันที่จัดการการเรียก API ดังนั้นประวัติแยกช่อง ขีดจำกัดอัตรา การลองใหม่ และการจำกัดอายุจะถูกเขียนครั้งเดียวและนำไปใช้ซ้ำได้

อัปเดต

จุดสำคัญ

  1. แยกตรรกะ API ไว้ในโมดูลเดียวและทำให้ตัวปรับแต่งแต่ละแพลตฟอร์มมีขนาดเล็ก
  2. เก็บประวัติแบบจำกัดแยกตามช่องหรือแชทเพื่อให้การสนทนาไม่ปนกัน
  3. จำกัดอัตราในสามชั้น: เว้นระยะสำหรับผู้ใช้รายบุคคล, หน้าต่างเลื่อนทั่วโลกที่จำกัดไม่เกิน 300 คำขอต่อนาที และขีดจำกัดความพร้อมใช้งาน
  4. จำกัดการใช้งานผู้ใหญ่: เฉพาะช่อง Discord ที่ทำเครื่องหมายว่า NSFW และยืนยัน /adult ชัดเจนใน Telegram

สิ่งที่เรากำลังสร้าง

บอทขนาดเล็กสองตัว ใช้สมองร่วมกัน ไฟล์ llm.py จัดการทุกสิ่งที่โต้ตอบกับ API: พรอมต์, ตัวจำกัดอัตรา, และตรรกะการเรียกซ้ำ บอท Discord และบอท Telegram ทำหน้าที่แปลงเหตุการณ์แพลตฟอร์มเป็นรายการข้อความและส่งกลับ เพิ่มแพลตฟอร์มที่สามในภายหลังและคุณเขียนเพียงตัวเชื่อมต่อ

ติดตั้ง dependencies ด้วย pip install httpx discord.py python-telegram-bot. ส่งออก API_KEY จาก หน้าบัญชีของคุณ รวมถึง DISCORD_TOKEN และ/หรือ TELEGRAM_TOKEN จากการตั้งค่าบอทของแต่ละแพลตฟอร์ม บอททั้งสองด้านล่างสมมติว่าใช้ Python 3.10 ขึ้นไป

รูปแบบคำขอคือรูปแบบ chat-completions แบบธรรมดา ซึ่งครอบคลุมใน คู่มือเริ่มต้นใช้งานหลายภาษา ไม่ต้องใช้ SDK

แกนกลางร่วมกัน: บุคลิก ตัวจำกัด และการลองใหม่

วางส่วนที่เสี่ยงในจุดเดียว โมดูลด้านล่างรักษาหน้าต่างเลื่อนของเวลาเกิดคำขอและรอเมื่อเข้าใกล้ 240 การเรียกต่อนาที ซึ่งเป็นขอบเขตที่จงใจไว้ต่ำกว่า 300 ต่อนาทีต่อคีย์ ตัวจำกัดความพร้อมใช้งานจำกัดความพร้อมใช้งานสูงสุดไว้ที่สี่ เพื่อให้ช่องที่วุ่นวายไม่สามารถยิงคำขอ 20 คำขอพร้อมกันได้

# 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 หมายถึงตัวกรองเนื้อหาทำงาน บอทจึงตอบด้วยข้อความที่เป็นกลางแทนที่จะลองใหม่ ข้อผิดพลาดอื่นจะ raise ซึ่งไลบรารีแพลตฟอร์มของคุณจะบันทึก หากเห็น 402 แสดงว่ายอดเงินหมดหรือเครดิตทดลองใช้หมด เติมยอดเงินแบบเติมเงินล่วงหน้า

ตัวปรับแต่ง Discord

บอท Discord ต้องเปิด intent เนื้อหาข้อความในพอร์ทัลผู้พัฒนาและในโค้ด มิฉะนั้น 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 ขึ้นไปเป็น async ซึ่งเข้าคู่กับโมดูลหลักได้อย่างเป็นธรรมชาติ 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: ตอบเฉพาะในช่อง guild ที่ทำเครื่องหมายว่าจำกัดอายุ การตรวจสอบ channel.is_nsfw() ไม่มีค่าใช้จ่ายและบอทจะปฏิเสธที่อื่น รวมถึงข้อความส่วนตัว
  • Telegram: ต้องมีการยืนยัน /adult ที่ชัดเจนต่อแชทก่อนการสร้างข้อความใดๆ และระบุกฎในข้อความต้อนรับ
  • ทั้งสอง: อย่าเสนอบอทในพื้นที่ที่มุ่งเป้าไปที่เยาวชน และลบการเข้าถึงทันทีหากคุณทราบว่าผู้ใช้มีอายุต่ำกว่า 18 ปี

คำสั่งยืนยันเป็นประตู ไม่ใช่การพิสูจน์อายุ เนื้อหาทางเพศที่เกี่ยวข้องกับเด็กจะถูกบล็อกโดย API เสมอด้วย 403 รวมถึงนวนิยายและบทบาทสมมติ และบอทของคุณไม่ควรพยายามหลบเลี่ยงการตอบสนองนั้น

การรันและการทดสอบโดยไม่ใช้กลุ่มใหญ่

เริ่มบอทแต่ละตัวในเทอร์มินัลของตัวเองด้วย python discord_bot.py หรือ python telegram_bot.py สำหรับการรันครั้งแรก ให้สร้างเซิร์ฟเวอร์ทดสอบส่วนตัวหรือแชทที่มีเฉพาะคุณเท่านั้น เดินผ่านรายการตรวจสอบสั้นๆ และคุณจะจับข้อบกพร่องของผู้เริ่มต้นได้เกือบทั้งหมด

  1. กล่าวถึงบอทในช่องที่ไม่ใช่ NSFW และยืนยันว่ามันปฏิเสธ สิ่งนี้พิสูจน์ว่าประตูทำงาน
  2. กล่าวถึงมันในช่องที่ทำเครื่องหมายและส่งข้อความสองข้อความอย่างรวดเร็ว ข้อความที่สองควรได้รับปฏิกิริยานาฬิกาทราย ซึ่งพิสูจน์ว่าการหน่วงเวลาทำงาน
  3. ทำการสนทนาสี่ข้อความ จากนั้นอ้างอิงกลับไปที่ข้อความแรก หากบอทจำได้ ประวัติถูกต่อสายถูกต้อง
  4. ตั้งค่าคีย์ API เป็นค่าผิดชั่วคราวและยืนยันว่าความล้มเหลวปรากฏในบันทึกของคุณแทนที่จะหายไปอย่างเงียบๆ
  5. วางบล็อกข้อความยาวและดูการตอบกลับแยกออกเป็นข้อความหลายข้อความภายใต้ขีดจำกัดความยาวของแพลตฟอร์ม

หากการตอบกลับดูทั่วไป ปัญหาอาจอยู่ที่พรอมต์มากกว่าโค้ด แก้ไขประโยคเดียวใน PERSONA รีสตาร์ท แล้วเปรียบเทียบ เนื่องจากพรอมต์อยู่ในโมดูลร่วม การแก้ไขหนึ่งครั้งจะเปลี่ยนบอททั้งสองทันที ซึ่งเป็นเหตุผลที่โครงสร้างนี้คุ้มค่ากับไฟล์เพิ่มเติม

เมื่อพร้อมที่จะใช้งาน ตัวจัดการกระบวนการแบบ always-on ใดๆ ก็ใช้ได้ บอทมีการเชื่อมต่อระยะยาวกับแพลตฟอร์มและทำ HTTPS call แบบสั้นไปยัง API จึงไม่ต้องใช้พอร์ตขาเข้าและใช้หน่วยความจำน้อยมาก เพิ่มนโยบายรีสตาร์ทเพื่อให้การ crash ไม่ทำให้ชุมชนของคุณคุยกับบอทที่เงียบ

ขีดจำกัดอัตรา ขนาดประวัติ และค่าใช้จ่าย

ปุ่มควบคุมสามตัวควบคุมพฤติกรรมของบอทภายใต้ภาระ การเว้นระยะสำหรับผู้ใช้รายบุคคลหยุดไม่ให้บุคคลหนึ่งผูกขาดคีย์ หน้าต่างทั่วโลกปกป้องเพดาน 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 คำขอต่อนาทีของคีย์นั้น ดังนั้นจึงควรแบ่งการควบคุมอัตราภายในระหว่างกระบวนการทำงาน

บอทจำการสนทนาหลังจากการรีสตาร์ทได้หรือไม่?

ไม่ในตัวอย่างเหล่านี้; ประวัติจะถูกเก็บไว้ในหน่วยความจำ หากต้องการความต่อเนื่อง ให้บันทึกข้อมูล deque ลงในไฟล์หรือฐานข้อมูล

จะป้องกันเด็กและเยาวชนได้อย่างไร?

จำกัดการตอบกลับของ Discord ให้เป็นช่องที่จำกัดอายุ กำหนดให้ยืนยันคำสั่งใน Telegram และหลีกเลี่ยงพื้นที่ที่เน้นเยาวชน เหล่านี้เป็นเพียงประตูกั้น ไม่ใช่หลักฐาน ดังนั้นจึงควรดำเนินการตามรายงานที่ได้รับอย่างรวดเร็ว

จะเกิดอะไรขึ้นเมื่อเครดิตหมด?

API ส่ง 402 พร้อมรหัส no_credit จับในโมดูลหลักแล้วแจ้งผู้ใช้ว่าบอทกำลังหยุดทำงานชั่วคราว

คีย์ของคุณอยู่ห่างแค่แบบฟอร์มเดียว

สร้างบัญชี คัดลอกคีย์ เปลี่ยน Base URL นั่นคือการตั้งค่าทั้งหมด

รับคีย์ API