/** * WeChatAI Content Generation Workflow * 内容生成工作流 - 读取选题、匹配模板、生成文章 */ const fs = require('fs'); const path = require('path'); // 配置 const CONFIG = { baseDir: '/Users/yibo/Documents/LemonAI/lemonboss/data/workspace/wechatai', templatesDir: '/Users/yibo/Documents/LemonAI/lemonboss/data/workspace/wechatai/config/templates', outputDir: '/Users/yibo/Documents/LemonAI/lemonboss/data/workspace/wechatai/articles', hotspotsDir: '/Users/yibo/Documents/LemonAI/lemonboss/data/workspace/wechatai/hotspots', }; // 模板配置 const TEMPLATE_CONFIG = { morning_report: { file: 'morning_report.md', minWords: 300, maxWords: 500, description: 'AI早报' }, hotspot_analysis: { file: 'hotspot_analysis.md', minWords: 1000, maxWords: 1500, description: '热点解读' }, deep_dive: { file: 'deep_dive.md', minWords: 2000, maxWords: 3000, description: '深度专题' }, weekly_digest: { file: 'weekly_digest.md', minWords: 1500, maxWords: 2000, description: '周盘点' } }; /** * 读取精选选题 * @param {string} date - 日期 YYYY-MM-DD * @returns {Array} 选题列表 */ function readCuratedTopics(date) { const filePath = path.join(CONFIG.hotspotsDir, date, 'curated_topics.json'); if (!fs.existsSync(filePath)) { console.error(`[ERROR] 选题文件不存在: ${filePath}`); return []; } try { const content = fs.readFileSync(filePath, 'utf-8'); return JSON.parse(content); } catch (error) { console.error(`[ERROR] 解析选题文件失败: ${error.message}`); return []; } } /** * 读取模板 * @param {string} contentType - 内容类型 * @returns {string} 模板内容 */ function readTemplate(contentType) { const config = TEMPLATE_CONFIG[contentType]; if (!config) { console.error(`[ERROR] 未知的模板类型: ${contentType}`); return null; } const templatePath = path.join(CONFIG.templatesDir, config.file); if (!fs.existsSync(templatePath)) { console.error(`[ERROR] 模板文件不存在: ${templatePath}`); return null; } return fs.readFileSync(templatePath, 'utf-8'); } /** * 生成文章大纲 * @param {Object} topic - 选题对象 * @returns {Object} 大纲对象 */ function generateOutline(topic) { const outlines = { morning_report: { sections: ['今日亮点', '要闻速览', '一句话总结'], keyPoints: [ { title: '亮点事件', angle: '最有价值的AI进展' }, { title: '行业动态', angle: '公司和产品更新' }, { title: '技术突破', angle: '研究论文和开源项目' } ] }, hotspot_analysis: { sections: ['背景速览', '核心解读', '影响与展望', '小结'], keyPoints: [ { title: '事件背景', angle: '时间线和来龙去脉' }, { title: '技术细节', angle: '核心功能和原理' }, { title: '市场影响', angle: '对行业和用户的影响' } ] }, deep_dive: { sections: ['背景铺垫', '技术分析', '竞争格局', '应用案例', '趋势预测', '总结'], keyPoints: [ { title: '发展脉络', angle: '技术演进历程' }, { title: '核心原理', angle: '深入技术细节' }, { title: '对比分析', angle: '与竞品的优劣势' }, { title: '实际应用', angle: '落地场景和案例' }, { title: '未来趋势', angle: '发展方向预测' } ] }, weekly_digest: { sections: ['本周Top5', '分类速览', '下周预告'], keyPoints: [ { title: '重大发布', angle: '本周最重要的5个事件' }, { title: '模型进展', angle: '大模型更新和性能提升' }, { title: '商业动态', angle: '投融资和产品发布' }, { title: '下周看点', angle: '预告值得关注的事件' } ] } }; return outlines[topic.content_type] || outlines.hotspot_analysis; } /** * 使用模板生成文章 * @param {Object} topic - 选题对象 * @param {string} template - 模板内容 * @returns {string} 生成的文章 */ function generateArticle(topic, template) { const now = new Date(); const dateStr = now.toISOString().split('T')[0]; const outline = generateOutline(topic); // 基础变量替换 let article = template .replace(/\{\{TITLE\}\}/g, topic.title) .replace(/\{\{DATE\}\}/g, dateStr) .replace(/\{\{SOURCE\}\}/g, topic.source || 'WeChatAI') .replace(/\{\{SOURCES\}\}/g, topic.sources?.join(', ') || topic.source || '综合整理') .replace(/\{\{TAGS\}\}/g, topic.tags?.join(', ') || 'AI, 人工智能') .replace(/\{\{SUMMARY\}\}/g, topic.summary || ''); // 根据内容类型生成不同内容 switch (topic.content_type) { case 'morning_report': article = generateMorningReportContent(article, topic); break; case 'hotspot_analysis': article = generateHotspotAnalysisContent(article, topic); break; case 'deep_dive': article = generateDeepDiveContent(article, topic, outline); break; case 'weekly_digest': article = generateWeeklyDigestContent(article, topic); break; } return article; } /** * 生成早报内容 */ function generateMorningReportContent(article, topic) { // 生成开头导语 const opening = `早上好!这里是 WeChatAI 早报。 今天是 ${new Date().toLocaleDateString('zh-CN')},AI 领域又发生了哪些新鲜事?让我们一起来看看。`; // 生成新闻条目(模拟数据,实际应从 topic 数据中提取) const newsItems = topic.news_items || [ { title: 'AI 领域最新动态', summary: '详细内容待填充...' }, { title: '技术突破', summary: '详细内容待填充...' }, { title: '产品发布', summary: '详细内容待填充...' } ]; let newsContent = ''; newsItems.forEach((news, index) => { newsContent += `### ${index + 1}. ${news.title}\n${news.summary}\n\n`; }); const summary = 'AI 行业持续高速发展,新技术和新产品不断涌现。保持关注,把握先机!'; return article .replace(/\{\{SUMMARY\}\}/g, opening) .replace(/\{\{HIGHLIGHT_ITEM\}\}/g, newsItems[0]?.title || '今日AI要闻') .replace(/\{\{NEWS_1_TITLE\}\}/g, newsItems[0]?.title || '') .replace(/\{\{NEWS_1_SUMMARY\}\}/g, newsItems[0]?.summary || '') .replace(/\{\{NEWS_2_TITLE\}\}/g, newsItems[1]?.title || '') .replace(/\{\{NEWS_2_SUMMARY\}\}/g, newsItems[1]?.summary || '') .replace(/\{\{NEWS_3_TITLE\}\}/g, newsItems[2]?.title || '') .replace(/\{\{NEWS_3_SUMMARY\}\}/g, newsItems[2]?.summary || '') .replace(/\{\{NEWS_4_TITLE\}\}/g, newsItems[3]?.title || '') .replace(/\{\{NEWS_4_SUMMARY\}\}/g, newsItems[3]?.summary || '') .replace(/\{\{NEWS_5_TITLE\}\}/g, newsItems[4]?.title || '') .replace(/\{\{NEWS_5_SUMMARY\}\}/g, newsItems[4]?.summary || '') .replace(/\{\{ONE_SENTENCE_SUMMARY\}\}/g, summary) .replace(/\{\{SOURCE_COUNT\}\}/g, String(newsItems.length)); } /** * 生成热点解读内容 */ function generateHotspotAnalysisContent(article, topic) { // 开头三句话 const opening = `${topic.title}是近期AI领域最受关注的热点事件。 它的发布不仅标志着技术的重大突破,更可能对整个行业格局产生深远影响。 本文将带你快速了解事件背景、深入解读核心看点、并展望其未来影响。`; // 背景 const background = `${topic.title}于近期正式发布,引发了业界广泛关注。 从技术层面看,这一进展代表了AI领域的最新突破。 从市场反应来看,各方评价普遍积极。`; // 核心解读 const keyPoint1 = `${topic.title}在**技术架构**上实现了重要创新。 相比前代产品,在性能和效率方面都有显著提升。 这种改进使其在实际应用场景中更具竞争力。`; const keyPoint2 = `从**商业角度**分析,这一发布将加剧市场竞争。 主要厂商纷纷跟进,行业格局可能因此重塑。 对于用户而言,这意味着将有更多优质选择。`; const keyPoint3 = `长期来看,这项技术将**推动整个行业**向前发展。 新的应用场景将不断涌现,商业价值也将持续释放。 我们可以期待更多基于此技术的创新产品出现。`; // 影响与展望 const impact = `${topic.title}的发布是一个重要里程碑。 短期内,我们将看到更多基于该技术的产品和应用落地。 中长期来看,它可能重新定义行业标准和用户期望。 建议读者持续关注后续发展,把握机遇。`; // 小结 const conclusion = `${topic.title}代表了AI领域的最新进展,值得关注。 无论是技术从业者还是普通用户,都将从中受益。 我们将继续跟进报道,敬请期待。`; return article .replace(/\{\{OPENING_PARAGRAPH\}\}/g, opening) .replace(/\{\{BACKGROUND_CONTENT\}\}/g, background) .replace(/\{\{KEY_POINT_1_TITLE\}\}/g, '技术突破') .replace(/\{\{KEY_POINT_1_CONTENT\}\}/g, keyPoint1) .replace(/\{\{KEY_POINT_2_TITLE\}\}/g, '商业影响') .replace(/\{\{KEY_POINT_2_CONTENT\}\}/g, keyPoint2) .replace(/\{\{KEY_POINT_3_TITLE\}\}/g, '未来展望') .replace(/\{\{KEY_POINT_3_CONTENT\}\}/g, keyPoint3) .replace(/\{\{IMPACT_CONTENT\}\}/g, impact) .replace(/\{\{CONCLUSION\}\}/g, conclusion); } /** * 生成深度专题内容 */ function generateDeepDiveContent(article, topic, outline) { const opening = `${topic.title}是近年来AI领域最重要的技术突破之一。 它不仅改变了我们对AI能力的认知,更开启了全新的应用可能。 本文将从技术原理、发展历程、应用案例和未来趋势四个维度,为你全面解析这一革命性进展。`; const section1 = `${topic.title}的诞生并非偶然,而是多年技术积累的结果。 从最初的构想到最终落地,经历了多次技术迭代和突破。 关键里程碑包括基础架构的确立、核心算法的优化、以及大规模验证的成功。`; const section2 = `在技术层面,${topic.title}采用了创新的架构设计。 其核心优势在于**高效的信息处理能力**和**优秀的泛化性能**。 具体来说,它通过改进的注意力机制和优化的训练策略,实现了性能的质的飞跃。`; const section3 = `当前市场上,${topic.title}面临着激烈的竞争。 主要竞品包括来自各大科技巨头的同类产品。 但凭借独特的技术优势和先发制人的策略,${topic.title}在市场上占据了有利地位。`; const section4 = `${topic.title}的实际应用已经覆盖多个领域。 在**内容创作**方面,它能够辅助生成高质量的文本、图像和视频。 在**代码开发**领域,它可以显著提高开发效率,降低错误率。 在**数据分析**场景,它展现了强大的洞察力和决策支持能力。`; const section5 = `展望未来,${topic.title}将继续演进和完善。 预计下一代产品将在**多模态理解**和**推理能力**方面取得突破。 同时,随着成本的降低和易用性的提升,它将在更多行业和场景中得到应用。 我们可以期待一个AI能力更加普惠的未来。`; const discussion = `你觉得${topic.title}最令人兴奋的应用场景是什么? 欢迎在评论区分享你的想法!`; return article .replace(/\{\{OPENING_PARAGRAPH\}\}/g, opening) .replace(/\{\{SECTION_1_TITLE\}\}/g, '发展历程') .replace(/\{\{SECTION_1_CONTENT\}\}/g, section1) .replace(/\{\{SECTION_2_TITLE\}\}/g, '技术解析') .replace(/\{\{SECTION_2_CONTENT\}\}/g, section2) .replace(/\{\{SECTION_3_TITLE\}\}/g, '竞争格局') .replace(/\{\{SECTION_3_CONTENT\}\}/g, section3) .replace(/\{\{SECTION_4_TITLE\}\}/g, '应用案例') .replace(/\{\{SECTION_4_CONTENT\}\}/g, section4) .replace(/\{\{SECTION_5_TITLE\}\}/g, '未来趋势') .replace(/\{\{SECTION_5_CONTENT\}\}/g, section5) .replace(/\{\{DISCUSSION_QUESTION\}\}/g, discussion); } /** * 生成周盘点内容 */ function generateWeeklyDigestContent(article, topic) { const opening = `本周AI领域精彩纷呈,多个重磅消息值得关注。 从大模型更新到产品发布,从技术突破到商业动态,信息量巨大。 本文为你梳理本周最值得关注的5大事件,以及各类别的重要进展。`; const weekRange = `${new Date().toLocaleDateString('zh-CN')} 所在周`; // 模拟本周Top5 const topItems = topic.top_items || [ { title: '大模型重要更新', summary: '性能大幅提升,引发行业热议。' }, { title: '新产品发布', summary: '创新功能惊艳亮相,用户体验升级。' }, { title: '开源项目亮点', summary: '社区贡献显著,生态系统进一步完善。' }, { title: '研究论文突破', summary: '理论基础得到加强,应用前景广阔。' }, { title: '商业合作动态', summary: '产业链整合加速,市场格局生变。' } ]; const modelSummary = '本周大模型领域进展显著。主要厂商发布了重要更新,性能指标全面提升。开源社区也有诸多贡献,生态日益繁荣。'; const fundingSummary = '资本市场对AI领域持续看好。本周有多起融资事件,涉及大模型、应用层和基础设施等多个方向。'; const productSummary = '产品层面,多个创新功能上线。用户体验得到显著改善,应用场景进一步拓展。'; const policySummary = '政策层面,各国继续加强对AI的监管和规范。行业自律也在加强,可持续发展成为共识。'; const nextWeekPreview = '下周值得关注的是几家主要厂商的发布会,以及多个重要学术会议。预计将有更多技术和产品动态发布。'; return article .replace(/\{\{OPENING_PARAGRAPH\}\}/g, opening) .replace(/\{\{WEEK_RANGE\}\}/g, weekRange) .replace(/\{\{TOP_1_TITLE\}\}/g, topItems[0]?.title || '') .replace(/\{\{TOP_1_SUMMARY\}\}/g, topItems[0]?.summary || '') .replace(/\{\{TOP_2_TITLE\}\}/g, topItems[1]?.title || '') .replace(/\{\{TOP_2_SUMMARY\}\}/g, topItems[1]?.summary || '') .replace(/\{\{TOP_3_TITLE\}\}/g, topItems[2]?.title || '') .replace(/\{\{TOP_3_SUMMARY\}\}/g, topItems[2]?.summary || '') .replace(/\{\{TOP_4_TITLE\}\}/g, topItems[3]?.title || '') .replace(/\{\{TOP_4_SUMMARY\}\}/g, topItems[3]?.summary || '') .replace(/\{\{TOP_5_TITLE\}\}/g, topItems[4]?.title || '') .replace(/\{\{TOP_5_SUMMARY\}\}/g, topItems[4]?.summary || '') .replace(/\{\{MODEL_SUMMARY\}\}/g, modelSummary) .replace(/\{\{FUNDING_SUMMARY\}\}/g, fundingSummary) .replace(/\{\{PRODUCT_SUMMARY\}\}/g, productSummary) .replace(/\{\{POLICY_SUMMARY\}\}/g, policySummary) .replace(/\{\{NEXT_WEEK_PREVIEW\}\}/g, nextWeekPreview); } /** * 质量自检 * @param {string} article - 文章内容 * @param {string} contentType - 内容类型 * @returns {Object} 检查结果 */ function qualityCheck(article, contentType) { const config = TEMPLATE_CONFIG[contentType]; const checks = { wordCount: { passed: false, value: 0, required: `${config.minWords}-${config.maxWords}` }, hasOpening3Sentences: { passed: false, note: '开头3句话检查' }, hasBoldText: { passed: false, note: '加粗标记检查' }, paragraphLength: { passed: false, note: '段落长度检查' }, formatCheck: { passed: true, note: '格式规范检查' } }; // 字数检查 const chineseChars = article.match(/[\u4e00-\u9fa5]/g) || []; const wordCount = chineseChars.length; checks.wordCount.value = wordCount; checks.wordCount.passed = wordCount >= config.minWords && wordCount <= config.maxWords; // 开头3句话检查(检查是否有「这是/什么/本文」等关键词) const openingPattern = /这是|什么|本文|为什么|重要|讲什么/; checks.hasOpening3Sentences.passed = openingPattern.test(article.substring(0, 500)); // 加粗检查 checks.hasBoldText.passed = /\*\*.+?\*\*/.test(article); // 段落长度检查(每段不超过150字) const paragraphs = article.split('\n\n'); const longParagraphs = paragraphs.filter(p => p.length > 150); checks.paragraphLength.passed = longParagraphs.length <= 3; const allPassed = Object.values(checks).every(c => c.passed); return { passed: allPassed, contentType, wordCount, checks, issues: allPassed ? [] : Object.entries(checks) .filter(([_, c]) => !c.passed) .map(([name, _]) => name) }; } /** * 保存文章 * @param {string} topicId - 选题ID * @param {string} date - 日期 * @param {string} content - 文章内容 */ function saveArticle(topicId, date, content) { const dir = path.join(CONFIG.outputDir, date); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } const filePath = path.join(dir, `${topicId}.md`); fs.writeFileSync(filePath, content, 'utf-8'); console.log(`[INFO] 文章已保存: ${filePath}`); return filePath; } /** * 主流程:生成文章 * @param {string} date - 日期 * @param {string} topicId - 特定选题ID(可选) */ async function generate(date, topicId = null) { console.log(`[INFO] 开始生成文章: date=${date}, topicId=${topicId || 'all'}`); const topics = readCuratedTopics(date); if (topics.length === 0) { console.log('[WARN] 没有找到选题'); return []; } const results = []; for (const topic of topics) { if (topicId && topic.topic_id !== topicId) continue; console.log(`[INFO] 处理选题: ${topic.topic_id} - ${topic.title}`); // 读取模板 const template = readTemplate(topic.content_type); if (!template) { console.error(`[ERROR] 无法获取模板: ${topic.content_type}`); continue; } // 生成文章 const article = generateArticle(topic, template); // 质量检查 const check = qualityCheck(article, topic.content_type); console.log(`[INFO] 质量检查: ${check.passed ? '通过' : '未通过'} (${check.wordCount}字)`); if (!check.passed) { console.log(`[WARN] 检查未通过项: ${check.issues.join(', ')}`); } // 保存文章 const filePath = saveArticle(topic.topic_id, date, article); results.push({ topicId: topic.topic_id, title: topic.title, contentType: topic.content_type, wordCount: check.wordCount, filePath, qualityCheck: check }); } console.log(`[INFO] 文章生成完成: ${results.length} 篇`); return results; } // CLI 入口 if (require.main === module) { const args = process.argv.slice(2); const date = args[0] || new Date().toISOString().split('T')[0]; const topicId = args[1] || null; generate(date, topicId).then(results => { console.log('\n=== 生成结果 ==='); results.forEach(r => { console.log(`✓ ${r.topicId}: ${r.title} (${r.wordCount}字)`); }); process.exit(0); }).catch(err => { console.error('[ERROR] 生成失败:', err); process.exit(1); }); } module.exports = { generate, readCuratedTopics, readTemplate, generateOutline, generateArticle, qualityCheck, TEMPLATE_CONFIG };