週報
Dev 環境每天把過去七天的 Kafka 動態整理成一份簡短的雙語摘要:主題卡片、依階段排列的 KIP 提案,以及一個標題;每一句都引用它所根據的紀錄。文字由語言模型撰寫,能不能發布則由確定性的規則決定。
流程
週報 cron Prod 關閉
在 Dev 發布後 40 分鐘執行;發布還在跑時每次延後 15 分鐘,最多 4 次。
來源: apps/data-publisher-worker/wrangler.development.jsonc, docs/runbooks/cloudflare-data-publisher.md
當天的快照
週報固定讀某一份已發布的 release,自己不呼叫 GitHub、Jira 或郵件列表,所以每次執行都能依輸入重現。
挑選候選 thread
在 release 時間往前 7 天內,至少有一筆人類紀錄的 thread;機器人的紀錄不算。
依主題分類
@cf/cloudflare/clef-flash 對每個 thread 回答一題選擇題:12 個主題(releases、clients、streams、KRaft、security…)或例行維護。
- 門檻
- 例行維護需 ≥ 0.6;主題信心低於 0.35 歸入「未分類」
- 快取
- 以分類輸入與版本為鍵:thread 沒變就不重問
計分與放置
分數 = Σ 0.5^(天數 / 3.5) / k(加總人類紀錄,k 是該作者在此 thread 的第幾則),同一人重複發言的分量遞減。每個 thread 只會出現在一個地方:主題卡、例行維護或未分類。
來源: packages/reference-pipeline/src/digest/candidates.ts, packages/reference-pipeline/src/digest/mixing.ts
寫摘要
@cf/meta/llama-3.3-70b-instruct-fp8-fast 每張卡最多寫 3 句、每個 KIP 列 1 句,再寫一個標題與 3 條重點。模型只看得到被選中的 thread,每句都必須引用它們,例如 (KAFKA-PR-23829, closed)。
- Prompt
digest-prompts@4(D98,2026-10-20):措辭忠於狀態;open、討論中、投票中的項目只能用 would 或 is proposed
來源: packages/reference-pipeline/src/digest/prompts.ts, apps/data-publisher-worker/src/digest/workers-ai.ts
逐句驗證
用確定性的規則擋句子,不合格就不發布:長度不對、沒有引用、引用了輸入以外的東西、狀態詞與來源不符(PR 還 open 卻寫 merged、沒有 [RESULT] 卻寫 verified)、立場詞(objected、rejected)、一行裡出現第二個提案。整張卡都被擋下時顯示「AI summary unavailable」。
- 最近一次
- 1 個無法解析的模型輸出、1 個
status:verified、1 個status:fixed - 時態規則
- D97,2026-10-20 起在 Dev:完成語氣需要有已完成的引用項目;
tense:closed;[k/N]分段 PR 為tense:partial;同一子句中前面有情態詞則不算
翻成繁體中文
@cf/qwen/qwen3-30b-a3b-fp8 以每批 60 句翻譯通過驗證的英文。編號、引用與連結先換成佔位符;若佔位符遺失,該項保留英文並標示「Not translated」。
- 狀態詞檢查
- D99:狀態詞不一致時保留英文、計入
translate:status-drift,且不寫入快取 - 術語表
kafka-glossary@1(D100):offloading → 卸載、telemetry → 遙測…
來源: packages/reference-pipeline/src/digest/protect.ts, packages/reference-pipeline/src/digest/translation.ts, packages/reference-pipeline/src/digest/profiles.ts
寫出兩種語言
先寫 en.json,再寫 zh-Hant.<hash>.json,最後才更新指標,網站不會出現沒有原文的翻譯。
Neuron 帳本
每次呼叫模型之前先記帳;同一 UTC 日超過 5,000 估計 neurons 就停止。第二道限制在 AI Gateway:每小時 60 次、每月 2 美元。
來源: packages/reference-pipeline/src/digest/estimate.ts, docs/runbooks/cloudflare-data-publisher.md
英文週報
品質門檻審的就是這份:卡片、KIP 區塊、標題與重點,每句附引用。
繁體中文
英文週報逐項對應的翻譯。
This week 僅 Dev
由上到下:標題、時間範圍與統計、最多 3 條重點、依階段排列的 KIP 提案(討論、投票、實作中)、主題卡片,最後是收合的未分類與例行維護。
品質門檻 未通過
人工逐句標註一個真實的週報,bun run digest -- eval 計算錯誤數;達到門檻才開 Prod。
- 英文
status-mismatch0、overbroad-stance0(已定);其餘由負責人決定- 翻譯
- D102,2026-10-20 定案:每週
status-drift0、omission0、term-error≤ 2
來源: packages/reference-pipeline/src/digest/eval.ts, packages/reference-pipeline/scripts/digest.ts
執行數字取自 Dev 2026-10-19 22:47 UTC 那次執行(/health 的 digest.lastRun,2026-10-20 讀取)。Prod 未開啟週報。
模型透過 AI Gateway(加上速率與花費上限的代理)在 Cloudflare Workers AI 上執行。分工是刻意的:小而便宜的分類器對每個 thread 回答一題選擇題;大模型只根據交給它的 thread 寫作;第三個模型負責翻譯。排序、放置與驗證都是一般程式碼(Spec 014)。
為什麼要用規則檢查模型
檢視 2026-10-08 那一週的真實輸出時,發現有句子聲稱某個 PR 已合併,但它其實還開著;也有句子說某人反對,但沒有人這樣說過。光靠 prompt 擋不住,所以每句話在發布前都要對照來源紀錄檢查,不合格的句子直接丟掉,不嘗試修補(validate.ts):
| 拒絕原因 | 擋下什麼 |
|---|---|
length | 空白或超過 240 字元 |
no-cites、cite-outside-inputs | 沒有引用,或引用了模型沒拿到的紀錄 |
status:<word> | 沒有已合併的 PR 或已解決的 Jira 卻寫 merged、landed、fixed;沒有 [ANNOUNCE] 卻寫 released、shipped;沒有 [RESULT] 或 [ANNOUNCE] 卻寫 verified、accepted |
stance:<word> | objected、rejected、pushed back 等誇大討論的立場詞 |
other-proposal | 描述單一提案的那一行裡出現第二個 KIP |
tense:<form>、tense:closed、tense:partial | 使用完成語氣(is added、gets implemented、now supports)但沒有任何引用項目已完成(已合併的 PR、已解決的 Jira、[RESULT] 或 [ANNOUNCE] thread);或引用項目為 closed;或唯一完成的項目是分段 PR([1/N])而句子沒寫「first step」「part k of」 |
時態規則(D97,2026-10-20 於 PR #101 合併,已在 Dev 執行)在同一子句中完成語氣之前出現情態詞(would、will、may…)時不算,所以「would be added」可以通過。摘要 prompt 也同時改為要求忠於狀態的措辭(D98,digest-prompts@4);prompt 版本是快取鍵的一部分,所以下一次 Dev 執行(22:47 UTC)會重新產生每一句。
翻譯的狀態詞檢查與術語表
- 狀態詞檢查(D99)。 引用括號內的中文狀態詞必須與英文一致(open → 仍在進行、merged → 已合併、closed → 已關閉、proposed → 已提出、discussing → 討論中、resolved → 已解決、voting → 投票中,以及列出的變體)。比對時最長的詞優先,所以「投票進行中」是 voting,不會被當成 open 的「進行中」。不一致時該項保留英文並標示「Not translated」,執行紀錄計入
translate:status-drift,而且這次翻譯不寫入快取,下次執行會重翻;同一次執行內不重試(translation.ts)。 - 術語表(D100)。
kafka-glossary@1固定 Dev 上翻錯或必須保持一致的術語:offloading → 卸載、telemetry → 遙測、assignor → 指派器、rebalance → 再平衡;share group 與 KRaft 保留英文。術語表版本是翻譯快取鍵的一部分(profiles.ts)。
上 Prod 前的品質門檻
週報要先由人工標註一週真實輸出,評估達到門檻後才會上 Prod(Spec 014 Behavior 31)。
- 英文句子的錯誤類別:
status-mismatch、misattribution、invented-claim、overbroad-stance。 - 翻譯的錯誤類別(D101):
status-drift、term-error、omission;已標註的句子可以帶這些類別,eval也會對每個已翻譯句子執行狀態詞檢查。 - 已定的門檻:
status-mismatch為 0、overbroad-stance為 0。另外兩類以及重要 thread 召回率的門檻由負責人決定(規格中的例子是召回率 ≥ 0.8)。 - 翻譯門檻(D102,負責人已於 2026-10-20 定案): 每個已標註週
status-drift0、omission0、term-error最多 2;標註檔可以覆寫。 - 黃金資料集: 版本庫中的一份標註檔;目前只有 2026-10-08 檢視時找到的 5 個反例,還沒有重要 thread 的標註(topic-digest-labels.v0.json)。
- 評估:
bun run digest -- eval(離線,不連網)依原因統計保留與丟棄的句子、每個已標註錯誤是否被擋下,以及召回率;bun run digest -- measure在一次執行可能超過 neuron、呼叫數或讀取次數上限時失敗(scripts/digest.ts、eval.ts)。
截至 2026-10-20:門檻尚未通過,所以週報只在 Dev 執行;Prod 沒有設定 DIGEST_ENABLED(docs/feature-map.md)。
已知限制
- 時態規則只認得列出的說法:「X lands」「X is in trunk」抓不到,要靠黃金資料集把關。
- 狀態詞檢查比對的是狀態的集合,而不是哪個狀態屬於哪個引用;兩個項目的狀態對調時會通過,要靠
status-drift標註抓出。 - 較早的狀態詞規則也會擋掉「would be released」這類帶情態詞的句子(issue #104,未解決)。
- 已知誤判(issue #104):以「Now <名詞>」開頭的句子,例如「Now logs are structured」,會被當成
now logs,因為列表中有幾個動詞也是名詞。 - 在 2026-10-20 的 Dev 週資料上,時態規則擋下 5 句卡片與提案句和 1 條重點,全都把尚未完成的工作寫成已完成;兩個已記錄的週資料都是版本庫中的測試資料,所以規則的準確度可以離線重現(Spec 014 D97)。
成本
| 項目 | 值 | 來源 |
|---|---|---|
| 每日上限 | 每個 UTC 日 5,000 估計 neurons(Dev 與 Prod 相同) | estimate.ts |
| 估算方式 | 價目表 × 1.28,依 Workers AI 回報的 token 數校正 | Spec 014 |
| 最近一次 Dev 執行 | 29 次模型呼叫、1,637 估計 neurons、99 秒(2026-10-19 22:47 UTC) | Dev /health |
| Gateway | 每小時 60 次、每月 2 美元;被拒絕的呼叫會讓這次執行以 limited 結束 | runbook |
快取以輸入與版本為鍵,沒有變動的 thread 不會重新分類或摘要;修改 prompt 會讓快取失效,下一次執行的花費會接近從頭生成。bun run digest -- measure 估計以 digest-prompts@4 從頭執行一次為 2,215 價目表 neurons,約 2,835 估計 neurons,在 5,000 上限內。