130 lines
4.4 KiB
JavaScript
130 lines
4.4 KiB
JavaScript
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);
|