正在为您加载破荒时刻...

 Hugo 部署 AI 自动摘要功能教程

Hugo 部署 AI 自动摘要功能教程

DeepSeek AI 摘要

前言

前几天看一篇博文《Hi,AI 摘要 》时,突然我也想弄一个 AI 摘要功能。 Xalaok 博主给了我一个折腾的思路,我突然想起我的 GitHub Actions 的免费额度一直没有用,所以就想到用 GitHub Actions 来实现我的愿望,说干就干!

挑选 AI

我从六家 AI 进行挑选(包括 ChatGPT , Claude , Gemini , DeepSeek , 豆包, Grok),原本打算用 Google Gemini API,因为 Gemini 是我最喜欢用的 AI ,而且 Google 很大方,它的 API 免费!但是由于地区限制 + 我的魔法不是很灵,这个迟迟不让我申请,然后我就转向了 DeepSeek ,虽然我最讨厌 DeepSeek,但我记得我有 DeepSeek 的免费10元额度,所以我就选了 DeepSeek ,后来才发现我之前用过。

申请 API

  1. 访问DeepSeek 开放平台
  2. 注册一个账号
  3. 获取 Key:点击左侧 “ API Keys ” ,创建并保存好 sk- 开头的密钥。
  4. 充值:10元钱应该就够,下面是 DeepSeek API 的计费规则
方式 价格 备注
百万tokens输入(缓存命中) 0.2元 内容高度相似
百万tokens输入(缓存未命中) 2元 内容崭新
百万tokens输出 3元 输出内容

扣减费用 = token 消耗量 × 模型单价

配置 GitHub Secrets

  1. 在你博客的 GitHub 仓库中 - > Settings -> Secrets and variables -> Actions
  2. 点击 New repository secret
  3. 名称:DEEPSEEK_API_KEY
  4. 值:填入刚才的 sk-... 密钥

全自动摘要 Python 脚本

  1. 在仓库根目录下创建 .github/scripts/summarize.py,内容写下面内容(下面内容由 Gemini 替我编写,效果只能说一般,我感觉是 DeepSeek 的问题)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import os, requests, frontmatter
from pathlib import Path

API_KEY = os.environ.get("DEEPSEEK_API_KEY")
API_URL = "https://api.deepseek.com/v1/chat/completions"

def get_summary(content):
    headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
    # 优化后的结构化 Prompt
    prompt = (
        "你是一个专业的博文摘要助手。请阅读以下文章内容,并遵循以下准则:\n"
        "1. 撰写一段150字以内的中文摘要。\n"
        "2. 摘要必须准确、客观地概括全文核心论点或主要内容,严禁臆想或加入文中未提及的事实。\n"
        "3. 语言要精炼,直接输出摘要正文,不要有'这篇文章介绍了'、'摘要如下'等废话。\n"
        "4. 尊重原意,保持中立的专业语气。\n\n"
        f"文章内容如下:\n{content[:3500]}" # 稍微增加了截取长度以提供更多上下文
    )
    
    data = {
        "model": "deepseek-chat",
        "messages": [{"role": "user", "content": prompt}],
        "temperature": 0.3 # 降低随机性,让输出更严谨、更尊重原文
    }
    try:
        res = requests.post(API_URL, json=data, headers=headers).json()
        return res['choices'][0]['message']['content'].strip()
    except Exception as e:
        print(f"API 请求出错了: {e}")
        return None

# --- 地毯式搜索 ---
base_dir = Path(__file__).resolve().parent.parent.parent
print(f"当前仓库根目录定位在: {base_dir}")

files_checked = 0
for path in base_dir.rglob("*.md"):
    # 1. 过滤掉 .github, archetypes 以及所有 index.md (包括 _index.md)
    if any(part in str(path) for part in [".github", "archetypes"]) or path.name.lower() in ["index.md", "_index.md"]:
        continue
        
    files_checked += 1
    post = frontmatter.load(path)
    
    print(f"检测到文件: {path.relative_to(base_dir)}")
    
    # 2. 逻辑判断:没有 description,且不是草稿
    if not post.get('description') and not post.get('draft'):
        print(f"  🚀 正在生成摘要...")
        summary = get_summary(post.content)
        if summary:
            # 移除摘要中可能出现的换行符,保证 Front Matter 格式整洁
            post['description'] = summary.replace('\n', ' ')
            with open(path, 'wb') as f:
                frontmatter.dump(post, f)
            print(f"  ✅ 摘要已写入!")
    elif post.get('description'):
        print(f"  ⏩ 跳过:已有摘要")
    elif post.get('draft'):
        print(f"  ⏩ 跳过:是草稿(draft: true)")

print(f"扫描完毕,共检查了 {files_checked} 个有效的文章文件。")
  1. 然后点击右上角绿色的 Commit changes… 按钮
  2. 回到仓库主页,再次点击 Add file -> Create new file
  3. 文件名输入:.github/workflows/summary.yml,它是告诉 GitHub 何时运行上面的脚本。我们设置的是“当你 Push(推送)新文章时”,它就自动叫醒 summarize.py 起来打工。输入下面内容(下面内容由 Gemini 替我编写)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
name: DeepSeek Auto Summary

on:
  push:
    branches: [ main ] # 如果你的主分支叫 master,记得改成 master

jobs:
  summarize:
    runs-on: ubuntu-latest
    # 这一步极其重要:赋予 GitHub Action 把生成的摘要写回你仓库的权限
    permissions:
      contents: write

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # 获取完整历史

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'

      - name: Install dependencies
        run: pip install requests python-frontmatter

      - name: Run Summary Script
        env:
          DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
        run: python .github/scripts/summarize.py

      - name: Commit and Push changes
        run: |
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"
          git add .
          # 如果没有新摘要生成,git commit 会报错,这里加个 echo 避免任务失败
          git commit -m "chore: auto generate AI summaries by DeepSeek" || echo "No changes to commit"
          git push
  1. 回到你本地的 VS Code ,在终端输入git pull origin main --rebase来让你本地和 GitHub 拥有相同的文件。

如何使用

在本地 post 当中的 markdown 文件只要没有 description 且不是 draft 模式, AI 就会自动运行,填写 description 来写摘要。

做个美化

  1. 在 custom.scss 文件中加入下面代码(包含打字机效果、打字动画、光标闪烁):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/* 打字机动画效果 */
.article-details .article-description {
    display: inline-block;
    white-space: normal; /* 允许换行 */
    overflow: hidden;
    border-right: 2px solid; /* 光标效果 */
    animation: typing 3.5s steps(40, end), blink-caret .75s step-end infinite;
}

/* 打字动画 */
@keyframes typing {
    from { max-height: 0; opacity: 0; }
    to { max-height: 500px; opacity: 1; }
}

/* 光标闪烁 */
@keyframes blink-caret {
    from, to { border-color: transparent }
    50% { border-color: var(--accent-color); }
}
  1. 在你的博客根目录下,创建文件:layouts/partials/head/custom.html(如果文件夹不存在就新建,有内容就加到最后)。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<script src="https://unpkg.com/typed.js@2.1.0/dist/typed.umd.js"></script>

<style>
    /* 定制打字机光标样式 */
    .typed-cursor {
        color: var(--accent-color); 
        font-size: 1.1em;
        margin-left: 2px;
    }
    /* 确保摘要容器高度不会因为没有文字而塌陷 */
    .article-description.is-typing {
        min-height: 1.5em;
    }
</style>
  1. 打开layouts/partials/article/components/details.html,然后找到显示 {{ with .Params.description }} 的位置,,将其替换为:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
{{ with .Params.description }}
<div class="ai-summary-container">
    <div class="ai-badge">
        <span class="ai-icon"></span>
        <span class="ai-text">DeepSeek AI 摘要</span>
    </div>
    
    <h3 class="article-subtitle is-typing" id="typed-summary-{{ $.File.UniqueID }}"></h3>
</div>

<script>
    (function() {
        const initTyped = () => {
            if (window.Typed) {
                new Typed('#typed-summary-{{ $.File.UniqueID }}', {
                    strings: [{{ . | safeHTML }}],
                    typeSpeed: 40,
                    startDelay: 800, // 稍微延迟,等毛玻璃动画出现
                    showCursor: true,
                    cursorChar: '_',
                    loop: false
                });
            } else {
                setTimeout(initTyped, 100);
            }
        };
        initTyped();
    })();
</script>

<style>
    /* AI 摘要卡片增强:毛玻璃效果更深邃 */
    .ai-summary-card {
        margin: 2rem 0;
        padding: 2rem; /* 增加内边距,让大号文字有呼吸空间 */
        border-radius: 16px;
        background: rgba(var(--card-background-rgb), 0.5); 
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        border: 1px solid rgba(var(--accent-color-rgb), 0.25);
        box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
        transition: transform 0.3s ease;
    }

    /* 悬停微动效果 */
    .ai-summary-card:hover {
        transform: translateY(-2px);
        border: 1px solid rgba(var(--accent-color-rgb), 0.4);
    }

    /* AI 标识标签:更大更显眼 */
    .ai-badge {
        display: inline-flex;
        align-items: center;
        gap: 8px;
        background: var(--accent-color);
        color: #fff;
        padding: 5px 15px; /* 增大内边距 */
        border-radius: 30px;
        font-size: 1.4rem;  /* 标签文字加大 */
        font-weight: 700;
        margin-bottom: 1.5rem;
        box-shadow: 0 4px 10px rgba(var(--accent-color-rgb), 0.3);
        letter-spacing: 0.5px;
    }

    .ai-badge-icon {
        font-size: 1.6rem; /* 图标同步加大 */
    }

    /* 摘要正文:大字号,高清晰度 */
    .article-subtitle.is-typing {
        margin: 0 !important;
        font-size: 1.8rem !important; /* 核心文字再次加大 */
        line-height: 1.8 !important; /* 增加行高,提升大字号的阅读舒适度 */
        color: var(--card-text-color-main);
        font-weight: 500; /* 略微加粗,让文字更稳重 */
        letter-spacing: 0.2px;
    }

    /* 打字机光标:同步加粗 */
    .typed-cursor {
        color: var(--accent-color);
        margin-left: 4px;
        font-size: 2rem;
        font-weight: bold;
    }
</style>
{{ end }}

我遇到的可笑问题

前面说过我以为我有免费的额度,所以我就没充值,然后 Gemini 给我写的脚本让强制运行成功(就是避免那种 Description 都写完了,运行不了而报错),所以 GitHub Action 运行日志外围显示绿色的✅,我也没进去看日志,我一直以为是 Gemini 给我写的脚本问题,忙活半天,我才去看日志,一看吓一跳: “ API 请求出错了!”,当时我才意识到我充值问题,然后充值了10元钱,但其实要不是我以为我不用花钱,我绝对用豆包。

最好笑的事情:这篇文章明里暗里不喜欢 DeepSeek ,却还得用 DeepSeek 给我生成摘要……

Licensed under CC BY-NC-SA 4.0
万物合鸣·独守一荒
共 28.86k 字 · 共 25 篇文章
本站已稳定运行 00 小时 00
载入旅行者一号距离信息...
AI Summary DeepSeek GitHub Hugo License Stack 萌ICP备 雾备 备案号 Umami Cloudflare Vercel Twikoo