index.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /**
  2. * LangGraph 书籍生成器 - 主入口(策略门面)
  3. *
  4. * 使用策略模式,通过 strategies/selector.ts 配置切换不同生成方案
  5. *
  6. * 当前支持策略:
  7. * 1. sequential - 串行(原始方案)
  8. * 2. one-step-outline - 一步大纲 + 并行内容
  9. * 3. per-chapter - 逐章内聚
  10. * 4. deep-plan-parallel - DeepPlan+RichOutline+Concurrent+Edit(当前推荐,默认策略)
  11. *
  12. * 大纲层级(genLevel):
  13. * 1 = 仅章(短文/小说/故事类)
  14. * 2 = 章→节(科普/商业/大众类)
  15. * 3 = 章→节→小节(教材/技术教程/专业类)
  16. */
  17. import { bookStore } from './book-generator.store';
  18. import { getScaleConfig } from './book-type-config';
  19. import { getCurrentStrategy, setCurrentStrategy, getAllStrategies, getCurrentStrategyName } from './strategies/selector';
  20. import type { StrategyName } from './strategies/selector';
  21. // ============ 书籍类型 → 大纲层级映射 ============
  22. const BOOK_TYPE_GEN_LEVEL: Record<string, number> = {
  23. '教材': 3,
  24. '技术教程': 3,
  25. '小说': 1,
  26. '传记': 1,
  27. '商业': 2,
  28. '科普': 2,
  29. '历史': 2,
  30. '学术': 3,
  31. '心理学': 2,
  32. };
  33. /**
  34. * 将书籍类型映射为大纲层级
  35. */
  36. export function mapBookTypeToGenLevel(bookType: string): number {
  37. return BOOK_TYPE_GEN_LEVEL[bookType] ?? 2;
  38. }
  39. /**
  40. * 根据书籍规模和话题文本自动推荐大纲层级
  41. * 增强版:如未指定 genLevel,会从话题文本推断书籍类型→层级
  42. */
  43. export function resolveGenLevel(bookScale: string, userGenLevel?: number | string, topic?: string): number {
  44. if (userGenLevel !== undefined && userGenLevel !== null) {
  45. const n = typeof userGenLevel === 'string' ? parseInt(userGenLevel) : userGenLevel;
  46. if ([1, 2, 3].includes(n)) return n;
  47. }
  48. const config = getScaleConfig(bookScale);
  49. if (!config) return 2;
  50. if (config.isShortArticle) return 1;
  51. // 从话题文本推断书籍类型,增强 genLevel 推荐准确度
  52. if (topic) {
  53. const text = topic.toLowerCase();
  54. if (/教材|教程|编程|开发|实战|教学|课程/i.test(text)) return 3;
  55. if (/小说|故事|传记|散文|诗歌/i.test(text)) return 1;
  56. }
  57. return 2;
  58. }
  59. // ============ 策略切换 API(外部可调用) ============
  60. export { setCurrentStrategy, getCurrentStrategyName, getAllStrategies } from './strategies/selector';
  61. export type { StrategyName } from './strategies/selector';
  62. // ============ 主类(策略门面) ============
  63. export class LangGraphBookGenerator {
  64. async generate(
  65. bookId: string,
  66. topic: string,
  67. bookScale: string = '1000',
  68. genLevel?: number
  69. ): Promise<void> {
  70. const userSpecified = genLevel !== undefined; // true=用户选了层级, false=自动
  71. const level = genLevel ?? resolveGenLevel(bookScale, undefined, topic);
  72. // 获取当前激活的策略并执行
  73. const strategy = getCurrentStrategy();
  74. console.log(`[LangGraph] 开始生成: bookId=${bookId}, scale=${bookScale}, genLevel=${level}, strategy=${strategy.name}`);
  75. await strategy.generate(bookId, topic, bookScale, level, userSpecified ? level : undefined);
  76. }
  77. }
  78. export const langGraphGenerator = new LangGraphBookGenerator();
  79. // 重新导出 book-type-config 中的函数供外部使用
  80. export { getScaleConfig } from './book-type-config';
  81. // ============ 独立大纲生成函数(供 API 预览调用,不依赖完整策略) ============
  82. import { callLLMWithMessages } from '../../services/llm';
  83. import { buildOutlineMessages } from './prompts/builder';
  84. import { parseOutline } from './parsers/outline.parser';
  85. /**
  86. * 独立的大纲生成函数(供 API 预览调用,不依赖策略系统)
  87. * 用于让用户在正式开始生成前预览大纲结构
  88. */
  89. export async function generateOutline(bookId: string, topic: string, bookScale: string = '1000'): Promise<any> {
  90. console.log('[generateOutline] 预览大纲, bookId:', bookId, 'scale:', bookScale);
  91. const messages = buildOutlineMessages(topic, bookScale);
  92. const response = await callLLMWithMessages(messages);
  93. const outline = parseOutline(response);
  94. if (!outline) {
  95. throw new Error('大纲解析失败');
  96. }
  97. return outline;
  98. }