歌词尚未加载
这篇文章专门记录博客里的 AI 摘要系统。
它和 QQ 群通知是两套独立工作流:
- AI 摘要负责生成文章摘要、更新
deploy、触发 Cloudflare 部署 - QQ 群通知负责在新文章真正上线后发送群消息
这篇只记录 AI 摘要部分,方便以后回顾架构、排查问题,或者继续修改生成逻辑。
目前的分支结构
博客现在使用两个 Git 分支:
1 | main |
日常开发只操作:
1 | main |
不要手动修改:
1 | deploy |
一句话概括:
1 | 我维护 main,机器人维护 deploy,Cloudflare 只部署 deploy。 |
为什么不用 main 直接保存摘要
最初的方案是让 GitHub Actions 把摘要缓存提交回 main:
1 | source/_data/ai-summaries.json |
这样虽然能工作,但机器人每生成一次摘要,远程 main 就会多出一个提交。
本地继续推送时可能出现:
1 | ! [rejected] main -> main (fetch first) |
然后需要额外执行:
1 | git pull --rebase origin main |
如果本地还有未提交内容,还可能需要:
1 | git stash |
为了避免机器人不断修改我日常使用的 main,后来把自动生成内容全部放到了独立的 deploy 分支。
现在:
1 | main |
这样本地发布文章时,不会再因为摘要机器人提交而产生同步冲突。
AI 摘要工作流的文件位置
GitHub Actions 工作流:
1 | .github/workflows/generate-ai-summaries.yml |
摘要生成脚本:
1 | .github/scripts/generate-ai-summaries.mjs |
Hexo 摘要渲染脚本:
1 | scripts/ai-summary-render.js |
摘要样式:
1 | source/css/ai-summary.css |
摘要缓存:
1 | source/_data/ai-summaries.json |
其中,摘要缓存只由 deploy 分支保存。
main 中通过 .gitignore 忽略:
1 | source/_data/ai-summaries.json |
完整自动流程
当我把内容推送到 main 后,AI 摘要工作流自动启动:
1 | 本地修改文章或博客源码 |
Cloudflare 不再直接部署 main。
只有 deploy 更新时,才会触发正式网站构建。
当前使用的 AI 模型
当前模型:
1 | @cf/zai-org/glm-4.7-flash |
通过 Cloudflare Workers AI REST API 调用。
GitHub 仓库中需要配置两个 Secrets:
1 | CLOUDFLARE_ACCOUNT_ID |
Token 不能写入代码、文章或普通仓库文件中。
摘要什么时候会重新生成
脚本会根据文章内容生成一个哈希:
1 | sourceHash |
它用于判断文章是否发生变化。
规则如下:
1 | 新文章 |
因此不会每次部署都重复调用模型。
摘要缓存保存了什么
ai-summaries.json 中每篇文章大致包含:
1 | { |
其中:
title:文章标题slug:用于匹配文章summary:最终显示的摘要sourceHash:判断缓存是否仍然有效model:摘要来源generatedAt:生成时间
摘要如何显示到文章里
Hexo 构建时,scripts/ai-summary-render.js 会读取:
1 | source/_data/ai-summaries.json |
然后根据以下信息匹配文章:
1 | 文章源文件路径 |
匹配成功后,把 AI 摘要卡片插入正文最前面:
1 | 文章标题与元信息 |
摘要是构建时静态写入 HTML 的,不是访客打开页面后再请求 AI。
这样做的好处:
- AI Token 不会暴露给浏览器
- 访客打开文章时不需要等待模型
- 已生成摘要不会受 AI 服务临时故障影响
- 搜索引擎能直接读取静态 HTML
- 不会增加每次访问文章的 AI 调用成本
私密文章的处理
脚本默认不会把私密文章发送给 AI。
满足以下任意条件时,会跳过:
1 | permalink: /private/... |
或者:
1 | private: true |
或者:
1 | tags: |
或者:
1 | categories: |
日志会显示:
1 | 私密文章默认不发送给 AI |
允许某篇私密文章调用 AI
1 | ai_summary_private: true |
只有确认文章内容可以发送给模型时才使用。
关闭某篇文章的 AI 摘要
1 | ai_summary: false |
自己填写摘要,不调用模型
1 | ai_summary_text: > |
手动摘要仍会显示在文章中,但不会消耗 Workers AI 调用。
手动运行摘要工作流
进入:
1 | GitHub |
Use workflow from 始终选择:
1 | main |
不要选择 deploy。
missing 模式
1 | 生成范围:missing |
作用:
1 | 为缺少摘要的文章生成摘要 |
这是最常用的模式。
single 模式
1 | 生成范围:single |
适合只测试一篇文章。
all 模式
1 | 生成范围:all |
它会强制重新生成候选文章。
通常只有在以下情况使用:
- 修改了摘要提示词
- 更换了模型
- 想把所有旧摘要重写一遍
平时不需要选择 all。
Cloudflare 的相关设置
Cloudflare 连接的仓库:
1 | zqf1314/zqf-blog |
生产分支:
1 | deploy |
非生产分支构建:
1 | 关闭 |
所以:
1 | main 更新 |
当前构建命令:
1 | pnpm run build |
对应执行:
1 | hexo generate |
当前部署命令:
1 | pnpm exec wrangler deploy |
最终部署的是:
1 | public/ |
修改不同内容时会发生什么
新增文章
1 | 推送 main |
修改旧文章正文
1 | 推送 main |
修改主题、CSS 或 JavaScript
1 | 推送 main |
日志出现下面内容是正常的:
1 | 本次候选文章:0 |
这表示本次没有文章需要调用 AI,不代表部署失败。
删除文章
1 | 推送 main |
总结
当前 AI 摘要系统可以概括为:
1 | main 保存人工维护的源码 |
以后只需要维护 main。
deploy、AI 摘要缓存和 Cloudflare 部署全部由自动化流程处理。
评论