TH ▾
รับคีย์ API

บทบาทสมมติแบบข้อความด้วย API LLM

อัปเดต

บทบาทสมมติแบบข้อความทำงานได้ดีที่สุดเมื่อโมเดลแสดงเป็นผู้บรรยายที่มีกฎ และโค้ดของคุณเป็นเจ้าของสถานะ บทความนี้จะแนะนำเครื่องยนต์ขนาดเล็กใน Python: พรอมต์ การสตรีมมิง ความจำ และการประมาณค่าใช้จ่ายสำหรับเซสชันยาว

ไดออรามาของเวทีขนาดเล็กที่มีฟองคำพูดเรืองแสงแสดงถึงบทบาทสมมติแบบข้อความ

ประเด็นสำคัญ

  • แบ่งงาน: โมเดลเขียนเรื่องราว โค้ดของคุณเก็บข้อเท็จจริง สินค้าคงคลัง และกฎ
  • สตรีมการตอบกลับและทำให้แต่ละสตรีมสั้นพอที่จะปลดช่องความพร้อมใช้งานพร้อมกันได้เร็ว
  • หน้าต่าง 100,000 โทเคนรองรับเซสชันที่ยาวมาก แต่การสรุปผลช่วยลดค่าใช้จ่ายและความเบี่ยงเบน
  • เซสชัน 200 เทิร์นที่ 6,000 โทเคนอินพุตและ 400 โทเคนเอาต์พุตต่อเทิร์นมีค่าใช้จ่ายประมาณ $0.22

เริ่มที่ผู้บรรยาย ไม่ใช่พล็อตเรื่อง

ผู้สร้างสถานการณ์บทบาทสมมติแบบข้อความมักเริ่มจากการเขียนพล็อตเรื่อง ซึ่งเป็นการทำกลับด้าน สถานการณ์คือวงจรระหว่างผู้เล่นและผู้บรรยาย และผู้บรรยายต้องการคำอธิบายงานก่อนต้องการเรื่องราว โมเดลต้องรู้ว่าใครเป็นผู้พูด สามารถตัดสินใจแทนผู้เล่นได้แค่ไหน คำตอบควรยาวแค่ไหน และไม่ควรทำอะไรบ้าง ส่วนที่เหลือสามารถด้นสดได้

พรอมต์ระบบที่ดีสำหรับเครื่องจำลองสถานการณ์มีสี่ส่วน ส่วนแรกคือบทบาท: ผู้กำกับเกม ผู้สัมภาษณ์ คอมพิวเตอร์บนเรือ หรือตัวละครในละคร ส่วนที่สองคือกฎของโลกด้วยประโยคเรียบง่าย: น้ำเสียง ฉาก สิ่งที่มีและไม่มี ส่วนที่สามคือกฎการจัดรูปแบบ เพราะโค้ดของคุณอาจต้องอ่านค่าเหล่านี้: เช่น "ลงท้ายทุกการตอบกลับด้วยบรรทัดที่ขึ้นต้นด้วย OPTIONS:" ส่วนที่สี่คือขอบเขต API ข้อความที่นี่ปรับให้ตอบโดยไม่มีการปฏิเสธเนื้อหาสำหรับการใช้งานผู้ใหญ่ที่ถูกต้องตามกฎหมาย ซึ่งทำให้เหมาะสำหรับนิยายดาร์ก ตัวร้ายที่มีอันตรายจริง และพล็อตที่สีเทาทางศีลธรรม มันยังมีเส้นห้ามข้ามเส้นเดียว: ไม่มีเนื้อหาทางเพศที่เกี่ยวข้องกับผู้เยาว์ ใส่กฎนั้นไว้ในข้อกำหนดการใช้งานของคุณเองด้วย และบังคับใช้การจำกัดอายุในแอปของคุณหากสถานการณ์ของคุณมุ่งเป้าไปที่ผู้ใหญ่

รักษาพรอมต์ให้อยู่ที่ประมาณ 600 คำ รายการกฎที่ยาวเกินไปจะถูกปฏิบัติตามเพียงครึ่งเดียว หากคุณต้องการกฎจำนวนมาก ให้จัดลำดับความสำคัญและตัดหนึ่งในสามส่วนล่างออก

วงจรการทำงานพร้อมสตรีมมิง

สตรีมมิงมีความสำคัญมากกว่าในการบทบาทสมมติเมื่อเทียบกับการใช้งานส่วนใหญ่ ผู้เล่นที่อ่านนิยายต้องการให้ข้อความปรากฏขึ้นในขณะที่โมเดลกำลังเขียน และคำตอบขนาด 300 โทเคนจะรู้สึกช้ากว่าความเป็นจริงหากส่งมาทั้งหมดในครั้งเดียว API ส่งข้อมูลผ่านเซิร์ฟเวอร์ส่งเหตุการณ์ (SSE) ด้วย stream: true และ SDK ของ OpenAI จัดการการแยกวิเคราะห์ เอนด์พอยต์นี้เข้ากันได้กับ OpenAI รหัสโมเดลคือ uncensored และ Base URL ของเว็บไซต์นี้คือ 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.")

การตั้งค่าปรับแต่งสำหรับงานเขียนเชิงนิยาย ค่า temperature ประมาณ 0.8 ถึง 1.0 ให้สำนวนที่หลากหลาย และ top_p ที่ใกล้กับ 0.95 จะตัดตัวเลือกคำที่แปลกที่สุดออก การปรับค่า presence penalty เล็กน้อยจะลดแนวโน้มที่ผู้บรรยายจะวนกลับมาใช้ภาพเดิมซ้ำๆ ตั้งค่า max_tokens เพื่อจำกัดความยาวของคำตอบ ซึ่งเป็นตัวเลือก แต่หากไม่ตั้งค่า ผู้บรรยายที่พูดมากอาจเขียนยาวเกินที่คุณต้องการ สำหรับฉากที่คุณต้องการเล่นซ้ำอย่างแม่นยำในการทดสอบ ให้ส่ง seed และคงพารามิเตอร์อื่นๆ ให้คงที่

ให้โค้ดควบคุมข้อเท็จจริง

ความล้มเหลวที่พบบ่อยที่สุดในบทบาทสมมติแบบยาวคือการเบี่ยงเบน คีย์อยู่ในกระเป๋าผู้เล่นในรอบที่ 5 และอยู่บนโต๊ะในรอบที่ 40 เจ้าของโรงเตี๊ยมถูกเรียกว่ามารา แล้วเป็นมาร์ตา โมเดลที่อ่านประวัติ 30,000 โทเคนมักจะจัดการเรื่องนี้ได้ถูกต้อง แต่ "มักจะ" ไม่ใช่การออกแบบ เก็บข้อเท็จจริงไว้ในโครงสร้างขนาดเล็กที่โปรแกรมของคุณอัปเดต แล้วใส่โครงสร้างนั้นเข้าไปในทุกคำขอ ตามที่บรรทัด STATE ด้านบนทำ

คุณจะอัปเดตสถานะได้อย่างไร? ถามโมเดลให้รายงานการเปลี่ยนแปลงหลังจากแต่ละรอบ ในคำขอที่สองที่ราคาถูกกว่าซึ่งใช้โหมด JSON คำขอแรกเขียนเรื่องราวสำหรับผู้เล่น คำขอที่สองอ่านข้อความใหม่และส่งกลับเฉพาะสิ่งที่เปลี่ยนแปลง

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:]

จำกัดรายการข้อเท็จจริง เหมือนที่ slice ทำ หรือบล็อกสถานะจะเติบโตจนหนักเท่ากับประวัติที่มันควรแทนที่ หากการตอบกลับ JSON ล้มเหลวในการ parse ให้ข้ามการอัปเดตในรอบนั้นและดำเนินการต่อ; ข้อเท็จจริงที่พลาดหนึ่งข้อมีราคาถูกกว่าการ crash

การทอยลูกเต๋า สุขภาพ และตัวจับเวลา ควรจัดการด้วยโค้ดธรรมดา เมื่อผู้เล่นพยายามทำสิ่งที่มีความเสี่ยง ให้ทอยลูกเต๋าใน Python และบอกผลลัพธ์ให้ผู้บรรยาย: "ความพยายามของผู้เล่นล้มเหลว" จากนั้นโมเดลจะเขียนผลลัพธ์ที่เกิดขึ้น วิธีนี้ทำให้โมเดลไม่ปล่อยให้ผู้เล่นชนะทุกครั้งโดยปริยาย ซึ่งเป็นสิ่งที่โมเดลภาษามีแนวโน้มจะทำ

หน่วยความจำสำหรับเซสชันที่ทำงานเป็นชั่วโมง

หน้าต่างบริบทคือ 100,000 โทเคน นับรวมพรอมต์และการสร้างข้อความรวมกัน การตอบกลับทั่วไป 250 โทเคนบวกข้อความผู้เล่น 30 โทเคนคือประมาณ 280 โทเคนต่อรอบ ดังนั้นประวัติดิบเพียงอย่างเดียวสามารถเก็บหลายร้อยรอบได้ คุณสามารถส่งทั้งหมดได้ ผู้สร้างจำนวนมากยังไม่ได้ทำเนื่องจากสองเหตุผล: ค่าใช้จ่ายเพิ่มขึ้นในทุกรอบ เพราะประวัติทั้งหมดจะถูกเรียกเก็บเป็นข้อมูลนำเข้าทุกครั้ง และรายละเอียดเก่าอาจเบี่ยงเบนความสนใจของโมเดล

เลย์เอาต์ที่เหมาะสมควรรักษาสามชั้น:

  1. Pinned: พรอมต์ระบบและบล็อกสถานะ ส่งเสมอ
  2. สรุป:ย่อหน้าหรือสองย่อหน้าที่สรุปสิ่งที่เกิดขึ้น เขียนใหม่ทุก 10 ถึง 15 รอบด้วยคำขอสั้นๆ
  3. รอบล่าสุด: ข้อความล่าสุด 10 ถึง 20 ข้อความแบบตรงตัว เพื่อให้จังหวะการเขียนคงที่

เมื่อหน้าต่างของรอบล่าสุดเต็ม ให้ รวม รอบเก่าสิบรอบเข้าไปในบทสรุปและลบออก การเรียกบทสรุปสามารถใช้ temperature ต่ำและจำกัดที่ 300 token ผู้เล่นแทบไม่สังเกตเห็นการบีบอัด ตราบใดที่ชื่อ คำสัญญา และ ภัยคุกคามที่ยังไม่ได้แก้ไข เข้าไปในบทสรุป บอกสิ่งนั้นอย่างชัดเจนใน prompt สรุป: "เก็บชื่อ หนี้ บาดแผล คำถามที่ยังเปิดอยู่"

หากคุณต้องการให้ตัวละครรักษาเสียงพูดที่เสถียร ให้ให้การ์ดสไตล์สั้นๆ ในชั้นที่ตรึงไว้: ตัวอย่างประโยคการพูดสามบรรทัดและสองสิ่งที่ตัวละครไม่เคยพูด ตัวอย่างสั้นๆ กำหนดน้ำเสียงได้ดีกว่าคำคุณศัพท์

ต้นทุนของเซสชัน

ราคาอยู่ที่ $0.15 ต่อ 1M โทเคนข้อมูลนำเข้า และ $0.50 ต่อ 1M โทเคนข้อมูลส่งออก พร้อมเครดิตแบบเติมเงินล่วงหน้าและไม่มีแผนสมาชิก ทำงานผ่านเซสชันยาว สมมติ 200 รอบ พร้อมชั้นที่ตรึงไว้ สรุป และรอบล่าสุด ซึ่งรวมกันเป็นค่าเฉลี่ย 6,000 โทเคนข้อมูลนำเข้าต่อคำขอ และ 400 โทเคนข้อมูลส่งออกต่อคำตอบ (คำตอบเรื่องราวบวกส่วนเล็กๆ สำหรับการเรียกสถานะและสรุป)

ข้อมูลนำเข้า: 200 x 6,000 = 1,200,000 โทเคน ซึ่งคือ 1.2 x $0.15 = $0.18. ข้อมูลส่งออก: 200 x 400 = 80,000 โทเคน ซึ่งคือ 0.08 x $0.50 = $0.04 เซสชันนี้มีค่าใช้จ่าย $0.22

เปรียบเทียบเวอร์ชันเกียจคร้านที่ส่งประวัติดิบทั้งหมดกลับใหม่ โดยรอบที่ 200 ประวัติจะมีขนาดประมาณ 56,000 โทเคน และตลอดเซสชัน ข้อมูลนำเข้าเฉลี่ยต่อคำขอคือประมาณ 28,000 โทเคน นั่นคือ 200 x 28,000 = 5,600,000 โทเคนข้อมูลนำเข้า หรือ 5.6 x $0.15 = $0.84 บวกกับ $0.04 เดียวกันสำหรับข้อมูลส่งออก ซึ่งรวมเป็น $0.88 ยังจ่ายได้ แต่สูงกว่าสี่เท่าโดยไม่มีการปรับปรุงคุณภาพ สำหรับแอปที่มีผู้เล่นจำนวนมาก ช่องว่างนี้จะเป็นตัวกำหนดกำไรของคุณ

คำขอที่ล้มเหลวหรือถูกปฏิเสธจะไม่ถูกเรียกเก็บเงิน และเครดิตไม่มีวันหมดอายุ ดังนั้นยอดเงินที่ไม่ได้ใช้จะรออยู่ การเติมเงินเริ่มต้นที่ $20 ถึง $500 เป็นจำนวนเต็มดอลลาร์ พร้อมโบนัส 5% จาก $50, 10% จาก $100 และ 15% จาก $200 ดู หน้าราคา สำหรับรายการตัวเลือกทั้งหมด

การรันผู้เล่นจำนวนมากพร้อมกัน

คีย์แบบเต็มอนุญาตให้ทำคำขอพร้อมกัน (concurrent requests) ได้ 8 คำขอ และ 300 คำขอต่อนาที คำขอแบบสตรีมจะครอบครองช่องของมันจนกว่าสตรีมจะจบ ดังนั้นด้วย 8 ช่อง และคำตอบที่ใช้เวลาประมาณสิบวินาที คุณสามารถให้บริการสตรีมคำตอบได้ประมาณ 48 สตรีมต่อนาที โดยสมมติว่าไม่มีบริการอื่นทำงานอยู่ นี่เป็นกฎโดยประมาณ ไม่ใช่ตัวเลขที่วัดได้จริง เนื่องจากความเร็วแปรผันตามภาระงานและความยาวของคำตอบ จุดสำคัญคือการวางแผน: หากเกมของคุณมีผู้เล่นพร้อมกันมากกว่าจำนวนช่อง ให้คิวคำขอในเซิร์ฟเวอร์ของคุณ และแสดงสถานะ "ผู้บรรยายกำลังคิด" สั้นๆ แทนการยิงคำขอทั้งหมดพร้อมกัน

เมื่อคุณเกินขีดจำกัด API จะส่ง HTTP 429 รหัสคือ rate_limited สำหรับคำขอต่อนาที และ concurrency สำหรับจำนวนมากเกินไปในเวลาเดียวกัน การโอเวอร์โหลดชั่วคราวยังให้ 429 พร้อมส่วนหัว Retry-After: 5 การลองใหม่แบบง่ายที่รอห้าวินาทีนั้นเพียงพอสำหรับเกมทั่วไป อ่านส่วนหัวการตอบกลับด้วย: X-RateLimit-Limit-Requests และ X-RateLimit-Limit-Concurrency แสดงขีดจำกัดของคุณ และ X-Balance-USD แสดงสิ่งที่เหลืออยู่ ซึ่งคุณสามารถแสดงในหน้าจอผู้ดูแลระบบ

อย่าเรียกใช้ฟังก์ชันการแยกสถานะ (state-extraction) แบบขนานกับการเล่นของผู้เล่นรายถัดไป รอให้เสร็จก่อน มิฉะนั้นผู้บรรยายจะเขียนจากข้อเท็จจริงที่ล้าสมัย ทางออกที่ดีคือเริ่มการแยกข้อมูลทันทีที่สตรีมจบ และปล่อยให้ผู้เล่นอ่านไปขณะที่ยังทำงานอยู่

การเชื่อมโยงฉากเข้ากับไพล์ไลน์รูปภาพของคุณ

เว็บไซต์นี้สร้างมาสำหรับผู้ที่ใช้โมเดลข้อความร่วมกับเวิร์กโฟลว์ Stable Diffusion และสถานการณ์ก็เข้ากันได้ดี API นี้เป็นข้อความเท่านั้น: มันไม่สร้างภาพ เสียง หรือวิดีโอ แต่ผู้บรรยายสามารถเขียนคำอธิบายฉากที่ ไปป์ไลน์ ของคุณเปลี่ยนเป็นพรอมต์ภาพ เพิ่มการเรียก JSON อีกหนึ่งครั้งหลังจากการเปลี่ยนแปลงฉากสำคัญ โดยขอคำอธิบายภาพสั้นๆ ของสถานที่พร้อมแสง บรรยากาศ และมุมกล้อง จากนั้นส่งสตริงนั้นไปยังเครื่องมือสร้างภาพที่คุณใช้งาน หน้า docs แสดงรูปแบบคำขอสำหรับการเรียกเขียนพรอมต์ และบทความเกี่ยวกับ SD prompt generator ลงลึกในด้านนั้น

เพื่อลองใช้เอนจิน ให้สร้างบัญชีและรับเครดิตทดลองใช้ ผู้ใช้ใหม่ได้รับเครดิตทดลองใช้ $0.50 ด้วยคลิกเดียวที่ หน้าคีย์ API ใช้ได้ 7 วันไม่ต้องใช้บัตร ด้วยตัวเลขข้างต้น เพียงพอสำหรับเซสชันเต็มสองเซสชัน คีย์ทดลองใช้จำกัดคำขอพร้อมกัน 2 คำขอและ 60 คำขอต่อนาที ซึ่งเหมาะสำหรับการทดสอบรายบุคคล

รักษาความเป็นนิยายไว้ในนิยาย สถานการณ์ที่มีธีมผู้ใหญ่เป็นการใช้งานที่ถูกต้องตามกฎหมายเมื่อทุกคนที่เกี่ยวข้องเป็นผู้ใหญ่ กฎเดียวที่ไม่ยอมอ่อนข้อคือไม่มีเนื้อหาทางเพศที่เกี่ยวข้องกับผู้เยาว์ พรอมต์ที่ส่งไปยัง API ไม่ถูกใช้ในการฝึกฝน

ถาม-ตอบ

โมเดลสามารถแสดงตัวละครหรือแนวเรื่องใดก็ได้หรือไม่?

นี่คือโมเดลข้อความทั่วไปที่ปรับแต่งไม่ให้ปฏิเสธคำขอที่เป็นผู้ใหญ่และถูกต้องตามกฎหมาย ดังนั้นสยองขวัญ อาชญากรรม ดราม่า และคอมเมดี้จึงใช้ได้ทั้งหมด ขีดจำกัดเดียวที่แข็งกร้าวคือเนื้อหาทางเพศที่เกี่ยวข้องกับผู้เยาว์

เซสชันจะยาวแค่ไหนก่อนที่หน้าต่างบริบทจะเต็ม?

หน้าต่างคือ 100,000 โทเคนสำหรับพรอมต์บวกกับการสร้างข้อความ ด้วยชั้นบทสรุป คุณสามารถดำเนินการได้ไกลกว่านั้นในทางปฏิบัติ เนื่องจากรอบเก่าถูกบีบอัด

ฉันควรสตรีมคำตอบหรือไม่?

ใช่ สำหรับเนื้อหาที่บุคคลอ่านแบบเรียลไทม์ การสตรีมช่วยให้คุณทราบการใช้งานเมื่อสิ้นสุด และสตรีมจะครอบครองช่องคำขอพร้อมกันหนึ่งช่องจนกว่าจะเสร็จสิ้น

มีวิธีทำให้ฉากซ้ำกันพอดีหรือไม่?

ส่งค่า seed เดียวกันพร้อมข้อความและการตั้งค่าที่เหมือนกัน มันคือเครื่องมือทดสอบและไม่รับประกันข้อมูลส่งออกที่เหมือนกันทุกไบต์

คีย์ของคุณอยู่ห่างเพียงขั้นตอนเดียว

สร้างบัญชี คัดลอกคีย์ และเปลี่ยน base URL นั่นคือการตั้งค่าทั้งหมด

รับคีย์ API