Community Notes:同一邊的人一起說好,推不動分數
X 把 Community Notes 的評分程式碼公開在 GitHub。每位評分者與每則 note 都只拿到一個座標,模型先用「你們本來就站同一邊」解釋掉一致的評分,剩下解釋不掉的才進得了分數——截距的正則化在建構式裡被寫成 factor 的 5 倍。核心模型要截距 0.40 才升 Helpful,而刷評分要付兩次代價。
事實分級說明
數字取自
twitter/communitynotes(Apache 2.0)2026 年 8 月 10 日的 HEAD 快照。README 自陳,評分器在內部 repo 開發,每次部署更新就匯出到 GitHub——這份程式碼是線上系統的匯出,不是線上系統本體。另有一條貫穿全文的分別:matrix_factorization.py與mf_base_scorer.py裡的值是建構式的預設,run_scoring.py在建立各個 scorer 時會覆寫其中一部分,兩者要分開讀。
一則貼文底下掛上了 Community Note。作者不服氣,在自己的帳號上號召粉絲:全部去點那則 note 的「沒幫助」。
粉絲人數夠多,動員也真的做得到。但在這套評分程式碼裡,這個動作推不動分數。
原因不是有人在後台盯著誰在動員。是這套數學從第一步就不獎勵同溫層的同意——一群立場一致的人給出一致的評分,這份一致會先被模型拿去解釋成「你們本來就站同一邊」,扣完之後剩下的,才進得了那則 note 的分數。
X 把 Community Notes 的評分程式碼放在 GitHub 上,倉庫叫 twitter/communitynotes。這個設計不是外面推敲出來的,是一行一行寫在建構式裡的。
每位評分者在模型裡只有一個座標
Community Notes 的核心是一個矩陣分解模型。矩陣分解在推薦系統裡很常見:把「誰對什麼有什麼反應」這張大表拆成兩組數字,一組描述人,一組描述東西,兩組相乘去逼近原表。
一般的推薦系統會給每個人幾十甚至幾百個維度。Community Notes 給一個。
matrix_factorization/model.py 第 26 行:
n_factors: int = 1,
第 37 行的說明更直接:
n_factors (int, optional): number of dimensions. Defaults to 1. Only 1 is supported.
只支援 1。每位評分者身上掛一個數字,每則 note 身上也掛一個數字,程式碼與文件都叫它 factor,或者 viewpoint。除了 factor 之外,每則 note 還有一個截距,那才是決定它能不能升上 Helpful 的分數。
把這一維直接說成左右政治光譜,是外部的推論,不是倉庫裡的說法。程式碼與 documentation/under-the-hood/ranking-notes.md 第 54 到 56 行都只叫它 viewpoint 或 factor,沒有貼上任何政治標籤。這一維實際上裝了什麼,這份程式碼沒有回答。
截距的正則化被直接寫成 factor 的 5 倍
scoring/src/scoring/matrix_factorization/matrix_factorization.py 第 40 到 44 行,是整份倉庫裡最值得慢慢看的五行:
userFactorLambda=0.03,
noteFactorLambda=0.03,
userInterceptLambda=0.03 * 5,
noteInterceptLambda=0.03 * 5,
globalInterceptLambda=0.03 * 5,
lambda 是正則化強度。正則化在做的事,用白話說是模型在學習的時候,對每一個它想調大的數字收一筆罰金:這個數字長得越大,罰得越重。罰得重的那一項,模型會盡量少用它來解釋資料。
所以這五行在說:解釋一筆評分的時候,模型手上有兩種工具。一種是 factor,也就是「這些人本來就站在同一邊」;一種是截距,也就是「這則 note 真的有幫助」。用截距解釋,罰金是用 factor 解釋的 5 倍。
模型會怎麼選,不必猜。它會先把能用 factor 解釋掉的部分全部解釋掉,剩下用 factor 怎麼樣都對不上的那一塊,才會被推進截距。而升上 Helpful 看的是截距。
值得注意的是寫法。原始碼寫的不是 0.15,是 0.03 * 5。那個 5 不是外面算出來的比例,是有人在建構式裡把「截距要比 factor 難五倍」這件事直接打成了一個乘法。
射程要標清楚:這是 MatrixFactorization 的建構式預設,不是全系統通則。run_scoring.py 對 Group 14、Group 18 與 Group 15 會覆寫 lambda,其中 InDimensionTwo 的 userInterceptLambda 甚至是 5。準確的說法是,預設把截距的正則化明寫成 factor 的 5 倍,不是所有模型都是 5 倍。
核心模型要截距 0.40,不同人群的模型用更低的線
罰金決定的是分數難不難長。真正決定放不放行的是門檻。
mf_base_scorer.py 第 172 到 202 行的預設值:
| 參數 | 預設值 |
|---|---|
crhThreshold(升 Helpful 的截距門檻) |
0.40 |
factorThreshold(Helpful 的 factor 絕對值上限) |
0.5 |
minRatingsNeeded / minNumRatersPerNote |
5 / 5 |
minNumRatingsPerRater |
10 |
minRaterAgreeRatio |
0.66 |
crnhThresholdIntercept / 乘數 |
−0.05 / −0.8 |
crhThresholdNoHighVol / crhThresholdNoCorrelated |
0.37 / 0.37 |
factorThreshold 這一項容易被跳過,但它是門檻表裡的第二道鎖。一則 note 光是截距衝高還不夠,factor 的絕對值不能超過 0.5。翻成白話:一則明顯只有某一邊喜歡的 note,就算被那一邊推到分數很高,還是會卡在這一關。
通過率呢?ranking-notes.md 第 70 到 74 行有一句:
In general, we set the thresholds to achieve a "Helpful" status at 0.40, including less than 10% of the notes…
逐字讀就好。官方沒有界定這個 notes 的分母——是所有被寫出來的 note、被評分過的 note,還是某一輪計分的輸入,文件裡都沒有寫。
還有一件事不能省。0.40 是核心模型的門檻,Community Notes 跑的模型不只一個。mf_group_scorer.py 第 9 到 23 行把一般的 group 模型數量設為 14,另外還有試驗性的 Group 14、NMR Group 33、NMR trial Group 18,以及 Gaussian NMR trial Group 15;除了 group 模型,enums.py 第 24 到 32 行還列了以主題切分的 scorer,包括 Unassigned、UkraineConflict、GazaConflict、MessiRonaldo、Scams 與 InDimensionTwo,run_scoring.py 第 241 到 266 行對這些主題全部建立了 scorer。
這些模型的門檻不一樣。run_scoring.py 裡 Group 14 是 0.15、Group 18 是 0.2、Group 15 是 0.25——都比核心模型的 0.40 低。所以正確的講法是:核心模型的門檻是 0.40,不同人群的 group 模型用的是更低的線。
〈X 推薦權重表:分數一旦翻負,差多少就不重要了〉裡有一個一樣的形狀:一個數字被拿出來當金句之前,要先問它是誰的數字。0.40 也是。
防刷是設計出來的四層,不是一個開關
同溫層推不動分數,那組織一批帳號、專門去刷呢?倉庫裡處理這件事的不是一個開關,是四層各自獨立的設計。
第一層是共選偵測,而且不是單一門檻。post_selection_similarity.py 第 16 到 26 行、第 154 到 175 行、第 323 到 338 行,用 1 分鐘、5 分鐘、20 分鐘三個時間窗去看兩個評分者的行為重疊:writerCoverage 分別是 0.2、0.3、0.4,raterAffinity 分別是 0.2、0.45、0.7,任何一組超標就把這兩個人標成一組 pair;另外還保留 smoothed NPMI 大於等於 0.55、或 MinSim 比例大於等於 0.4 的 pair。標完之後 quasi_clique_detection.py 第 16 到 27 行、第 137 到 198 行接手,在 13 週的資料裡找出共同評分超過 50 次、涵蓋至少 25 篇貼文、至少 5 位評分者、note 與 rater 密度都大於等於 0.25 的群,用貪婪演算法把整群圈出來。三個時窗、兩種指標,再加一次分群。想繞過去,要避開的不是一條線,是一整組互不相同的統計特徵。
第二層是「拿掉再跑一次」,而且跑兩次。一次剔除評分量最高的那 0.1% 評分者,一次剔除被判定為共選的評分者,各自把整個計分重跑一遍。這則 note 在兩次重跑之後都必須仍然過 0.37 這條線,才留得住結果。意思是:一則 note 的狀態不能只由最活躍的那批人撐著,也不能只由行為高度同步的那批人撐著,拿掉誰都得站得住。
第三層是評分的時窗。只有在 note 建立後 48 小時內做出的評分才算有效評分。
第四層是信譽門檻的第二輪。第一輪跑完之後,系統會挑出信譽夠格的評分者,只用他們的評分再跑一次,最終狀態由第二輪決定。
四層裡有兩層值得單獨拆開講,因為它們合起來構成了刷評分真正的代價。
刷評分要付兩次代價
第一次代價當場就付掉。一群立場一致的帳號給出一致的評分,這份一致會被 factor 那一項吸收掉,進不了截距。這是前面那個 5 倍在做的事。
第二次代價是延後結算的,落在評分者自己身上。
contributor-scores.md 第 41 到 43 行寫了什麼評分才算有效:
only ratings that were made before the rater could've known what the final note status label is are eligible… Made within the first 48 hours of the note's creation (because we publicly release all rating data after 48 hours)
括號裡那句話是重點。48 小時不是隨手訂的期限,是因為所有評分資料在 48 小時之後就會公開釋出——過了那個點,任何人都查得到別人是怎麼評的,跟著風向評一票不再證明任何事,所以那之後的評分不算進信譽。
有效評分的射程要說準。文件第 50 行的說法比一般的理解更窄:一筆評分算不算有效,不會改變它在該 note 當次狀態計算裡的影響。但這不代表它與最終狀態無關。helpfulness_scores.py 第 178 到 196 行把後半段接了起來:有效評分餵給評分者信譽,信譽算出 aboveHelpfulnessThreshold 這個旗標,旗標決定誰能進第二輪,第二輪決定最終狀態。所以準確的說法是,有效與否不改變這筆評分當次的權重,但會經由信譽間接影響最終結果。
那第二輪的門有多窄?contributor-scores.md 第 56 到 62 行加上 helpfulness_scores.py 第 178 到 196 行,條件不只三項:
- 總評分至少 10 次;
- 有效評分至少 1 次;
- 兩道信譽檢查——一般的
raterAgreeRatio要大於等於 0.66,另外一個帶騷擾懲罰的同一比率也要大於等於 0.66,兩道都得過; - 如果這位評分者自己寫過 note,而且那些 note 至少收到 5 個評分,那麼他的 CRH 對 CRNH 比率要大於等於 0.0,平均 note score 要大於等於 0.05。
兩道信譽檢查是常被漏掉的一項。一般比率過了、帶騷擾懲罰的比率沒過,一樣進不去。
把兩次代價擺在一起看,動員刷評分的算式就很不划算了:當次的評分被數學吃掉,同時又在自己的信譽帳上記了一筆,下一輪連入場資格都拿不到。
兩週之後狀態會被鎖起來
時間還會再關一道門。
ranking-notes.md 第 368 到 371 行:一則 note 滿兩週之後,系統會把當下的 helpfulness status 存起來,之後就沿用這個存下來的值。文件明說這個鎖定值用在兩個地方——站上的顯示,以及貢獻者統計。
意思是,這件事有時效。一則 note 上去或沒上去,兩週之後就不是靠繼續評分能改的了。
上架與翻盤各有一個模型
除了矩陣分解,倉庫裡還有兩個監督式模型。名字都帶 CRH,做的卻是相反方向的事,混在一起講會得到錯的結論。
pcrh_model.py 第 1 到 23 行的那個,看的是早期評分,預測這則 note 最後會不會達到 CRH。用途是讓有希望的 note 提早上架,不必等評分累積完。同一套機制也會往回收:constants.py 第 80 到 89 行的 pcrhRevokeThreshold 是 0.5,一則已經超過門檻的 note,如果當前的預測機率掉到 0.5 以下,pcrh_model.py 第 838 到 866 行會把它撤下來。
pflip_plus_model.py 第 1 到 29 行的那個方向相反,它處理的是已經 CRH 的 note,預測它會不會在穩定期翻回 NMR。run_scoring.py 第 2010 到 2079 行說明了它跑在哪裡:穩定期的 note,以及近 24 小時內重新拿到 CRH 的 note。
一個負責提早開門,一個負責事後回頭檢查門有沒有開錯。
X 把 bridging 搬去用在讚上
如果這套 bridging 只是拿來管事實查核,它的射程就到此為止了。但 X 自己已經把它搬出去試了。
倉庫裡有一個目錄叫 liked-by-different-perspectives。score_posts.py 第 14 到 16 行三個常數:FACTOR_SPLIT_POINT = 0.15、MIN_LINGERS = 29、QUANTILE_THRESHOLD = 0.7。第 129 到 138 行用正負 0.15 把使用者依 factor 座標切成左、中、右三桶;第 205 到 239 行再加條件:兩側的停留次數都要嚴格大於 29、不能有負向評分、要通過資格檢查,還要越過一個動態計算出來的正向門檻。
同一個座標、同一種「兩側都要買單」的判準,換了一個對象:從「哪則備註有幫助」變成「哪則貼文被不同立場的人一起按讚」。這是倉庫裡的試點程式碼,不是線上系統本體,但方向很清楚——bridging 在 X 內部不只被當成查核工具,也被當成一種排序原則在試。
往外擴的不只是評分那一端。AI 也已經進了這套系統,但進的是寫的那一端。documentation/api/overview.md 第 62 到 71 行寫了 AI Note Writer 的收錄門檻:從最近 50 則 test_mode 提交的 note 裡挑,必須同時通過 ClaimOpinion high 大於等於 30%、low 小於等於 30%、UrlValidity high 大於等於 95%、HarassmentAbuse high 大於等於 98% 這四道,通過之後仍然是自動且隨機選入試點。而 AI 寫手不能評分——評分權還在人身上。
每一道設計都往「不放行」的方向加
把整份倉庫的設計擺在一起看,方向是一致的:截距的罰金是 factor 的 5 倍,門檻要 0.40,factor 絕對值不能超過 0.5,拿掉最吵的 0.1% 再跑一次、拿掉共選者再跑一次都要仍然過 0.37,評分要在 48 小時內做,評分者要過兩道信譽檢查才進得了第二輪,上架之後還有一個模型盯著會不會翻盤。
每一道都是往「不放行」的方向加的。官方文件說這條線讓 less than 10% of the notes 拿到 Helpful,跟上面這串條件擺在一起看,數字不意外。
〈它不是在評分,是在打安全牌〉講過一個系統為什麼會系統性地偏保守。Community Notes 的偏保守是明寫在參數裡的:漏掉一則該掛的備註,成本是這則貼文沒被標;掛錯一則不該掛的,成本是整個機制的公信力。程式碼選了前者。
給非工程師的一句話
想讓一則 Community Note 上去或下來,最沒有用的做法就是找一群跟自己意見相同的人一起去點。這套模型第一件做的事,就是把「意見相同」本身先解釋掉,解釋不掉的才算分。〈你叫的名字,和你拿到的東西〉與〈它不是在說謊,是在賭〉講的是同一種閱讀習慣:與其記別人翻譯過的結論,不如把那幾行程式碼打開來看一遍——matrix_factorization.py 第 40 到 44 行,五行,倉庫是公開的。
常見問題
動員粉絲一起去點「沒幫助」,能把一則 Community Note 弄下來嗎?
程式碼裡的設計不獎勵立場一致的評分。核心是 rank-1 矩陣分解,每位評分者與每則 note 各拿到一個 factor 座標;matrix_factorization.py 的建構式把截距的正則化寫成 0.03 乘以 5,是 factor 正則化的 5 倍。一群立場一致的人給出一致的評分,模型會優先用 factor 把這份一致解釋掉,解釋不掉的部分才進得了截距,而升 Helpful 看的正是截距。要注意這 5 倍是建構式的預設值,部分 scorer 在建立時會被覆寫。
一則 Community Note 要達到什麼門檻才會顯示為 Helpful?
核心模型的預設是截距達到 0.40,同時 factor 的絕對值不超過 0.5,另外還要至少 5 筆評分、至少 5 位評分者。官方文件的說法是,門檻訂在 0.40 讓 less than 10% of the notes 拿到 Helpful,文件沒有界定這個分母指的是哪一群 note。不同人群的 group 模型用的是更低的線,實際建立時分別是 0.15、0.2 與 0.25。
Community Notes 的 48 小時評分時窗是什麼意思?
只有在 note 建立後 48 小時內做出的評分才算有效評分,理由寫在官方文件裡:所有評分資料在 48 小時之後就會公開釋出,之後任何人都查得到別人怎麼評,所以那之後的評分不算進評分者信譽。一筆評分算不算有效,不會改變它在該 note 當次狀態計算裡的權重,但有效評分會累積成評分者信譽,信譽決定誰進得了第二輪,第二輪決定最終狀態。
這套 bridging 的數學只用在事實查核上嗎?
倉庫裡有一個叫 liked-by-different-perspectives 的試點,把同一套 factor 座標搬去用在讚上:以正負 0.15 為切點把使用者分成左、中、右三桶,要求兩側的停留次數都嚴格大於 29、沒有負向評分、通過資格檢查,並超過動態計算出來的正向門檻。這是倉庫裡的試點程式碼,不是線上系統本體。
📚 收進你的工具
For AI Reading Era把這篇文章交給你日常用的工具——做研究、整理筆記,或當 AI 的 context。