Featured image of post Hi,AI 摘要

Hi,AI 摘要

又又又来折腾博客了,看不少博友都加上了 AI 总结文章的功能,也想自己整一个。本文借鉴了大大的小蜗牛并进行了部分修改。

效果图

获取摘要数据

AI 生成总结

方式有三种:

  • 接入 TianliGPT,自动在访问时生成(需要购买 Key)
  • 通过脚本从 ChatGPT 或 Claude 获取
  • 手动把文章内容喂给 ChatGPT 或 Claude 获取

我自己用的是第三种。因为我博客也就三十几篇文章,TianliGPT 9 块钱能生成至少 50 篇文章的摘要,而且目前博客访问的人也不多,能省就省省😅。脚本虽然很方便,但貌似我还不太会使用,搞不出来。正好之前部署过 NextChat 且有一个免费的 GPT-3.5 的 API Key,所以就手动喂给 GPT 了。

数据存在哪

有两种方式:

  1. 在 /data 目录下用 json 文件保存
  2. 把摘要结果放在文章 Front Matter 的 summary

方式 1 显然要比方式 2 方便维护。

在 /data 新建 summary.json, 数据格式如下:

{
  "summaries": [
    {
      "title": "",
      "slug": "",
      "generated": true,
      "summary": ""
    }
    ]
}

渲染 AI 摘要

修改模板文件

Hugo 可以直接修改位于 /layouts 的页面模板文件,大大的小蜗牛直接把代码加在 single.html 里了,我为了单个文件不要太长难看懂,单独将 AI 摘要部分放在一个文件里。如果同样是 Stack 主题,可以直接跟着下文操作,其他主题也大差不差。

/layouts/partial/article/components 创建 aisummary.htmlgetJSON 仅适用于 Hugo 0.134.3 及以下,新版的 resource.Get 我搞不明白):

<!-- 获取数据 -->
{{ $summary := getJSON "data/summary/summary.json" }}

<!-- 以 slug 作为锚点来对应文章与摘要 -->
{{ $currentSlug := .Params.slug }}
{{ $matchingSummary := index (where $summary.summaries "slug" $currentSlug) 0 }}

<div class="post-ai">
    <div class="ai-title">
        <i class="fas fa-robot ai-title-icon"></i>
        <div class="ai-title-text">AI 摘要</div>
    </div>

    <!-- Typeit 打字机效果,不需要则注释掉下面这行代码 -->
    <div id="ai-explanation" class="ai-explanation"></div>

    <div class="ai-explanation ai-explanation-content">
        {{ if $matchingSummary.summary }}
            {{ $matchingSummary.summary }}
        {{ else }}
            AI 摘要接口暂时失联……
        {{ end }}
    </div>
</div>

<!-- 打字机效果的 JS 不需要则注释掉 -->
<script src="https://npm.elemecdn.com/typeit@8.7.1/dist/index.umd.js"></script>

<script>
document.addEventListener("DOMContentLoaded", function () {
    // 从 .ai-explanation-content 取值
    const matchingSummary = document.querySelector(".ai-explanation-content").textContent;

    new TypeIt("#ai-explanation", {
        strings: matchingSummary,
        speed: 10,
        lifeLike: true,
        waitUntilVisible: true,
    }).go();
});
</script>

<i class="fas fa-robot ai-title-icon"></i> 中的 fas fa-robot 需要更改为你自己的图标 CSS 里的名称(生成 CSS 可用 Fontello)
如不需要打字机效果,需要将 <div id="ai-explanation" class="ai-explanation"></div> 和 JS 部分注释掉。
这里的修改是把 unpkg 换成了国内的饿了么 npm 镜像,并且调快了打字机速度(原来感觉有点太慢了,如果还觉得慢可以把 speed 数值继续调小)
然后把摘要引入文章的模板文件。在 /layouts/partial/article/article.htmlheadercontent 中间加上 {{ partial "article/components/aisummary" . }}

添加 CSS

为了方便管理我单独创建了 ai.scss。在 /assets/scss 下的合适位置(我是 /assets/scss/custom)创建 ai.scss

.post-ai {
    background: #f5f5f5;
    border-radius: 2rem;
    padding: 1rem;
    line-height: 1.5;
    border: 10px solid #ffffff;
    margin: 1rem 0;
}

.ai-title {
    display: flex;
    color: #2d96bd;
    border-radius: 0.5rem;
    align-items: center;
    padding: 0 0.25rem;
    cursor: default;
    user-select: none;
}

.ai-title-icon {
    width: 20px;
    height: auto;
    margin-right: 0.25rem;
}

.ai-title-text {
    font-weight: bold;
    margin-left: 1rem;
    line-height: 1;
}

.ai-explanation {
    margin-top: 1rem;
    padding: 0.5rem 1rem;
    background: #fff;
    border-radius: 0.5rem;
    border: 1px solid #cfe6f3;
    font-size: 1.5rem;
    line-height: 1.7;
    display: inline-block;
    width: 100%;
}

.ai-explanation span {
    margin-left: 0.5rem;
}

// 打字机效果,不需要则注释掉
.ai-explanation-content {
    display: none !important;
}

部分参数可以自行根据喜好更改。
如不需要打字机效果,也要把最后一项 ai-explanation-content 的 CSS 注释掉。
然后在 /assets/scss/custom.scss 中引入(@import "custom/ai.scss";)。

单篇文章禁用摘要

这是我自己添加的功能。有些文章代码太多,总字符数很大,导致喂给 GPT 会超出最大字符数,无法生成摘要。并且一些文章并不需要 AI 摘要,比如我的 Hugo-theme-Stack 魔改美化博客魔改美化(通用) 这两篇文章,几乎都是代码片段,右侧的目录本身就是总结。所以禁用单篇文章摘要的功能来了。受到 article.html 里面 {{ if or .Params.math .Site.Params.article.math }}{{ partialCached "article/components/math.html" . }}{{ end }} 的启发,可以通过调用 Hugo 的函数方式实现。

询问 ChatGPT 后得知,上面的代码意思是:

这段代码是在Hugo模板中使用的条件语句,用于根据条件来决定是否插入数学公式。让我们逐步解释这段代码的含义:

  1. {{ if ... }} ... {{ end }}:这是 Hugo 模板中的条件语句,表示如果条件为真,则执行条件语句块中的内容。

  2. or .Params.math .Site.Params.article.math:这部分是条件语句的条件部分。它使用了逻辑运算符or来判断两个条件中只要有一个为真即为真。具体解释如下:

    • .Params.math:这是访问当前页面(文章)的 Front Matter 参数中的 math 字段的值。通常,这个字段用于标识该文章是否包含数学公式。
    • .Site.Params.article.math:这是访问网站全局参数中的 article.math 字段的值。这个字段可能用于设置整个网站是否启用数学公式显示。
  3. {{ partialCached "article/components/math.html" . }}:如果条件为真,将会调用名为 article/components/math.html 的部分模板。这个部分模板可能包含用于显示数学公式的相关代码。

综合起来,这段代码的意思是:如果当前页面的 Front Matter 中包含 math 字段,或者网站全局参数中的 article.math 字段为真,那么就会插入数学公式相关的内容,可能是通过调用特定的部分模板来实现数学公式的显示。

那么我们一葫芦画瓢,写一个“除非当前页面的 Front Matter 中的 ai 字段为 false,那么就插入文章摘要”的条件语句。
翻了下 Hugo 写得很复杂的文档后找到了一个 ne 函数,它的作用是判断两个值是否不相等,如果不相等,则返回 true,否则返回 false
那么我们需要的代码就是 {{ if ne .Params.ai false }}{{ end }}
现在仅实现了在单篇文章的 Front Matter 中禁用,如果要能够统一禁用所有的 AI 摘要,就需要在网站全局参数中设置一个字段,如 article.ai 字段。
修改一下,使用 and 函数来要求两个条件同时为真才执行条件语句中的内容。只有当 Front Matter 中的 ai 字段和网站全局参数中的 article.ai 字段的值都不为 false 时,才会执行条件语句块中的内容:{{ if and (ne .Params.ai false) (ne .Site.Params.article.ai false) }}{{ end }}

现在将最终的代码片段加在 /layouts/partial/article/article.htmlheadercontent 中间:

{{ if and (ne .Params.ai false) (ne .Site.Params.article.ai false) }}
    {{ partial "article/components/aisummary" . }}
{{ end }}

再在 hugo.yamlconfig.yaml 中加一个 article.ai 字段并设为 true,想要禁用单篇文章摘要在 Front Matter 中加上 ai: false 即可。

Enjoy~

阅读量: 0
Licensed under CC BY-NC-SA 4.0 转载请在留言板告知
最后更新于 2024-12-13 21:50