MyFramework User 04ad7a956a feat: AI 规划阶段输出 TTS 配置(音色/语速/情感) 2 月之前
..
nodes 04ad7a956a feat: AI 规划阶段输出 TTS 配置(音色/语速/情感) 2 月之前
parsers 60035a4230 fix: 修复后端 TypeScript 编译错误 3 月之前
prompts 04ad7a956a feat: AI 规划阶段输出 TTS 配置(音色/语速/情感) 2 月之前
strategies 04ad7a956a feat: AI 规划阶段输出 TTS 配置(音色/语速/情感) 2 月之前
test 29f20e7c0c feat: Step2交互式规划UX重构 - 卡片化展示 + 自然语言反馈 + 竖向按钮布局 3 月之前
utils 3d96c37e39 feat: 全面更新前端UI + 后端优化 + 工具脚本集 3 月之前
FAULT_TOLERANCE.md 63d8ff6612 feat: 实现书籍批量视频生成和视频播放功能 4 月之前
README.md ed13c05c3b feat: 大纲生成优化 - jsonrepair + 48000 tokens + Markdown兜底 + mustNotRepeat章号引用 3 月之前
ai-generate-controller.ts 7ac66b656a feat: 实现订阅支付系统基础功能 4 月之前
album-controller.ts 6ef8b368b7 feat: 优化有声书创建流程界面交互 3 月之前
album-management.controller.ts 00d5ccbc57 feat: 实现功能34 - 内容管理(重命名和移动) 4 月之前
audio-scanner.ts 3d96c37e39 feat: 全面更新前端UI + 后端优化 + 工具脚本集 3 月之前
book-generator-optimizations.ts 9fa22eacdc fix: 修复控制器语法错误 - 删除多余的括号和修复模板字符串 4 月之前
book-generator.controller.ts c89e650d63 feat: 全面优化 - 状态系统重构 + 前端UI升级 + 团队协作文档 3 月之前
book-generator.service.ts 6ef8b368b7 feat: 优化有声书创建流程界面交互 3 月之前
book-generator.store.ts 04ad7a956a feat: AI 规划阶段输出 TTS 配置(音色/语速/情感) 2 月之前
book-generator.types.ts 04ad7a956a feat: AI 规划阶段输出 TTS 配置(音色/语速/情感) 2 月之前
book-queue.processor.ts 9a5c3a3bf0 fix: 全局统一默认bookScale为1000而非130000(8处修正) 3 月之前
book-type-config.ts 6429b1cef2 fix: CosyVoice SSE 增加详细诊断日志,定位未收到音频数据错误 3 月之前
fault-tolerance.ts 9a5c3a3bf0 fix: 全局统一默认bookScale为1000而非130000(8处修正) 3 月之前
graph.ts 04ad7a956a feat: AI 规划阶段输出 TTS 配置(音色/语速/情感) 2 月之前
index.ts 04ad7a956a feat: AI 规划阶段输出 TTS 配置(音色/语速/情感) 2 月之前
langgraph-controller.ts 04ad7a956a feat: AI 规划阶段输出 TTS 配置(音色/语速/情感) 2 月之前
langgraph-generator.ts.bak 9fa22eacdc fix: 修复控制器语法错误 - 删除多余的括号和修复模板字符串 4 月之前
langgraph-types.ts 29f20e7c0c feat: Step2交互式规划UX重构 - 卡片化展示 + 自然语言反馈 + 竖向按钮布局 3 月之前
stage-manager.ts 3d96c37e39 feat: 全面更新前端UI + 后端优化 + 工具脚本集 3 月之前
tts-queue.ts 04ad7a956a feat: AI 规划阶段输出 TTS 配置(音色/语速/情感) 2 月之前
utils.ts 3d96c37e39 feat: 全面更新前端UI + 后端优化 + 工具脚本集 3 月之前

README.md

书籍生成模块 (Book Generator)

基于 LangGraph 的三级目录书籍生成模块。

核心设计

三级目录结构

章 (level=1, parentId=null)
 └─ 节 (level=2, parentId=章ID)
      └─ 小节 (level=3, parentId=节ID) ← 存储实际正文内容

内容存储规则

层级 level parentId content 说明
1 null 不存储 只做目录
2 章ID 不存储 只做目录
小节 3 节ID 存储 唯一内容存储

设计原则:正文只存在于小节,章/节只做目录导航,无冗余数据。

数据库结构

BookChapter 表

model BookChapter {
  id              Int       @id @default(autoincrement())
  bookId          Int
  parentId        Int?      // 父节点ID(null = 章这一级)
  level           Int       @default(1)  // 1=章, 2=节, 3=小节
  number          Int       // 同级排序序号
  title           String    // 章节标题
  summary         String?   @db.Text
  keyPoints       String?   @db.Text  // JSON数组
  estimatedWords  Int       @default(1000)
  content         String?   @db.LongText  // 仅小节存储正文
  wordCount       Int       @default(0)
  status          String    @default("pending")

  book            Book      @relation(fields: [bookId], references: [id], onDelete: Cascade)
  parent          BookChapter? @relation("ChapterChildren", fields: [parentId], references: [id])
  children        BookChapter[] @relation("ChapterChildren")

  @@unique([bookId, level, number])
  @@index([bookId])
  @@index([bookId, parentId])
  @@index([bookId, level])
}

示例数据

id bookId parentId level number title
1 1 null 1 1 第一章:人工智能概述
5 1 1 2 1 1.1 人工智能的历史
10 1 5 3 1 1.1.1 早期发展
11 1 5 3 2 1.1.2 符号主义与统计方法

生成流程

1. generateOutlineNode
   └─ 生成章标题 → 入库 level=1

2. generateFullOutlineNode
   └─ 为每章生成节 → 入库 level=2
   └─ 为每节生成小节 → 入库 level=3

3. writeChaptersNode
   └─ 逐小节生成 content → 写入 level=3
   └─ 不再合并到 level=1/2

4. writeForewordNode → 写入 Book.foreword

5. writeAfterwordNode → 写入 Book.afterword

状态流转

draft → generating → planning → generating → completed
         (创建)      (大纲)    (内容)     (完成)
状态 说明
draft 草稿
generating 生成中(创建/内容阶段)
planning 规划中(大纲生成阶段)
completed 已完成
failed 失败

API 接口

创建书籍(LangGraph 异步)

POST /api/book-generator/langgraph/books

获取书籍详情

GET /api/book-generator/langgraph/books/:id

返回章节数据示例:

{
  "book": {
    "id": "1",
    "title": "人工智能入门",
    "chapters": [
      {
        "id": "1",
        "number": 1,
        "title": "第一章:人工智能概述",
        "level": 1,
        "parentId": null,
        "content": ""
      },
      {
        "id": "5",
        "number": 1,
        "title": "1.1 人工智能的历史",
        "level": 2,
        "parentId": 1,
        "content": ""
      },
      {
        "id": "10",
        "number": 1,
        "title": "1.1.1 早期发展",
        "level": 3,
        "parentId": 5,
        "content": "正文内容..."
      }
    ]
  }
}

前端渲染

按 parentId 分组构建树

function buildChapterTree(chapters: Chapter[]) {
  const map = new Map<number | null, Chapter[]>();
  chapters.forEach(c => {
    const key = c.parentId;
    if (!map.has(key)) map.set(key, []);
    map.get(key)!.push(c);
  });
  return {
    chapters: map.get(null) || [],  // 章 level=1
    getSections: (chapterId: number) => map.get(chapterId) || [],  // 节 level=2
    getSubsections: (sectionId: number) => map.get(sectionId) || [],  // 小节 level=3
  };
}

Vue 模板示例

<view v-for="chapter in chapters.filter(c => c.level === 1)" :key="chapter.id">
  <!-- 章 -->
  <text class="chapter-title">{{ chapter.title }}</text>

  <view v-for="section in chapters.filter(c => c.parentId === chapter.id)" :key="section.id">
    <!-- 节 -->
    <text class="section-title">{{ section.title }}</text>

    <view v-for="sub in chapters.filter(c => c.parentId === section.id)" :key="sub.id">
      <!-- 小节 -->
      <text class="subsection-title">{{ sub.title }}</text>
      <text v-if="sub.content">{{ sub.content }}</text>
    </view>
  </view>
</view>

核心文件

文件 说明
langgraph-generator.ts LangGraph 工作流定义,5个节点
book-generator.store.ts 数据库操作,BookStore 类
book-generator.types.ts 类型定义
book-type-config.ts 书籍类型配置
langgraph-controller.ts API 路由

LangGraph 节点

节点 说明
generateOutlineNode 生成章大纲
generateFullOutlineNode 生成节和小节,存入 DB
writeChaptersNode 生成小节 content,存入 DB
writeForewordNode 生成前言
writeAfterwordNode 生成后记

大纲输出格式(大纲策略)

当前方案:JSON(主力)

  • 格式{"chapters":[{"writingInstructions":{...}}]}
  • 模型:一次性生成全部章节,利用上下文全局视野保证跨章一致性
  • 容错:jsonrepair 自动修复 + 4 层兜底策略 + Markdown 解析(策略5)
  • maxTokens:大纲专用 48000 tokens(richOutlineNode 中配置)
  • 跨章避重:prompt 明确要求 mustNotRepeat 注明章号(如"不要重复第3章的XX")

备选方案:Markdown(未来可切换)

与 JSON 方案做过 4 章 / 65 章全量对比测试,Markdown 格式有以下优势:

维度 JSON Markdown
LLM 原生性 低(训练语料少) (母语格式)
格式容错 依赖 jsonrepair 天生容错(单点故障只影响当前章节)
文笔质感 学院派,精准 更自然,对话感强
跨章引用 依赖 prompt 约束 天然写"不要与第13章混淆"
人可读性 需解析 直接阅读
下游兼容 ✅ 无需改动 ❌ 需改造 quality_check / rewrite 等节点
切换方式 默认 process.env.OUTLINE_FORMAT='markdown'

切换方法

# 环境变量方式(整个服务生效)
OUTLINE_FORMAT=markdown npm run dev

# 代码方式(单次调用)
process.env.OUTLINE_FORMAT = 'markdown';

切换前提(暂未实施):

  1. quality-check.node.ts:解析 writingInstructions 时改用 Markdown 正则
  2. rewrite.node.ts:同上
  3. content.node.ts:同上
  4. 前端大纲预览组件:支持渲染 Markdown 大纲

结论:JSON 当前是最佳选择(零成本适配下游),Markdown 已作为策略5兜底 + 未来切换方案就绪。

扩展方向

  1. 并行生成:章→节→小节三层可并行生成
  2. 增量更新:支持单独更新某个小节内容
  3. 版本管理:记录每次生成的历史版本
  4. 导出格式:支持导出 PDF、EPUB、DOCX