最近看到很多博客都加上了 AI 摘要功能,觉得挺有意思,于是也尝试给自己的博客加了一个。

我的需求很简单:

  1. 自动生成:发布新文章时自动调用 API 生成摘要。
  2. 融入评论区:不想额外增加 UI 模块,最好能像一条普通的“置顶评论”一样展示。
  3. 零成本:利用现有的免费 API(DeepSeek V3)。

目前已经实现,效果还算满意。简单记录一下实现过程。

1. 后端:生成 AI 评论

写了一个简单的 Node.js 脚本,遍历文章目录,提取正文并调用 SiliconFlow 的 API 生成评论,最后回写到 Front Matter 中。

核心代码 (scripts/ai_comment.js):

// ... (imports & config)

async function generateComment(content) {
    const prompt = `你是一个热情的博客读者。请阅读以下文章内容,并写一段简短的评论(100字以内)。
    ...
    文章内容:${content.substring(0, 2000)}...`;

    // 调用 SiliconFlow API
    const response = await axios.post(SILICONFLOW_URL, {
        model: 'deepseek-ai/DeepSeek-V3',
        messages: [{ role: 'user', content: prompt }],
        // ...
    }, { headers: { 'Authorization': `Bearer ${process.env.SILICONFLOW_API_KEY}` } });
    
    return response.data.choices[0].message.content.trim();
}

// 遍历文件并处理
async function processFiles(dir) {
    // ...
    if (parsed.data.ai_comment) return; // 跳过已生成的文章

    const comment = await generateComment(cleanContent);
    if (comment) {
        parsed.data.ai_comment = comment;
        // 回写文件
        await fs.promises.writeFile(filePath, matter.stringify(parsed.content, parsed.data));
    }
}

2. 自动化:GitHub Actions

为了省去手动运行脚本的麻烦,将其集成到了 CI/CD 流程中。

.github/workflows/upy.yml 中添加步骤:

    # 生成 AI 评论
    - name: Generate AI Comments
      env:
        SILICONFLOW_API_KEY: ${{ secrets.SILICONFLOW_API_KEY }}
      run: node scripts/ai_comment.js

    # 提交变更 (注意需要 permissions: contents: write)
    - name: Commit AI Comments
      run: |
        git config --global user.name "GitHub Actions"
        git config --global user.email "actions@github.com"
        git add content/post
        if ! git diff-index --quiet HEAD; then
          git commit -m "chore: auto-generate ai comments [skip ci]"
          git push
        fi        

3. 前端:Artalk 集成

最后一步是在前端展示。利用 Artalk 的事件机制,将 AI 评论动态插入到评论列表头部,并加上打字机特效。

核心代码 (assets/js/main.js):

window.artalk.on('list-loaded', function() {
    // 检查是否有 AI 评论数据
    if (window.artalkConfig.aiComment && !document.querySelector('.atk-ai-comment')) {
        var listBody = document.querySelector('.atk-list-body') || document.querySelector('.atk-list');
        
        if (listBody) {
            // 避免同时出现“此时无声胜有声”
            var noComment = document.querySelector('.atk-list-no-comment');
            if (noComment) noComment.style.display = 'none';

            // 创建 DOM 结构
            var aiDiv = document.createElement('div');
            aiDiv.className = 'atk-comment atk-ai-comment';
            aiDiv.innerHTML = `...`; // 填充 HTML
            
            // 插入到列表头部
            listBody.prepend(aiDiv);
            
            // ... (打字机效果)
        }
    }
});

4. 适配 PJAX

由于博客使用了 PJAX,页面切换时需要重新初始化 Artalk。我们将初始化逻辑封装在 initArtalk 函数中,并在 pjax:complete 事件中调用。

// mypjax.js
document.addEventListener("pjax:complete", function () {
    // ...
    // 重载评论
    if (typeof window.initArtalk === 'function') {
        window.initArtalk();
    }
});

这样就完成了一个简单实用的 AI 摘要功能。既丰富了页面内容,又没有过度干扰阅读体验。