⏳

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

 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
万物合鸣·独守一荒
共 41.87k 字 · 共 35 篇文章
本站已稳定运行 0 天 0 小时 0 分 0 秒
载入旅行者一号距离信息...
AI Summary DeepSeek GitHub Hugo License Stack 萌ICP备 雾备 备案号 Umami Cloudflare Vercel Twikoo
not by ai boyouquan blogsclub blogsclub