前言

工作的时候经常要在网上搜索一些资料,偶然间发现某个博客站点竟然有了「AI 摘要」这样的功能,在大模型如此火热的时代,All in AI 已然是唯一的选择,于是乎捣鼓起了免费的大模型,历经如下的痛苦过程:

  • 货比三家、模型选择
  • 读模型文档
  • SDK 上手
  • prompt 编写
  • 自动化处理文章

至于为什么说痛苦呢,因为在 2024 年,居然还有厂商没有适配 openai 的 api,搞自己的一套 SDK

文档也是非常松散,左一堆右一堆的,甚至还有 v1 和 v2 的区别

AKSK 生成的位置也是非常逆天,到底我是要生成这个云账号的通用 AKSK 呢,还是要生成大模型专用的 AKSK(主要这俩生成的页面还不一样

以上都是痛苦的经历,明明我只需要import openai,然后输入token,最后编写prompt就能完成...(还不是因为没钱买额度,不管怎么说,白嫖的还是最爽的!)

至此,一段以大模型为由的捣腾记录就此拉开序幕...

背景

在聊 zola 的折腾过程之前,肯定有人会问了——「zola 是个啥?」

Zola is a static site generator (SSG), similar to Hugo, Pelican, and Jekyll (for a comprehensive list of SSGs, please see Jamstack). It is written in Rust and uses the Tera template engine, which is similar to Jinja2, Django templates, Liquid, and Twig.

以上介绍来自 zola 的官方文档,简单来说就是一个 rust 编写的静态站点生成器(这几年「rust 重构」的风气很流行,好像什么东西都要被 rust 重写一遍)zola 的功能和 hugo 基本一样,可以直接平替了。

至于为什么是用 zola,这还要从我第一个是用的博客框架说起...

最开始我博客的域名还不是这个,而是 .top 的顶级域名,之前的博客是用 halo 1.6 的版本,用自己腾讯云的机器+Docker 部署,大概陪伴了我大学三年的时间,直到某一天上了腾讯云,发现 .top 的域名和腾讯云机器会在 24 年的 10 月过期,想着迁移博客数据虽然简单,但是这个域名的国内备案和这台腾讯云的机器强绑定了,一旦这个机器过期,那不是又得备案一次。说起来备案这玩意也是挺难顶的,三年多多少少打了不下 10 次我的电话,说备案怎么怎么了,导致我对备案这件事情望而生畏。

契机来到了 23 年的 Q3,看着 .cn 域名也挺便宜,于是又买了目前这个域名,当时是 .top 和 .cn 双持的,而 .cn 又没有机器绑定,所以搞起来了 github page + cname 的方式部署了一个hexo 生成的静态站点在 .cn 上,当时用的是 hexo 支持的github action,那时候也不懂 github action 到底干了个啥,也就没去管,部署上了就行了,当时使用 hexo 主要还是因为其中的一个 oranges 主题挺好看,所以也是用上了。

趁着捣腾 hexo 的期间,我也在选择 halo 的主题,无意间发现了 terminal 这个主题,当时还对其做了魔改,非常喜欢这种风格的样式。

随着时间的推移,我需要将 halo 中的博客数据导出,用静态站点的方式,将文章迁移到 .cn 这个新域名上。顺带一提,halo 的后台自带导出 markdown 的功能,这点还是非常方便的。之后就将 markdown 适配了 hexo 的文章样式,在 md 的顶部是用 yaml 的配置进行文章配置。

23 年 Q3 那会,.cn 这个站点还是是用 hexo + oranges 主题 + github page 的方式进行部署的。但是渐渐的我发现,每次需要git pull hexo 站点的源码然后编辑,这样的操作太难受了,而且hexo 使用 github page 自动部署的方式我选择的是在源码仓库中新建一个 branch用于 page 的显示。最难顶的一点来了,GitHub 的普通用户,如果仓库开启了 github page,那么这个仓库必须 public。这样我有些加密的文档那不都给别人看全了。虽然可以通过 hexo 源码放在仓库 A,生成的静态内容放置在仓库 B,这样的方式来解决,但是当时我根本懒得去钻研,直到看到了 hugozola 这两个不同于 hexo 的框架。

为什么在 hugo 和 zola 中选择了 zola 呢?原因是我认为 zola 的 zola-theme-terminimal 主题比 hugo 的 hugo-theme-terminal 要好看不少,并且 zola-terminimal 这个主题仅用 html + scss 实现,没有任何的 js。所以我直接选择了「zola」!

刚刚也提到了 github page 的问题,为了能够使用 private 的仓库来存储 blog 的源码,我使用了 cloudflare pages 来部署本站点,并且配合 cloudflare pages 的构建功能,我只需要对源码仓库 git push 了任意数据,cloudflare pages 就能自动构建一次。

image-20241030151342252

cloudflare pages 的唯一缺点就是,存储限制 25mb。由于本站点生成的 rss.xml 有 28mb,导致不得不关闭了 rss。

image-20241030151659269

新功能

在介绍完使用 zola 的背景后,开始介绍这个月对 zola theme 捣鼓了啥(之前使用shortcode编写了个加密功能

所有的 theme 功能都可以在源码中找到 Aoodwhale/zola-theme-terminimal,是基于 pawroman/zola-theme-terminimal 二开的

AI 摘要

小小的「AI 摘要」,生成其实非常的简单,就两步:

  1. 给大模型灌输 system 的 prompt 指令
  2. 输入文章内容,等待大模型的输出

我选用的模型是百度千帆的ERNIE-128k, prompt 如下:

你是一个博客文章总结专家,你擅长提取博客文章的核心内容,生成总结。你需要将给定的博客的内容进行总结。
约束条件:
- 当博客内容发送给你时,请直接回复总结内容,不需要说无关的话。
- 你应该尽可能提取博客的核心内容,生成简洁的总结。
- 不要输出 "总结:""全文总结:""博客文章总结:",这样的文字。
- 如果存在关键代码,可以简单说明代码的作用,或者理解代码的功能并简述用途。
- 总结内容使用 markdown 格式,让总结更具条理性。
- 总结内容使用中文输出。
- 总结内容最好不超过 300 个字符。

但是,如何适配 zola,这是个问题!

第一个问题是,「我如何编写一个好看的前端页面来展示 AI 生成的摘要内容?」

前端这个东西,能不碰就不碰,因为改 css、js 这种东西不仅耗时耗力,而且自己总是不会满意。于是乎,我用起了 Xunflash 在毕设期间大量使用推荐的 v0.dev。之前就体验过它的强大之处,短短几个月,我感觉它更好用了。只需要输入你的需求,然后AI 就能自动生成前端代码(主要是 React 和原生样式)。我用如下的 prompt + 样式图片上传 就拿到了第一版的 AI 摘要样式:

帮我编写一个富含科技感的 AI分析总结框,可以适配dark 和 light 模式,能够折叠或展开(默认展开),包含文章总结、最后更新时间、使用的 AI 模型信息。请使用原生的 css 或者 Tailwind 实现,不要使用 react 或者 vue 实现,因为我需要将这个样式部署在静态博客系统上,请使用原生 js、html、css 实现。请适配我的博客页面主题

之后就是对生成的 html 进行修修改改,你可以在 ai_summary.htmlsummary.scss 看到我目前使用的样式,都是基于 AI 生成后修修补补的。

第二个问题是,「有了前端我该如何注入 AI 生成的内容?」

得益于 zola 的模版样式,我可以在 templates 中直接嵌入 AI 生成的内容的文件路径,在 ai_summary.html 的源码中,通过 zola 自带的 load_data 函数,就能够读取文件的内容并嵌入到变量中 {% set data = load_data(path="summary/" ~ src) %}

第三个问题是,「我该如何指定 AI 生成的内容位置,并配置是否需要 AI 总结?」

得益于 zola 的 md 配置,我可以在 md 文件的开头的 toml 或 yaml 配置中指定extra这个 key,同时通过读取该配置来决定是否渲染 AI 总结的样式,具体源码在 post.html#L26,而文章编辑者只需要在md文件的开头写下如下的extra配置即可:

---
date: 2024-03-02
description: 没想到,原来输入法也有自己的圈子...
extra:
  ai:
    model: Baidu-ERNIE
    src: use-rime-input
    update: '2024-10-23 20:15:41'
slug: use-rime-input
taxonomies:
  tags:
  - Casual
title: 【Talk】RIME输入法上手
---

至此,AI摘要的功能就完美实现了。该功能我一共写了两个版本,第一个版本是使用 shortcodes 实现的,需要在每个md 文件的开头部分注入 \{\{ summary(src="ai-summary", update="2024-10-29 12:12:12", model="chatgpt3.5")\}\} 这样的shortcode,但是这样太麻烦了,随后就有了上述版本,只需要在配置中指定extra.ai就能实现。

内容搜索

对于有后端的系统,搜索功能直接 MySQL 语句 或者是用 solr 等引擎就能实现实时搜索,但是静态站点就得去构建索引然后通过 js 去搜索了。

在搜索了一段时间后发现,pagefind 这个基于 rust 编写的静态页面搜索框架非常的好用,不仅自带 UI,而且一个命令就能自动生成索引并接入。官方文档中写的也非常简单,一共两步

第一步,生成 pagefind 数据,在 zola build 之后,会生成一个public目录,该目录下都是静态页面的数据,通过如下的命令,能够直接生成一个public/pagefind文件夹,其中存储了必要的数据

npx -y pagefind --site public --serve

第二步,在 zola theme 中嵌入如下的内容,这样站点就能直接显示搜索了,我二开的主题源码在 search.html

<link href="/pagefind/pagefind-ui.css" rel="stylesheet">
<script src="/pagefind/pagefind-ui.js"></script>
<div id="search"></div>
<script>
    window.addEventListener('DOMContentLoaded', (event) => {
        new PagefindUI({ element: "#search", showSubResults: true });
    });
</script>

进一步的data-pagefind-bodydata-pagefind-metadata-pagefind-filter等内容可以在官方文档中查阅使用。我用到的位置 post.html#L29post.html#L80post.html#L123

效果如下:

image-20241030155722857

评论系统

静态站点接入评论系统的选择还是挺多的,有基于GitHub issue的,也有基于后端数据库的。

基于GitHub:

  • https://github.com/giscus/giscus
  • https://github.com/gitalk/gitalk

基于后端:

  • https://github.com/walinejs/waline (本站点选用)
  • https://github.com/twikoojs/twikoo

考虑到GitHub的DNS污染和访客无需登录就能评论的情况,最终我还是选择了 waline 进行免费的部署:

  • https://waline.js.org/ 官方文档

  • https://tidbcloud.com/ 数据库

  • https://vercel.com/ 管理端

官方给人的感觉就是,内容太多,很多东西需要搜索才能找到,最后选用了免费的 5GB TiDB + vercel 进行部署

在 vercel 中编辑如下的环境变量就可以正常使用了:(DISABLE_USERAGENT 和 DISABLE_REGION不必要)

image-20241030161019232

至于如何在 zola 中使用,这是我的源码 comment.htmlpage.html(后续计划将serverURL抽离到 config.toml 配置中)

效果还是挺不错的:

image-20241030163232899

播放器

前端的播放器主流的就两个:音乐播放器APlayer 和 视频播放器DPlayer

视频在博客站点也不常用,但是分享 True Music还是必要滴,于是乎,使用shortcode编写了一版 music.html

需要导入 aplayer 的 js 和 css,然后就是解析器 MetingJS

以上必要的 js 和 css 我都在 cdn.html 中导入了

这两周也是一直在循环大同老师的新专「梦想家 The Dreamer」,就以这首《没啥好说》在这小节结尾吧

后话

给 zola 捣鼓了四个新功能,好玩

参考文档:

  1. Qianfan

    • https://github.com/baidubce/bce-qianfan-sdk
    • https://github.com/fruitbars/simple-one-api/blob/main/docs/%E7%99%BE%E5%BA%A6%E5%8D%83%E5%B8%86speed%E5%92%8Clite%E6%A8%A1%E5%9E%8B%E7%94%B3%E8%AF%B7%E6%B5%81%E7%A8%8B.md
  2. pagefind

    • https://github.com/cloudcannon/pagefind

    • https://pagefind.app/docs/

  3. waline

    • https://waline.js.org/

    • https://tidbcloud.com/

    • https://vercel.com/

  4. alpayer

    • https://github.com/metowolf/MetingJS
    • https://github.com/DIYgod/APlayer

2024-11-01 站点适配了 pjax 加载,具体的内容有时间再水篇博客吧,还是好好 enjoy weekend 吧!