UNPKG

article-writer-cn

Version:

AI 驱动的智能写作系统 - 专注公众号/自媒体文章创作

337 lines 12 kB
/** * AI 接口层 * 为 AI 助手提供简化的功能调用接口 * 支持自然语言参数和引导式交互 */ import { MethodAdvisor } from './method-advisor.js'; import { MethodConverter } from './method-converter.js'; import { HybridMethodManager } from './hybrid-method.js'; import fs from 'fs-extra'; import path from 'path'; /** * AI 接口主类 */ export class AIInterface { advisor; converter; hybridManager; constructor() { this.advisor = new MethodAdvisor(); this.converter = new MethodConverter(); this.hybridManager = new HybridMethodManager(); } /** * 智能引导选择写作方法 * AI 通过对话收集信息后调用 */ async guideMethodSelection(context) { // 解析自然语言参数 const features = this.parseContext(context); // 获取推荐 const scores = this.advisor.recommend(features); const top = scores[0]; // 加载对应模板 const templatePath = await this.getMethodTemplate(top.method); return { method: top.method, reason: top.reasons.join(';'), template: templatePath, tips: this.getMethodTips(top.method) }; } /** * 引导式问答收集信息 * 返回需要询问用户的问题 */ getGuidingQuestions() { return [ "这是一个什么类型的故事?(奇幻/科幻/爱情/悬疑/现实/其他)", "预计写多少字?(短篇3万字以内/中篇10万字左右/长篇20万字以上)", "目标读者是谁?(儿童/青少年/成人/大众)", "你希望故事的节奏如何?(紧凑刺激/平稳推进/缓慢深入)", "你更注重什么?(精彩的情节/丰富的人物/深刻的主题)" ]; } /** * 解析上下文为特征参数 */ parseContext(context) { // 智能解析长度 let length = 100000; // 默认10万字 if (context.estimatedLength) { if (context.estimatedLength.includes('短')) length = 30000; else if (context.estimatedLength.includes('长')) length = 200000; else if (context.estimatedLength.includes('超长')) length = 500000; // 提取数字 const match = context.estimatedLength.match(/(\d+)/); if (match) { const num = parseInt(match[1]); if (context.estimatedLength.includes('万')) { length = num * 10000; } else if (context.estimatedLength.includes('千')) { length = num * 1000; } else { length = num; } } } // 智能解析节奏 let pace = '中'; if (context.tone?.includes('紧') || context.tone?.includes('刺激')) pace = '快'; else if (context.tone?.includes('缓') || context.tone?.includes('深')) pace = '慢'; // 智能解析复杂度 let complexity = '中等'; if (length > 200000 || context.description?.includes('复杂')) complexity = '复杂'; else if (length < 50000 || context.description?.includes('简单')) complexity = '简单'; // 智能解析经验(根据描述推测) let experience = '初级'; if (context.description?.includes('系列') || complexity === '复杂') experience = '中级'; return { genre: context.genre || '通用', length, audience: context.targetAudience || '大众', experience, focus: this.parseFocus(context), pace, complexity }; } /** * 解析创作重点 */ parseFocus(context) { if (context.description?.includes('人物') || context.description?.includes('角色')) { return '角色'; } if (context.description?.includes('情节') || context.description?.includes('剧情')) { return '情节'; } if (context.themes && context.themes.length > 0) { return '主题'; } return '平衡'; } /** * 获取方法对应的模板路径 */ async getMethodTemplate(method) { const methodMap = { 'three-act': 'three-act', 'hero-journey': 'hero-journey', 'story-circle': 'story-circle', 'seven-point': 'seven-point', 'pixar-formula': 'pixar-formula' }; const methodDir = methodMap[method] || 'three-act'; return `spec/presets/${methodDir}/specification.md`; } /** * 获取方法使用提示 */ getMethodTips(method) { const tips = { 'three-act': [ '第一幕要快速建立冲突', '第二幕可设置多个小高潮避免拖沓', '第三幕要紧凑有力' ], 'hero-journey': [ '不必严格遵循所有12个阶段', '重点关注角色的内在转变', '导师角色可以多样化' ], 'story-circle': [ '角色的需求必须足够强烈', '每个步骤都要推进内在变化', '可以嵌套小循环增加深度' ], 'seven-point': [ '确保每个节点都推进故事', '中点必须是真正的转折', '收紧点很重要,不要省略' ], 'pixar-formula': [ '保持简洁,不要过度描写', '强调因果关系的清晰连接', '结局要满意但可留有思考空间' ] }; return tips[method] || ['遵循方法的基本结构', '保持故事的连贯性']; } /** * 智能转换建议 * 分析当前项目并建议是否需要转换 */ async suggestConversion(currentMethod, storyProgress) { // 分析进度 const hasContent = storyProgress.chapters && storyProgress.chapters.length > 0; if (!hasContent) { return { needConversion: false, reason: '项目刚开始,可以直接切换方法' }; } // 分析内容特征 const contentFeatures = this.analyzeContent(storyProgress); // 获取推荐方法 const recommended = this.advisor.recommend(contentFeatures)[0]; if (recommended.method === currentMethod) { return { needConversion: false, reason: '当前方法已经最适合' }; } // 生成转换方案 const conversionMap = this.converter.convert(storyProgress, recommended.method); return { needConversion: true, targetMethod: recommended.method, reason: recommended.reasons[0], conversionMap, impact: this.assessConversionImpact(storyProgress, conversionMap) }; } /** * 分析内容特征 */ analyzeContent(progress) { // 基于实际内容分析 return { genre: progress.genre || '通用', length: progress.plannedLength || 100000, audience: progress.audience || '大众', experience: '中级', focus: progress.focus || '平衡', pace: progress.pace || '中', complexity: progress.complexity || '中等' }; } /** * 评估转换影响 */ assessConversionImpact(progress, conversionMap) { const chaptersWritten = progress.chapters?.filter((c) => c.written).length || 0; if (chaptersWritten === 0) { return '无影响,还未开始写作'; } else if (chaptersWritten < 5) { return '影响较小,只需调整少量章节'; } else if (chaptersWritten < 20) { return '影响中等,需要重新组织部分内容'; } else { return '影响较大,建议保持当前方法完成作品'; } } /** * 智能混合方案生成 * 根据故事特点自动设计混合方案 */ async designHybridScheme(context) { const features = this.parseContext(context); // 判断是否需要混合 if (features.complexity === '简单' || features.length < 50000) { return { needHybrid: false, reason: '简单故事使用单一方法即可', recommendation: this.advisor.recommend(features)[0].method }; } // 推荐混合方案 const hybrid = this.hybridManager.recommendHybrid(features.genre, features.length, features.complexity); if (!hybrid) { return { needHybrid: false, reason: '此类型故事适合单一方法', recommendation: this.advisor.recommend(features)[0].method }; } // 生成详细方案 const structure = this.hybridManager.createHybridStructure(hybrid, { ...features, subPlots: context.description?.includes('支线') ? ['支线1'] : [], characters: context.description?.includes('群像') ? ['角色1', '角色2'] : [] }); return { needHybrid: true, reason: this.getHybridReason(features), scheme: hybrid, structure, guidelines: structure.guidelines }; } /** * 获取使用混合方法的理由 */ getHybridReason(features) { if (features.genre === '奇幻' && features.length > 200000) { return '长篇奇幻适合用英雄之旅构建主线,故事圈追踪角色成长'; } if (features.genre === '悬疑' && features.complexity === '复杂') { return '复杂悬疑适合七点结构控制节奏,章节用三幕组织'; } if (features.focus === '角色' && features.length > 150000) { return '角色驱动的长篇适合混合方法,主线和角色线分别处理'; } return '故事较复杂,混合方法能更好地组织结构'; } /** * 获取当前项目配置 */ async getCurrentConfig() { const configPath = path.join(process.cwd(), '.content', 'config.json'); if (await fs.pathExists(configPath)) { return await fs.readJson(configPath); } return null; } /** * 更新项目方法配置 */ async updateProjectMethod(method) { const configPath = path.join(process.cwd(), '.content', 'config.json'); if (await fs.pathExists(configPath)) { const config = await fs.readJson(configPath); if (typeof method === 'string') { config.method = method; } else { // 混合方法配置 config.method = 'hybrid'; config.hybridScheme = method; } config.updatedAt = new Date().toISOString(); await fs.writeJson(configPath, config, { spaces: 2 }); } } /** * 获取方法的中文名称 */ getMethodDisplayName(method) { const names = { 'three-act': '三幕结构', 'hero-journey': '英雄之旅', 'story-circle': '故事圈', 'seven-point': '七点结构', 'pixar-formula': '皮克斯公式', 'hybrid': '混合方法' }; return names[method] || method; } } /** * 导出单例实例供 AI 直接使用 */ export const aiInterface = new AIInterface(); //# sourceMappingURL=ai-interface.js.map