20260910 會議記錄
:::info
-
所有會議記錄 編輯當週文件 準備 總結 - 本次改線上(9/10 週四晚上 NPO Hub 被 functional thursday 借走)
- 線上出席:bil, mrorz, nonumpa, yutin
- https://meet.google.com/mrz-dgrd-pri :::
上週待辦
- 追蹤 devops#12:開放 user-driven 爬蟲存取政策
- 追蹤 devops#17:rumors-site / line-bot-zh / url-resolver 記錄 request header,並修 rumors-api GraphQL log header 迴歸
- 追蹤 devops#18:記錄 Cloudflare Analytics retention(31 天 / 3 天)與 Logpush Enterprise-only 限制
- cofacts.ai session 週報:GGM 手動貼到 #collab;MrOrz 準備 DC bot 之後自動化
- nonumpa:繼續研究 FB / IG preview 仍是登入畫面的問題(threads shared URL 的 oembed 做法可參考)
- MrOrz:cofacts.ai 前端先打底(frontend skill + storybook),之後請 yutin 接手
- MrOrz(原定 9/1 起七天後)Log retention 收尾:
- 檢視 GCS bucket
- 開 BigQuery table
- 改寫 devops 教 agent 怎麼查 log
可 Review: https://github.com/cofacts/devops/pull/19/changes
- rumors-api#388 vector search:更新 rumors-db submodule、補 userId / appId backfill
- 更新 rumors-db 已 merge https://github.com/cofacts/rumors-api/pull/402
- Review 待處理 PR:rumors-db#80(ES9 breaking change)、kb#22(semantic search design doc)
- 回覆 bestian:
app-id/app-secret申請方式;hackfoldr 上 API docs 連結要改成_blank(後台 Google Sheets 需開權限) - 正式站追蹤:GCE 磁碟使用率 87%(58G/67G)
- 正式站追蹤:09-01 ES / server.js / build-index.js CPU 同步尖峰原因
- 正式站觀察:cofacts-ai Cloud Run CPU p99 緩升(0.35 → 0.42)
[!Note] TODO MrOrz 把 DB mapping 送到 staging & production DB
Cofacts.ai
新訊息回報入口
@MrOrz:針對 8/18 讓 cofacts.ai 作為回報入口的設計(design doc: https://github.com/cofacts/kb/pull/16 )設計師子龍覺得讓回報者進 AI 容易分心,因此設計了獨立的訊息回報流程,基本上就是把 LINE bot 的流程做成網頁版這樣。我想了想,覺得如果做成 LINE bot 那種流程,確實會比靠 LLM 來弄穩定,而且 UI 上要做的東西其實差不多(就算做在 chat 也要刻展示搜尋列表、送出表單確認等 UI),所以我會重新 plan 回報入口的部分唷
- PR: https://github.com/cofacts/ai/pull/138

- Closes all kb design docs, use PR#138’s decision log as design https://github.com/cofacts/ai/blob/4ca8afb384af1ae1894b117c0f0eecc184242bc4/docs/decisions/20260905-report-form-page.md
- Penpot: https://design.penpot.app/?_gl=11eyik72_gcl_auOTI3NzQxMDkuMTc4NDM3NjA2Ni4tLi0uMTc4NDYzOTM1OS44MDY1NDMyNjYuMTc4NDYzOTM2MC4xNzg0NjM5MzU5_gaNzE5NDgzNDU1LjE3ODQzNzYwNjU._ga_K0KF97C51Q*czE3ODg5NzA5MzkkbzE2JGcwJHQxNzg4OTcwOTM5JGo2MCRsMCRoMA..#/workspace?team-id=1710bc7f-8249-8127-8007-d006475d6947&file-id=81f57451-85cc-819d-8008-71f291481dd2&page-id=47d0d5f8-c40d-80a6-8008-6e9f528e4cc9
有人在問「是誰在回報什麼訊息」,如 cofacts 舊網站的功能 [name=bil]
- 對 researcher 來說,誰會接觸到什麼訊息也是有價值的
- 更容易發現 spammer
- 記得當時的決策是不要,要撈一下過去的紀錄 [name=mrorz]
- 好像是隱私 [name=bil]
- 可能會減少一個使用者發送訊息的意願 [name=bil]
- builder 的是 reply request
- API 都撈得到 –> spammer AI 已經在追蹤這個了 [name=mrorz]
- researcher 也能用 open data 與 API 拿 [name=mrorz]
- 可能做得比較隱密 [name=bil]
- community builder 就好 [name=bil]
- 或是 user profile 頁面加個 tab 顯示這個帳號送過哪些訊息? [name=mrorz]
[!NOTE] TODO
- 先撈過去的決策紀錄,看為啥當時新網站決定不要放 message author 與 profile page
- 下周討論是否要做在 profile page
hint 不要放 placeholder,有 accessibility 問題 [name=nonumpa]
- placeholder 打字就會消失,對比度也比較低 [name=nonumpa]
- 截圖裡面的 case 好像剛好都是 example,這個放 placeholder 好像合理? [name=mrorz]
[!NOTE] TODO
- Ask AI about accessibility advice
- placeholder 寫太長的 example 會影響 lighthouse / accesibility 分數嗎
URL resolver in Cofacts
https://github.com/cofacts/ai/pull/118
- 增加 ADK callback 示意圖
- 增加 URL resolution 流程圖
目前狀態:仍在 agent code review + 我在和 AI 細修
- URL resolution 好像沒有增加參考
hyperlinks的邏輯
User-level memory:Langfuse session 分析(cofacts/ai#125 後續)
Issue: https://github.com/cofacts/ai/issues/125
接 20260818 的兩件事:#125 的「觀察 session 裡使用者是不是會一直重複某些 prompt」,以及「用 AI + Langfuse skill 找找看使用者敘述的 session 是什麼」。翻了 Langfuse production 資料 + 讀了 ADK 1.26.0 原始碼與 Vertex 文件。
結論:值得做,但只值得做窄版的 —— per-user 的「編輯約束清單」,不是通用的對話式記憶。建議用 Vertex Memory Bank 當儲存層,V1 只用它的 CRUD、不用 LLM 自動萃取。成本實質上 $0。
資料範圍:environment=production,2026-07-29 ~ 09-09
- 226 turns / 80 sessions / 14 位使用者(production 全部有登入,memory 有可靠的 key)
- 4 位重度使用者佔 65/80 sessions(81%)、209/226 turns(92%)
- 232 次
draft_factcheck_response(平均每 session 3.2 次,最多一個 session 15 次) - 分類分佈:RUMOR 107 / NOT_RUMOR 86 / OPINIONATED 39
- latency median 125s、p90 310s;6 週總花費 $20.07
- 註:session 是長命的,會跨天(有一個從 08-07 用到 08-12),「session」≠「一次坐下來」
發現 1:重複的 prompt 確實存在,集中在「佐證資料來源政策」
xPyH-IYBC7Q3lHuU6oTY(7 sessions / 22 turns,其中 9 個 turn 跟來源有關)把同一條媒體黑白名單講了四次:
08-07 佐證資料不要使用中時,NowNews,PCHome等媒體⋯⋯改用中央社與公視和報導者這類較為公允的媒體 08-14 佐證資料請不要引用聯合報及UDN來源⋯⋯UDN若是轉角國際的新聞來源則可以引用 08-30 佐證資料以中央社<公視新聞 08-30 (同一個 session 內,隔幾個 turn)佐證資料以中央社,公視新聞,央廣,報導者等資料為主,不要使用東森新聞
- 最後兩條是同一個 session 內講兩次 –> 連 session 內都在漏
- writer prompt Step 2 已經有「Track editorial constraints」要求記成 bullet list 全程帶著走,08-30 那次沒生效
- 所以這題其實有兩層:session 內的 constraint list 要先修好,跨 session 才有意義
- 這位應該就是 08-18 紀錄裡的「E:要求改用某些媒體後,AI 附的 url 正確了」
sPyB-IYBC7Q3lHuU-YQl也有同類但零散的來源政策:「佐證資料的來源不要跟可疑訊息來源相同」「應找到台灣官方的報導,不應引用香港的媒體」「佐證資料選3則就好」- 全體:226 turns 裡 31 個(14%)帶來源相關指正、12 個(5%)是篇幅/精簡要求,合計 19%
發現 2:四位重度使用者的工作風格完全不同(我認為這是最強的論據)
| 使用者 | sessions | turns/session | 開場帶自己立場 | 特徵 |
|---|---|---|---|---|
sPyB-IYBC7Q3lHuU-YQl |
23 | 2.1 | 0/23 | 貼 URL 就等成品;不滿意就整個重跑(「重新查核一次」6 次) |
_1YnAG8BV0DITCqGm7go |
20 | 5.7 | 0/20 | 逐條稽核型:15 個 turn 在查佐證資料連結能不能開、對不對題 |
AVriAlOoyrDaTqlmmqhC |
15 | 1.7 | 13/15 | 「我先下判斷,你幫我寫」;7 個 turn 是語氣/切入角度 |
xPyH-IYBC7Q3lHuU6oTY |
7 | 3.1 | 1/7 | 媒體可信度守門型(見發現 1) |
0/23、0/20對13/15這個對比很乾淨。AVriAlOoyrDaTqlmmqhC幾乎每次開場都是「URL + 我覺得這是⋯⋯」:- 「我覺得這是包裝成廣告的詐騙商品」「我希望以個人意見,或是川普的意見為回應出發點」「有一些類似人身攻擊的短捏造訊息,希望能有類似的公版進行回應」
- 而
sPyB/_1YnAG8開場永遠只有一個裸 URL - 同一份 writer prompt 不可能同時服務「貼 URL 就要成品」和「逐條稽核每個佐證資料」這兩種人 –> 這比省 token 是更好的理由
sPyB的「請把查核的標題改掉」+ 6 次「重新查核」對得上 08-18 紀錄的「老鶴:偶爾查核到一半就停下來、標題取得怪⋯⋯會請 AI 重寫」(同樣待對照 User ID)
發現 3:分類與訊息類型
- 主題(72 個有 draft 的 session 粗略分類):政治/兩岸 17、詐騙/投資 12、醫療保健 10、政府政策/福利 10、國際 5、食安 4、其他 22
- 「含有個人意見」是最常被人工推翻的分類
_1YnAG8在兩個不同 session 都推同一件事:「針對Cofacts查核規範⋯⋯請思考此查核回應是否以『含有個人意見』回應」AVriAlOoyrDaTqlmmqhC也兩次把方向往個人意見帶
- 「公版」的需求(見發現 2)就是「不同分類的訊息的做法」的原型
- 但建議跟 user memory 分開:主題 playbook(詐騙/保健/政治宣傳/政府補助)應該是全體共用資產,不是個人記憶。塞進個人 memory 會讓每個人各自累積一份品質不一的分類守則,而這本來該是社群共識
發現 4:有相當比例的重複 prompt 是 bug,不是 memory 缺口
先修這些,再上 memory —— 否則 memory 會把「這個人總是要我重跑」記成偏好:
- 佐證資料 URL 失效/張冠李戴 ——
_1YnAG8有 15 個 turn 在做這件事(「此出處來源連結已失效」「報導者並沒有這篇文章」「請查明此連結是否可開啟」),還有一次是拿尚未被查證的 Cofacts 訊息當佐證資料。這該是 writer/verifier 自己 pre-flight 檢查 - 使用者裸打
draft_factcheck_response當訊息送出 9 次以上,還有兩次直接送[^draft_factcheck_response-call7886]–> UI/引導問題 - 「重新查核一次」6 次,某個 session 結尾使用者說「沒有 draft_factcheck_response 查核回應結論」–> 收尾不穩(對得上老鶴說的「查到一半停下來」)
AVqVwjqQyrDaTqlmmp_a在三個不同 session 開了同一篇文章(oqfr07on1plt)–> article-scoped 的「這篇之前查到哪」可能跟 user memory 一樣有價值,而且風險低得多
儲存層:user: state vs Memory Bank
#125 寫「ADK user-level session 可以記錄 memory,只要設計一個 tool 就行」—— 這個猜測成立,但要分清楚三件不同的東西:
- ADK
user:session state — 存我們自己的 Postgres(StorageUserState),scope(app_name, user_id) - ADK
BaseMemoryService— 對話片段形狀,search_memory(query)檢索 - Vertex Agent Engine Memory Bank — 真正的後端服務,有自己完整的 REST API
(2) 是 (3) 的一層薄且有損的 wrapper,評估 Memory Bank 不該用 ADK 的介面去評估它:
preload_memory拿使用者當下這一輪的訊息當檢索 query(user_content.parts[0].text)。而sPyB23/23、_1YnAG820/20 的開場訊息是裸 Cofacts URL –> 拿 URL 去檢索永遠撈不回「不要引用中時」,會在最需要它的兩位使用者身上、在第一個 turn 就失效- 但 Memory Bank 原生支援 scope-only retrieval:
memories.retrieve(scope={"user_id": X})可以「retrieve all memories within the scope」,不需要 query,是確定性的
- 但 Memory Bank 原生支援 scope-only retrieval:
- ADK 的 HTTP 層只有一支
PATCH /apps/{app}/users/{uid}/memory(把整個 session 灌進去),沒有 list/get/delete- 但 Vertex 的
reasoningEngines.memories有完整 CRUD:create/get/list/patch/delete/retrieve/generate
- 但 Vertex 的
- ADK 的
add_memory()只吃MemoryEntry(Content 形狀),而 Memory Bank 原生支援memories.create(fact="...", scope={...})
–> 結論:繞過 BaseMemoryService,直接用 vertexai client 打 Memory Bank。 用 Memory Bank,但不用 ADK 的 memory 整合。
錢:我們這個規模實質上是 $0(Memory Bank 2026-09-01 才開始計費,之前 preview 免費)
| 資源 | 免費額度/月/帳號 | 超出後 | 我們的用量 |
|---|---|---|---|
| Agent Storage | 1 GiB-month | $0.30/GiB-month(含 revisions) | 14 使用者 × 10 條 ≈ 30 KB |
| Agent Compute(讀) | 50 vCPU-h = 1.5 億次讀 | $0.085/vCPU-h(300 萬次讀 = 1 vCPU-h) | 6 週 226 turns |
| Agent Compute(寫) | 同上 = 5 千萬次寫 | 100 萬次寫 = 1 vCPU-h | 6 週個位數 |
- 唯一要錢的是 model tokens(「memory generation and embeddings are billed separately under their respective model SKUs」)
- V1 用
memories.create(fact=...)寫我們自己萃取好的偏好 –> 沒有 generation 的 model call –> $0 - 未來做
generate自動萃取(= #125 第二層):實測 session transcript 是 25k–170k tokens(median 47k),照我們自己 Langfuse 記到的實際單價 $0.364/1M input,一次 consolidation ≈ $0.017/session,80 個 session ≈ $1.4/6 週(現有花費的 7%)
Region:asia-east1(台灣)支援,v1 GA —— 跟現有 Cloud Run + Cloud SQL 同區。Memory Bank 不支援的只有 Jakarta/Melbourne/Toronto。
- ⚠️ 但用
globalendpoint 就不能用 CMEK(KMS 需要固定地理邊界)。我們現在是GOOGLE_CLOUD_LOCATION=global
Memory Bank 相對 user: state 的三個實質優勢
- user-scoped 資源自帶 CRUD –> 設定頁直接對它讀寫。
user:state 只有 session-scoped 的 endpoint,設定頁得借一個 session id 或自己補一支 BFF endpoint - 不汙染 session payload –>
list_sessions()會把 user state merge 進回傳清單裡的每一個 session(sPyB有 45 個 session,1KB 的 memory 會被複製 45 次);Memory Bank 沒這問題 scope是任意 dict(上限 5 個 key) –>{"user_id": X}放個人偏好、{"user_id": X, "category": "醫療保健"}放分類 playbook,發現 3 用同一套機制就解決。另外 TTL 內建
缺點
- 新的 GCP 依賴:一個
reasoningEngine資源 + IAM(client.agent_engines.create()不帶參數就好,不用部署 agent,沒有 runtime 要維運)。prod/preview/staging 必須分開,否則 preview 會寫進正式使用者的記憶 - 繞過 ADK 抽象 = 自己維護一層薄 client,ADK 之後改進 memory 整合不會自動吃到
- 熱路徑多一次外部呼叫 –> 要 fallback:retrieve 失敗就當沒有偏好繼續跑,別讓查核卡住
- 資料放在 Google 而不是我們自己的 Postgres –> 見下方待拍板
可見性與隔離
可見性照 Claude 的作法(參考)—— 看得到、改得動、關得掉、有隔離:
- 設定頁一個「我的查核偏好」清單,顯示全文、可逐條刪除、可整體關閉;預設 opt-in
- 每條記下來源(哪個 session、什麼時候、因為哪句話)
- 每次套用時在回覆開頭一行講明「(已套用你的 2 條偏好:⋯⋯)」–> 可被察覺、可當場否決
- 只記「how」不記「what」:記表達方式,不記事實、不記結論
- 只記表達偏好,不記結論偏好 ——
AVriAlOoyrDaTqlmmqhC有 13/15 個 session 開場就帶自己的判斷,如果 memory 學成「這個人希望結論偏向 X」,就做出一台 confirmation bias 機器而不是查核工具。這條界線建議寫死在 prompt 裡 - 這兩點在 Cofacts 特別重要,因為查核回覆是公開的、社群共有的。把「絕對不要引用聯合報/中時/東森」寫進某位查核者的 profile,等於把一位編輯的媒體政治觀點固化進公開查核回覆
隔離立場:memory 是私人的。session 分享出去只分享對話內容;別人接關時只載入對話內容 + 接關者自己的 memory。 跟 #124 一起看:
- Memory Bank 在這點明顯較安全:memory 不在 session 物件裡,
get_session不會 merge 它進來 - 若選
user:state,#124 目前的規劃會漏:#124 寫「從 ADK session ID 找 user id 才能 load session」,而get_session(app_name, user_id=<原作者>, session_id)會把原作者的user:state merge 進session.state–> 唯讀模式直接把 state 交給瀏覽器就洩漏了。BFF 唯讀路徑必須濾掉所有user:前綴 key - 另外
list_sessions(user_id=None)會撈出 app 底下所有使用者的 user state –> #124 的公開 session 索引很容易踩到 - #124 的「讓 agent 參考其他 public session」那個 tool 也不該去 retrieve 原作者的 memory
- 接關本身是安全的:新 session 建在接關者自己的
user_id底下 - 一個必須誠實講的限制:偏好是使用者打在對話裡的,tool call 也是 event。所以 session 公開後「這個人不信任聯合報」還是會從對話紀錄看得出來。我們能隔離的是「儲存的 profile 不外流、不套用到別人身上」,不是「這個人的偏好不被看見」
效益的誠實估計
- 可省掉的 turns:約 15–25 個 / 6 週(佔 follow-up turns 的 10–17%)
- 省的錢:$0.75–1.25 / 6 週。零錢。所以這件事的價值不在省成本
- 真正的價值:
- 使用者不用每個 session 重打同一段話(
xPyH那條媒體名單打過至少 4 次,每次 60+ 字) - latency median 125s / p90 310s –> 少一輪就是少等兩分鐘
- 第一份草稿的採用率
- 使用者不用每個 session 重打同一段話(
建議的成功指標(都有現成 baseline)
| 指標 | 現況 |
|---|---|
| turns/session | 2.8(重度使用者 1.7–5.7) |
| 帶來源/篇幅指正的 turn 比例 | 43/226 = 19% |
| drafts per session | 3.2 |
| 單 turn 就結束的 session 比例 | 36/80 = 45% |
建議的 V1 scope
- 一個
remember_editorial_preference(preference, kind)tool,writer 只在使用者給出跨訊息都適用的指示時呼叫。kind二選一:sources/style。不做自動偵測 memories.create(fact=..., scope={"user_id": X, "kind": ...});讀取用memories.retrieve(scope={"user_id": X})。硬上限約 10 條、總長約 800 chars,超過要求使用者先刪。不呼叫generate- 注入用
before_model_callback(writer 已經有inject_article_attachment這個 pattern),接在既有 Step 2 constraint list 前面。比 instruction 的{user:xxx}templating 安全 —— 後者 key 不存在時會炸 - 設定頁「我的查核偏好」:可看、可逐條刪、可整體關閉
- prod/preview/staging 用不同 Memory Bank 實例或不同 scope
- retrieve 失敗 fallback 成「沒有偏好」繼續跑
V1 不做
- 自動偵測/每週 retrospect(#125 第二層)—— 先看 explicit tool 的採用率;4 位使用者的樣本量還撐不起自動萃取的誤判成本
- 主題 playbook 當 user memory(見發現 3)
- 記任何事實或結論
[!Warning] 待拍板 查核者的偏好資料要放我們自己的 Postgres,還是 Google 的 Memory Bank? 這是立場題不是技術題。技術上 Memory Bank 較優(獨立 CRUD 介面、不汙染 session payload、scope 多維、TTL、成本 $0、asia-east1 同區);但如果「使用者資料必須留在我們自己的資料庫」對 Cofacts 是原則,就用
user:state,代價是設定頁多一支 BFF endpoint +list_sessionspayload 膨脹。
- 會議討論結果:放 Google Vertex AI Memory Bank!
[!Note] TODO
- 發現 4 的四件事排在 memory 前面 —— 這四件都是使用者在重複講同一件事,但原因是產品有 bug,不是 AI 忘記偏好。先修這些,否則 memory 會把「這個人總是要我重跑」記成他的偏好:
- 佐證資料連結/對題 –> 推進 #118(已有解法,draft 狀態)。另外補兩個 #118 沒涵蓋的:不要拿未查證的 Cofacts 訊息當佐證資料
- 「查到一半停下來」有可偵測的訊號了(承 08-18「超難捕捉與修復」):turn 的 observation tree 裡 tool 回來之後沒有下一次 writer
call_llm,且最後一個 generation output 為 null。08-30 那個 case 就是這個形狀,值得寫成一支查詢/alert- 裸打 tool name 的 UI 問題:使用者把
draft_factcheck_response當訊息送出 9 次以上,還有兩次直接送[^draft_factcheck_response-call7886]這種 citation marker- article-scoped 的「這篇之前查到哪」:
AVqVwjqQyrDaTqlmmp_a在三個不同 session 開了同一篇文章。這比 user memory 風險低得多,可以先做- 資料放哪拍板之後(見上方待拍板),V1 開 issue 到 cofacts/ai,接到 #125
- 實作前從本紀錄寫成 ADR(跨
src/+adk/、新增資料存放位置)
[!Note] 只有選
user:state 才需要的 TODO 目前 code 完全沒有用user:/app:前綴的 state(只有title、lastEventTime、lastOpenedAt三個 session-scoped key),所以下面兩件事是「選了user:state 才會新增的風險」。選 Memory Bank 就不需要做 —— memory 不在 session 物件裡,get_session沒東西可以漏。
- #124 的唯讀路徑:BFF 要濾掉
session.state裡所有user:前綴的 key,否則原作者的偏好會跟著唯讀頁面送到別人瀏覽器- 不要有任何路徑呼叫
list_sessions(user_id=None)—— 那會撈出 app 底下所有使用者的 user state 並各自 merge 進回傳的 session
[!Note] 兩條路都要做的 #124 約束 #124 的「讓 agent 參考其他 public session 的內容」那個 tool,只回傳對話 content,不要去 retrieve 原作者的 memory。接關者用自己的 memory。
上週重點整理(2026-09-01 ~ 2026-09-09)
GitHub 活動
cofacts/ai
- #136 Fall back to Cofacts’ stored page text when the verifier’s live fetch fails(opened 09-01 / merged 09-03)
- #130 M1: a receptionist agent in front of the writer, so pasting a message works(closed 09-09,未 merge)
- #137 M2 (demo cut): file a new message into the database, in English(opened 09-04 / closed 09-09,未 merge;Global gathering demo 用的純英文版)
- #138 Report a suspicious message through a form at /report, and make the app installable(opened 09-05,draft 進行中)
cofacts/rumors-api
- #400 refactor(transcript): 直接把 media URI 交給 Vertex,不再複製到 GCS(opened 09-08,review 中)
- #401 fix: article 更新在樂觀鎖競爭中失敗時重試(opened 09-08,review 中)
- #402 chore(rumors-db): 先行導入 hybrid search 的 embeddings schema(opened 09-08 / merged 09-09)
cofacts/rumors-db
- #79 scanIndex: restore vector validation via _source_exclude_vectors: false(issue closed 09-08)
- #80 fix(reloadSchema): use snake_case wait_for_completion for ES9 client(待 review,卡住 hybrid search schema 的 deploy)
cofacts/rumors-site
- #628 Llm translated(opened 09-02,@macpaul)
- #629 功能請求: “網友回報補充”部份接受安全的 markdown(issue opened 09-08)
- #630 feat: render reply request reasons as safe Markdown(opened 09-08,@bestian)
- #280 iOS users cannot perform search(09-08 有新留言)
cofacts/rumors-line-bot
- #415 Llm translated(opened 09-02,@macpaul)
cofacts/devops
- #15 takedown skill: open PRs as cofacts-takedown GitHub App(opened / merged 09-01)
- #16 docs(GCE): document GCS log sink for long-term archival(opened / merged 09-01)
- #17 讓 rumors-site / line-bot-zh / url-resolver 記錄 request header(含 cf-connecting-ip),並修 rumors-api GraphQL log 的 header 迴歸(issue opened 09-09)
- #18 記錄 Cloudflare 端 Analytics retention 現況(31 天 / 3 天)與匯出限制(Logpush 為 Enterprise-only)(issue opened 09-09)
- #19 docs(GCE): document BigQuery external tables for querying archived logs(opened 09-09)
cofacts/takedowns
- #342 [TEST] Verify cofacts-takedown GitHub App identity(09-01,驗證 GitHub App 身分用,已關閉)
- 本週 spam 帳號 takedown:#343、#344、#345、#346(09-04 ~ 09-09,其中 #346 merged,其餘關閉)
cofacts/kb
- #18 docs(wiki): add spam/fraud takedown project page(merged 09-09)
- #23 doc: add 20260901 meeting notes(merged 09-09)
Discord 重點討論
general
@mrorz:目前不需要 app-id 與 app-secret 可以直接接取唷!hackfoldr 已經修正,感謝指出問題
@bestian:我成功直接接取了,謝謝! 想請問沒有 app-id 與 app-secret 的情況下,同一 cloudflare worker 後端服務,接取 cofacts API 資料,目前有使用量上限嗎? 也附上開發中的專案 repo,供參考:https://github.com/g0v/fact-check-api
@bestian:或是有 X402 付費牆嗎? 想瞭解如果未來服務擴大,cofacts API 接口這邊的橋接規則(https://developers.cloudflare.com/agents/tools/payments/x402/ )
@mrorz:(使用量上限)目前沒有唷,但如果太頻繁導致我們的 Cloudflare 發現異常,可能會被判斷為是 DoS attack 然後擋下來⋯⋯ XD
@mrorz:其實我們有在規劃做 MCP 方便 coding agent 接取這樣
dev
@MrOrz:Global gathering 用的純英文 + submission 的版本,這個版本就是 for demo 方便使用者送訊息,不會 merge 進 master,到時候的送出流程以子龍版設計為準(demo: https://pr-137—cofacts-ai-sgnrxas52q-de.a.run.app/ )
@yutin:把 PR 拆一小部分出來 https://github.com/cofacts/rumors-api/pull/400
@MrOrz:https://github.com/cofacts/rumors-db/pull/80 這個也請看一下,沒問題的話可以給我個 approve,不然我沒辦法 deploy @yutin 的 hybrid search schema(rumors-db#78)
@MrOrz:@yutin 拆的兩個 PR 我都 review 囉,大感謝
Cofacts 正式環境狀態報告
報告期間:2026-09-01 ~ 2026-09-09(距上次會議 9 天) 比較基準:2026-08-25 ~ 2026-09-01(前一期間,取自歷史 metrics summary)
一、GCE 主機狀態(cofacts-prod)
現況快照(2026-09-09 15:52)
| 項目 | 數值 |
|---|---|
| Uptime | 125 天 21 小時(未重啟) |
| Load Average | 0.69 / 0.51 / 0.61(1/5/15 分鐘) |
| 記憶體(RAM) | 21 GB used / 31 GB total(66–67%) |
| Swap | 1.8 GB used / 4 GB total(~47%,穩定) |
| 磁碟 | 59 GB / 67 GB(88% ⚠️,見下方調查) |
GCE CPU / 記憶體 / Swap 逐日明細
格式:min | avg | p95 | max
| 日期 | CPU(%) | Mem(%) | Swap(%) |
|---|---|---|---|
| 09-01 | 11.8 | 21.4 | 29.9 | 32.9 | 64.7 | 66.8 | 68.4 | 73.7 | 43.1 | 45.3 | 48.2 | 49.6 ✅ |
| 09-02 | 10.0 | 19.3 | 28.4 | 38.4 | 63.9 | 66.4 | 68.1 | 68.8 | 45.5 | 47.1 | 49.4 | 50.4 ✅ |
| 09-03 | 8.7 | 17.5 | 25.3 | 45.7 | 64.2 | 66.2 | 68.0 | 68.6 | 45.3 | 47.4 | 49.7 | 50.4 ✅ |
| 09-04 | 9.8 | 16.5 | 23.5 | 38.9 | 63.9 | 66.4 | 68.1 | 68.9 | 45.0 | 46.7 | 49.1 | 49.8 ✅ |
| 09-05 | 7.5 | 15.6 | 21.4 | 38.8 | 64.8 | 66.6 | 68.7 | 69.3 | 44.9 | 46.5 | 49.5 | 51.4 ✅ |
| 09-06 | 8.9 | 15.7 | 22.6 | 39.6 | 64.1 | 65.9 | 67.7 | 68.8 | 47.1 | 48.8 | 50.8 | 52.2 ✅ |
| 09-07 | 8.6 | 16.5 | 26.1 | 39.9 | 65.0 | 67.3 | 69.6 | 71.1 | 45.0 | 46.6 | 48.1 | 49.8 ✅ |
| 09-08 | 8.9 | 16.6 | 30.1 | 36.4 | 64.3 | 66.4 | 68.8 | 70.1 | 46.0 | 47.5 | 49.2 | 57.5 ✅ |
| 09-09 | 11.0 | 16.2 | 20.9 | 28.5 | 64.0 | 66.3 | 68.6 | 69.7 | 45.2 | 47.4 | 49.7 | 49.8 ✅ |
觀察:CPU 平均使用率自 9/1 的 21.4% 逐日降至 9/9 的 16.2%,無異常尖峰。RAM 穩定在 66–67%,Swap 穩定在 45–49%(9/8 出現單一 max 57.5% 的短暫波動,之後隨即回落,不影響穩定度)。相較 4 月曾出現的 swap 滿載(98–100%)事件,目前狀態健康,
memswap_limit設定持續發揮效果。
二、GCE 程序層級資源(Top 消耗者,與前一期間 8/25–9/1 比較)
CPU(原始計數器單位,僅比較相對量級)
| 程序 | 前期 peak / avg 範圍 | 本期 peak / avg 範圍 | 觀察 |
|---|---|---|---|
java(Elasticsearch) |
482,664 / 173,680–261,433 | 511,262 / 211,352–340,657 | 🟡 avg 上升約 20–30% |
node server.js(rumors-api) |
261,867 / 140,208–189,664 | 393,346 / 158,649–210,029 | 🟡 peak 明顯上升(+50%),avg 略升,建議留意流量來源 |
node build/index.js(rumors-site) |
206,673 / 98,547–129,621 | 189,010 / 112,217–149,793 | ➡️ 大致持平,avg 略升 |
cloudflared tunnel |
35,496 / 15,691–22,291 | 41,505 / 17,474–26,934 | ➡️ 略升,穩定 |
| Chromium renderer(Puppeteer) | 15,485 / 7,193–8,162 | 23,144 / 8,082–11,825 | 🟡 peak 上升,屬瞬間 spike(截圖/爬取任務) |
python main.py(cofacts-ai) |
18,292 / 3,484–5,876 | (跌出本期 Top 15) | ✅ 本期未進入 Top 15,CPU 占用下降 |
pm2-runtime start ecosystem |
13,981 / 9,204–10,665 | (跌出本期 Top 15) | ✅ 同上 |
RSS 記憶體(MB)
| 程序 | 前期 peak / avg 範圍 | 本期 peak / avg 範圍 | 觀察 |
|---|---|---|---|
java(Elasticsearch) |
19,694 / 19,144–19,289 | 19,563 / 19,155–19,265 | ➡️ 持平,極穩定(std < 150) |
node server.js(rumors-api) |
1,450 / 269–314 | 1,450 / 289–322 | ➡️ 持平 |
node build/index.js(rumors-site) |
736 / 143–149 | 725 / 141–146 | ➡️ 持平 |
pm2-runtime ecosystem.config.js |
326 / 102–154 | 346 / 115–196 | 🟡 std 上升(103),波動略增 |
| Chromium renderer(Puppeteer) | 379 / 117–341 | 345 / 125–329 | ➡️ 持平 |
結論:主機整體資源穩定,唯
node server.js(rumors-api)CPU peak 上升約 50%,建議下次確認是否對應特定流量事件(例如新聞熱點、爬蟲)。ES 記憶體/CPU 持續是最大單一消耗者但無異常波動。
三、Cloud Run 狀態
所有 11 個服務均正常運行(✔)。近期部署:
cofacts-ai:2026-09-09 15:00(本次期間內有新部署)site-tw/site-en/site-ja:2026-04-09(未變動)site-staging-*:2026-08-17line-bot-en/ja/tw:2025-05-16(未變動)
四、Cloud Run CPU 比較(p50 / p95 / p99,vCPU)
| 服務 | 前期 8/25–9/1 (p50 | p95 | p99) | 本期 9/1–9/9 (p50 | p95 | p99) | 觀察 |
|---|---|---|---|
| site-tw(主力) | 0.035–0.074 | 0.668–0.798 | 0.823–0.982 | 0.042–0.138 | 0.649–0.798 | 0.823–1.012 | 🟡 p50 上升(尤其 9/1 高峰),p99 觸頂 1.0,建議觀察 |
| cofacts-ai | 0.015–0.016 | 0.127–0.397 | 0.284–0.415 | 0.015–0.016 | 0.152–0.367 | 0.245–0.370 | ✅ 穩定 |
| line-bot-en | 0.005–0.014 | 0.010–0.224 | 0.120–0.268 | 0.006–0.015 | 0.061–0.292 | 0.132–0.339 | ➡️ 略升,仍在合理範圍 |
| line-bot-ja | 0.006–0.015 | 0.101–0.182 | 0.128–0.339 | 0.005–0.012 | 0.075–0.310 | 0.110–0.381 | ➡️ 持平 |
| site-staging-en/ja/tw | 皆為低流量測試環境 | 皆為低流量測試環境 | ➡️ 無異常 |
line-bot-tw、site-en、site-ja本期與前期皆無回傳指標資料(Cloud Monitoring 查無時間序列),研判為該服務在查詢窗口內請求量趨近於 0(無活躍 instance)。
五、Cloud Run 記憶體比較(p50,GB)
| 服務 | 前期 p50 | 本期 p50 | 變化 |
|---|---|---|---|
| site-tw | 0.742–0.764 | 0.764–0.787 | ➡️ 持平略升 |
| site-staging-tw | 0.787–0.913 | 0.586–0.811 | 🟢 下降(測試環境負載減少) |
| line-bot-en/ja | 0.376–0.411 | 0.387–0.423 | ➡️ 持平 |
| cofacts-ai | 0.056–0.065 | 0.056–0.065 | ➡️ 持平 |
整體記憶體無異常增長。
六、Cloud Run 網路流出量(site-tw,每日 egress)
| 日期 | Bytes | 備註 |
|---|---|---|
| 09-01 | 6.85 GB | 本期最高點 |
| 09-02 | 5.59 GB | |
| 09-03~09-08 | 3.9–4.4 GB | 穩定區間 |
| 09-09 | 2.75 GB | 當日未滿(擷取當下) |
前期(8/25–9/1)每日約 3.3–4.5 GB,本期 9/1 出現單日高點(6.85 GB),其餘天數回落至與前期相當的區間。無需立即處理,但可留意是否為特定事件流量。
七、磁碟使用調查
磁碟使用率從 4/28 的 62%(29 GB / 48 GB)上升至本期 88%(59 GB / 67 GB,注意:磁碟容量本身也從 48GB 擴增至 67GB,實際使用量仍成長約 2 倍)。上機查看佔用來源:
| 路徑 | 大小 | 佔比 |
|---|---|---|
/var(總計) |
42 GB | 佔根目錄 71% |
└ /var/lib/docker |
37 GB | 主要成因 |
└ /var/lib/snapd |
2.4 GB | |
└ /var/log(含 journal) |
1.5 GB | |
/srv |
11 GB | 應用程式碼與資料 |
/usr |
2.3 GB |
docker system df 明細:
| 類型 | 數量 | 總大小 | 可回收 |
|---|---|---|---|
| Images | 61(13 個使用中) | 20.78 GB | 7.58 GB(36%) |
| Containers | 13(全數使用中) | 6.44 GB | 0 GB |
根因:每次 docker-compose 重新 build/pull 後,舊版 image 未被清除,累積成 44 個 dangling(<none>)image,最舊可追溯到 16 個月前(cofacts/rumors-line-bot:latest-tw)。這是磁碟成長的主因。
已執行清理(2026-09-10,經確認後執行 docker image prune -f,只清 dangling image,未動有 tag 的 v6-backup/almir-webhook):
| 清理前 | 清理後 | |
|---|---|---|
| 磁碟使用率 | 88%(59GB/67GB) | 68%(45GB/67GB) |
| 可用空間 | 8.2GB | 22GB |
| Dangling image 數量 | 44 | 0 |
實際回收約 14GB,優於原估 7.6GB。目前使用中的 13 個 container/image 未受影響。
後續建議:評估是否需要定期(如 cron)清理舊 image,避免再次累積到 88%。
八、整體健康評估
| 維度 | 狀態 | 說明 |
|---|---|---|
| CPU | 🟢 正常 | avg 16–21%,逐日下降,無尖峰 |
| RAM | 🟢 正常 | 66–67%,穩定 |
| Swap | 🟢 正常 | 45–49%,遠低於 4 月曾出現的滿載風險 |
| 磁碟 | 🟢 已處理 | 原 88%,清除 44 個 dangling docker image 後降至 68%(回收 ~14GB),建議評估定期清理避免再次累積 |
| Cloud Run | 🟢 全部正常 | 11 服務皆 ✔ |
| site-tw CPU | 🟡 略高 | p50/p99 較前期上升,p99 觸及 1.0 vCPU 上限,建議持續觀察 |
node server.js CPU |
🟡 待觀察 | peak 較前期上升約 50% |
下次開會時間
一~四 bil 在國外,選項:
- 9/14 (一) 20:00 線上
- (二) (三) 晚上沒有時間
- 9/17 (四) 21:00 線上
- 9/18 (五) 20:00 實體
[!NOTE] 下次開會:9/14 (一) 20:00 線上