| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- /**
- * LangGraph 书籍生成器 - 主入口(策略门面)
- *
- * 使用策略模式,通过 strategies/selector.ts 配置切换不同生成方案
- *
- * 当前支持策略:
- * 1. sequential - 串行(原始方案)
- * 2. one-step-outline - 一步大纲 + 并行内容
- * 3. per-chapter - 逐章内聚
- * 4. deep-plan-parallel - DeepPlan+RichOutline+Concurrent+Edit(当前推荐,默认策略)
- *
- * 大纲层级(genLevel):
- * 1 = 仅章(短文/小说/故事类)
- * 2 = 章→节(科普/商业/大众类)
- * 3 = 章→节→小节(教材/技术教程/专业类)
- *
- * 成本追踪:通过 AsyncLocalStorage 上下文,所有 LLM/TTS 调用自动携带 bookId/chapterId
- */
- import { bookStore } from './book-generator.store';
- import { getScaleConfig } from './book-type-config';
- import { getCurrentStrategy, setCurrentStrategy, getAllStrategies, getCurrentStrategyName } from './strategies/selector';
- import type { StrategyName } from './strategies/selector';
- import { runWithContext } from '../../services/llm-context';
- // ============ 书籍类型 → 大纲层级映射 ============
- const BOOK_TYPE_GEN_LEVEL: Record<string, number> = {
- '教材': 3,
- '技术教程': 3,
- '小说': 1,
- '传记': 1,
- '商业': 2,
- '科普': 2,
- '历史': 2,
- '学术': 3,
- '心理学': 2,
- };
- /**
- * 将书籍类型映射为大纲层级
- */
- export function mapBookTypeToGenLevel(bookType: string): number {
- return BOOK_TYPE_GEN_LEVEL[bookType] ?? 2;
- }
- /**
- * 根据书籍规模和话题文本自动推荐大纲层级
- * 增强版:如未指定 genLevel,会从话题文本推断书籍类型→层级
- */
- export function resolveGenLevel(bookScale: string, userGenLevel?: number | string, topic?: string): number {
- if (userGenLevel !== undefined && userGenLevel !== null) {
- const n = typeof userGenLevel === 'string' ? parseInt(userGenLevel) : userGenLevel;
- if ([1, 2, 3].includes(n)) return n;
- }
- const config = getScaleConfig(bookScale);
- if (!config) return 2;
- if (config.isShortArticle) return 1;
- // 从话题文本推断书籍类型,增强 genLevel 推荐准确度
- if (topic) {
- const text = topic.toLowerCase();
- if (/教材|教程|编程|开发|实战|教学|课程/i.test(text)) return 3;
- if (/小说|故事|传记|散文|诗歌/i.test(text)) return 1;
- }
- return 2;
- }
- // ============ 策略切换 API(外部可调用) ============
- export { setCurrentStrategy, getCurrentStrategyName, getAllStrategies } from './strategies/selector';
- export type { StrategyName } from './strategies/selector';
- // ============ 主类(策略门面) ============
- export class LangGraphBookGenerator {
- async generate(
- bookId: string,
- topic: string,
- bookScale: string = '1000',
- genLevel?: number,
- userId?: number,
- userSpecifiedVoiceSpeed?: boolean,
- ): Promise<void> {
- const userSpecified = genLevel !== undefined;
- const level = genLevel ?? resolveGenLevel(bookScale, undefined, topic);
- const strategy = getCurrentStrategy();
- console.log(`[LangGraph] 开始生成: bookId=${bookId}, userId=${userId ?? '-'}, scale=${bookScale}, genLevel=${level}, strategy=${strategy.name}, userSpecifiedVoiceSpeed=${userSpecifiedVoiceSpeed}`);
- // 设置异步上下文,后续所有 LLM/TTS 调用自动携带 userId / bookId
- await runWithContext({ userId, bookId: parseInt(bookId) }, async () => {
- await strategy.generate(bookId, topic, bookScale, level, userSpecified ? level : undefined, userSpecifiedVoiceSpeed);
- });
- }
- }
- export const langGraphGenerator = new LangGraphBookGenerator();
- // 重新导出 book-type-config 中的函数供外部使用
- export { getScaleConfig } from './book-type-config';
- // ============ 独立大纲生成函数(供 API 预览调用,不依赖完整策略) ============
- import { callLLMWithMessages } from '../../services/llm';
- import { buildOutlineMessages } from './prompts/builder';
- import { parseOutline } from './parsers/outline.parser';
- /**
- * 独立的大纲生成函数(供 API 预览调用,不依赖策略系统)
- * 用于让用户在正式开始生成前预览大纲结构
- */
- export async function generateOutline(bookId: string, topic: string, bookScale: string = '1000'): Promise<any> {
- console.log('[generateOutline] 预览大纲, bookId:', bookId, 'scale:', bookScale);
- const messages = buildOutlineMessages(topic, bookScale);
- const response = await callLLMWithMessages(messages);
- const outline = parseOutline(response);
- if (!outline) {
- throw new Error('大纲解析失败');
- }
- return outline;
- }
|