hexo-ai-summary-liushen
Version:
Hexo 插件:使用 AI(如 ChatGPT 或腾讯混元)自动为 Markdown 博文生成摘要,并将摘要写入 front-matter,可控制并发请求。
94 lines (79 loc) • 3.63 kB
JavaScript
const strip = require('./strip')
const ai = require('./ai')
const fs = require('hexo-fs')
const fm = require('hexo-front-matter')
const pLimit = require('p-limit')
const config = hexo.config.aisummary || {}
if (!config.api) {
console.error('[Hexo-AI-Summary-LiuShen] 请在配置文件中设置 api')
return
}
const limit = pLimit(config.concurrency || 2) // 设置最大并发数,比如 2
const fieldName = config.summary_field || 'summary' // 默认为 'summary'
const defaultPrompt = config.prompt || '请为这些内容生成一个简短的摘要:'
// 日志等级枚举
const LOG_LEVELS = {
SILENT: 0, // 只输出错误
NORMAL: 1, // 输出错误和需要生成摘要的文章
VERBOSE: 2 // 输出所有信息,包括跳过的文章
}
// 获取当前的日志等级,默认为 NORMAL
const logLevel = config.logger ?? LOG_LEVELS.NORMAL
hexo.extend.filter.register('before_post_render', async function (data) {
// 检查是否为文章页面
if (data.layout != 'post' || !data.source.startsWith('_posts/')) {
if (logLevel >= LOG_LEVELS.VERBOSE) {
console.info(`[Hexo-AI-Summary-LiuShen] 跳过 ${data.title},不是文章页面`)
}
return data
}
return await limit(async () => {
if (!config.enable && !data.is_summary) {
if (logLevel >= LOG_LEVELS.VERBOSE) {
console.info(`[Hexo-AI-Summary-LiuShen] 文章 ${data.title} 被标记为不进行摘要,跳过`)
}
return data
}
if (data[fieldName] && data[fieldName].length > 0 && config.cover_all !== true) {
if (logLevel >= LOG_LEVELS.VERBOSE) {
console.info(`[Hexo-AI-Summary-LiuShen] 文章 ${data.title} 已经有摘要,跳过`)
}
return data
}
let content = strip(data.content, data.title, config)
const path = this.source_dir + data.source
const frontMatter = fm.parse(await fs.readFile(path))
// 去掉 frontMatter 中的 _content,并保存到 MdContent 变量中,删除MDContent 文本开始可能存在的换行符
const MdContent = frontMatter._content.replace(/^\n+|\n+$/g, '')
delete frontMatter._content
try {
const ai_content = await ai(
config.token,
config.api,
config.model,
content,
defaultPrompt
)
// 检测内容是否为空,是否有换行,是否有#,$,%之类的特殊字符
if (!ai_content || ai_content.length < 10 || /[\n#$%]/.test(ai_content)) {
if (logLevel >= LOG_LEVELS.NORMAL) {
console.info(`[Hexo-AI-Summary-LiuShen] 文章 ${data.title} 的摘要内容不符合要求,跳过`)
}
if (logLevel >= LOG_LEVELS.VERBOSE) {
console.info(`[Hexo-AI-Summary-LiuShen] 文章 ${data.title} 的摘要内容为:${ai_content}`)
}
return data
}
frontMatter[fieldName] = data[fieldName] = ai_content
await fs.writeFile(path, `---\n${fm.stringify(frontMatter)}\n${MdContent}`)
if (logLevel >= LOG_LEVELS.NORMAL) {
console.info(`[Hexo-AI-Summary-LiuShen] 摘要 ${data.title} 完成`)
}
} catch (err) {
if (logLevel >= LOG_LEVELS.SILENT) {
console.error(`[Hexo-AI-Summary-LiuShen] 生成摘要失败:${data.title}\n${err.message}`)
}
}
return data
})
})