NsfwAiApi/Panduan
API LLM NSFW di Python: Streaming, JSON, dan Alat
Untuk menggunakan API LLM NSFW dari Python, Anda hanya memerlukan paket openai standar dan dua perubahan: URL dasar dan kunci. Panduan ini menunjukkan permintaan pertama, streaming, mode JSON, pemanggilan alat, dan penanganan batas laju yang bersih.

Persiapan: instal dan buat panggilan pertama
Anda memerlukan Python 3 saat ini, paket openai (pip install openai) dan kunci API. Akun baru dapat mengklaim uji coba senilai $0,50 di halaman kunci API dengan satu klik setelah sign-up; tidak memerlukan detail pembayaran. Simpan kunci dalam variabel lingkungan, bukan dalam kode sumber.
Layanan ini menggunakan protokol penyelesaian obrolan OpenAI: POST /v1/chat/completions untuk generasi dan GET /v1/models untuk daftar model. Autentikasi adalah token bearer, dan ID model adalah uncensored. Ini adalah skrip kerja terkecil:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.nsfwaiapi.com/v1",
api_key=os.environ["NSFWAIAPI_KEY"],
)
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "You are a fiction co-writer for adult readers. Write vivid, non-explicit scenes."},
{"role": "user", "content": "Open a noir story in a rainy harbor town, three sentences."},
],
temperature=0.8,
)
print(resp.choices[0].message.content)
print(resp.usage)
Jika Anda lebih suka memeriksa koneksi dari shell terlebih dahulu, permintaan yang sama berfungsi dengan curl:
curl https://api.nsfwaiapi.com/v1/chat/completions \
-H "Authorization: Bearer $NSFWAIAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "uncensored", "messages": [{"role": "user", "content": "Say hello in five words."}]}'
Model ini disesuaikan untuk menjawab tanpa penolakan konten untuk penggunaan dewasa yang sah. Hal itu memengaruhi nada tulisan yang akan dihasilkan, bukan bentuk API, sehingga sisa kode Anda terlihat seperti integrasi OpenAI lainnya. Simpan prompt untuk fiksi, obrolan karakter, dan proyek dewasa lain yang sah, dan pastikan setiap karakter adalah orang dewasa.
Beberapa kebiasaan membantu sejak hari pertama. Masukkan instruksi yang tidak pernah berubah dalam pesan sistem, dan simpan pesan pengguna untuk bagian yang berubah setiap giliran. Pilih satu suhu untuk tugas dan biarkan saja saat Anda membandingkan prompt, karena mengubah dua hal sekaligus tidak mengajarkan apa pun. Catat ID permintaan dan jumlah token dari resp.usage di samping setiap panggilan, sehingga ketika tagihan atau output Anda mengejutkan Anda, ada catatan untuk diperiksa.
Balasan streaming dengan SSE
Atur stream=True dan server mengirim token sebagai event yang dikirim server. Untuk aplikasi obrolan, ini sangat penting karena pembaca melihat kata-kata pertama dengan cepat daripada menunggu balasan lengkap. Total penggunaan tiba di akhir stream, sehingga permintaan yang dialirkan masih dapat ditagih dan dicatat secara akurat.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.nsfwaiapi.com/v1",
api_key=os.environ["NSFWAIAPI_KEY"],
)
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Write a short scene: two rival smugglers share a lantern during a storm."}],
stream=True,
)
text = ""
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
piece = chunk.choices[0].delta.content
text += piece
print(piece, end="", flush=True)
usage = getattr(chunk, "usage", None)
if usage:
print("\n[usage]", usage)
Dua detail menghemat waktu debugging. Pertama, chunk terakhir dapat memiliki daftar choices kosong, itulah sebabnya loop memeriksanya sebelum pengindeksan. Kedua, permintaan yang dialirkan memegang slot konkurensinya hingga stream berakhir, sehingga jika kode Anda meninggalkan stream tanpa menutupnya, slot itu tetap sibuk. Gunakan with client.chat.completions.create(..., stream=True) as stream: atau panggil stream.close() saat Anda berhenti membaca lebih awal.
Mode JSON untuk output terstruktur
Ketika program Anda memerlukan data dan bukan prosa, seperti lembar karakter, daftar ketukan adegan, atau tag untuk cerita, gunakan mode JSON dengan response_format={"type": "json_object"}. Juga katakan "JSON" dalam prompt dan jelaskan kunci yang Anda inginkan. Pengaturan meminta objek JSON, tetapi tidak dapat berjanji bahwa kunci Anda ada, jadi periksa mereka.
import json
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.nsfwaiapi.com/v1",
api_key=os.environ["NSFWAIAPI_KEY"],
)
resp = client.chat.completions.create(
model="uncensored",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Reply with a JSON object with keys: name, age, goal, secret. All characters are adults."},
{"role": "user", "content": "Create a ship's cook for a pirate adventure."},
],
temperature=0.7,
)
sheet = json.loads(resp.choices[0].message.content)
missing = [k for k in ("name", "age", "goal", "secret") if k not in sheet]
if missing:
raise ValueError(f"model skipped keys: {missing}")
print(sheet["name"], "-", sheet["goal"])
Jika jawaban panjang terpotong oleh max_tokens, JSON akan tidak lengkap dan json.loads akan gagal. Biarkan max_tokens tidak diatur, karena opsional dan penyelesaian dapat menggunakan sisa jendela, atau atur dengan murah hati.
Pemanggilan alat
Pemanggilan alat memungkinkan model meminta kode Anda melakukan sesuatu, seperti melempar dadu, mencari catatan karakter, atau mengambil harga. Anda meneruskan tools dan, jika Anda mau, tool_choice. Balasan berisi tool_calls; Anda menjalankannya dan mengirim hasilnya kembali sebagai pesan dengan role: "tool". Respons yang dialirkan membawa tool_calls dalam delta juga.
import json
import os
import random
from openai import OpenAI
client = OpenAI(
base_url="https://api.nsfwaiapi.com/v1",
api_key=os.environ["NSFWAIAPI_KEY"],
)
tools = [{
"type": "function",
"function": {
"name": "roll_die",
"description": "Roll one die with the given number of sides",
"parameters": {
"type": "object",
"properties": {"sides": {"type": "integer", "minimum": 2}},
"required": ["sides"],
},
},
}]
messages = [
{"role": "system", "content": "You run a tabletop fiction game. Use roll_die for any chance-based outcome."},
{"role": "user", "content": "I try to pick the lock on the captain's cabin. Roll a d20."},
]
first = client.chat.completions.create(
model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)
msg = first.choices[0].message
if msg.tool_calls:
messages.append(msg)
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = random.randint(1, args["sides"])
messages.append({"role": "tool", "tool_call_id": call.id, "content": str(result)})
final = client.chat.completions.create(
model="uncensored", messages=messages, tools=tools
)
print(final.choices[0].message.content)
else:
print(msg.content)
Perlakukan argumen sebagai input yang tidak dapat dipercaya. Validasi sebelum Anda bertindak, persis seperti yang Anda lakukan untuk formulir web. Model terkadang mengirim bidang yang hilang atau tipe yang salah, dan pengaman kecil di sekitar json.loads menjaga satu panggilan buruk dari mengakhiri sesi Anda.
Batas laju, percobaan ulang, dan saldo Anda
Batas melindungi layanan dan memberikan perilaku yang dapat diprediksi. Kunci penuh memungkinkan 8 permintaan konkuren dan 300 permintaan per menit. Kunci uji coba memungkinkan 2 dan 60. Ukuran body maksimum adalah 8 MB. Dua jenis kesalahan batas kembali sebagai HTTP 429: kode rate_limited berarti terlalu banyak permintaan per menit, dan concurrency berarti terlalu banyak sekaligus. Beban berlebih sementara juga mengembalikan 429, dengan header Retry-After: 5.
SDK OpenAI mencoba kembali beberapa kesalahan secara default. Untuk kontrol, matikan itu dan tulis loop kecil yang menghormati Retry-After:
import os
import time
from openai import OpenAI, RateLimitError
client = OpenAI(
base_url="https://api.nsfwaiapi.com/v1",
api_key=os.environ["NSFWAIAPI_KEY"],
max_retries=0,
)
def ask(messages, tries=5):
for attempt in range(tries):
try:
raw = client.chat.completions.with_raw_response.create(
model="uncensored", messages=messages
)
print("balance:", raw.headers.get("X-Balance-USD"), "request id:", raw.headers.get("X-Request-Id"))
return raw.parse()
except RateLimitError as err:
wait = float(err.response.headers.get("Retry-After", 2 ** attempt))
time.sleep(wait)
raise RuntimeError("still rate limited after retries")
reply = ask([{"role": "user", "content": "Describe a market at dawn in two sentences."}])
print(reply.choices[0].message.content)
Setiap respons membawa X-Request-Id, yang merupakan yang Anda kutip jika menghubungi dukungan, dan X-Balance-USD, yang menunjukkan sisa kredit Anda. Header X-RateLimit-Limit-Requests dan X-RateLimit-Limit-Concurrency memberi tahu Anda batas mana yang berlaku untuk kunci Anda. Untuk menjalankan banyak pekerjaan sekaligus, batasi paralelisme dalam kode Anda sendiri dengan semaphore yang ukurannya disesuaikan dengan kunci Anda, 8 untuk kunci penuh dan 2 untuk kunci uji coba, sehingga Anda jarang melihat 429 sama sekali.
Menjalankan banyak permintaan secara paralel
Pekerjaan batch, seperti menghasilkan tag untuk beberapa ratus fragmen cerita, adalah di mana batas konkurensi penting. Kunci penuh menerima 8 permintaan sekaligus, jadi jalankan pekerjaan melalui klien asinkron dan semaphore berukuran itu. Jika Anda menggunakan kunci uji coba, gunakan 2.
import asyncio
import os
from openai import AsyncOpenAI
client = AsyncOpenAI(
base_url="https://api.nsfwaiapi.com/v1",
api_key=os.environ["NSFWAIAPI_KEY"],
)
gate = asyncio.Semaphore(8)
async def summarize(fragment):
async with gate:
resp = await client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "Summarize the passage in one sentence."},
{"role": "user", "content": fragment},
],
temperature=0.3,
)
return resp.choices[0].message.content
async def main(fragments):
return await asyncio.gather(*(summarize(f) for f in fragments))
results = asyncio.run(main(["The tide came in early.", "Marta hid the ledger under the floor."]))
print(results)
Semaphore adalah trik utamanya. Tanpanya, daftar 200 fragmen memicu 200 permintaan bersama-sama, dan sebagian besar dari mereka kembali sebagai error 429 dengan kode concurrency. Dengan itu, pekerjaan mengalir dengan kecepatan yang memungkinkan kunci Anda dan tidak ada yang terbuang. Jika Anda juga menjalankan anggaran per menit, 300 permintaan per menit pada kunci penuh setara dengan lima per detik, sehingga permintaan yang sangat pendek dapat mencapai batas per menit sebelum batas konkurensi.
Masalah umum dan perbaikan
- 401 atau kesalahan autentikasi. Kunci hilang, terpotong, atau dikirim ke host yang salah. Cetak
client.base_urldan periksa variabel lingkungan. Header harus membacaAuthorization: Bearerdiikuti oleh kunci Anda. - Model tidak ditemukan. Satu-satunya ID model adalah
uncensored. Contoh yang disalin yang mengatakan nama lain akan gagal, jadi panggilGET /v1/modelsjika Anda tidak yakin. - Balasan kosong atau pendek dalam loop cerita. Periksa apakah Anda menambahkan balasan asisten ke daftar pesan sebelum giliran berikutnya. Tanpanya, model hanya melihat pesan terakhir Anda.
- Balasan yang mengulangi diri sendiri. Naikkan
frequency_penaltysedikit, misalnya menjadi 0,3, atau turunkantemperaturejika teks menyimpang. Penalti,top_p,stopdanseedsemuanya diteruskan. - Output berbeda setiap dijalankan. Atur
seeddantemperaturerendah saat Anda memerlukan hasil yang dapat diulang sebanyak mungkin saat Anda melakukan debugging. - Permintaan terlalu besar. Batas ukuran body adalah 8 MB, dan prompt plus penyelesaian harus muat dalam 100.000 token. Potong atau ringkas konteks lama sebelum mencapai batas tersebut.
Ketika sesuatu terlihat salah di sisi server, simpan header X-Request-Id dari respons dan kirimkan ke halaman kontak dukungan bersama dengan deskripsi singkat. Ini memungkinkan operator menemukan permintaan tepat Anda.
Biayanya dan apa yang tidak dapat dilakukan
Harga adalah $0.15 per 1 juta token input dan $0.50 per 1 juta token output, dari saldo prabayar tanpa langganan. Permintaan yang gagal atau ditolak tidak dikenakan biaya, dan saldo tidak pernah kedaluwarsa. Sebagai contoh perhitungan, skrip yang mengirim 3.000 token dan menerima 800 membayar $0.00045 untuk input ditambah $0.0004 untuk output, yaitu $0.00085 per panggilan, sehingga 1.000 panggilan menghabiskan $0.85. Top up dimulai dari $20 hingga $500, dengan bonus +5% dari $50, +10% dari $100, dan +15% dari $200. Situs ini hanya menerima kripto, yaitu USDT pada jaringan TRC20 atau USDC pada jaringan Base. Lihat halaman harga untuk tabel lengkap, dan dokumentasi untuk referensi endpoint.
Batasannya jelas. Ini adalah satu model bobot terbuka, dijalankan oleh penyedia independen, dan bukan API resmi dari vendor model mana pun. Jendela konteksnya adalah 100.000 token untuk prompt ditambah completion. Model ini tidak menghasilkan gambar, audio, atau video, tidak menyediakan embedding, dan tidak mendukung fine-tuning. Gunakan hanya untuk penggunaan dewasa yang sah, dan perhatikan batas kerasnya: tidak ada konten seksual yang melibatkan anak di bawah umur. Prompt tidak digunakan untuk pelatihan.
Panduan lainnya
Tanya jawab
Apakah Anda memerlukan SDK khusus untuk memanggil API ini dari Python?
Tidak. Paket openai resmi berfungsi. Atur base_url ke https://api.nsfwaiapi.com/v1, masukkan kunci Anda, dan gunakan ID model uncensored.
Apakah streaming bekerja sama seperti dengan OpenAI?
Ya. Teruskan stream=True dan baca event yang dikirim server secara bertahap. Penggunaan dilaporkan di akhir stream.
Apa yang harus dilakukan jika mendapatkan error 429?
Tunggu dan coba lagi. Jika respons memiliki header Retry-After, hormati header tersebut. Kode error rate_limited berarti terlalu banyak permintaan per menit, dan concurrency berarti terlalu banyak permintaan sekaligus.
Bisakah Anda mengujinya tanpa membayar?
Ya. Setelah sign-up, Anda dapat mengklaim kredit uji coba senilai $0,50 di halaman kunci API. Tidak memerlukan detail pembayaran, berlaku selama 7 hari, dan hanya satu per orang.
Kunci Anda hanya selangkah lagi dari satu formulir
Buat akun, salin kunci, ubah URL dasar. Itu saja seluruh proses pengaturannya.
Dapatkan kunci APINsfwAiApiAPI LLM Tanpa Sensor untuk Pembuatan Teks NSFW