NsfwAiApi/指南
Python 版 NSFW LLM API:串流輸出、JSON 與工具
若要採用 Python 風格的 nsfw llm api 呼叫方式,你只需要標準的 openai 套件以及兩項變更:base URL 與金鑰。本指南將展示首次請求、串流輸出、JSON 模式、工具呼叫以及速率限制的清晰處理方式。

設定:安裝並進行首次呼叫
你需要當前的 Python 3、openai 套件(pip install openai)以及 API 金鑰。新帳戶可在註冊後一鍵於 API 金鑰頁面 領取 $0.50 試用額度;該試用無需付款資訊。請將金鑰存放在環境變數中,而非原始碼內。
該服務採用 OpenAI 聊天完成協定:POST /v1/chat/completions 用於生成,GET /v1/models 用於取得模型列表。驗證方式為 bearer token,模型 ID 為 uncensored。這是能運行的最小腳本:
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)
如果你希望先從 Shell 檢查連線,相同的請求也可使用 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."}]}'
該模型經過調整,在合法成人用途下不會拒絕內容(即不會拒絕回答)。這會影響其撰寫的語氣,但不會改變 API 的結構,因此你的程式碼看起來與其他 OpenAI 整合並無二致。請保留用於小說、角色聊天及其他合法成人專案的提示詞,並維持每個角色都是成年人的狀態。
從第一天開始養成好習慣。將永不變更的指示放在系統訊息中,並將使用者訊息保留給每次輪替時會變化的部分。為特定任務選擇一個 temperature 值,並在比較提示詞時保持不變,因為同時變更兩件事無法讓你學到東西。記錄每次呼叫的請求 ID 與 resp.usage 中的 token 計數,這樣當帳單或輸出令你驚訝時,就有記錄可供查核。
使用 SSE 串流回覆
設定 stream=True,伺服器會以伺服器發送的事件(SSE)傳送 token。對於聊天應用程式而言這很重要,因為讀者能很快看到第一個字,而不必等待完整回覆。總用量會在串流結束時到達,因此串流請求仍可準確計費與記錄。
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)
兩個細節可節省除錯時間。首先,最後一個區塊可能包含空的 choices 列表,這就是迴圈在索引前檢查它的原因。其次,串流請求會佔用其並行槽位直到串流結束,因此如果你的程式碼在未關閉的情況下放棄串流,該槽位仍會保持忙碌。使用 with client.chat.completions.create(..., stream=True) as stream: 或在提早停止讀取時呼叫 stream.close()。
用於結構化輸出的 JSON 模式
當你的程式需要資料而非散文時,例如角色表、場景節奏列表或故事標籤,請使用 JSON 模式並設定 response_format={"type": "json_object"}。同時在提示詞中說明「JSON」並描述你需要的鍵。此設定要求 JSON 物件,但無法保證你的鍵會存在,因此請檢查它們。
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"])
如果長回答被 max_tokens 截斷,JSON 將不完整且 json.loads 會失敗。將 max_tokens 保持未設定狀態,因為它是可選的,且完成生成可以使用剩餘的視窗,或者將其設為較大的值。
函式呼叫
工具呼叫讓模型要求你的程式執行某些動作,例如擲骰子、查詢角色備註或取得價格。你傳入 tools,如果需要也可傳入 tool_choice。回覆包含 tool_calls;你執行它們並將結果以 role: "tool" 訊息傳回。串流回應也在增量中攜帶 tool_calls。
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)
將引數視為不受信任的輸入。在根據它們執行動作之前先進行驗證,就像處理網頁表單一樣。模型有時會遺漏欄位或傳送錯誤的類型,而在 json.loads 周圍加上小保護措施,可防止一次錯誤呼叫導致你的會話結束。
速率限制、重試與你的餘額
限制保護服務並提供可預測的行為。完整金鑰允許 8 個並行請求和每分鐘 300 個請求。試用金鑰允許 2 個和 60 個。最大主體為 8 MB。兩種限制錯誤以 HTTP 429 回傳:程式碼 rate_limited 表示每分鐘請求過多,concurrency 表示同時請求過多。暫時過載也會回傳 429,並帶有 Retry-After: 5 標頭。
OpenAI SDK 預設會重試一些錯誤。為了控制,請關閉該功能並撰寫一個小迴圈以尊重 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)
每個回應都帶有 X-Request-Id,這是你在聯絡支援時引用的內容,以及 X-Balance-USD,顯示你剩餘的額度。X-RateLimit-Limit-Requests 和 X-RateLimit-Limit-Concurrency 標頭告訴你哪些限制適用於你的金鑰。要同時執行許多工作,請在你的程式碼中使用訊號量來限制並行度,其大小應對應你的金鑰限制(完整金鑰為 8,試用金鑰為 2),這樣你幾乎不會看到 429。
並行執行許多請求
批次工作(例如為幾百個故事片段生成標籤)是並行限制發揮作用的地方。完整金鑰一次接受 8 個請求,因此請透過非同步客戶端和該大小的訊號量來執行工作。如果你使用的是試用金鑰,請使用 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)
訊號量是整個訣竅。沒有它,200 個片段的列表會同時發出 200 個請求,其中大多數會以程式碼為 concurrency 的 429 錯誤回傳。有了它,工作會以你的金鑰允許的速度流動,且不會浪費。如果你還執行每分鐘的速率限制,完整金鑰每分鐘 300 個請求相當於每秒五個,因此非常短的請求可能會在達到並行限制之前觸及每分鐘限制。
常見問題與解決方案
- 401 或驗證錯誤。 金鑰遺失、截斷或傳送至錯誤的主機。列印
client.base_url並檢查環境變數。標頭必須讀取Authorization: Bearer後接你的金鑰。 - 找不到模型。 唯一的模型 ID 是
uncensored。複製的範例如果指定其他名稱會失敗,因此如果你不確定,請呼叫GET /v1/models。 - 故事迴圈中的空回應或短回應。 檢查你是否在下一輪之前將助手回覆附加到訊息列表中。沒有它,模型只能看到你的最後一條訊息。
- 重複的回覆。 稍微提高
frequency_penalty,例如設為 0.3,或在文字漂移時降低temperature。懲罰值top_p、stop和seed都會通過。 - 每次執行輸出不同。 設定
seed和低temperature,以便在除錯時獲得盡可能可重複的結果。 - 請求太大。 主體限制為 8 MB,提示詞加上完成必須符合 100,000 token。在達到任一限制之前,請修剪或摘要舊的上下文。
當伺服器端看起來有問題時,請儲存回應中的 X-Request-Id 標頭,並將其與簡短描述一起發送到 支援頁面 聯絡方式。這讓操作員可以找到你的確切請求。
費用與限制
定價為每 1M 輸入 token $0.15,每 1M 輸出 token $0.50,從預付額度扣除,無訂閱。失敗或被拒絕的請求不會收費,且額度永不過期。作為一個實例,一個發送 3,000 token 並接收 800 token 的腳本,輸入需支付 $0.00045,輸出需支付 $0.0004,每次呼叫共 $0.00085,因此 1,000 次呼叫成本為 $0.85。儲值範圍從 $20 到 $500,紅利為:$50 起 +5%,$100 起 +10%,$200 起 +15%。本站僅接受加密貨幣,即 TRC20 上的 USDT 或 Base 上的 USDC。請參閱 定價頁面 查看完整表格,並參閱 文件 查看端點參考。
界限很明確。這是一個單一開放權重模型,由獨立供應商運行,並非任何模型廠商的官方 API。上下文視窗為 100,000 token(包含提示詞與完成)。它不生成圖像、音訊或影片,不提供嵌入,也不支援微調。僅用於合法成人用途,並注意硬性限制:不含涉及未成年人的性內容。提示詞不用於訓練。
更多指南
問答
從 Python 呼叫此 API 需要特殊 SDK 嗎?
不需要。官方 openai 套件即可運作。將 base_url 設為 https://api.nsfwaiapi.com/v1,傳入你的金鑰,並使用模型 ID uncensored。
串流運作方式與 OpenAI 相同嗎?
是的。傳入 stream=True 並逐區塊讀取伺服器發送的事件。用量會在串流結束時回報。
收到 429 錯誤時該怎麼辦?
等待並重試。如果回應包含 Retry-After 標頭,請遵守該指示。錯誤程式碼 rate_limited 表示每分鐘請求過多,concurrency 表示同時請求過多。
我可以免費測試嗎?
是的。完成註冊後,你可以在 API 金鑰頁面領取 $0.50 的試用額度。無需提供付款資訊,有效期為 7 天,每人限領一次。