Scenariusze tekstowe RPG z API LLM
Scenariusze tekstowe RPG najlepiej działają, gdy model gra narratora z zasadami, a Twój kod zarządza stanem. Ten artykuł przedstawia mały silnik w Pythonie: prompt, strumieniowanie, pamięć i szacunkowy koszt długiej sesji.

Kluczowe punkty
- Podziel pracę: model pisze historię, Twój kod przechowuje fakty, ekwipunek i zasady.
- Strumieniuj odpowiedzi i utrzymuj każdy strumień wystarczająco krótki, aby szybko zwolnić slot współbieżności.
- Okno 100,000 tokenów mieści bardzo długą sesję, ale streszczenia obniżają koszty i dryf.
- Sesja 200 tur przy 6,000 tokenach wejściowych i 400 wyjściowych na turę kosztuje około $0.22.
Zacznij od narratora, nie od fabuły
Osoby tworzące tekstowe scenariusze RPG często zaczynają od napisania fabuły. To odwrotne podejście. Scenariusz to pętla między graczem a narratorem, a narrator potrzebuje opisu zadań przed potrzebą historii. Model musi wiedzieć, kto mówi, co może decydować za gracza, jak długa powinna być odpowiedź i czego nigdy nie powinien robić. Wszystko inne można improwizować.
Dobry system prompt dla silnika scenariuszowego ma cztery części. Po pierwsze rola: mistrz gry, prowadzący wywiad, komputer pokładowy statku, postać w sztuce. Po drugie, zasady świata w kilku prostych zdaniach: ton, otoczenie, co istnieje, a czego nie ma. Po trzecie, zasady formatowania, bo twój kod może je parsować: na przykład „zakończ każdą odpowiedź jedną linią zaczynającą się od OPTIONS:". Po czwarte, granice. Interfejs API do tekstu jest tu dostrojony do odpowiadania bez odrzuceń treści dla użytku dorosłych, co sprawia, że nadaje się do mrocznej fikcji, złoczyńców z prawdziwym zagrożeniem i moralnie szarych fabuł. Nadal ma jedną twardą linię: brak treści seksualnych z udziałem nieletnich. Wpisz tę zasadę we własnych warunkach użytkowania i wymuś weryfikację wieku w swojej aplikacji, jeśli scenariusze są skierowane do dorosłych.
Utrzymuj prompt poniżej 600 słów. Długie listy zasad są często częściowo stosowane. Jeśli potrzebujesz wielu zasad, posortuj je i usuń dolną trzecią.
Działająca pętla ze strumieniowaniem
Strumieniowanie jest ważniejsze w roleplay niż w większości zastosowań. Gracz czytający historię chce, aby słowa pojawiały się, gdy model je pisze, a odpowiedź o 300 tokenach wydaje się wolniejsza niż jest, gdy spada na raz. API strumieniuje przez wydarzenia wysyłane przez serwer z stream: true, a biblioteki OpenAI SDK zajmują się parsowaniem. Endpoint jest kompatybilny z OpenAI, ID modelu to uncensored, a Base URL dla tej strony to https://api.sdxlapi.com/v1.
from openai import OpenAI
client = OpenAI(base_url="https://api.sdxlapi.com/v1", api_key="YOUR_KEY")
SYSTEM = """You are the narrator of a noir mystery set in a rainy harbour city.
Write in second person, present tense, 120 to 200 words per reply.
Never decide what the player says or does. Invent details freely, but stay
consistent with the STATE block you are given.
End every reply with one line: OPTIONS: a | b | c"""
state = {"place": "Pier 9 office", "time": "23:40", "inventory": ["brass key"], "facts": []}
history = []
def turn(player_text: str) -> str:
history.append({"role": "user", "content": player_text})
msgs = [{"role": "system", "content": SYSTEM + "\nSTATE: " + str(state)}] + history[-20:]
stream = client.chat.completions.create(
model="uncensored", messages=msgs, stream=True,
temperature=0.9, top_p=0.95, max_tokens=500,
presence_penalty=0.3,
)
reply = ""
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
piece = chunk.choices[0].delta.content
reply += piece
print(piece, end="", flush=True)
history.append({"role": "assistant", "content": reply})
return reply
turn("I check the desk drawer.")Ustawienia są dostosowane do fikcji. Temperatura około 0,8 do 1,0 daje zróżnicowaną prozę, a top_p w pobliżu 0,95 odfiltrowuje najdziwniejsze wybory słów. Mała kara za obecność zniechęca narratora do wracania do tych samych obrazów. Ustaw max_tokens, aby ograniczyć długość odpowiedzi; jest to opcjonalne, ale bez tego gadatliwy narrator może napisać znacznie więcej, niż chciałeś. Dla sceny, którą chcesz dokładnie odtworzyć podczas testowania, przekaż seed i utrzymaj inne parametry stałe.
Pozwól kodowi zarządzać faktami
Najczęstszą porażką w długim roleplay jest dryf. Klucz jest w kieszeni gracza w turze 5, a na stole w turze 40. Karczmarz został nazwany Marą, potem Martą. Model czytający 30 000 tokenów historii często to zrozumie, ale „często” to nie projekt. Trzymaj fakty w małej strukturze, którą twój program aktualizuje, i wstaw tę strukturę do każdego zapytania, tak jak robi to linia STATE powyżej.
Jak zaktualizować stan? Poproś model o raportowanie zmian po każdej turze w drugim, tanim wywołaniu używającym trybu JSON. Pierwsze wywołanie pisze historię dla gracza. Drugie czyta nową partię i zwraca tylko to, co się zmieniło.
import json
def extract_changes(passage: str) -> dict:
r = client.chat.completions.create(
model="uncensored",
response_format={"type": "json_object"},
temperature=0,
max_tokens=250,
messages=[
{"role": "system", "content":
'Read the passage. Return JSON: {"place": str|null, "inventory_add": [str], '
'"inventory_remove": [str], "new_facts": [str]}. Only report what the passage states.'},
{"role": "user", "content": passage},
],
)
return json.loads(r.choices[0].message.content)
def apply(ch: dict):
if ch.get("place"):
state["place"] = ch["place"]
for item in ch.get("inventory_add", []):
if item not in state["inventory"]:
state["inventory"].append(item)
state["inventory"] = [i for i in state["inventory"] if i not in ch.get("inventory_remove", [])]
state["facts"] = (state["facts"] + ch.get("new_facts", []))[-30:]Ogranicz listę faktów, jak robi to slice, lub blok stanu będzie rósł, aż będzie tak ciężki jak historia, którą miał zastąpić. Jeśli odpowiedź JSON nie zostanie przeanalizowana, pomiń aktualizację dla tej tury i przejdź dalej; jeden pominięty fakt jest tańszy niż awaria.
Kości, zdrowie i timery lepiej obsłużyć w zwykłym kodzie. Gdy gracz próbuje czegoś ryzykownego, rzuć w Pythonie i powiedz narratorowi wynik: „Próba gracza się nie udała”. Model pisze następnie konsekwencje. To zapobiega cichemu wygrywaniu gracza za każdym razem, co modele językowe mają tendencję do robienia.
Pamięć dla sesji trwających godziny
Okno kontekstu wynosi 100 000 tokenów, licząc prompt i uzupełnienie łącznie. Typowa odpowiedź o długości 250 tokenów plus wiadomość gracza o długości 30 tokenów to około 280 tokenów na turę, więc sama surowa historia mogłaby pomieścić setki tur. Możesz wysłać wszystko. Wielu twórców nadal tego nie robi z dwóch powodów: koszt rośnie z każdą turą, ponieważ cała historia jest rozliczana jako wejście za każdym razem, a stare szczegóły mogą odwracać uwagę modelu.
Rozsądny układ utrzymuje trzy warstwy:
- Przypięte: system prompt i blok stanu. Zawsze wysyłane.
- Podsumowanie: bieżący akapit lub dwa opisujące to, co się stało, przepisane co 10 do 15 tur krótkim wywołaniem.
- Ostatnie tury: ostatnie 10 do 20 wiadomości dosłownie, aby proza zachowała rytm.
Gdy okno ostatnich tur się wypełni, złóż najstarsze dziesięć w streszczenie i usuń je. Wywołanie streszczenia może używać niskiej temperatury i limitu 300 tokenów. Gracze rzadko zauważają kompresję, o ile imiona, obietnice i nierozwiązane zagrożenia trafią do streszczenia. Powiedz to wyraźnie w poleceniu streszczającym: „zachowaj imiona, długi, rany, otwarte pytania”.
Jeśli chcesz, aby postać zachowała stabilny głos, dodaj krótką kartę stylu w warstwie przypiętej: trzy przykładowe linie jej mowy i dwie rzeczy, których nigdy nie mówi. Krótkie przykłady kształtują ton lepiej niż przymiotniki.
Koszt sesji
Ceny to $0,15 za 1M tokenów wejściowych i $0,50 za 1M tokenów wyjściowych, z przedpłaconym kredytem i bez subskrypcji. Przeanalizuj długą sesję. Powiedzmy 200 tur, z warstwą przypiętą, podsumowaniem i ostatnimi turami dodającymi średnio 6,000 tokenów wejściowych na zapytanie i 400 tokenów wyjściowych na odpowiedź (odpowiedź fabularna plus mała część dla wywołań stanu i podsumowania).
Wejście: 200 x 6,000 = 1,200,000 tokenów, co jest 1,2 x $0,15 = $0,18. Wyjście: 200 x 400 = 80,000 tokenów, co jest 0,08 x $0,50 = $0,04. Sesja kosztuje $0,22.
Porównaj leniwą wersję, która ponownie wysyła całą surową historię. Przy turze 200 historia ma około 56,000 tokenów, a średnie wejście w całej sesji to około 28,000 tokenów na zapytanie. To 200 x 28,000 = 5,600,000 tokenów wejściowych, czyli 5,6 x $0,15 = $0,84, plus te same $0,04 za wyjście, co daje $0,88. Nadal opłacalne, ale czterokrotna faktura bez zysku w jakości. Dla aplikacji z wieloma graczami ta luka decyduje o Twojej marży.
Nieudane lub odrzucone zapytania nie są rozliczane, a kredyt nigdy nie wygasa, więc niewykorzystane środki po prostu czekają. Doładowania wynoszą od $20 do $500 w pełnych dolarach, z bonusem 5% od $50, 10% od $100 i 15% od $200. Zobacz stronę z cenami, aby zobaczyć pełną listę opcji.
Uruchamianie wielu graczy jednocześnie
Pełny klucz pozwala na 8 równoległych zapytań i 300 zapytań na minutę. Strumieniowane zapytanie zajmuje swój slot do końca strumienia, więc z 8 slotami i odpowiedziami trwającymi około dziesięciu sekund możesz obsłużyć około 48 strumieni odpowiedzi na minutę, zakładając, że nic innego nie działa. To przybliżona zasada, a nie mierzona figura, ponieważ prędkość różni się w zależności od obciążenia i długości odpowiedzi. Chodzi o to, aby to zaplanować: jeśli Twoja gra ma więcej jednoczesnych graczy niż slotów, kolejkuj zapytania na serwerze i pokaż krótki stan „narrator myśli” zamiast wysyłać wszystko naraz.
Gdy przekroczysz limit, API zwraca HTTP 429. Kod to rate_limited dla zapytań na minutę i concurrency dla zbyt wielu naraz. Tymczasowe przeciążenie daje również 429, z nagłówkiem Retry-After: 5. Proste ponowne wywołanie z oczekiwaniem tych pięciu sekund wystarczy dla gry casualowej. Przeczytaj również nagłówki odpowiedzi: X-RateLimit-Limit-Requests i X-RateLimit-Limit-Concurrency pokazują Twoje limity, a X-Balance-USD pokazuje, co zostało, co możesz wyświetlić na ekranie administracyjnym.
Nie uruchamiaj wywołania ekstrakcji stanu równolegle z następną turą gracza. Poczekaj na to, lub narrator będzie pisał na podstawie przestarzałych faktów. Dobrym kompromisem jest rozpoczęcie ekstrakcji zaraz po zakończeniu strumienia i pozwolenie graczowi na czytanie, podczas gdy działa.
Łączenie scen z Twoim potokiem obrazów
Ta witryna jest zbudowana dla ludzi, którzy używają modeli tekstu wokół przepływów pracy Stable Diffusion, a scenariusze dobrze się do tego pasują. API jest samo w sobie tylko tekstowe: nie generuje obrazów, dźwięku ani wideo. Ale narrator może napisać opis sceny, który Twój potok zamieni w prompt obrazu. Dodaj kolejne wywołanie JSON po zmianie dużej sceny, prosząc o krótki opis wizualny ustawienia z oświetleniem, nastrojem i kątem kamery, a następnie przekaż ten ciąg do dowolnego narzędzia obrazowego, którego używasz. Strona dokumentacji pokazuje kształt zapytania dla wywołań pisania promptów, a artykuł na generatorze promptów SD idzie głębiej w tym obszarze.
Aby wypróbować silnik, załóż konto i odbierz kredyt próbny. Nowi użytkownicy mogą uzyskać $0.50 kredytu próbnego jednym kliknięciem na stronie klucza API, ważnym przez 7 dni bez potrzeby podawania karty. Przy powyższych liczbach starcza to na kilka pełnych sesji. Klucze próbne są ograniczone do 2 równoległych zapytań i 60 na minutę, co wystarcza do testów solo.
Trzymaj fikcję w fikcji. Scenariusze o tematyce dla dorosłych są legalnym użyciem, gdy wszyscy zaangażowani są dorosłi; jedyną regułą, która się nie zagina, jest brak treści seksualnych z udziałem nieletnich. Prompty wysłane do API nie są używane do trenowania.
Więcej przewodników
Pytania i odpowiedzi
Czy model może wcielić się w dowolną postać lub gatunek?
To uniwersalny model tekstu, który nie odrzuca zgodnych z prawem żądań dotyczących treści dla dorosłych, więc horror, kryminał, dramat i komedia są w pełni akceptowalne. Jednym twardym limitem jest treść seksualna z udziałem nieletnich.
Jak długa może być sesja przed wyczerpaniem okna kontekstu?
Okno wynosi 100,000 tokenów dla promptu i uzupełnienia. Dzięki warstwie streszczeń możesz w praktyce znacznie przekroczyć ten limit, ponieważ starsze zwroty są kompresowane.
Czy strumieniować odpowiedzi?
Tak, dla wszystkiego, co osoba czyta na żywo. Strumieniowanie daje Ci zużycie na końcu, a strumień zajmuje jeden z Twoich slotów współbieżności do momentu zakończenia.
Czy istnieje sposób na dokładne powtórzenie sceny?
Przekaż to samo seed z identycznymi wiadomościami i ustawieniami. To pomoc do testów i nie gwarantuje identycznego wyniku bajt po bajcie.
Twój klucz jest o jeden formularz stąd
Utwórz konto, skopiuj klucz, zmień bazowy URL. To cała konfiguracja.