126 lines
4.2 KiB
Python
126 lines
4.2 KiB
Python
"""
|
||
爽文提示词解析 — 用户自然语言 + 内部 JSON 输出格式(不暴露给前端)。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
from typing import Dict
|
||
|
||
# 新建书籍时的默认用户向提示(自然语言,不含 JSON 结构)
|
||
USER_DEFAULT_PROMPTS: Dict[str, str] = {
|
||
"openBook": (
|
||
"你是爽文开书优化助手。根据用户创作灵感,提炼书名、优化简介,"
|
||
"并生成主角人设、核心爽点、读者体验策略与创作禁区。"
|
||
"从情绪流目录中挑选 1–4 个最匹配的条目。"
|
||
),
|
||
"coarseOutline": (
|
||
"你是爽文大纲助手。根据本书设定与进度,生成事件链级别的粗纲,"
|
||
"每个事件包含标题与概要,节奏紧凑、爽点清晰。"
|
||
),
|
||
"eventPlan": (
|
||
"你是爽文事件规划助手。将粗纲中的事件展开为章节级计划,"
|
||
"结合情绪流起承转合,为每章规划核心冲突与爽点。"
|
||
),
|
||
"chapter": (
|
||
"你是爽文章节写作助手。根据事件计划、guide 设定与上文撰写正文,"
|
||
"节奏明快、对话推动冲突、章末留钩子。"
|
||
),
|
||
"nudge": (
|
||
"你是爽文创作教练。根据当前进度与读者体验目标,"
|
||
"给出 1–3 条简短的下一步写作建议,不直接写正文。"
|
||
),
|
||
}
|
||
|
||
# 调用 LLM 时在系统提示末尾追加的输出格式(用户 UI 不可见)
|
||
_INTERNAL_FORMAT: Dict[str, str] = {
|
||
"openBook": """
|
||
|
||
【输出格式】只输出 JSON,不要 markdown 代码块外的文字:
|
||
{
|
||
"title": "书名",
|
||
"optimizedIntro": "优化后的开书灵感",
|
||
"guide": {
|
||
"persona": "主角人设:身份、性格、欲望、能力边界与成长方向",
|
||
"highlight": "核心爽点:本书最稳定兑现的爽点、打脸方式、升级/获得感",
|
||
"experience": "用户体验:视角/人称、听感、节奏、世界感与读者情绪承诺",
|
||
"forbiddenZones": "创作禁区:不能写、不能破坏、不能弱化的内容"
|
||
},
|
||
"allowedFlowIds": ["flow-id"]
|
||
}""",
|
||
"volumeOutline": """
|
||
|
||
【输出格式】只输出 JSON,不要 markdown 代码块外的文字:
|
||
{
|
||
"id": "vol_001",
|
||
"order": 1,
|
||
"title": "卷名",
|
||
"goal": "本卷目标",
|
||
"coreConflict": "本卷核心冲突",
|
||
"powerProgression": "本卷成长/变化",
|
||
"emotionalPromise": "本卷情绪承诺",
|
||
"endingHook": "本卷结尾钩子",
|
||
"targetChapterCount": 20,
|
||
"primaryEmotionFlowId": "emotion-flow-id",
|
||
"status": "active"
|
||
}""",
|
||
"eventChain": """
|
||
|
||
【输出格式】只输出 JSON,不要 markdown 代码块外的文字:
|
||
{
|
||
"events": [
|
||
{
|
||
"id": "evt_0001",
|
||
"volumeId": "vol_001",
|
||
"order": 1,
|
||
"title": "事件标题",
|
||
"summary": "事件概要",
|
||
"purpose": "事件作用",
|
||
"conflict": "事件冲突",
|
||
"turningPoint": "事件转折",
|
||
"expectedPayoff": "预期兑现",
|
||
"targetChapterCount": 3,
|
||
"emotionFlowId": "emotion-flow-id",
|
||
"emotionStepKey": "情感链步骤 key",
|
||
"emotionStepText": "情感链步骤 text",
|
||
"status": "planned"
|
||
}
|
||
]
|
||
}""",
|
||
"chapterPlan": """
|
||
|
||
【输出格式】只输出 JSON,不要 markdown 代码块外的文字:
|
||
{
|
||
"chapterPlan": [
|
||
{
|
||
"title": "章标题",
|
||
"goal": "本章目标",
|
||
"opening": "开场内容",
|
||
"mainConflict": "本章主要冲突",
|
||
"emotionalTurn": "本章情绪变化",
|
||
"emotionStepKey": "情感链步骤 key",
|
||
"emotionGoal": "本章情绪目标",
|
||
"payoff": "本章兑现",
|
||
"endingHook": "章末信息",
|
||
"forbidden": "本章禁止事项",
|
||
"targetWords": 2000,
|
||
"status": "planned"
|
||
}
|
||
]
|
||
}""",
|
||
"chapter": """
|
||
|
||
【输出格式】只输出 JSON:
|
||
{ "title": "章标题", "body": "正文(可分段)" }""",
|
||
"nudge": "",
|
||
}
|
||
|
||
|
||
def resolve_prompt(prompt_key: str, user_text: str | None) -> str:
|
||
"""合并用户自然语言指令与内部 JSON 输出格式,供 LLM 系统提示使用。"""
|
||
base = (user_text or "").strip()
|
||
if not base:
|
||
base = USER_DEFAULT_PROMPTS.get(prompt_key, "")
|
||
fmt = _INTERNAL_FORMAT.get(prompt_key, "")
|
||
if fmt and fmt.strip() not in base:
|
||
return base + fmt
|
||
return base
|