廢文小天地

隨意分享,隨便看看

DIY 系列:來做個「相關文章」功能

部落格文章有個特性:可以在文章內插入超連結,串聯到自己過去寫過的文章,或者像 Jaron 一樣整理成「延伸閱讀」。

我自己也會這樣做(又是被 Wiwi 影響),每次寫到一半,想到以前寫過相關文章,就會跑去搜尋欄查一下,再手動把網址貼回來。不過這也只限於「有印象」且「剛好想到」的時候,隨著文章越寫越多、時間久了,有時候連自己寫過什麼都快忘了。

在這種情境下,其實我們可以藉助 AI 的「語義理解」來幫忙找出相似文章哦,先來看看效果吧!

網站/部落格

《設計極簡部落格》(原文
相關文章 相似度
網站改版:DIY 靜態網站生成器 89%
RSS Feed 86%
DIY 網站留言簿 86%
Bear Blog ʕ•ᴥ•ʔ 85%
部落格問題挑戰 84%

音樂/播放器

《卡式錄音機》(原文
相關文章 相似度
使用 YouTube 聽音樂 85%
DJ SET 83%
MP3 網頁播放器 83%
YouTube 歌單備份 83%
網路曾經只是生活中的一部分 82%

旅遊/景點

《九份》(原文
相關文章 相似度
貓空纜車 84%
花蓮四日小旅行 83%
YouBike 2.0E 電輔車 82%
不上班ㄉ阿替 82%
逛全聯 81%

以下這兩個連結有完整的清單,有興趣的話可以去看一下。


運作原理

第一步:收集文章資訊當作輸入:比如標題、內文、大綱、分類等等。我這邊是使用「標題」和「內文」。(因為我懶得幫文章加標籤跟摘要

第二步:透過 AI 模型把文章轉換成語義向量(Embedding)。這段向量可以理解為:AI 模型把文章的「意思」壓縮成了一組數字。兩篇文章如果語義相近,它們在向量空間中的距離也會很接近。

第三步:有了所有文章的向量之後,計算它們彼此之間的餘弦相似度,由高到低排序取前幾名,就是「相關文章」了。


兩種 Embedding 方案

方案一:Gemini(API)

可以到 Google AI Studio 申請一組 API Key(免費),然後把文章內容透過 API 丟給 gemini-embedding-001 模型就能得到語義向量了,(教學文檔)。

需要注意的是免費方案有速率限制,我的做法是每篇擷取前 2000 字(小廢文哪來的 2000 字),每隔兩秒呼叫一次,每天最多可以呼叫 1000 次(依官方為準)。

方案二:BGE-M3(本地)

如果不想依賴外部 API,也可以用 BGE-M3 這個開源的 Embedding 模型,透過 Ollama 在本機跑,完全離線、免費,而且用 CPU 就能順順跑。

Python 版的大致流程如下:

  1. 下載 OllamaPython
  2. 下載 BGE-M3 模型:ollama pull bge-m3
  3. 安裝 Python 套件:pip install ollama
  4. 透過 Python 的 ollama 套件呼叫 BGE-M3 模型,輸入文章內容,獲得語義向量

計算相似度與排序

有了所有文章的語義向量之後,計算每篇文章之間的餘弦相似度(越接近 1 代表語義越相近),接著對每篇文章做排序後取前幾名,就可以得到推薦清單了。

快取機制

我這邊用 Hash(標題+內文) 的方式來判斷文章是否有改變,只要文章內容沒有改變,就不需要重新計算向量。

相似度的計算目前還是全部重跑一次(讓新、舊文章之間可以互相連結),我自己實測一百多篇大概要跑三秒,還可以接受。

如果你的文章很多的話,可以考慮使用 Vector DB,或者只針對「新文章 vs 舊文章」做增量計算就好。


完整執行流程

  1. 載入快取,用 Hash 比對找出需要更新的文章。
  2. 清除已刪除文章的舊快取。
  3. 對需要更新的文章做 Embedding 存進快取。
  4. 計算所有文章之間的相似度,由高到低排序,取前 K 名。
  5. 輸出成 related.json,前端直接讀取渲染,或者生成靜態的 HTML 區塊。

小補充

  • 可以加入「時間權重」,讓比較新的文章更容易出現在推薦裡,Bear Blog 也有採用類似的做法。
  • 如果你覺得「標題」、「分類」比較重要的話,可以在餵給 AI 之前多重複幾次關鍵資訊,例如:{標題}{標題}{分類}{內文},這個做法簡單又有效。
  • AI 太精準有時會少了點驚喜,可以對相似度分數加入一點點隨機分數,或者在推薦清單中固定留一個位置給「隨機抽樣」的文章。
  • 這種做法完全不需要收集使用者資訊哦(按讚數、瀏覽數、停留時間等等),純粹是靠文章內容本身的語義來做推薦,對於不喜歡測量的朋友來說還不錯。
  • 雖然功能做好了,但我還在考慮要不要加進網站裡,不然就是當作自己手動插入「延伸閱讀」的參考工具就好。XD

訂閱內容:我的書架不大

最近注意到 YouTube 網頁版的訂閱頁面 /feed/subscriptions 介面變了,原本只有「最新影片」一個區塊,現在則是變成這樣:

「最相關」→「Shorts」→「最新影片」

這代表說,即使是你自己訂閱的頻道,也可能會有資訊過載的問題,而演算法可以幫你破除選擇障礙(?)

畢竟每個油土伯都會叫你「訂閱、按讚、分享」嘛,看得完才有鬼。

你是哪種類型的讀者?

我目前每天抓取訂閱內容的兩大主要來源就是「YouTube」和「RSS 閱讀器」。

根據訂閱內容,我覺得可以分成兩種消費模式:

1. 「輸入多 → 篩選型」

  • 訂閱數很多,每天都會收到大量更新
  • 有自己的一套篩選系統、能夠接受「大部分內容不看」
  • 依靠快速掃描來消費資訊(影片的話就是開兩倍速)
  • 喜歡掌握大範圍的最新資訊

2. 「輸入少 → 滿足型」

  • 訂閱數較少,每天只會收到少量更新
  • 不需要做太多的篩選,有時間看完訂閱內容
  • 看得慢、看得深,偶爾會停下來思考,印象也會比較深
  • 眼不見為淨,比較少焦慮

這兩種其實沒有誰比較好,而是要看適不適合你的心理結構。有些人看到很多資訊會覺得自由、可能性多;有些人則會覺得壓力大、永遠看不完。

「JOMO 派」 vs 「FOMO 派」!

嗯...我亂取的,反正你懂我的意思,就是「Joy of Missing Out」 vs 「Fear of Missing Out」。

我很明顯是 FOMO 派的,現在的網路環境很容易把人推向快速掃描、跳來跳去的狀態。

如果資訊太多,我常常會想要去清除那個「未讀數」(即使沒顯示),結果就是每次都大量、快速的瀏覽,卻很少真正消化,整個多巴胺的消費都變得很廉價。

而減少資訊量之後,我就可以慢慢讀、停下來思考、或者記住內容。當輸入的內容變少了,獲得的滿足感反而變得更多、更深層。

訂閱源分類法

我在之前的「這篇文章」有提到一種主題分類法:

  • 怦然心動的內容:只保留一定數量的訂閱源,確保自己有時間可以消化完,不會產生閱讀壓力
  • 資訊類、新聞類:通常只需掃描標題跟內容大綱,不必每篇都讀完

我依然覺得這是個不錯的方法,但問題是我太貪心了,每次第一類的訂閱數都會膨脹到無限大。

整理訂閱源就像是整理書櫃

我每年都有賣二手書的習慣,其實這是一樣的道理。

有些人喜歡多留書,想到的時候隨時可以拿出來翻;有些人則是偏向極簡主義,會用「容器」的概念來限制數量。例如:書架最多就只能放 30 本書,想增加一本書或一個訂閱源,就必須要移除一個舊的,這會逼自己不斷優化自己的「口袋名單」。

這其實是一個循環

訂閱循環:想知道新的東西→訂閱很多來源→資訊過載→開始篩選→只留怦然心動的訂閱源

講這麼多,我只是想說:「十幾個,就夠了」,我也是這麼覺得。

好啦,我要去整理我的書櫃了,這不代表書有什麼問題,只是我的書櫃擺不下了。

題外話:「Wiwi 百科」真的好用。

醫院一日遊記

今天早上去醫院的眼科與免疫科報到。

原本打算趁空檔看書,沒想到報到後第一件事就是點散瞳劑,帶來的書瞬間變成了吉祥物,只好被迫進入發呆模式了。

(話說,身為一個用眼過度、整天盯著螢幕的宅宅,我竟然沒近視也沒散光耶,真是太神奇了,傑克)

不吉利的數字

  • 「第一檢查室」
  • 「第二檢查室」
  • 「第三檢查室」
  • 「...」
  • 「第五檢查室......?」

啊,原來是避開了不吉利的數字!

不過我其實對「四」沒什麼意見耶,小時候老家就住在四樓,房價還因此比較便宜。對省錢一族來說,這根本就是幸運數字吧!(迷之吐槽:但也不好賣啊~)

不過現在的建商都學聰明了,直接跳過四樓就沒事啦,我以前的大學就是這樣:1F、2F、3F、5F。

神奇的外套

今天看到一位女士,外套上印著大大的四個英文字「MILF」,我看到的當下差點從椅子上摔下來,真是嚇死我了!(我以前也常常亂穿就是了 XD)

YouTube 自動配音

候診時,看到有人在刷 YouTube Shorts,明明看起來是個中文影片,也有中文字幕,但 YouTube 偏偏覺得這位臺灣人一定很想聽 AI 自動生成的英文配音,真不知道為什麼。(有原聲的話,應該沒有人會想聽 AI 的配音吧?不是只有我這樣吧!?

看醫生其實跟做運動很像

這兩件事有個共同點:每次執行前都很抗拒,能拖就拖,出門前百般不情願,但一切結束後,又會慶幸自己「還好有來」

還在拖什麼?馬上給我去掛號!(這段是給未來的自己喊話,因為我已經預測到以後的我會拖延了)

Magic

magic-table magic-hat magic-rabbit magic-frog

(對不起......)

設計極簡部落格

前幾天看到了「How to make a website in 5 minutes」這篇文章。

於是我也重新思考了一下,如果從零開始打造,要怎麼用我喜歡的方式,設計一個「簡單好上手」、「人人都能做出來」的極簡部落格。

雖然還有許多沒考慮到的部分,不過概念大概是這樣:

網站頁面(Demo)

網站裡面包含六篇文章,介紹了部落格的使用方式。如果你太閒的話可以看一下。

主要頁面

  • 首頁
  • 文章列表
    • 文章1
    • 文章2
  • RSS Feed

架構

simple-blog/
├── index.html                    # 首頁
├── feed.xml                      # RSS Feed
├── assets/                       # 共用資源
│   └── style.css                 # 網站樣式
└── posts/                        # 文章目錄
    ├── index.html                # 文章列表
    └── 2026-01-01-first-post/
        ├── index.html            # 文章頁面
        └── img.webp              # 文章圖片

後記

我覺得,這樣一個簡單的架構,其實就足夠稱為一個部落格網站了。如果要做為教學,大概也只需要 1-2 堂課的時間。(另一堂課可以教部署、客製化,或是 AI 輔助)

自己動手做過一次之後,也能更實際地理解靜態網站生成器的好處。

另外,我在這篇文章也寫了一些比較詳細的碎碎念,如果你太閒有興趣的話,也是可以去看一下 XD。

STS2 is about to drop!

Slay the Spire 2》終於要推出 Early Access 版了。

當年跟著 Hafu, Dogdog, Amaz, Jorbs, Lifecoach 入坑一代,也是一起見證了神作的誕生呢。

問題是......

Slay the Spire 2 梗圖

智慧手環&搖步機

智慧手環

最近剛過完年,覺得睡眠品質有點差,決定要調整作息與運動習慣(又來了 XD),就買了一只智慧手環來監測看看。

先不論數據到底準不準,只要戴著它,就會更有意識地注意自己的睡眠時間與活動量,還挺值得的。

搖步機的故事

我父親是個非常喜歡運動的人,每天清晨都會早起去爬山,日復一日,年復一年。

多年前,他曾經迷上了用手機裡的「微信運動」來記錄步數。這個 APP 裡有個很重要的功能,叫做「步數排行榜」,可以跟朋友圈比較當天的排名。而要衝排行榜,光靠日常走路當然不夠,有時候步數沒達到他心中的標準,那就只好......自己用手搖囉

「搖啊搖~搖啊搖~搖啊搖~」,就這樣持續了好幾個月。

身為一個會寫一點程式的人,每天看到這種純手動作業,真的是看得有點小痛苦。有一天我實在是忍不住,上蝦皮買了一台「搖步器」送他,從此告別手搖人生!

自動搖步機
▲ 搖步機,插電之後就會一直搖。

衝動

這次我戴的智慧手環,當然也有計步功能。

當預設的目標步數只差一點點就能達標時,我腦中也產生了一股想揮動手臂的衝動......冏。

看來,有些東西真的是不要隨便測量啊。

卡式錄音機

我的櫃子裡有一台舊錄音機,卡帶裡存的是《波波羅古洛伊斯物語》系列的歌曲,小時候我都把 YouTube 的音樂放進去當隨身聽。

cassette recorder
▲ 卡式錄音帶/錄音機

不過,要怎麼放音樂進去勒?

  1. 打開 YouTube 影片,放置五分鐘,等進度條全部跑完。
  2. 麥克風對準喇叭,按下錄音鍵,把影片拉到片頭重新播放。
  3. 關上房門,避免錄到家人的聲音。
  4. 給我一首歌的時間~🎵
  5. 等影片快播完的時候,回去按下暫停鍵,接著再錄下一首。
  6. 最後,用原子筆寫下側標,大功告成!
cassette recorder and speaker
▲ 誰需要什麼 YT-DLP 阿!

話說,以前只要翻翻瀏覽器的快取資料夾,通常就能直接拿到「完整的」 FLV、MP4 或 MP3 檔案。

其它相關

cassette recorder and speaker

(聽說很有江湖味的 CD,兩年前買的 XD)

RSS 訂閱失敗

最近在同樂會上發現了幾個很讚的部落格,想訂閱時卻發現 RSS 被擋掉了

原因都是因為網站經過了 Cloudflare 的保護,可能是因為開啟了「機器人對抗模式」或是「高安全性等級」的選項,導致存取時會需要通過 JS 驗證之類的操作。

剛好我的閱讀器(FreshRSS)是架在 VPS 虛擬機上,很容易就被當成機器人攔截掉了。

跳板

目前我的解決方案是寫一個 Cloudflare Workers 當跳板去抓資料,再重新包裝成 XML 回傳。(沒錯,他們不擋自家人!)

雖然說有解法,但還是小小希望站長們能稍微調整一下,畢竟像我這樣用自架服務抓 RSS 的讀者應該也不少。(還是說,其實是我的問題...QQ)

有解嗎?

也許可以試試看設定「WAF 排除 RSS 路徑」或是「關閉機器人對抗模式」等等操作。

接著透過「Feed Validation Service」的服務,測試看看自己的 RSS/Atom 網址是否可以被正常讀取。

如果還有問題的話,或許可以請「JN 來幫你」唷!

(當然也歡迎寄信給我啦!只是我怕我也解決不了,浪費到大家的時間,嗚嗚嗚)

抹茶主題

抹茶

去年有一陣子很喜歡喝全家的抹茶拿鐵。雖然很好喝,但糖量卻是驚人的 45g!因此久久才敢買一次。

前幾天心血來潮,決定訂個抹茶粉來自己泡泡看,這樣糖量就比較可以控制了。不過在收到貨之前,先來把網站改成抹茶色吧!(嗯?)

還有還有,由於文章變多的關係,順手也把「文章列表」的行距改得緊湊一點,還加入了自動顯示年份的功能。(想不到吧,一年前的我,這個網站竟然可以活超過一年!)

怕怕

話說回來,在改網站顏色時,明明心裡想著的是抹茶,卻莫名的開始擔心會被貼上政治標籤、會被罵、會被炎上什麼的。

欸,我已經好幾年沒用社群平台了耶,這種莫名的恐懼到底是怎麼回事啊,太恐怖了吧。

滷蛋

BTW,說到超商食物,讓我想到之前碩人哥分享的溏心蛋做法。但我真的是太懶了,只有入坑到動福滷蛋的部分...連剝殼都不用也太爽。(一邊吃一邊打這篇 XD)