技能:Aperture
摘要 — 一個專為 AI 助手設計的技能,讓它們能產出更好的每日報告,並發掘更多使用者真正想要的內容。Aperture 會掃描來源首頁、與昨天比對差異、使用加權設定檔進行預篩選、透過 LLM 審查、去重、發布,並根據使用者回饋進化設定檔。所有決策都會被記錄到一個僅能追加的日誌中。
此技能與實作無關。AI 助手可以透過閱讀此檔案、呼叫內含的 Python 參考實作,或將模式移植到其自己的執行環境來執行此技能。
1. 目的
為 AI 助手提供一個確定性、可稽核的新聞策展技能,以取代靜態 RSS 閱讀器和一次性 LLM 摘要工具:
- 掃描首頁 — 將「閱讀首頁」視為一級操作,而不僅僅是 Feed 輪詢。
- 記錄每個決策 — 將每個來源快照、項目、拒絕原因、設定檔版本和報告記錄到一個僅能追加的日誌中,以利稽核和重播。
- 從使用者回饋中學習 — 透過明確的回饋來更新 AI 助手的品味,並保留每個變更的版本記錄,使其可逆。
當 AI 助手執行此技能時,它可以從日誌中回答「為什麼選擇這個?」以及「如果換成昨天會有什麼不同?」。
2. 核心概念
| 概念 | 意義 |
|---|---|
| 領域 (Vertical) | 一個已設定的新聞類別(例如:科技、汽車、AI 政策)。每個領域都有自己的來源、設定檔和日誌。 |
| 日誌 (Tape) | 僅能追加的 JSONL 日誌檔案。每個領域一個檔案。每個來源快照、項目、設定檔版本、回饋和報告都是一筆記錄。 |
| 設定檔 (Profile) | 該領域的「品味」:加權關鍵字、帶有加成的類別以及負面詞彙。有版本控制;每次變更都會被記錄。 |
| 掃描 (Scan) | 擷取每個來源的列表頁面,提取標題/連結,標準化 URL,並與先前的快照比對差異。 |
| 反思循環 (Reflection loop) | 使用者回饋 → 解析設定檔操作 → 版本升級 → 進化記錄 → 重新檢查近期已彙整的項目。 |
3. 四階段管線
┌─────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐
│ 收集 │ -> │ 篩選 │ -> │ 審查 │ -> │ 發布 │
│ (掃描) │ │(預篩選 │ │ (LLM) │ │ (去重 + │
│ │ │ 規則) │ │ │ │ 報告) │
└─────────┘ └──────────┘ └─────────┘ └──────────┘
│ │ │ │
└───────────────┴───────────────┴───────────────┘
│
僅能追加的日誌
3.1 收集 — 掃描首頁
目標: 從每個已設定的來源產生今天的候選項目。
步驟:
- 對於每個來源,擷取
list_url。 - 使用該來源的
extract_profile提取{title, url}配對:rss— 解析<item>區塊。generic_links— 解析<a href>標籤。regex— 使用包含 title/url/date 命名群組的正規表達式。json_api— 導覽 JSON 路徑並讀取 title/url 鍵值。
- 標準化每個 URL:
- 移除片段和追蹤參數 (
utm_*,fbclid等)。 - 移除結尾斜線和開頭的
www.。 - 強制使用
https協定,並將主機名稱轉為小寫。
- 移除片段和追蹤參數 (
- 與此來源的前一個首頁快照(從日誌讀取)進行比對。
- 新的
url_norm值成為候選項目。 - 將完整的目前快照儲存為新的
frontpage日誌記錄。
- 新的
- 更新來源健康狀態:
- 成功 → 重設
fail_count。 - 失敗 → 增加
fail_count;如果連續失敗次數 ≥ 3,則發出警報。
- 成功 → 重設
為什麼要與首頁比對,而不是解析發布日期? 因為許多來源的時間戳記不可靠,或佈局會反爬蟲。「首頁上的新內容」是「今天視窗內的新聞」一個穩健的代理指標。
時間視窗防護(確定性,非 LLM):
對於確實暴露 pubDate 的拉取來源 (RSS/Atom),掃描器在比對前會套用一個硬截止時間。預設視窗為 36 小時;可使用 extract_profile.window_hours 覆寫。早於視窗的項目將被丟棄。缺少或無法解析日期的項目預設為排除 (missing_date_policy: exclude),因為引擎無法驗證的日期,就是無法信任的日期。僅在來源日期已知不可靠且首頁比對是主要訊號時,才設定 missing_date_policy: include。
此規則存在是因為日期視窗的執行是記帳工作,而非判斷工作。它必須是確定且可稽核的——絕不委派給 LLM,因為 LLM 容易誤讀日期,並將過時的故事混入今天的報告中。
3.2 篩選 — 使用設定檔進行預篩選
目標: 使用低成本規則為候選項目評分;保持寬漏斗。
公式:
得分 = 總和(配對關鍵字權重)
+ 總和(類別配對加成)
- 總和(配對負面權重)
步驟:
- 載入該領域的最新設定檔。
- 對於每個候選標題:
- 配對關鍵字和類別(ASCII 術語使用整個單詞邊界)。
- 減去負面分數。
- 記錄任何配對術語的
last_hit。
- 閾值:預設
score >= 2通過;較低分數將被拒絕,原因為reject_reason: low_score。 - 將每個候選項目作為
item記錄寫入日誌:- 通過 →
stage: prescreened。 - 拒絕 →
stage: rejected,並附帶reject_reason。
- 通過 →
被拒絕的項目是校準的燃料。絕不要刪除它們。
3.3 審查 — 結構化的第二輪審查
目標: 驗證預篩選過的項目是真實新聞、符合主題,且不是廣告/工作。
步驟:
- 按得分(降序)排序預篩選項目。
- 限制每個來源的項目數量(例如每個來源最多 4 個)以避免壟斷。
- 對於每個項目,擷取文章文字(前 ~1000 字元),並透過後備鏈提取發布日期:
- JSON-LD
datePublished <meta article:published_time>
- JSON-LD
- 向已設定的 LLM 提供者發送批次提示。要求對每個項目:
is_news— 非廣告/工作/公告is_ad,is_job— 取消資格vertical_fit— 0 到 1 的相關性分數summary— 2-3 句摘要
- 套用拒絕原因:
not_news,is_ad,is_job,low_fit。
- 將結果作為
item記錄寫入日誌,並帶有stage: verified或stage: rejected。
如果未設定任何 LLM 提供者: 管線以 --dry 純規則模式運行,並直接提升預篩選項目。
3.4 發布 — 去重並產生報告
目標: 合併重複項並產出可讀的每日報告。
步驟:
- 載入近期已彙整的項目(過去 14 天,不含今天)。
- 對已驗證項目進行兩層去重:
- 完全相同的
url_norm匹配 → 跳過。 - 標題
simhash漢明距離 ≤ 3 → 同一事件;分組到一個叢集中。
- 完全相同的
- 對於每個叢集,選擇得分最高的項目作為主要項目;其他項目成為相關來源。
- 按來源數量和得分排序叢集。
- 格式化報告。附加一個狀態頁尾:
- 掃描的來源數、預篩選項目數、拒絕數、彙整數、報告項目數
- 來源健康狀態警報
- 各階段耗時
- 將
report記錄寫入日誌。
4. 反思循環(自我進化)
觸發條件: 使用者閱讀報告並提供回饋,例如: