""" 爽文提示词解析 — 用户自然语言 + 内部 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