把資訊流,整理成重點。
摘流(ZhaiLiu)是一個以 Python 開發的 RSS 文章摘要 Worker。它能解析 RSS/Atom、擷取文章正文,透過 Cloudflare Workers AI 產生結構化繁體中文摘要,並將文章狀態與摘要結果保存至 SQLite。
專案以 Raspberry Pi 等資源有限的常駐主機為主要部署環境。LLM 推論在 Cloudflare 執行,因此主機不需要在本機載入大型模型。
Important
文章標題與正文會傳送至 Cloudflare Workers AI。請勿將含有敏感或未授權內容的文章送出。
已完成:
- 從 FreshRSS 指定分類同步未讀文章
- continuation 分頁與 SQLite 文章去重
- 使用 Trafilatura 擷取與清理網頁正文
- 呼叫 Cloudflare Workers AI 產生結構化摘要
- 使用 Pydantic 驗證模型輸出
- 將文章狀態及摘要保存至 SQLite
- 每次執行安全地處理一篇文章
- 正式的
zhailiu-worker執行入口 - 不連外的單元測試
尚未完成:
- 失敗重試與卡住任務復原
- 將摘要呈現在 FreshRSS
- systemd timer 與正式部署設定
flowchart LR
A["FreshRSS AI 摘要分類"] --> B["FreshRSS API"]
B --> C["SQLite 任務與去重"]
C --> D["Article Extractor"]
D --> E["Cloudflare Workers AI"]
E --> F["Pydantic 驗證"]
F --> G["SQLite 摘要儲存"]
FreshRSS 的已讀狀態不會被 Worker 修改;即使未讀文章重複出現在同步結果中,也不會重複產生摘要。
{
"summary": "150 字以內的繁體中文摘要",
"key_points": ["重點一", "重點二", "重點三"],
"category": "科技",
"importance": 4,
"source_quality": "full_article"
}| 欄位 | 說明 |
|---|---|
summary |
150 字以內的摘要 |
key_points |
恰好三個文章重點 |
category |
文章分類 |
importance |
1 到 5 的重要程度 |
source_quality |
摘要依據,目前正文擷取為 full_article |
需求:
- Python 3.12 以上
- uv
- Cloudflare 帳戶與 Workers AI API Token
uv sync --all-groups在專案根目錄建立 .env:
ZHAILIU_FRESHRSS_URL=http://127.0.0.1:8080
ZHAILIU_FRESHRSS_USERNAME=你的_FreshRSS_使用者名稱
ZHAILIU_FRESHRSS_API_PASSWORD=你的_FreshRSS_API_密碼
ZHAILIU_CF_ACCOUNT_ID=你的_Cloudflare_Account_ID
ZHAILIU_CF_API_TOKEN=你的_Cloudflare_API_Token
# 以下皆為選填
ZHAILIU_DATABASE_PATH=data/zhailiu.db
ZHAILIU_SUMMARY_CATEGORY=AI 摘要
ZHAILIU_SYNC_LIMIT=500
ZHAILIU_CF_MODEL=@cf/qwen/qwen3-30b-a3b-fp8.env 已列入 .gitignore,不得將任何密碼或 Token 提交至 Git。Cloudflare API Token 應只授予所需帳戶的 Workers AI 權限。
執行一次同步,並處理最多一篇文章:
uv run --env-file .env zhailiu-worker成功時會顯示新增文章數量,以及本次摘要的文章 ID。沒有待處理文章時會正常結束;摘要失敗時則回傳非零退出碼,方便日後交給 systemd timer 監控。
Cloudflare Workers AI 會記錄 Neurons 用量;綁定付費方式的帳戶應在 Cloudflare 控制台監控用量與帳務。 Cloudflare Workers AI 會記錄 Neurons 用量;綁定付費方式的帳戶應在 Cloudflare 控制台監控用量與帳務。
簡短提示詞:
uv run --env-file .env python scripts/test_cloudflare_ai.py \
--prompt "請使用繁體中文,用三句話介紹 PostgreSQL。"擷取並摘要文章:
uv run --env-file .env python scripts/test_cloudflare_ai.py \
--url "https://example.com/article" \
--max-characters 12000這個腳本會真的呼叫 Cloudflare,可能產生 Neurons 用量。
from zhailiu.worker.feed import parse_feed
entries = parse_feed("https://example.com/feed.xml")
for entry in entries[:3]:
print(entry.model_dump_json(indent=2))import os
from zhailiu.worker.processor import process_article
result = process_article(
"https://example.com/article",
account_id=os.environ["ZHAILIU_CF_ACCOUNT_ID"],
api_token=os.environ["ZHAILIU_CF_API_TOKEN"],
)
print(result.model_dump_json(indent=2))請使用 uv run --env-file .env python ... 執行上述程式,讓環境變數從 .env 載入。
from zhailiu.worker.feed import parse_feed
from zhailiu.worker.repository import FeedRepository
entries = parse_feed("https://example.com/feed.xml")
with FeedRepository("data/zhailiu.db") as repository:
added_count = repository.add_feed_entries(entries)
pending_entries = repository.get_pending_entries(limit=1)
print(f"本次新增:{added_count}")
print(f"等待處理:{len(pending_entries)}")data/ 與 SQLite 相關檔案已列入 .gitignore。
文章狀態:
pending → processing → completed
↘ failed
save_summary(entry_id, result) 會在同一個 transaction 中保存摘要、將文章標記為 completed,並清除舊的錯誤訊息。
## 專案結構
```text
src/zhailiu/
├── cli.py # 正式 Worker 執行入口與環境設定
├── service.py # FreshRSS 同步與文章處理 orchestration
├── freshrss/
│ ├── client.py # FreshRSS GReader API 客戶端
│ ├── exceptions.py
│ └── sync.py # 未讀文章同步
└── worker/
├── exceptions.py
├── extractor.py # 網頁下載與正文擷取
├── feed.py # RSS/Atom 解析
├── model.py # Pydantic 資料模型
├── processor.py # 單篇文章擷取與摘要流程
├── repository.py # SQLite 文章狀態與摘要儲存
├── runner.py # 每次領取一篇待處理文章
└── summarizer.py # Cloudflare Workers AI 客戶端
scripts/
└── test_cloudflare_ai.py
tests/
├── freshrss/
├── worker/
├── test_cli.py
└── test_service.py