# All files / modules/book-generator/prompts builder.ts

0% Statements 0/196
0% Branches 0/1
0% Functions 0/1
0% Lines 0/196

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296

     /**
     * 提示词组装器
     * 根据需求分析动态组装提示词
     * 增强版：扩展正则覆盖 + 集成 DeepPlan AI 输出
     */

    import { ChatMessage } from '../../../services/llm';
    import {
      OUTLINE_SYSTEM_PROMPT,
      SECTION_SYSTEM_PROMPT,
      SUBSECTION_SYSTEM_PROMPT,
    } from './templates';
    import {
      BOOK_TYPE_PROMPTS,
      AUDIENCE_PROMPTS,
      DEPTH_PROMPTS,
      INDUSTRY_PROMPTS,
    } from './dynamic.config';

    // ============ 规模配置 ============

    // ============ 规模配置（黄金数 φ=1.618，基数13万）============
    // 字数为精确值，AI 生成时自行理解 ±20% 浮动

    export const SCALE_CHAPTER_RANGE: Record<string, number> = {
      '340000': 35,   // 上2：34万字
      '210000': 27,   // 上1：21万字
      '130000': 17,   // 标准：13万字
      '80000': 12,    // 下1：8万字
      '50000': 9,     // 下2：5万字
      '31000': 7,     // 下3：3.1万字
      '19000': 5,     // 下4：1.9万字
      '12000': 4,     // 下5：1.2万字
      '7000': 3,      // 下6：7千字
      '4000': 2,      // 下7：4千字
      '3000': 1,      // 下8：3千字
      '2000': 1,      // 下9：2千字
      '1000': 1,      // 下10：1千字
    };

    export const SCALE_DESC: Record<string, string> = {
      '340000': '上2，约34万字',
      '210000': '上1，约21万字',
      '130000': '标准，约13万字',
      '80000': '下1，约8万字',
      '50000': '下2，约5万字',
      '31000': '下3，约3.1万字',
      '19000': '下4，约1.9万字',
      '12000': '下5，约1.2万字',
      '7000': '下6，约7千字',
      '4000': '下7，约4千字',
      '3000': '下8，约3千字',
      '2000': '下9，约2千字',
      '1000': '下10，约1千字',
    };

    // ============ 需求分析（增强版） ============

    /**
     * 需求分析: 从用户描述中提取关键信息
     * 增强版：覆盖更多关键词模式，可接受 AI deepPlan 输出作为高置信度来源
     */
    interface BookRequirements {
      bookType?: string;      // 教材/技术教程/小说/商业/科普/传记/历史/学术/心理学
      audience?: string;      // 儿童/青少年/初学者/大学生/研究生/专业人士/大众读者/中老年
      depth?: string;         // 入门/基础/进阶/高级/专家
      industry?: string;      // IT/金融/医学/教育/法律/建筑/农业
      specialNeeds?: string[]; // 特殊需求: 有案例/有代码/有习题等
    }

    export function analyzeRequirements(topic: string, description?: string, deepPlan?: any): BookRequirements {
      const text = `${topic} ${description || ''}`.toLowerCase();
      const req: BookRequirements = {
        specialNeeds: [],
      };

      // 分析书籍类型（扩展覆盖）
      if (/教材|教科书|课本|课程|教学大纲|教案/i.test(text)) {
        req.bookType = '教材';
      } else if (/教程|实战|开发|编程|代码|软件开发|框架|语言入门/i.test(text)) {
        req.bookType = '技术教程';
      } else if (/小说|故事|文学|散文|诗歌|剧本/i.test(text)) {
        req.bookType = '小说';
      } else if (/传记|自传|回忆录|生平|口述/i.test(text)) {
        req.bookType = '传记';
      } else if (/商业|管理|营销|创业|投资|经济|理财|商业模式/i.test(text)) {
        req.bookType = '商业';
      } else if (/科普|百科|科学|探索|揭秘|知识普及/i.test(text)) {
        req.bookType = '科普';
      } else if (/历史|古代|近代|朝代|文明|考古/i.test(text)) {
        req.bookType = '历史';
      } else if (/学术|论文|研究|理论|方法论|综述/i.test(text)) {
        req.bookType = '学术';
      } else if (/心理|情感|情绪|认知|行为|精神/i.test(text)) {
        req.bookType = '心理学';
      }

      // 分析目标读者（扩展覆盖）
      if (/儿童|小学生|幼儿|宝宝|小朋友|童书/i.test(text)) {
        req.audience = '儿童';
      } else if (/青少年|中学生|高中生|青春期/i.test(text)) {
        req.audience = '青少年';
      } else if (/初学者|入门|新手|零基础|小白|初学|入门级/i.test(text)) {
        req.audience = '初学者';
      } else if (/大学生|本科生|高校|大学/i.test(text)) {
        req.audience = '大学生';
      } else if (/研究生|硕士|博士|硕博/i.test(text)) {
        req.audience = '研究生';
      } else if (/专业|高级|深入|专家|资深|从业者|工程师/i.test(text)) {
        req.audience = '专业人士';
      } else if (/大众|通俗|普及|广泛|普通人|一般读者|社会/i.test(text)) {
        req.audience = '大众读者';
      } else if (/中老年|退休|老年|养老|银发/i.test(text)) {
        req.audience = '中老年';
      }

      // 分析知识难度（扩展覆盖）
      if (/入门|零基础|简单|易懂|新手向|轻松|小白/i.test(text)) {
        req.depth = '入门';
      } else if (/基础|基本概念|循序渐进|打好基础|基本功/i.test(text)) {
        req.depth = '基础';
      } else if (/进阶|深入|系统全面|提升|精进/i.test(text)) {
        req.depth = '进阶';
      } else if (/高级|专业深入|前沿|尖端|最新/i.test(text)) {
        req.depth = '高级';
      } else if (/专家|研究|底层原理|源码|架构|大师/i.test(text)) {
        req.depth = '专家';
      }

      // 分析行业领域（扩展覆盖）
      if (/计算机|IT|编程|软件|互联网|AI|人工智能|机器学习|深度学习|算法/i.test(text)) {
        req.industry = 'IT/计算机';
      } else if (/金融|股票|投资|银行|证券|基金|保险|理财/i.test(text)) {
        req.industry = '金融';
      } else if (/医学|医疗|健康|临床|疾病|医生|护理|药学/i.test(text)) {
        req.industry = '医学';
      } else if (/教育|教学|学习|学校|课程|考试|培训/i.test(text)) {
        req.industry = '教育';
      } else if (/法律|法规|律师|合同|诉讼|司法|民法|刑法/i.test(text)) {
        req.industry = '法律';
      } else if (/建筑|设计|施工|工程|土木|装修/i.test(text)) {
        req.industry = '建筑/工程';
      } else if (/农业|种植|养殖|畜牧|渔业|农产品/i.test(text)) {
        req.industry = '农业';
      }

      // 分析特殊需求（扩展覆盖）
      if (/案例|实例|例子|示例/i.test(text)) req.specialNeeds!.push('有案例');
      if (/代码|源码|编程|示例代码/i.test(text)) req.specialNeeds!.push('有代码');
      if (/习题|练习|作业|测试|考题/i.test(text)) req.specialNeeds!.push('有习题');
      if (/图表|插图|配图|图解|示意图/i.test(text)) req.specialNeeds!.push('有图表');
      if (/项目|实战|实践|动手|实验/i.test(text)) req.specialNeeds!.push('有项目实战');
      if (/总结|小结|回顾|要点/i.test(text)) req.specialNeeds!.push('有总结');
      if (/引用|参考文献|资料|出处/i.test(text)) req.specialNeeds!.push('有参考文献');

      // 如果有 AI deepPlan 输出，用高置信度结果覆盖正则匹配
      if (deepPlan) {
        if (deepPlan.bookType) req.bookType = deepPlan.bookType;
        if (deepPlan.contentDepth) {
          const depthMap: Record<string, string> = { '入门': '入门', '基础': '基础', '进阶': '进阶', '高级': '高级', '专家': '专家' };
          req.depth = depthMap[deepPlan.contentDepth] || req.depth;
        }
        if (deepPlan.audienceCalibration?.desiredOutcome) {
          const outcome = deepPlan.audienceCalibration.desiredOutcome || '';
          if (/专业|高级|专家/i.test(outcome) && !req.audience) req.audience = '专业人士';
          if (/入门|新手|初学/i.test(outcome) && !req.audience) req.audience = '初学者';
        }
      }

      return req;
    }

    /**
     * 动态组装提示词
     * @param deepPlan 可选的 AI 深度规划结果
     */
    export function buildDynamicPrompt(topic: string, bookScale: string, description?: string, deepPlan?: any): string {
      const req = analyzeRequirements(topic, description, deepPlan);

      // 基础提示词
      let prompt = OUTLINE_SYSTEM_PROMPT;

      // 根据书籍类型添加
      if (req.bookType && BOOK_TYPE_PROMPTS[req.bookType]) {
        prompt += BOOK_TYPE_PROMPTS[req.bookType];
      }

      // 根据目标读者添加
      if (req.audience && AUDIENCE_PROMPTS[req.audience]) {
        prompt += AUDIENCE_PROMPTS[req.audience];
      }

      // 根据内容深度添加
      if (req.depth && DEPTH_PROMPTS[req.depth]) {
        prompt += DEPTH_PROMPTS[req.depth];
      }

      // 根据行业领域添加
      if (req.industry && INDUSTRY_PROMPTS[req.industry]) {
        prompt += INDUSTRY_PROMPTS[req.industry];
      }

      // 特殊需求
      if (req.specialNeeds!.length > 0) {
        prompt += `\n## 特殊要求\n`;
        prompt += `根据用户需求，本书应包含: ${req.specialNeeds!.join('、')}\n`;
      }

      console.log(`[DynamicPrompt] 检测到需求:`, req);

      return prompt;
    }

    // ============ 消息构建函数 ============

    /**
     * 从描述中提取明确的字数要求
     * 如 "生成200字文本" → 200
     */
    function extractWordCountFromDescription(description: string | undefined): number | null {
      if (!description) return null;
      const text = description.toLowerCase();
      const match = text.match(/(\d+)\s*字/i);
      if (match) {
        const n = parseInt(match[1]);
        return isNaN(n) ? null : n;
      }
      return null;
    }

    /**
     * 构建大纲生成消息（动态提示词）
     * @param bookPlan 前序规划节点的分析结果（可选），包含写作风格、结构逻辑、内容深度等
     */
    export function buildOutlineMessages(topic: string, bookScale: string, description?: string, bookPlan?: any): ChatMessage[] {
      const chapters = SCALE_CHAPTER_RANGE[bookScale as keyof typeof SCALE_CHAPTER_RANGE] || 10;

      // 使用动态提示词（传入 bookPlan 以利用 AI 分析结果增强正则匹配）
      let systemPrompt = buildDynamicPrompt(topic, bookScale, description, bookPlan);

      // 如果有规划结果，追加到系统提示词中
      if (bookPlan) {
        const planExtra: string[] = [];
        if (bookPlan.writingStyle) planExtra.push(`写作风格：${bookPlan.writingStyle}`);
        if (bookPlan.structureLogic) planExtra.push(`结构逻辑：${bookPlan.structureLogic}`);
        if (bookPlan.contentDepth) planExtra.push(`内容深度：${bookPlan.contentDepth}`);
        if (bookPlan.targetAudienceAnalysis) planExtra.push(`目标读者：${bookPlan.targetAudienceAnalysis}`);
        if (bookPlan.bookTypeAnalysis) planExtra.push(`书籍分析：${bookPlan.bookTypeAnalysis}`);
        if (bookPlan.reasoning) planExtra.push(`规划理由：${bookPlan.reasoning}`);

        if (planExtra.length > 0) {
          systemPrompt += `\n\n## 前序规划参考\n以下是对本书的规划分析结果，请据此生成大纲：\n${planExtra.join('\n')}`;
        }
      }

      // 如果 description 里有明确字数要求，优先用它作为规模
      const descWordCount = extractWordCountFromDescription(description);
      const scaleDesc = descWordCount !== null
        ? `约${descWordCount}字（用户明确要求）`
        : (SCALE_DESC[bookScale] || '中篇');

      return [
        { role: 'system', content: systemPrompt },
        {
          role: 'user',
          content: `书名：《${topic}》\n规模：${scaleDesc}\n章节数：约${chapters}章\n${description ? `需求描述：${description}\n` : ''}\n请生成书籍大纲。`,
        },
      ];
    }

    /**
     * 构建节大纲生成消息
     */
    export function buildSectionMessages(chapterTitle: string, chapterSummary: string, keyPoints: string[]): ChatMessage[] {
      return [
        { role: 'system', content: SECTION_SYSTEM_PROMPT },
        {
          role: 'user',
          content: `章标题：${chapterTitle}\n章概述：${chapterSummary}\n核心知识点：${keyPoints.join('、')}\n\n请为该章设计节的大纲（通常每章 2-4 节）。`,
        },
      ];
    }

    /**
     * 构建小节大纲生成消息
     */
    export function buildSubsectionMessages(sectionTitle: string, sectionSummary: string, keyPoints: string[]): ChatMessage[] {
      return [
        { role: 'system', content: SUBSECTION_SYSTEM_PROMPT },
        {
          role: 'user',
          content: `节标题：${sectionTitle}\n节概述：${sectionSummary}\n核心知识点：${keyPoints.join('、')}\n\n请为该节设计小节的大纲（通常每节 2-4 小节）。`,
        },
      ];
    }