lifekline / scripts /generate-content.js
miounet11
升级钱的狂欢
4d48c94
import dotenv from 'dotenv';
import fetch from 'node-fetch';
import { nanoid } from 'nanoid';
dotenv.config();
const API_BASE_URL = process.env.API_BASE_URL || 'https://ttkk.inping.com/v1';
const API_KEY = process.env.API_KEY;
const MODEL = process.env.DEFAULT_MODEL || 'gemini-2.5-flash';
// 文章生成 Prompt
const ARTICLE_PROMPT = (topic, category) => `
你是人生K线产品的知识内容作者。请为以下主题撰写知识文章:
主题:${topic}
类别:${category}
目标读者:对命理感兴趣但不懂术语的普通用户
要求:
1. 简明扼要,通俗易懂,不要有废话
2. 使用具体例子解释抽象概念
3. 关联到K线图的实际展示
4. 正文300-500字
请直接输出JSON格式(不要markdown代码块):
{
"title": "文章标题",
"summary": "一句话总结(60字内)",
"content": "正文内容(Markdown格式)"
}
`;
// 待生成的文章清单
const ARTICLES_TO_GENERATE = [
// 快速入门 (quickstart)
{ topic: '如何正确填写四柱(年柱、月柱、日柱、时柱)', category: 'quickstart' },
{ topic: '起运年龄是什么,虚岁与周岁的区别', category: 'quickstart' },
{ topic: '第一部大运怎么找,顺行逆行的简单判断', category: 'quickstart' },
{ topic: '一分钟看懂人生K线图(峰值、谷底、趋势)', category: 'quickstart' },
{ topic: '"吉"和"凶"不等于"好"和"坏",风险与机会的双面性', category: 'quickstart' },
{ topic: '为什么同一年对不同人意义完全不同', category: 'quickstart' },
// K线逻辑 (kline)
{ topic: 'K线四价(开盘、收盘、最高、最低)与人生事件的对应', category: 'kline' },
{ topic: '人生的牛市、熊市、震荡期如何把握决策节奏', category: 'kline' },
{ topic: '大运切换:为什么人生会"换挡"', category: 'kline' },
{ topic: '单年冲高回落:为什么看似好年也可能翻车', category: 'kline' },
{ topic: '单年深V走势:先苦后甜还是先甜后苦', category: 'kline' },
{ topic: '为什么K线模型必须有明显波动才有参考价值', category: 'kline' },
// 八字基础 (bazi)
{ topic: '四柱代表的四个信息维度:年月日时', category: 'bazi' },
{ topic: '天干地支入门:只需掌握这些就够用', category: 'bazi' },
{ topic: '五行生克的核心规则:生、克、泄、耗', category: 'bazi' },
{ topic: '阴阳与顺逆大运的逻辑关系', category: 'bazi' },
{ topic: '十神入门:与人生事件类型的映射', category: 'bazi' },
{ topic: '喜用神和忌神:为什么影响"同一年不同命"', category: 'bazi' },
{ topic: '身强身弱:对风险承受和人生节奏的意义', category: 'bazi' },
{ topic: '神煞是什么:如何理性看待和使用', category: 'bazi' },
// 大运流年 (dayun)
{ topic: '大运是背景,流年是触发器:理解两者的关系', category: 'dayun' },
{ topic: '大运十年如何分段:前期、中期、后期', category: 'dayun' },
{ topic: '流年冲合刑害的直观解释', category: 'dayun' },
{ topic: '太岁与犯太岁的现实意义和应对', category: 'dayun' },
{ topic: '迁移变动年:如何提前布局', category: 'dayun' },
{ topic: '贵人年与破财年的防守策略', category: 'dayun' },
// 方法误区 (method)
{ topic: '评分怎么看:不要只盯着最高分年份', category: 'method' },
{ topic: '常见误区:把命理当成确定性预言', category: 'method' },
{ topic: '常见误区:只追求旺运而忽视能力修炼', category: 'method' },
{ topic: '如何用K线图做人生复盘:年度、三年、十年规划', category: 'method' },
];
// 生成单篇文章
async function generateArticle(topic, category) {
const response = await fetch(`${API_BASE_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`,
},
body: JSON.stringify({
model: MODEL,
messages: [
{ role: 'user', content: ARTICLE_PROMPT(topic, category) }
],
temperature: 0.7,
}),
});
const data = await response.json();
let content = data.choices?.[0]?.message?.content || '';
// 清理 JSON
content = content.trim();
if (content.startsWith('```json')) content = content.slice(7);
if (content.startsWith('```')) content = content.slice(3);
if (content.endsWith('```')) content = content.slice(0, -3);
content = content.trim();
return JSON.parse(content);
}
// 主函数
async function main() {
console.log('开始生成知识文章...');
const results = [];
for (const item of ARTICLES_TO_GENERATE) {
console.log(`生成: ${item.topic}`);
try {
const article = await generateArticle(item.topic, item.category);
const slug = nanoid(10);
results.push({
id: nanoid(),
slug,
category: item.category,
level: 1,
tags: [],
...article,
createdAt: new Date().toISOString(),
});
console.log(` ✓ ${article.title}`);
// 避免 rate limit
await new Promise(r => setTimeout(r, 2000));
} catch (err) {
console.error(` ✗ 失败: ${err.message}`);
}
}
// 输出 SQL 插入语句
console.log('\n=== SQL 插入语句 ===\n');
for (const a of results) {
const sql = `INSERT INTO knowledge_articles (id, slug, title, category, level, tags, summary, content, created_at) VALUES ('${a.id}', '${a.slug}', '${a.title.replace(/'/g, "''")}', '${a.category}', ${a.level}, '${JSON.stringify(a.tags)}', '${a.summary.replace(/'/g, "''")}', '${a.content.replace(/'/g, "''")}', '${a.createdAt}');`;
console.log(sql);
}
// 保存为 JSON
const fs = await import('fs');
fs.writeFileSync('./scripts/generated-articles.json', JSON.stringify(results, null, 2));
console.log('\n已保存到 scripts/generated-articles.json');
}
main().catch(console.error);