LLM API ile Metin Tabanlı Rol Yapma Senaryoları
Rol yapma metin tabanlı senaryolar, model kuralları olan bir anlatıcıyı oynadığında ve kodunuz durumu yönettiğinde en iyi şekilde çalışır. Bu makale Python'da küçük bir motoru inceler: istem, akış, hafıza ve uzun bir oturum için maliyet tahmini.

Temel noktalar
- İşi bölün: model hikayeyi yazar, kodunuz gerçekleri, envanteri ve kuralları saklar.
- Yanıtları akış olarak gönderin ve her akışı, eşzamanlılık slotunu hızlıca serbest bırakacak kadar kısa tutun.
- 100.000 token'lık bir pencere çok uzun bir oturumu tutar, ancak özetler maliyeti ve bağlam kaymasını düşürür.
- Her dönüşte 6.000 giriş ve 400 çıkış token ile 200 dönüşlü bir oturum yaklaşık $0,22 tutar.
Hikayeden değil, anlatıcı ile başlayın
Rol yapma metin tabanlı senaryoları oluşturan kişiler genellikle bir hikaye kurgusu yazarak başlarlar. Bu tersidir. Bir senaryo, bir oyuncu ile bir anlatıcı arasındaki bir döngüdür ve anlatıcının bir hikayeye ihtiyaç duymadan önce bir iş tanımına ihtiyacı vardır. Modelin kimin konuştuğunu, oyuncu adına neye karar verebileceğini, bir yanıtın ne kadar uzun olması gerektiğini ve asla ne yapmaması gerektiğini bilmesi gerekir. Geri kalan her şey improvisasyon ile yapılabilir.
Bir senaryo motoru için iyi bir sistem istemi dört kısımdan oluşur. İlk olarak rol gelir: oyun yöneticisi, mülakat yapan kişi, geminin bilgisayarı veya bir tiyatro oyunundaki bir karakter. İkinci olarak, birkaç düz cümlede dünya kuralları gelir: ton, mekan, neyin var olduğu ve neyin olmadığı. Üçüncü olarak, kodunuzun bunları ayrıştırması gerekebileceği için biçimlendirme kuralları gelir: örneğin, "her yanıtı 'OPTIONS:' ile başlayan bir satırda bitirin". Dördüncü olarak, sınırlar. Metin API'si, yasal yetişkin kullanımı için içerik reddi olmadan yanıt verecek şekilde ayarlanmıştır; bu da gerçek tehdit taşıyan kötü karakterler ve ahlaki açıdan gri hikayeler için karanlık kurguya uygundur. Yine de tek bir kesin çizgisi vardır: reşit olmayanlar içeren cinsel içerik yok. Bu kuralı kendi kullanım koşullarınıza da ekleyin ve senaryolarınız yetişkinlere yönelikse uygulamanızda bir yaş sınırı uygulayın.
İstemi yaklaşık 600 kelime altında tutun. Uzun kural listeleri yarım uygulanır. Çok sayıda kurala ihtiyacınız varsa, bunları sıralayın ve en alttaki üçte birini atın.
Akış içeren çalışan bir döngü
Akış, rol yapmada diğer kullanımlara göre daha önemlidir. Bir hikaye okuyan oyuncu, model yazarken kelimelerin görünmesini ister ve 300 token'lık bir yanıt, hepsi birden geldiğinde olduğundan daha yavaş hissettirir. API, stream: true ile sunucu tarafından gönderilen olaylar üzerinden akış yapar ve OpenAI SDK'ları ayrıştırmayı yönetir. Uç nokta OpenAI uyumludur, model kimliği uncensored'dir ve bu site için Base URL https://api.sdxlapi.com/v1'dir.
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.")Ayarlar kurgu için ayarlanmıştır. Yaklaşık 0,8 ile 1,0 arasındaki bir temperature değişkeni çeşitli bir anlatım sağlar ve top_p değeri yaklaşık 0,95'te en tuhaf kelime seçimlerini keser. Küçük bir varlık cezası, anlatıcının aynı görsellere tekrar tekrar dönmesini engeller. Yanıt uzunluğunu sınırlamak için max_tokens değerini ayarlayın; bu isteğe bağlıdır ancak bu değer olmadan konuşkan bir anlatıcı istediğinizden çok daha fazla yazabilir. Test sırasında tam olarak tekrarlamak istediğiniz bir sahne için seed değerini iletin ve diğer parametreleri sabit tutun.
Gerçeklerin kod tarafından yönetilmesine izin verin
Uzun rol yapma oyunlarında en yaygın hata kaymadır. Anahtar, 5. dönüşte oyuncunun cebindedir ve 40. dönüşde masadadır. Konak sahibi Mara olarak çağrıldı, sonra Marta oldu. Geçmişin 30.000 tokenını okuyan bir model bunu genellikle doğru yapar, ancak "genellikle" bir tasarım değildir. Gerçekleri programınızın güncellediği küçük bir yapıda tutun ve bu yapıyı her istekte, yukarıdaki STATE satırının yaptığı gibi kullanın.
Durumu nasıl güncellersiniz? Modelden, her dönüşten sonra değişiklikleri bildirmesini isteyin; bu, JSON modunu kullanan ikinci, ucuz bir çağrıdır. İlk çağrı oyuncu için hikayeyi yazar. İkinci çağrı yeni bölümü okur ve yalnızca neyin değiştiğini döndürür.
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:]Gerçekler listesini, dilimleme gibi sınırlayın; aksi takdirde durum bloğu büyür ve yerine geçmesi gereken geçmiş kadar ağır hale gelir. Bir JSON yanıtı ayrıştırılamazsa, o dönüş için güncellemeyi atlayın ve devam edin; bir gerçek eksikliği, bir çökmekten daha ucuzdur.
Zar, sağlık ve zamanlayıcılar düz kodda daha iyi yönetilir. Oyuncu riskli bir şey denediğinde, Python'da zar atın ve anlatıcıya sonucu söyleyin: "Oyuncunun denemesi başarısız oldu." Model ardından sonuçları yazar. Bu, dil modellerinin genellikle yaptığı gibi, oyuncunun her zaman kazanmasını sessizce bırakmaktan modeli korur.
Saatlerce süren oturumlar için hafıza
Bağlam penceresi, istem ve tamamlama birlikte sayıldığında 100.000 token'dır. Ortalama bir yanıt 250 token ve bir oyuncu mesajı 30 token olmak üzere, dönüş başına yaklaşık 280 token eder; bu nedenle ham geçmiş yalnızca yüzlerce dönüşü tutabilir. Hepsi gönderilebilir. Yine de birçok geliştirici bunu yapmaz, iki nedenle: maliyet her dönüşle artar, çünkü tüm geçmiş her seferinde giriş olarak faturalandırılır ve eski detaylar modeli dağıtabilir.
Makul bir düzenleme üç katman barındırır:
- Sabitlenmiş: sistem istemi ve durum bloğu. Her zaman gönderilir.
- Özet: neler olduğunu anlatan bir veya iki paragraf, her 10 ila 15 dönüşte kısa bir çağrı ile yeniden yazılır.
- Son dönüşler: son 10 ila 20 mesajın birebir hali, böylece anlatım ritmi korunur.
Son dönüşler için pencere dolduğunda, en eski on dönüşü özetle birleştirin ve onları atın. Özet çağrısı düşük bir sıcaklık ve 300 tokenlik bir sınır kullanabilir. İsimler, vaatler ve çözümlenmemiş tehditler özetle yer aldıkça oyuncular sıkıştırmayı fark etmez. Özetleme isteminde bunu açıkça belirtin: "isimleri, borçları, yaralanmaları, açık soruları koru".
Bir karakterin kararlı bir sesi korumasını istiyorsanız, sabit katmanda kısa bir stil kartı verin: konuşmasının üç örnek satırı ve asla söylemediği iki şey. Kısa örnekler, sıfatlardan daha iyi bir ton oluşturur.
Bir oturumun maliyeti
Fiyatlandırma 1M giriş tokenı başına $0,15 ve 1M çıkış tokenı başına $0,50'dir; ön ödemeli kredi ve abonelik yoktur. Uzun bir oturum üzerinden çalışın. 200 dönüş, sabit katman, özet ve son dönüşler bir istek başına ortalama 6.000 giriş tokenı ve her yanıt için 400 çıkış tokenı (hikaye yanıtı ve durum ile özet çağrıları için küçük bir pay) toplamı olarak hesaplayın.
Giriş: 200 x 6.000 = 1.200.000 token, bu da 1,2 x $0,15 = $0,18 eder. Çıkış: 200 x 400 = 80.000 token, bu da 0,08 x $0,50 = $0,04 eder. Oturum $0,22 tutar.
Ham geçmişi yeniden gönderen tembel versiyonu karşılaştırın. 200. tura gelindiğinde geçmiş yaklaşık 56.000 token olur ve oturum boyunca ortalama giriş, istek başına yaklaşık 28.000 token olur. Bu, 200 x 28.000 = 5.600.000 giriş token veya 5,6 x $0,15 = $0,84 eder, çıkış için aynı $0,04 eklenirse $0,88 eder. Hala uygun, ancak kalitede bir kazanç olmadan faturada dört kat fark. Çok oyunculu bir uygulama için bu fark marjınızı belirler.
Başarısız veya reddedilen istekler faturalandırılmaz ve kredi hiç sona ermez, bu nedenle kullanılmayan bakiye yalnızca bekler. Yüklemeler $20 ile $500 arasında tam dolarlar halinde yapılır; $50'den itibaren %5, $100'den itibaren %10 ve $200'den itibaren %15 bonus vardır. Seçeneklerin tam listesini görmek için fiyatlandırma sayfasına bakın.
Aynı anda birçok oyuncuyu çalıştırma
Tam bir anahtar 8 eşzamanlı istek ve dakika başına 300 istek izni verir. Akışlı bir istek, akış bitene kadar slotunu tutar; bu nedenle 8 slot ve yaklaşık on saniye süren yanıtlar ile, başka hiçbir şey çalışmıyorsa dakikada yaklaşık 48 yanıt akışı sunabilirsiniz. Bu, yüke ve yanıt uzunluğuna bağlı olarak hızın değişmesinden dolayı ölçülmüş bir rakam değil, kabaca bir kuraldır. Nokta, bunu planlamaktır: oyununuz, slotlardan daha fazla eşzamanlı oyuncuya sahipse, istekleri sunucunuzda sıraya alın ve her şeyi aynı anda ateşlemek yerine kısa bir "anlatıcı düşünüyor" durumu gösterin.
Bir limiti aştığınızda API HTTP 429 döndürür. Kod, dakika başına istekler için rate_limited ve aynı anda çok fazla istek için concurrency şeklindedir. Geçici aşırı yüklenme de Retry-After: 5 başlığı ile 429 verir. Bu beş saniyeyi bekleyen basit bir yeniden deneme, rahat bir oyun için yeterlidir. Yanıt başlıklarını da okuyun: X-RateLimit-Limit-Requests ve X-RateLimit-Limit-Concurrency limitlerinizi gösterir ve X-Balance-USD ne kaldığını gösterir; bunu bir yönetici ekranında gösterebilirsiniz.
Durum çıkarma çağrısını, bir sonraki oyuncu dönüşü ile eşzamanlı olarak çalıştırmayın. Onu bekleyin; aksi takdirde anlatıcı eski gerçeklerden yazar. İyi bir çözüm, çıkarmayı akış bittiği anda başlatmak ve oyuncunun çalışırken okumasına izin vermektir.
Sahnelere görüntü pipeline'ınızı bağlama
Bu site, Stable Diffusion iş akışlarında metin modelleri kullananlar için hazırlanmıştır ve senaryolar buna uygun şekilde kurgulanmıştır. API yalnızca metin içerir: resim, ses veya video üretmez. Ancak anlatıcı, pipeline'ınızın bir görsel isteme dönüştürebileceği bir sahne betimi yazabilir. Büyük bir sahne değişikliğinden sonra, ortamın aydınlatma, ruh hali ve kamera açısı ile kısa bir görsel betimini isteyen bir JSON çağrısı ekleyin, ardından bu dizgiyi kullandığınız herhangi bir görsel aracına iletin. belgeler sayfası, istem yazma çağrıları için istek yapısını gösterir ve SD istem oluşturucu hakkındaki makale bu konuda daha derinlemesine inceler.
Motoru denemek için bir hesap oluşturun ve deneme kredisi talep edin. Yeni kullanıcılar API anahtarı sayfası üzerinde tek tıkla $0.50 deneme kredisi alabilir; bu kredi 7 gün boyunca geçerlidir ve kart gerekmez. Yukarıdaki sayılara göre bu, birkaç tam oturum için yeterlidir. Deneme anahtarları eşzamanlı 2 istek ve dakikada 60 istekle sınırlıdır; bu da bireysel testler için uygundur.
Kurguyu kurguda tutun. Yetişkin temalı senaryolar, tarafların yetişkin olduğu durumlarda yasal kullanımdır; bükülmeyen tek kural, reşit olmayanlar içeren cinsel içerik olmamasıdır. API'ye gönderilen istemler eğitim için kullanılmaz.
Daha fazla kılavuz
Sorular ve cevaplar
Model herhangi bir karakteri veya türü oynayabilir mi?
Yetişkinlere yönelik yasal istekleri reddetmeyecek şekilde ayarlanmış genel bir metin modelidir; korku, suç, drama ve komedi hepsi uygundur. Tek kesin sınır, reşit olmayanlar içeren cinsel içeriktir.
Bağlam dolmadan önce bir oturum ne kadar sürebilir?
Bağlam penceresi, istem ve tamamlama için 100.000 token'dır. Eski dönüşler sıkıştırıldığı için, bir özet katmanı ile pratikte bu sayının çok ötesine geçebilirsiniz.
Yanıtları akış olarak göndermeli miyim?
Evet, bir kişinin canlı olarak okuduğu her şey için. Akış, son kullanım verisini size verir ve bir akış, bitene kadar eşzamanlılık slotlarınızdan birini işgal eder.
Bir sahnenin tam olarak tekrarlanmasını sağlayabilir miyim?
Aynı mesajlar ve ayarlarla aynı seed değerini iletin. Bu bir test yardımcısıdır ve bayt-bayt aynı çıktıyı garanti etmez.
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.