なぜ AI 要約が必要か#
あまり覚えていませんが、中学校の時に新聞の読み方についての文章を学んだ印象があります。
私はその時の文中で紹介された習慣を読みながらずっと維持してきました。
精読が必要ない内容は飛ばし読みができます。
今、ChatGPT が大流行した後、多くのアプリケーションが登場し、その中でも AI 要約プラグインは私にとって大いに助けになっています。
情報過多の中で、私たちは多くの低価値の情報に爆撃されており、このようなプラグインは私が記事を細かく読む価値があるかどうかを迅速に判断するのに役立ちます。
多くの比較を経て、私は「ChatGPT 要約アシスタント - Chrome ウェブストア」をウェブブラウジング時の最優先プラグインとして選びました。
その使用効果は以下の通りです:
AI 要約は必須か#
必須ではありません!
私は AI 要約を統合したのは、私と同じ読み方の習慣を持つ人々のために便利にするためです。
私の個人ブログは生活を記録し、いくつかのメモを書くためのものであり、他の人にとっては全て低価値のデータです。
私は今、ブログに AI 要約機能を統合したのは、TianliGPTを使用したからです。
当時、「独立開発者を支援する」という気持ちから TianliGPT のサービスを購入しました。
購入したキーはすぐに消耗し、もう一つキーを買いましたが、それでも足りず、さらにもう一つキーを買いました。
それでも、私のブログには AI 要約がある記事は三分の二にも満たない状態です。
このままでは、底なしの穴のように感じます。
この時、AI 要約機能は歴史的な負担になってしまいました。
AI 要約機能を取り消すと、前に使った少額のお金が埋没コストになってしまいます。
情熱があるからといって、Geek 精神を妥協する必要はありません。
だから、自分で AI 要約を改造することに決めました。
これは、当初 Hugo 静的ブログに移行した目的にも合致し、できるだけデータを静的化することを目指しています。
できるだけページデータを SSG(Static-Site Generation)/ SSR(Server-Side Rendering)にしたいと思っています。
AI 要約をどう最適化するか#
推奨:https://github.com/Moraxyc/ai-summary-hugo を使用して summary.json を生成するための Python スクリプト
1. 方法#
AI 要約をローカルに置くには 2 つの考え方があります:
data
ディレクトリに.json
ファイルでデータを保存する
- 要約結果を記事の
.md
ファイルのフロントマターに置く
2. データ形式#
私は方法 1 を選び、すべての AI 要約を .json
ファイルに置くことにしました。これにより、後のメンテナンスが容易になり、既存の記事を壊すことがありません。
データの出所:
- TianliGPT がすでに生成した要約
- スクリプトを通じて ChatGPT と Claude2 から取得した要約
私は今、いくつかのスクリプトを使って要約を取得していますが、完璧なスクリプトは存在しないため、スクリプトは貼りません。
TianliGPT の要約は、ウェブページで F12 を押して DevTools を開くことで見つけることができます:
さまざまな方法で取得した AI 要約を集めて、summary.json
ファイルを生成します。
data
ディレクトリに新しく data/summary/summary.json ファイルを作成し、すべてのデータをそこにコピーします。データ形式は以下の通りです:
{
"summaries": [
{
"title": "2010年12月15日 雪景",
"slug": "snows",
"generated": true,
"summary": "この記事は、著者が2010年12月15日に経験した雪景について述べています。著者は、雪が降る前に空には数点の星のような白い点があり、誰もこんなに大きな雪が降るとは予想していなかったと述べています。著者は故郷ではもっと大きな雪が降るかもしれないと考えています。記事では、住所設定やプログラムエラーに関する問題にも触れ、デジタルガーデンを愛で発電することを結びにしています。"
},
{
"title": "2011 左へ、2010 右へ",
"slug": "goodbye2010",
"generated": true,
"summary": "この記事は、著者が2010年を振り返り、2011年への期待を語っています。彼は、過去一年間、他人のために生きすぎて自分を失ってしまったと考えています。新しい年にはもっと積極的で明るくなり、経験と感悟を財産としたいと願っています。最後に、彼はもう愚かに苦しみを語ることはせず、皆さんに新年の幸せを祈っています。"
}
]
}
ここで generated
は私が自分用に使う判断用語で、あってもなくても構いません。title
と slug
は記事のアンカーに対応するためのものです。
3. AI 要約のレンダリング#
summary.json
ファイルの AI 要約を各記事の冒頭にレンダリングするために、Hugo の記事テンプレートファイルを少し修正します。
異なるテーマのテンプレートファイルは少し異なるかもしれませんが、大体は似ています。
一般的に single.html
と呼ばれ、テーマの layouts
または Hugo のルートディレクトリの layouts
にあります。
例えば、DoIt のテンプレートは themes/DoIt/layouts/posts/single.html
にあります。
私はそれをルートディレクトリにコピーしました layouts/posts/single.html し、同名テンプレートが優先的にルートディレクトリでレンダリングされます。
記事テンプレート single.html
の {{ .Content }}
の前に、以下のコードを挿入します:
<!-- その他のコード -->
<!-- データを取得 -->
{{ $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>
<!-- 文書本文をレンダリング -->
{{ .Content }}
<!-- その他のコード -->
タイピング効果は必要ありませんので、上記の内容はすでに使用可能です。
タイピング効果が必要な場合は、<div id="ai-explanation" class="ai-explanation"></div>
のコメントを外す必要があります。
<div class="ai-explanation-content" style="display: none;">
に display: none
を追加して隠す必要があります。これは Typeit プラグインに値を与えるためだけの役割です。
JS を追加します:
<script src="https://unpkg.com/[email protected]/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: 50,
lifeLike: true,
waitUntilVisible: true,
}).go();
});
</script>
4. 簡単な CSS#
.post-ai {
background: #f5f5f5;
border-radius: 0.5rem;
padding: 0.5rem;
line-height: 1.3;
border: 1px solid #cfe6f3;
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: 0.25rem;
line-height: 1;
}
.ai-explanation {
margin-top: 1rem;
padding: 0.5rem 1rem;
background: #fff;
border-radius: 0.5rem;
border: 1px solid #cfe6f3;
font-size: 0.95rem;
line-height: 1.4;
display: inline-block;
width: 100%;
}
.ai-explanation span {
margin-left: 0.5rem;
}
/* .ai-explanation-content {
display: none !important;
} */