const fs = require('fs'); const path = require('path'); const matter = require('gray-matter'); const axios = require('axios'); require('dotenv').config(); // Configuration const CONTENT_DIR = path.join(__dirname, '../content/post'); const PROVIDER = process.env.AI_PROVIDER || 'siliconflow'; // 'siliconflow' or 'zhipu' const SILICONFLOW_API_KEY = process.env.SILICONFLOW_API_KEY; const ZHIPU_API_KEY = process.env.ZHIPU_API_KEY; // SiliconFlow Config const SILICONFLOW_URL = 'https://api.siliconflow.cn/v1/chat/completions'; const SILICONFLOW_MODEL = 'deepseek-ai/DeepSeek-V3'; // Zhipu Config const ZHIPU_URL = 'https://open.bigmodel.cn/api/paas/v4/chat/completions'; const ZHIPU_MODEL = 'glm-4'; async function generateComment(content) { const prompt = `你是"优世界"博客的常驻读者。你的评论风格: 声音: - 你是一名资深技术人员,评论冷静、精准、有洞察力 - 善于从技术细节中提炼出通用原理,或用简洁的类比让复杂问题变清晰 - 偶尔就事论事地指出文章中可以深入探讨的方向,像同行审阅一样,但不过度严肃 - 不强行搞笑,但可以有一丝冷幽默 格式: - 100 字以内 - 只输出评论文本,不加引号、不署名、不带 emoji 文章内容: ${content.substring(0, 2000)}`; try { if (PROVIDER === 'siliconflow') { if (!SILICONFLOW_API_KEY) throw new Error('SILICONFLOW_API_KEY is missing'); const response = await axios.post(SILICONFLOW_URL, { model: SILICONFLOW_MODEL, messages: [{ role: 'user', content: prompt }], temperature: 0.7, max_tokens: 200 }, { headers: { 'Authorization': `Bearer ${SILICONFLOW_API_KEY}`, 'Content-Type': 'application/json' } }); return response.data.choices[0].message.content.trim(); } else if (PROVIDER === 'zhipu') { if (!ZHIPU_API_KEY) throw new Error('ZHIPU_API_KEY is missing'); const response = await axios.post(ZHIPU_URL, { model: ZHIPU_MODEL, messages: [{ role: 'user', content: prompt }], temperature: 0.7 }, { headers: { 'Authorization': `Bearer ${ZHIPU_API_KEY}`, 'Content-Type': 'application/json' } }); return response.data.choices[0].message.content.trim(); } } catch (error) { console.error('API Error:', error.response ? error.response.data : error.message); return null; } } async function processFiles(dir) { const files = await fs.promises.readdir(dir); for (const file of files) { const filePath = path.join(dir, file); const stats = await fs.promises.stat(filePath); if (stats.isDirectory()) { await processFiles(filePath); continue; } if (!file.endsWith('.md')) continue; const content = await fs.promises.readFile(filePath, 'utf8'); const parsed = matter(content); if (parsed.data.ai_comment && !process.argv.includes('--force')) { console.log(`[Skip] ${file} already has ai_comment`); continue; } console.log(`[Generating] Comment for ${file}...`); // Remove front matter and HTML tags for prompt const cleanContent = parsed.content.replace(/<[^>]*>?/gm, ''); const comment = await generateComment(cleanContent); if (comment) { parsed.data.ai_comment = comment; const newContent = matter.stringify(parsed.content, parsed.data); await fs.promises.writeFile(filePath, newContent); console.log(`[Success] Updated ${file}`); } else { console.log(`[Failed] Could not generate comment for ${file}`); } } } // Check arguments const args = process.argv.slice(2); if (args.includes('--help')) { console.log(` Usage: node scripts/ai_comment.js Environment Variables (.env): AI_PROVIDER - 'siliconflow' (default) or 'zhipu' SILICONFLOW_API_KEY - Key for SiliconFlow ZHIPU_API_KEY - Key for Zhipu AI `); process.exit(0); } console.log(`Starting AI Comment Generator using ${PROVIDER}...`); processFiles(CONTENT_DIR).catch(console.error);