NsfwAiApi/Kılavuz
NSFW LLM API'si Python ile: Akış, JSON ve Araçlar
Python'dan NSFW LLM API'sini kullanmak için yalnızca standart openai paketi ve iki değişiklik gerekir: base URL ve anahtar. Bu kılavuz ilk isteği, akışı, JSON modunu, fonksiyon çağırma işlemini ve hız limitlerinin temiz şekilde yönetilmesini gösterir.

Kurulum: Kurulum ve ilk çağrı
Güncel bir Python 3'e, openai paketine (pip install openai) ve bir API anahtarına ihtiyacınız var. Yeni hesaplar, giriş yaptıktan sonra tek tıkla API anahtarı sayfasında 0,50 $'lık bir deneme kredisi talep edebilir; bu işlem için ödeme bilgisi gerekmez. Anahtarı kaynak kodunda değil, bir ortam değişkeninde saklayın.
Servis OpenAI chat completions protokolünü kullanır: POST /v1/chat/completions metin üretimi için ve GET /v1/models model listesi için. Yetkilendirme bir bearer token'dır ve model kimliği uncensored şeklindedir. İşte çalışan en küçük betik:
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)
Bağlantıyı önce bir kabuktan kontrol etmeyi tercih ederseniz, aynı istek curl ile de çalışır:
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, yasal yetişkin kullanım için içerik reddi olmadan yanıt verecek şekilde ayarlanmıştır. Bu, yazacağı şeyin tonunu etkiler, ancak API'nin yapısını değil, bu nedenle kodunuzun geri kalanı diğer OpenAI entegrasyonlarına benzer. Kurgu, karakter sohbeti ve diğer yasal yetişkin projeler için istemleri saklayın ve her karakterin yetişkin olduğundan emin olun.
Birkaç alışkanlık ilk günden itibaren yardımcı olur. Asla değişmeyen talimatları sistem mesajına koyun ve her turda değişen kısım için kullanıcı mesajını koruyun. Bir görev için bir sıcaklık seçin ve istemleri karşılaştırırken dokunmayın, çünkü aynı anda iki şeyi değiştirmek size hiçbir şey öğretmez. Her çağrının yanına istek kimliğini ve resp.usage'dan token sayılarını günlüğe kaydedin, böylece faturanız veya çıktınız sizi şaşırttığında karşılaştırabileceğiniz bir kayıt olur.
SSE ile akışlı yanıtlar
stream=True ayarlayın ve sunucu token'ları sunucu tarafından gönderilen olaylar olarak gönderir. Sohbet uygulamaları için bu çok önemlidir, çünkü okuyucu tam yanıtı beklemek yerine ilk kelimeleri hızlıca görür. Toplam kullanım bilgileri akışın sonunda gelir, bu nedenle akışlı bir istek hala doğru şekilde faturalandırılabilir ve günlüğe kaydedilebilir.
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)
İki detay hata ayıklama süresinden tasarruf sağlar. İlk olarak, son parça boş bir choices listesine sahip olabilir; bu nedenle döngü indekslemeden önce listeyi kontrol eder. İkinci olarak, akışlı bir istek, akış sonlanana kadar eşzamanlılık slotunu elinde tutar; bu nedenle kodunuz bir akışı kapatmadan bırakırsa, o slot meşgul kalır. with client.chat.completions.create(..., stream=True) as stream: kullanın veya erken okumayı bırakırsanız stream.close() çağrısını yapın.
Yapılandırılmış çıktı için JSON modu
Programınız düzyazıya değil veriye ihtiyaç duyduğunda, örneğin bir karakter sayfası, bir hikaye için sahne adımlarının listesi veya etiketler gerektiğinde, response_format={"type": "json_object"} ile JSON modunu kullanın. Ayrıca istemde "JSON" yazın ve istediğiniz anahtarları tanımlayın. Ayar bir JSON nesnesi ister ancak anahtarlarınızın mevcut olacağına söz veremez; bu nedenle onları kontrol edin.
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"])
Uzun bir yanıt max_tokens tarafından kesilirse, JSON eksik olur ve json.loads başarısız olur. max_tokens'i ayarlamadan bırakın, çünkü isteğe bağlıdır ve tamamlama pencerenin geri kalanını kullanabilir; ya da cömert bir değer verin.
Araç çağırma
Araç çağırma, modelin kodunuzdan bir şey yapmasını istemesini sağlar, zar atmak, bir karakter notuna bakmak veya bir fiyatı aramak gibi. tools ve isteğe bağlı olarak tool_choice iletirsiniz. Yanıt tool_calls içerir; bunları çalıştırırsınız ve sonuçları role: "tool" ile mesaj olarak geri gönderirsiniz. Akışlı yanıtlar, delta'larda da tool_calls taşır.
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)
Bağımsız değişkenleri güvenilmeyen girdi olarak ele alın. Bir web formu için yapacağınız gibi, eyleme geçmeden önce doğrulayın. Modeller bazen eksik bir alan veya yanlış bir tür gönderir ve json.loads etrafındaki küçük bir koruma, kötü bir çağrının oturumunuzu sonlandırmasını engeller.
Hız limitleri, yeniden denemeler ve bakiyeniz
Limitler servisi korur ve öngörülebilir davranış sağlar. Tam bir anahtar 8 eşzamanlı istek ve dakikada 300 istek izni verir. Bir deneme anahtarı 2 ve 60 izin verir. Maksimum gövde boyutu 8 MB'tır. İki tür limit hatası HTTP 429 olarak döner: rate_limited kodu dakikada çok fazla istek anlamına gelir ve concurrency aynı anda çok fazla istek anlamına gelir. Geçici bir aşırı yüklenme de Retry-After: 5 başlığı ile 429 döndürür.
OpenAI SDK varsayılan olarak birkaç hatayı yeniden dener. Kontrol için bunu kapatın ve Retry-After'a saygı duyan küçük bir döngü yazın:
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)
Her yanıt X-Request-Id taşır, bu destekle iletişime geçtiğinizde alıntılamanız gereken şeydir ve X-Balance-USD kalan kredinizi gösterir. X-RateLimit-Limit-Requests ve X-RateLimit-Limit-Concurrency başlıkları anahtarınız için hangi limitlerin geçerli olduğunu söyler. Aynı anda birçok iş çalıştırmak için, eşzamanlılığı kendi kodunuzda anahtarınıza göre boyutlandırılmış bir semaforla sınırlayın, tam anahtar için 8 ve deneme anahtarı için 2, böylece nadiren 429 görürsünüz.
Paralel olarak çok sayıda istek çalıştırma
Yüzlerce hikaye parçası için etiketler oluşturma gibi toplu işler, eşzamanlılık limitlerinin önemli olduğu yerlerdir. Tam bir anahtar aynı anda 8 isteği kabul eder, bu nedenle işi bir istemci ve bu boyutta bir semaforla çalıştırın. Deneme anahtarındaysanız 2 kullanın.
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)
Semafor tüm işin sırrıdır. O olmadan 200 parçadan oluşan bir liste aynı anda 200 istek tetikler ve bunların çoğu concurrency koduyla 429 hatası olarak döner. Onunla iş, anahtarınızın izin verdiği hızda akar ve hiçbir şey boşa gitmez. Ayrıca dakika başına bir bütçe de çalıştırıyorsanız, tam bir anahtar için dakikada 300 istek, saniyede beşe denk gelir; bu nedenle çok kısa istekler, eşzamanlılık limitinden önce dakika limitine takılabilir.
Yaygın sorunlar ve çözümler
- 401 veya kimlik doğrulama hataları. Anahtar eksik, kesik veya yanlış ana bilgisayara gönderiliyor.
client.base_urlyazdırın ve ortam değişkenini kontrol edin. BaşlıkAuthorization: Bearerşeklinde olmalı ve ardından anahtarınız gelmelidir. - Model bulunamadı. Tek model kimliği
uncensored'dir. Başka bir ad söyleyen kopyalanmış bir örnek başarısız olur, bu nedenle emin değilsenizGET /v1/modelsçağrısı yapın. - Hikaye döngüsünde boş veya kısa yanıtlar. Asistan yanıtını bir sonraki tur için mesaj listesine eklediğinizden emin olun. Bu olmadan model yalnızca son mesajınızı görür.
- Kendilerini tekrarlayan yanıtlar.
frequency_penalty'i biraz artırın, örneğin 0,3'e, veya metin saparsatemperature'i düşürün.top_p,stopveseedcezaları da iletilir. - Her çalıştırmada farklı çıktı. Hata ayıklarken mümkün olduğunca tekrarlanabilir sonuçlar gerektiğinde
seedve düşük birtemperatureayarlayın. - İstek çok büyük. Gövde limiti 8 MB'tır ve istem ile tamamlama 100.000 token'a sığmalıdır. Sınırlardan birine ulaşmadan önce eski bağlamı kısaltın veya özetleyin.
Sunucu tarafında bir şeyler yanlış görünüyorsa, yanıtın X-Request-Id başlığını kaydedin ve destek sayfası bağlantısı üzerinden kısa bir açıklama ile birlikte gönderin. Bu, operatörlerin tam isteğinizi bulmasını sağlar.
Maliyeti ve yapamadığı şeyler
Fiyatlandırma, ön ödemeli kredi ile, abonelik olmadan, 1M giriş token'ı başına 0,15 $ ve 1M çıktı token'ı başına 0,50 $'dır. Başarısız veya reddedilen istekler için ücret alınmaz ve kredi asla sona ermez. Bir örnek olarak, 3.000 token gönderen ve 800 alan bir betik, giriş için 0,00045 $ ve çıktı için 0,0004 $ öder, bu da çağrı başına 0,00085 $ eder, bu nedenle 1.000 çağrı 0,85 $ eder. Yüklemeler 20 $ ile 500 $ arasında değişir, 50 $'dan itibaren +%5, 100 $'dan itibaren +%10 ve 200 $'dan itibaren +%15 bonuslar sunar. Bu site yalnızca TRC20 üzerinde USDT veya Base üzerinde USDC olarak kripto kabul eder. Tam tablo için fiyatlandırma sayfasına ve uç nokta referansı için belgelendirmeye bakın.
Sınırlar açıktır. Bağımsız bir sağlayıcı tarafından çalıştırılan tek bir açık ağırlıklı modeldir ve herhangi bir model satıcısının resmi API'si değildir. Bağlam penceresi, istem ve tamamlama için toplam 100.000 token'dır. Görsel, ses veya video üretmez, embedding sağlamaz ve ince ayarı desteklemez. Yalnızca yasal yetişkin kullanımı için kullanın ve kesin sınıra dikkat edin: reşit olmayanlar içeren cinsel içerik yoktur. İstemler eğitim için kullanılmaz.
Daha fazla kılavuz
Sorular ve cevaplar
Bu API'yi Python'dan çağırmak için özel bir SDK'ya ihtiyacınız var mı?
Hayır. Resmi openai paketi çalışır. base_url'yi https://api.nsfwaiapi.com/v1 olarak ayarlayın, anahtarınızı girin ve uncensored model kimliğini kullanın.
Akış, OpenAI ile aynı şekilde çalışıyor mu?
Evet. stream=True parametresini iletin ve sunucu tarafından gönderilen olayları parça parça okuyun. Kullanım bilgisi akışın sonunda raporlanır.
429 hatası aldığınızda ne yapmalısınız?
Bekleyin ve yeniden deneyin. Yanıtta bir Retry-After başlığı varsa, buna uyun. rate_limited hata kodu dakikada çok fazla istek anlamına gelir, concurrency ise aynı anda çok fazla istek anlamına gelir.
Ödemeden test edebilir miyim?
Evet. Kayıt olduktan sonra API anahtarı sayfasında $0.50 deneme kredisi talep edebilirsiniz. Ödeme bilgisi gerektirmez, 7 gün boyunca geçerlidir ve kişi başına bir tanedir.
Anahtarınız tek bir formun uzağında
Bir hesap oluşturun, anahtarı kopyalayın ve base URL'yi değiştirin. Kurulum bu kadar basit.
API anahtarını alNsfwAiApiNSFW metin üretimi için sansürsüz LLM API'si