업데이트됨
중국 웹소설(网文) 및 역할극 앱: 컨텍스트, 캐릭터 및 비용
연재 중국 웹소설과 캐릭터 채팅은 가장 부하가 큰 텍스트 작업 중 두 가지입니다: 장당 수천 자, 수개월 동안 일관성을 유지해야 하는 등장인물, 그리고 모든 실수를 눈치채는 독자. 이 가이드는 프롬프트 구조화, 100,000토큰 컨텍스트 창 관리, 명시된 가정 하에 비용 추정 방법을 보여줍니다.
이러한 작업 부하의 특징
웹소설 연재는 장당 2,000~4,000자로 작성되며 종종 매일 발행되고 수백 장에 걸친 줄거리를 가집니다. 역할극 앱은 대화형 변종입니다: 페르소나, 시나리오, 긴 대화 기록이 필요합니다. 둘 다 모델 API에서 다음 세 가지가 필요합니다: 기억할 충분한 컨텍스트, 길게 작성할 수 있는 충분한 출력 예산, 그리고 일관된 스타일.
이 서비스는 https://api.chinesellmapi.com/v1에서 OpenAI 호환 채팅 엔드포인트를 제공하며, id가 uncensored인 단일 텍스트 모델을 사용합니다. 컨텍스트 창은 프롬프트와 완성 텍스트를 합쳐 100,000 토큰이며, max_tokens 기본값은 2,048이고 최대 32,000까지 설정할 수 있습니다. temperature, top_p, stop와 같은 표준 샘플링 필드가 전달됩니다. 스트리밍을 지원하므로 채팅에 적합합니다. 기본 설정 및 인코딩 관련 안내는 앱 시작하기에서 확인할 수 있습니다.
앞서 명시된 콘텐츠 규칙
이 서비스는 성인 전용입니다. 합법적인 성인 소설, 성숙한 주제, 논쟁적인 주제는 그 자체로 거부되지 않으며, 서비스는 18세 이상 사용자를 대상으로 합니다. 미성년자가 포함된 성적 콘텐츠는 소설이나 역할극으로 framing되더라도 항상 차단되며 403 content_blocked 오류를 반환합니다. 이를 변경하는 설정은 없습니다.
처음부터 이를 위해 구축하세요. 캐릭터 시트에 모든 캐릭터가 성인임을 명시하고 명시적인 나이를 기재하세요. 자체 제품에 연령 확인 단계를 추가하세요. 403은 해당 요청에 대한 최종 답변으로 처리하세요: 중립적인 메시지를 표시하고 프롬프트를 재구성하여 다시 시도하지 마세요. 이러한 조치는 플랫폼 규칙과 관계없이 좋은 제품 위생입니다.
캐릭터 시트와 스타일 블록
일관성은 안정적인 사실을 한 곳에 모아 모든 호출에서 반복함으로써 얻어집니다. 캐릭터 시트는 이름, 나이, 역할, 말버릇, 관계, 그리고 아직 드러내서는 안 될 비밀을 포함한 하드 제약 조건을 기록한 간결한 레코드입니다. 별도의 스타일 블록은 시점, 템포, 대화 비율, 장 길이, 엔딩 습관을 고정합니다. 둘 다 시스템 메시지에 넣어 모든 요청의 앞에 위치시킵니다.
CHARACTER_SHEET = """\
【人物卡】
姓名:沈清禾(女,28岁)
身份:江城古籍修复师,性格沉静,嘴硬心软
口头禅:“先别急,东西不会跑。”
说话方式:短句,少用感叹号,偶尔引用旧书里的句子
关系:与顾远舟(男,31岁,旧书商)是多年好友,彼此有未说出口的好感
禁忌:不提及她离开出版社的真正原因(第40章才揭晓)
"""
STYLE = """\
【文风】第三人称限知视角,贴近沈清禾;节奏舒缓,多写物件与天气的细节;
对话占比约四成;每章 2500 到 3000 字;结尾留一个小悬念。"""
이들은 중국어로 작성하세요. 중국어 예시에 담긴 어조나 문장 길이와 같은 말버릇은 영어 설명보다 훨씬 더 신뢰성 있게 전달됩니다. 각 시트는 수백 토큰 이내로 유지하고, 반복되는 캐릭터마다 하나의 시트를 만드세요. 열 명의 캐스트라도 수천 토큰에 불과합니다. 캐릭터의 상황이 바뀌면 이력(history)에 의존하기보다 시트 자체를 업데이트하세요.
연재 장을 위한 긴 컨텍스트
유혹은 이전 장을 모두 프롬프트에 붙여넣는 것입니다. 먼저 계산을 해보세요. 100,000토큰 창과 장당 약 4,500 토큰을 가정하면, 전체 창은 출력 공간 없이 약 14장만 담을 수 있으며 연재는 수백 장에 달합니다. 실행 가능한 패턴은 계층적 메모리입니다:
- 항상 존재하는 캐릭터 시트와 스타일 블록.
- 롤링 스토리 요약: 장당 수백 자 분량으로, 몇 장마다 새로 고치는 진행 요약으로 병합합니다.
- 직전 장의 전체 텍스트: 문체가 이음매에서 연결되도록 합니다.
- 작성 중인 장의 개요.
각 장이 끝난 후 모델에게 관계 변화와 열린 줄거리를 보존하는 짧은 요약을 요청하고, 이를 요약문에 추가하세요. 아래 코드는 장을 생성하고 다음 요약을 생성합니다. 또한 usage를 반환하여 실제 토큰 수를 로깅할 수 있습니다:
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.chinesellmapi.com/v1", api_key=os.environ["API_KEY"])
def write_chapter(sheet, style, story_so_far, last_chapter, outline):
messages = [
{"role": "system", "content": "你是一位连载网络小说的作者,所有人物均为成年人。严格遵守人物卡和文风设定。\n" + sheet + "\n" + style},
{"role": "user", "content": (
"【前情提要】\n" + story_so_far +
"\n\n【上一章全文】\n" + last_chapter +
"\n\n【本章大纲】\n" + outline +
"\n\n请直接写出本章正文,不要写标题以外的说明。")},
]
r = client.chat.completions.create(
model="uncensored",
messages=messages,
max_tokens=5000, # ~3,000 characters needs roughly 4,500 tokens under our assumption
temperature=0.9,
top_p=0.95,
)
return r.choices[0].message.content, r.usage
def summarize(chapter_text):
r = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "用 200 字以内概括下面这一章的剧情,保留人物关系的变化和未解的伏笔:\n" + chapter_text}],
max_tokens=400,
temperature=0.3,
)
return r.choices[0].message.content
역할극: 페르소나, 턴 구성 및 정지 시퀀스
역할극에는 동일한 시트 및 스타일 규칙과 몇 가지 채팅 전용 제어 기능이 필요합니다. 시스템 메시지에 페르소나를 넣고, 누가 누구를 연기하는지 명시하며, 응답 길이의 범위를 고정하고, 모델이 사용자의 캐릭터 행동을 쓰지 않도록 지시하세요. 모델이 사용자의 다음 대사를 쓰기 시작할 때 출력을 중단하려면 stop을 사용하고, 스트리밍을 사용하여 생성되는 대로 텍스트를 표시하세요.
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.chinesellmapi.com/v1", api_key=os.environ["API_KEY"])
PERSONA = (
"你扮演顾远舟,31岁的旧书商,说话随和,爱开玩笑,但在重要的事上很认真。"
"用户扮演沈清禾。所有角色均为成年人。保持第一人称,每次回复 80 到 200 字,"
"用(括号)写简短的动作描写,不要替用户的角色做决定。"
)
history = [{"role": "system", "content": PERSONA}]
def turn(user_text):
history.append({"role": "user", "content": user_text})
stream = client.chat.completions.create(
model="uncensored",
messages=history,
max_tokens=400,
temperature=1.0,
stop=["\n用户:"], # keep the model from writing the user's next line
stream=True,
)
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)
print()
history.append({"role": "assistant", "content": reply})
turn("(推开书店的门)这场雨下得真不是时候。")
이력은 한 턴마다 사용자 메시지 하나와 어시스턴트 메시지 하나씩 늘어납니다. 이력이 예산에 가까워지면 가장 오래된 부분을 단일 메시지로 요약하고, 최근 턴은 그대로 유지하세요. 캐릭터에 생동감 있는 대화를 부여하려면 온도를 0.9~1.0으로 설정하고, 페르소나가 대본에 엄격하게 따라야 할 때는 0.5 정도로 낮추세요.
긴 연재에서도 유지되는 스타일 제어
스타일 편차는 독자들이 가장 많이 불평하는 실패 사례입니다. 화자가 점차 수다스러워지고, 대화가 격식 있게 변하며, 템포가 빨라지는 현상입니다. 구체적인 지시로 이를 방지하세요. "우아한 스타일로 작성"이라고 하기보다 측정 가능한 습관을 설명하세요. 문장 길이, 관용구 사용 빈도, 날씨와 사물 묘사의 정도, 장이 끌림이나 잔잔한 여운으로 끝나는지 여부 등을 명시하세요. 대상 목소리의 짧은 샘플 단락 두세 개를 스타일 블록에 넣는 것이 형용사 한 페이지보다 더 효과적입니다.
장르에 따라 다른 설정이 필요합니다. 수양물이나 판타지 연재물은 영역, 문파, 기술 등 발명된 용어의 어휘집이 필요하며, 같은 이름이 두 가지로 철자되지 않도록 해야 합니다. 현대 로맨스는 대화의 리듬과 작은 신체 디테일에 의존합니다. 미스터리물은 클루 레지스터(독자가 본 사실들의 목록)가 필요합니다. 이를 통해 모델이 사실을 모순하지 않도록 합니다. 이러한 목록은 시스템 프롬프트에 유지하고 이야기가 진행됨에 따라 업데이트하세요.
마지막으로, 연재 내에서 temperature와 top_p를 고정하세요. 장 간에 샘플링을 변경하면 목소리가 바뀝니다. 텍스트 자체에는 온도를 올리지 말고 개요 브레인스토밍에만 사용하세요.
명시된 가정 하의 비용 계산
모든 수치는 100만 입력 토큰당 $0.25, 100만 출력 토큰당 $1.00의 공개된 요금과 중국어 문자당 1.5 토큰이라는 가정치를 사용합니다. 가정치를 자체 usage 로그의 숫자로 교체하세요.
| 시나리오 | 가정된 입력 토큰 | 가정된 출력 토큰 | 요청당 비용 |
|---|---|---|---|
| 연재 장 (3,000자 출력) | 8,000 | 4,500 | $0.0020 + $0.0045 = $0.0065 |
| 역극 턴, 20,000토큰 기록 | 20,000 | 300 | $0.0050 + $0.0003 = $0.0053 |
| 역극 턴, 전체 60,000토큰 기록 | 60,000 | 500 | $0.0150 + $0.0005 = $0.0155 |
장 행에서 8,000 입력 토큰은 1,200토큰의 캐릭터 시트와 스타일 블록, 2,000토큰의 요약, 4,500토큰의 직전 장, 300토큰의 개요로 구성됩니다. 100장의 비용은 약 $0.65입니다. 20,000토큰 기록 크기의 100회 역극 턴 비용은 약 $0.53입니다. 핵심은 기록 길이가 채팅 비용을 결정하므로, 기록을 줄이고 요약하는 것이 빠르게 비용을 상쇄한다는 것입니다.
7일 동안 유효한 $0.50 트레일 크레딧은 첫 번째 행의 가정 하에 약 76장을 커버합니다. 현재 요금은 가격을 확인하고 계정 세부사항은 트레일 FAQ을 참조하세요.
프로덕션을 위한 운영 참고사항
챕터 생성은 긴 요청이므로 generous한 타임아웃을 사용하거나 스트리밍하여 텍스트를 직접 조립하세요. 429 오류는 키당 분당 300개의 요청이 허용되므로 짧은 백오프로 처리하고, 503 오류는 upstream_busy로 처리하여 몇 초 후 재시도하세요. 402 오류는 선불 잔액이 고갈되었거나 무료 체험이 만료되었음을 의미하므로, 재시도하기보다 사용자에게 알리는 것이 좋습니다.
다음 장을 생성하기 전에 생성된 각 장과 요약을 자체 데이터베이스에 저장하세요. 밤새 배치 중 호출이 중간에 실패하면 마지막 저장된 장부터 재개할 수 있으며, 동일한 텍스트에 대해 두 번 지불하지 않습니다. 프롬프트 버전과 사용량 수치를 각 장 옆에 저장하여 장당 비용을 추측이 아닌 쿼리로 처리하세요.
역극 제품에서는 세션별 예산을 유지하세요. 단일 세션이 소모할 수 있는 턴 수나 총 토큰 수를 제한하고, 제한에 도달하면 사용자에게 명확한 메시지를 표시하세요. 프롬프트에는 이력이 포함되므로, 매우 긴 세션은 새로운 세션보다 턴당 비용이 훨씬 많이 듭니다. 따라서 컨텍스트 창에 맞추는 것뿐만 아니라 오래된 턴을 요약하는 것이 중요한 것입니다. 프롬프트는 학습에 사용되지 않으므로, 이를 제품 개인정보 보호 정책과 함께 명시할 수 있습니다.
질문과 답변
한 번의 요청으로 챕터 길이를 얼마나 길게 설정할 수 있나요?
출력은 요청당 토큰 32,000개로 제한되며 프롬프트와 100,000개의 컨텍스트 창을 공유합니다. 3,000자 분량의 챕터는 여유 있게 처리되므로, max_tokens는 예상치보다 약간 높게 설정하세요.
수백 편의 챕터에 걸쳐 캐릭터를 일관되게 유지하려면 어떻게 해야 하나요?
모든 요청에서 시스템 프롬프트에 캐릭터 시트와 스타일 블록을 유지하고, 줄거리는 롤링 요약과 이전 챕터를 이어가며 전달하세요.
성인 소설도 허용되나요?
성인 캐릭터 간의 합법적인 성인 소설은 거부되지 않으며, 서비스는 18세 이상 사용자를 대상으로 합니다. 미성년자가 관련된 성 콘텐츠는 소설과 역할극을 포함해 항상 403 오류로 차단됩니다.
롤플레이 응답을 스트리밍할 수 있나요?
네. 서버 전송 이벤트를 받기 위해 stream을 true로 설정하고, stop sequences를 설정하여 모델이 사용자 대사를 작성하지 않도록 방지하세요.
키는 양식 하나만 작성하면 받을 수 있습니다
계정을 생성하고 키를 복사한 후 base URL을 변경하세요. 설정은 이뿐입니다.