Isshin AI TextFlow_开发文档_第三回:剧本生成

5 阅读8分钟

生成剧本:技术逻辑梳理

工作流第二步「生成剧本」——在事件提取完成后,依次调用大模型生成故事骨架 → 改编策略 → 逐集剧本,写入 SQLite,供后续「生成资产 / 分镜 / 视频」使用。


1. 整体链路

上一节点 novel_chapters.event(每章 pipe 事件摘要)
        │
        ▼
用户发送「开始生成剧本」(或点击快捷指令)
        │
        ▼
runScriptPipeline(orchestrator.ts)
        │
        ├─► 阶段 1:故事骨架(1 次 LLM)
        │         └─ 写入 script_work_data.story_skeleton
        │
        ├─► 阶段 2:改编策略(1 次 LLM)
        │         └─ 写入 script_work_data.adaptation_strategy
        │
        └─► 阶段 3:逐集剧本(每章 1 次 LLM,顺序执行)
                  └─ 写入 scripts(name / content / script_state)
        │
        ▼
右侧工作台展示骨架、策略、逐集剧本表 → 下游资产 / 分镜

分步说明

  1. 前置:全部章节 event_state = 1event 非空(事件提取完成)。
  2. 触发:左侧编剧助手聊天发送「开始生成剧本」→ runScriptPipeline
  3. 三阶段流水线:骨架与策略各调 1 次 LLM;剧本按章 逐集顺序 调 LLM(默认 1 章 = 1 集)。
  4. 落库:中间产物进 script_work_data,逐集剧本进 scripts;成功后工作流可推进到下一节点。

一句话(含 LLM 输入)

本节点共 2 + N 次 LLM 调用(N = 章节数)。每次 POST /chat/completionsmessages 均为 [system Prompt, user 拼接块]max_tokens: 8192stream: false。user 块的核心输入来自:

阶段system Promptuser 主要数据来源
故事骨架STORY_SKELETON_PROMPT项目配置 + 导演手册 + 全部章节 event
改编策略ADAPTATION_STRATEGY_PROMPT项目配置 + 导演手册 + 故事骨架 + 全部章节 event
逐集剧本EPISODE_SCRIPT_PROMPT项目配置 + 导演手册 + 骨架 + 策略 + 本章 event + 本章原文 + 上一集剧本

2. 前置条件与数据依赖

2.1 入口校验

UIsrc/components/AiScriptStep.tsx
未完成事件提取时只显示提示,不展示工作台。

流水线runScriptPipeline 开头调用 isEventExtractionComplete(chapters),否则抛错「请先完成全部章节的事件提取」。

2.2 上游输入(来自「提取事件」)

字段用途
chapterIndexnovel_chaptersepisodeIndex 一一对应(默认 1 章 = 1 集)
chapternovel_chapters集标题、剧本名 {项目名} EP{NN}:{章名}
chapterDatanovel_chapters逐集剧本 user 消息中的「本章原文」
eventnovel_chapterspipe 事件行(含涉及角色、涉及场景等),写入「章节事件表」

事件在 user 消息中的格式(formatChapterEvents):

第1章《惊梦重生,回到十八年前》事件:|第1章 … | 林远、王雪 | 大学男生宿舍 | … |

2.3 项目侧输入

数据来源用途
project.name / novelType / intro / artStyle / aspectRatio创建项目时填写各阶段 user 的「项目配置」块
project.directorManual项目选定的导演手册 Skill ID加载手册正文,注入「导演手册(必须严格遵循)」块
config.baseUrl / apiKey设置页LLM 鉴权与地址
model界面所选模型请求体 model 字段

3. 阶段零:触发与编排(UI + Hook)

核心文件

  • src/components/AiScriptStep.tsx — 左聊天 + 右工作台布局
  • src/hooks/useScriptAgentChat.ts — 发送消息、启动流水线、进度展示
  • src/agents/workflowAgent/scriptGeneration/orchestrator.ts — 三阶段调度

用户发送「开始生成剧本」(或等价快捷指令)时:

  1. shouldStartScriptPipeline 识别意图 → 调用 runScriptPipeline
  2. onProgress 更新 UI(骨架 / 策略 / 逐集进度)
  3. onStageComplete 每完成一阶段即刷新右侧工作台(骨架、策略可先看到)
  4. 全部完成后 onWorkflowChange 推进工作流节点

聊天里还可走 编剧协调 Agent(流式对话 + 修改计划),那是修订分支,见 §8。


4. 阶段一:故事骨架(1 次 LLM)

Agentsrc/agents/workflowAgent/scriptGeneration/storySkeletonAgent.ts
Promptsrc/prompts/workflowAgent/scriptGeneration/storySkeleton.tsSTORY_SKELETON_PROMPT

4.1 user 消息拼装(baseUserContent

按顺序拼接 Markdown 文本块:

  1. 项目配置buildProjectConfigBlock(project)
  2. 导演手册buildDirectorSkillBlock(directorSkillContent)(有则注入)
  3. 总章节数ctx.chapters.length(默认 1 章 = 1 集)
  4. 章节事件表formatChapterEvents(chapters)全部章event
  5. 任务说明 — 要求先 200–300 字思路,再 Markdown 输出 6 个 ## 章节

4.2 最终 HTTP Body 结构

{
  "model": "用户选择的模型名",
  "stream": false,
  "max_tokens": 8192,
  "messages": [
    { "role": "system", "content": "<STORY_SKELETON_PROMPT>" },
    { "role": "user", "content": "<项目配置>\n<导演手册>\n总章节数:3\n\n## 章节事件表\n第1章《…》事件:|…|\n第2章…\n\n请基于以上事件表构建故事骨架…" }
  ]
}

API Trace 标签script-skeleton

4.3 期望输出与校验

  • 先 200–300 字思路阐述,再 Markdown 正文
  • 必须包含 6 个二级标题:故事核、隐线、三幕结构、分集决策、全局删减决策表、付费卡点设计
  • parseStorySkeletonOutput + getMissingStorySkeletonSections 校验;最多重试 3 次

4.4 落库

setScriptWorkData(projectId, { storySkeleton }) → SQLite script_work_data.story_skeleton


5. 阶段二:改编策略(1 次 LLM)

AgentadaptationStrategyAgent.ts
PromptadaptationStrategy.tsADAPTATION_STRATEGY_PROMPT

5.1 user 消息拼装

在骨架阶段基础上,user 块增加:

来源
故事骨架上一阶段产出 / script_work_data.story_skeleton
章节事件表仍带全部章 event(与骨架阶段相同)

5.2 最终 HTTP Body 结构

{
  "model": "…",
  "stream": false,
  "max_tokens": 8192,
  "messages": [
    { "role": "system", "content": "<ADAPTATION_STRATEGY_PROMPT>" },
    { "role": "user", "content": "<项目配置>\n<导演手册>\n\n## 故事骨架\n{骨架全文}\n\n## 章节事件表\n{全部 event}\n\n请基于故事骨架制定改编策略…" }
  ]
}

API Trace 标签script-adaptation

5.3 期望输出与校验

  • Markdown,5 个二级标题:改编基调、人物改编、场景改编、分集脚本指引、衔接规则
  • 最多重试 3 次setScriptWorkData({ adaptationStrategy })

6. 阶段三:逐集剧本(每章 1 次 LLM,顺序执行)

AgentepisodeScriptAgent.ts
PromptepisodeScript.tsEPISODE_SCRIPT_PROMPT
调度orchestrator.writeEpisodeScript无并发,按 chapterIndex 升序逐集生成

6.1 单集 user 消息拼装(baseUserContent

来源
项目配置CreationProject
导演手册Skill 正文
当前任务episodeIndex、章名 {chapter.chapter}
剧本名称{项目名} EP{NN}:{章名}(XML name 属性须一致)
故事骨架workData.storySkeleton
改编策略workData.adaptationStrategy
本章事件formatChapterEventsByIndexes(chapters, [episodeIndex])仅本章 event
本章原文chapter.chapterData
上一集剧本scriptsepisodeIndex - 1content(第 1 集无)

第 2 集及以后会带上第 1 集已生成的剧本正文,保证集间衔接。

6.2 最终 HTTP Body 结构(以第 1 集为例)

{
  "model": "…",
  "stream": false,
  "max_tokens": 8192,
  "messages": [
    { "role": "system", "content": "<EPISODE_SCRIPT_PROMPT>" },
    {
      "role": "user",
      "content": "## 项目配置\n作品名称:Demo1\n…\n\n当前任务:编写第 1 集剧本(对应第 1 章《惊梦重生,回到十八年前》)\n剧本名称(name 属性):Demo1 EP01:惊梦重生,回到十八年前\n\n## 故事骨架\n{骨架全文}\n\n## 改编策略\n{策略全文}\n\n## 本章事件\n第1章《…》事件:|…|\n\n## 本章原文\n{chapterData 全文}\n\n请编写本集完整剧本,使用 <scriptItem name=\"Demo1 EP01:…\"> 包裹正文。"
    }
  ]
}

API Trace 标签script-episode

6.3 期望输出与解析

模型应先输出思路阐述,再用 XML 包裹剧本:

<scriptItem name="Demo1 EP01:惊梦重生,回到十八年前">
# Demo1 EP01:惊梦重生,回到十八年前

## 剧情梗概
…

## 场景1 · 内 · 大学男生宿舍 · 日
△ …
林远:…
</scriptItem>

解析链:

stripThink(raw)
  → parseEpisodeScriptOutput(text, expectedName)
       → extractScriptItems(XML)或 extractScriptMarkdownFallback
  → { name, content }
  → upsertScript → scripts 表

最多重试 3 次;失败则 script_state = 2errorReason 存原因,不阻断后续集(当前实现是逐集 try/catch,失败集标记错误后继续下一集)。

6.4 落库与副作用

upsertScript(Rust script.rs)写入:

字段含义
episode_index= chapter.chapterIndex
name剧本名称
contentMarkdown 剧本正文
script_state1 成功 / 2 失败

副作用:maybe_advance_after_script 检查是否全部集成功 → 推进工作流;sync_episode_asset_bindings 扫描剧本绑定资产。


7. 调用大模型汇总表

项目
HTTPPOST {baseUrl}/chat/completions
鉴权Authorization: Bearer {apiKey}
调用方式chatCompletionsrc/services/chat.ts
总次数2 + N(N = 章节数;修订 / 重试会额外增加)
并发骨架、策略、各集均为 串行(逐集剧本 for 循环)
max_tokens8192(三阶段相同)

三阶段 LLM 输入对比

                    ┌─────────────┬─────────────┬─────────────┐
                    │  故事骨架   │  改编策略   │  逐集剧本   │
├───────────────────┼─────────────┼─────────────┼─────────────┤
│ 项目配置          │      ✓      │      ✓      │      ✓      │
│ 导演手册          │      ✓      │      ✓      │      ✓      │
│ 全部章节 event    │      ✓      │      ✓      │             │
│ 本章 event        │             │             │      ✓      │
│ 故事骨架          │             │      ✓      │      ✓      │
│ 改编策略          │             │             │      ✓      │
│ 本章原文          │             │             │      ✓      │
│ 上一集剧本        │             │             │  ✓(≥第2集)│
└───────────────────┴─────────────┴─────────────┴─────────────┘

8. 修订与重试(补充)

除首次「开始生成剧本」外,还有三条常见路径(同一套 Agent,user 块会附加「主创修改意见」等):

能力入口核心函数
重试失败集工作台「重试失败集」regenerateFailedEpisodes — 只重跑 script_state = 2 的集
聊天修订编剧助手对话 + 修改计划卡片applyRevisionPlan — 可按集 / 策略 / 骨架范围修订
协调对话非「开始生成剧本」的普通聊天streamCoordinatorChat — 流式,产出修订计划 JSON

修订时逐集 Agent 还可附带:previousDraft(当前剧本草稿)、cascadeFollowUp(连锁重生成后续集)。


9. 关键文件索引

职责文件
UI 入口、布局src/components/AiScriptStep.tsx
聊天、启动流水线src/hooks/useScriptAgentChat.ts
三阶段调度src/agents/workflowAgent/scriptGeneration/orchestrator.ts
故事骨架 AgentstorySkeletonAgent.ts + prompts/.../storySkeleton.ts
改编策略 AgentadaptationStrategyAgent.ts + prompts/.../adaptationStrategy.ts
逐集剧本 AgentepisodeScriptAgent.ts + prompts/.../episodeScript.ts
user 块拼装工具scriptGeneration/tools.ts
XML / Markdown 解析src/utils/xmlTags.ts
HTTP 调 LLMsrc/services/chat.ts
剧本持久化src/services/script.ts + src-tauri/src/script.rs
事件 pipe 解析(详情页人物/场景标签)src/utils/parseEventFields.ts
工作台展示src/components/ScriptWorkspacePanel.tsx

10. 设计要点(分享时可强调)

  1. 强依赖上一节点:剧本流水线不读原始粘贴全文做全局规划,而是读 结构化 event;逐集阶段同时读 本章原文 保证细节。
  2. 三阶段递进:先全局骨架 → 再改编策略 → 最后逐集落地;后阶段输入包含前阶段全部产出。
  3. 1 章 1 集chapterIndexepisodeIndex 对齐;逐集时带入上一集剧本做衔接。
  4. 导演手册贯穿:三阶段 system + user 均可注入 Skill 正文,优先级高于模型默认习惯。
  5. 格式硬校验 + 重试:骨架/策略查 Markdown 章节齐全;剧本查 <scriptItem> XML(含 Markdown 兜底)。
  6. 增量可见:每阶段完成即写库并刷新 UI,不必等全部 N 集结束。

11. 与下游的关系

  • scripts.content生成资产(从剧本提取人物/场景/道具)、制作分镜生成视频
  • novel_chapters.event 中的人物/场景 → 剧本详情页标签展示(parseEventCharactersAndScenes
  • 全部集 script_state = 1 后工作流进入「生成资产」等后续节点