← 共識引擎

第 1 章:第 1 章

哲維的房間在六樓,沒有電梯。

搬進來的時候他二十九歲,房東說這是邊間、採光好。邊間是真的——太陽從早上六點就照進房間,曬到桌上那台筆電的觸控板會燙手。採光好也是真的,好到他的螢幕在白天有一半時間看不清楚。

他習慣了。

螢幕上的收件匣有十二封未讀。他倒了一杯昨天沒喝完的水,坐下來,一封一封處理。

前六封是廣告信。和盟集團的系統更新公告——他訂閱了他們外包開發者的 mailing list,有時候裡面會夾帶新案子的公告,但不是今天。第七封是他上個案子的尾款通知,款項已經入帳。第八封是另一個客戶的报价詢問,要做一個小型電商網站的搜尋功能,预算不高,工期不短。他在心裡算了一下時薪,大概跟便利商店打工差不多。

第九封的寄件人是蘇薇。標題寫著:「外包案邀請 — 推薦系統異常修復(B 級)」。

他開了信。

內容不長。和盟集團商務中心旗下的推薦引擎持續整合模組,最近出現在使用者決策路徑中的異常現象。影響範圍約千分之三的使用者,目前判定為 B 級優先順序。需要一名外包工程師協助排查與修復。附件是技術規格文件、保密協議、與付款條件。

哲維把付款條件看了一遍。收款週期四十五天,預付款三成,不多不少,在業界算正常。他看了技術規格文件的摘要——是他熟悉的領域,推薦系統的數據 pipeline 和排序演算法,帶一點 A/B 測試框架的調校。

他把信轉寄到自己的另一個信箱,回了一個「收到,我會看一下,明天回覆」給蘇薇。沒有寒暄,沒有感謝。和盟的外包聯絡人專業得像是在做 SOP 演練,他也不想浪費時間客氣。

處理完剩下的三封信,他打開瀏覽器。沒有特別的目的,只是習慣。先看了一下 Hacker News 前幾篇——一篇關於 transformer 架構變體的論文摘要、一篇某間雲端服務供應商又漲價的討論、一篇標題寫著「你以為你在選擇,其實演算法在幫你選」的評論文章。

他沒有點最後那篇文章。不是沒興趣,是太累了。那種標題他已經看到不想看。每一篇都寫得好像發現了新大陸,核心論點永遠是同一句話:科技公司用演算法影響使用者的決策。對。然後呢。他關上瀏覽器。

十一點多了。他拿起手機,看到一個未讀訊息,是之前合作過的工程師傳來的,問他有沒有興趣接一個新案子,薪資不錯。他回了一個 OK 和一個問號。

然後他看到訊息列表裡有一個名字:陳若晴。

最後一篇訊息停在四個月前。她傳了一個訊息問他最近好不好,他回了「還好,你呢」,她回了「也不錯」,然後就沒了。

他沒有點進去。

把手機放下,哲維去廚房煮了一個泡麵。廚房在陽台旁邊,隔了一道塑膠門,抽油煙機的聲音比水滾的聲音還大。他站在那裡等麵熟的時候,看了一眼窗外的巷子。隔壁那棟樓的燈光大部分都暗了,只剩下一樓雜貨店的招牌還亮著,是一個紅色的燈管,寫著「雜貨」。燈管有幾根壞了,看起來像是「米七」。

回到電腦前面,麵已經有點太軟了。他不在意。吃麵的時候他重新打開蘇薇那封信,把技術規格文件完整讀了一遍。

B 級優先,修復一個推薦系統的決策路徑異常。規格文件寫得很清楚:某些使用者在特定推薦場景下,行為路徑出現了「高度一致性」,簡單來說就是使用者反复做同一個選擇。文件把這個現象稱為「決策迴圈」。

他讀到這裡停了一下。

「決策迴圈」這個詞他不是第一次在業界文件的場合見過。通常這意味著推薦系統的同質性太高,使用者的選擇空間被演算法收窄了,結果就是他每次看到的選項都差不多,久而久之就不會再探索新的東西。這是推薦系統的經典問題,技術上叫做 filter bubble。不新鮮。

但文件裡提到了另一件事:這些出現決策迴圈的使用者,他們的行為模式高度一致,但他們的背景資料分布很廣——不同年齡、不同地區、不同消費水準。如果只是 filter bubble,通常只會影響特定群體。這裡的分布是隨機的。

他把自己的想法記在了一個備忘錄裡,然後繼續讀完文件。

最後面是蘇薇的聯絡方式,和一個視訊會議的邀請連結。她把合作流程寫好了:先視訊確認工作範圍,再簽 NDA 和合約,然後開帳號權限。有效率,不浪費時間。

哲維把那碗麵吃完,把碗放在水槽裡,約了明天下午兩點的視訊。

那天晚上他看了一部之前在瀏覽器分頁裡放了不知道多久的紀錄片——關於海洋洋流的。紀錄片的聲音設計很好,洋流的聲音規律、低沉,像是有東西在很深的地方穩定地流動。他看到一半就睡著了。


隔天下午一點五十五分,哲維打開視訊通話。

蘇薇比他想得年輕。三十一、二左右,頭髮整齊地紮在後面,身後的壁紙是素面的灰——很典型的和盟員工。

「哲維?」她先開口。「感謝你這麼快回覆。我先跟你講一下這個案子的背景。」

「好。」他說。他在自己的螢幕上看到自己的臉,看起來比昨天更沒睡好。

「我們最近在推推薦引擎 7.2 的更新,持續整合模組在八週前上線。」她的語速比哲維快一拍,但他跟上了。「上線後的數據整體是正的——CTR 提升 1.2%,使用者停留時間增加 0.8%。但有大約千分之三的使用者,他們的決策路徑出現了異常。」

「決策迴圈。」哲維說。

「對。初步分析是推薦權重衰減出了問題,把使用者的選擇範圍收窄了。但在我看來——」她頓了一下。「分析結果有一點不合理。通常權重衰減造成的 filter bubble 都是群組性的,但這裡的使用者分布非常分散。而且他們的行為一致性太高了。高到不自然。

哲維靠在椅背上。「所以你們不確定這是 bug 還是⋯⋯」

「還不確定。」她說。「所以我需要一個外部工程師來排查。內部團隊目前人力都在 7.3 的開發上。你的背景看起來很適合——你在推薦系統和數據 pipeline 上有經驗。」

他確實有。兩年前待的那間新倒閉的新創,主力產品就是電商推薦引擎。他做了一整年,學了不少,然後公司倒了,他被裁了。這種事在這行不稀奇。

「工期的預估是多久?」他問。

「以 B 級優先的話,我們抓三到四週。如果需要更久,到時候再談。」

「付款條件跟信裡寫的一樣?」

「對。三成預七成結,看結案報告。」

哲維想了一下。三到四週的工作量、報酬還可以、是他擅長的領域。他不喜歡掛在大公司底下做事,但外包可以保持距離——他交東西、他們付錢,沒有 office politics,沒有 stand-up meeting。

「好。」他說。「NDA 跟合約可以先寄過來嗎?」

「馬上寄。簽完之後我會幫你開權限,到時候就可以開始看了。」蘇薇點了一下頭。「另外,如果你在排查的時候看到什麼不確定的東西,隨時找我。我不希望你花時間在我們沒有授權的範圍裡。」

這句話很正常。每一個客戶都会说类似的话。哲維只是點了頭。

「那我們保持聯絡。」蘇薇說完,很快就退出了通話。

哲維的螢幕回到自己的桌面。桌布是一張他不知道什麼時候下載的預設圖片——一個藍色的星球,不知道是地球還是什麼。他看著那個藍色的圓想了一下,然後打開瀏覽器開始準備其他案子的東西。

他的手機震了一下。是那個之前合作過的工程師回了他的報價詢問,寫了數字。他看了一眼,比自己預期的多了一成,还行。他回了一個 OK。

然後他把蘇薇那邊的事情排進了接下來的行事曆。週三簽 NDA,週四拿到權限開始看數據。

他把行事曆關上,去倒了一杯水。窗外的陽光打在那個壞掉的「米七」招牌上,看起來比較亮了一點。

他不知道這案子會花多久。也不知道蘇薇看到的那些數據到底有什麼不自然的地方。那些「決策迴圈」是 bug,這基本上不可能是别的。他在這一行做了幾年——系統永遠在出問題,問題永遠能debug,debug完就結案,結完就收錢。這就是外包工作的全部。

他回到電腦前,把那碗放在水槽裡两天了的泡麵碗洗了。


NDA 和合約在隔天的信哲裡躺好了。蘇薇的效率沒話說。

哲維把合約讀了一遍。NDA 的部分比一般的外包案多了一些——不只是程式碼和商業機密,還包括了在合作過程中接觸到的「系統數據、使用者行為分析、與任何未公開的產品訊息」。違約賠償的金額比他之前簽過的都高。但和盟是這種規模的公司,他們簽的外包案大概每一份都這樣。

他簽了名,把文件寄回去。

再隔天,他的信箱裡多了一封系統通知:他的外包開發者帳號已經被開通,權限範圍是「推薦引擎 7.2 — 持續整合模組 — 唯讀 access,log and metrics dashboard」。他點進去,看到了一個乾净的介面。和盟的內部工具設計得比大多數公司都好。

數據 dashboard 上有一排圖表:每日活躍使用者數、推薦點擊率、轉換率、跳出率。紅紅綠綠的線整整齊齊,像某種儀器的讀數。

蘇薇說的那千分之三,在地圖上看不到。規模太小了,被整體數據稀釋掉了。他需要把過濾條件調出來,才能看到那一小群孤僻的使用者在哪。

哲維把視窗縮小,又看了一眼整體數據。推薦點擊率 1.2% 的提升,停留時間 0.8% 的增加。和盟的數百萬——不,數十億使用者乘以這些百分比。每一個小數點後面都是巨大的商業價值。

他想到 Hacker News 上那篇文章的標題。「你以為你在選擇,其實演算法在幫你選。」

他搖了搖頭,把過濾條件打開。

前三天是暖身。

哲維把蘇薇給的文件全部讀完,然後花了兩個晚上摸清楚數據 dashboard 的結構。和盟的工具做得好,但權限管理很細——他能看到的東西被限制在「持續整合模組」的範圍裡,看不到其他產品線的數據。合理。外包工程師不該看到全部。

他把「決策迴圈」的使用者群組過濾出來。0.3% 的活躍用戶,大概八百多萬人在過去八十多天裡出現了高度一致的行為模式。

他從最基本的維度開始看:年齡、地區、消費分級、使用頻率。這幾個維度的分布很平均——就像蘇薇說的,沒有特定族群集中。二十歲的和五十歲的都有,台北的和紐約的和奈洛比的都有。如果這是 filter bubble,它的覆蓋方式不應該這麼隨機。

他做了一個交叉分析:這些使用者的行為一致性的「起始點」是在什麼時候出現的。

結果是這樣的——他們不是一開始就出現異常的。每個人變成「迴圈」的時間點不同,沒有週期性,沒有跟特定事件(促銷、更新、節日)的關聯。就是隨機的某一天,這個人開始反覆做同一個選擇。

他想到一個比喻:某個人走進一間餐廳,每天都點同樣一道菜。這不奇怪——很多人都有自己的固定選擇。但奇怪的是,你不知道為什麼他偏偏從這一天開始固定了。沒有換菜單、沒有漲價、沒有朋友推薦。就是某一天,他就固定了。

他把這個想法寫進了自己的備忘錄。不是報告格式,只是他的工作筆記。他用這個方式整理思緒。

第三天的晚上,他開始看個體層面的數據。和盟的 dashboard 允許他點進單一使用者的行為路徑,但看不到個人身份資訊——只有編號。他隨機抽了幾個「迴圈」群組裡的使用者來看。

第一個:32 歲女性,居住地區顯示為東南亞,消費分級中等。她的迴圈出現在六十三天前。在那之前,她的行為模式很正常——會瀏覽不同類別的商品、偶爾點擊推薦、有時買有時不買。六十三天後的某一天,她開始反复點擊同一個推薦位置——排序第三位的商品。不一定是同一個商品,但一定是同一個位置排序。她買了其中大約六成。

哲維把她的行為路徑截圖存了下來。

第二個:45 歲男性,北美,高消費。他的迴圈是四十一天前開始的。模式不一樣——他不是固定點哪個位置,而是固定了購物的時間和品類。每週三晚上,買同一類型的電子產品配件。金額差不多、品類差不多、品牌會換但價位帶固定。

第三個:19 歲,東亞,低消費。二十八天前開始迴圈。固定在使用 APP 的首頁待超過十二分鐘,然後直接點選最上面那個推薦內容,從不往下滑。

他看了十幾個案例。每個人的「迴圈」表現形式不一樣,但有一個共同點:他們的行為在特定時間點之後,變得極為規律。

真正的 bug 不是這樣運作的。推薦權重衰減导致的 filter bubble 是漸進的——你慢慢看到的東西愈來愈窄,不會是某一天突然固定住。而且他看過這些使用者在「迴圈」之前的行為數據,他們的推薦權重參數是正常的,沒有異常的衰減曲線。

他在螢幕前坐了很久。

然後他做了一件不在工作範圍內的事。

他把這些「迴圈」使用者的數據,跟整體使用者的數據做了一個比較分析。具體來說,他想看看:在這些人開始出現迴圈的當天,系統的推薦輸出有沒有什麼變化。

結果是有的。但不是一致的變化。有些人收到的推薦排序變了、有些人收到的價格帶微幅調動、有些人收到的內容類別收窄了。變化的方向不一樣,但時間點完全對齊——就是他們各自出現迴圈的同一天。

哲維靠回椅背,看著天花板。

這不是衰減。這不是 filter bubble。

這是有人在對這些使用者做測試。

天花板上有一條細長的裂紋,從燈座旁邊延伸出來,像一條河。他搬進來的時候就在了,他不確定這條裂紋有沒有變長。

他把分析結果存了下來,但沒有寫進要交給蘇薇的報告裡。

他拿起手機想了一下,然後放下了。

不是bug。

但他還不確定這是什麼。在搞清楚之前,他不想讓蘇薇知道他在看超出工作範圍的東西——她那句話「隨時找我」和「不要花時間在沒有授權的範圍」是同一件事的正反兩面。

他把備用電源的線拉過來插在筆電上,繼續看數據。

螢幕上的紅線和綠線穩定流動著。整體數據還是漂亮的——CTR、轉換率、停留時間全部在目標範圍內。這一小群八千多萬的「迴圈」使用者被淹沒在幾十億的正常數據裡,像一粒沙子掉進沙灘。

哲維把地圖維度打開。這些使用者在哪裡——全球分佈。然後他把另一個圖層打開:他們使用的服務類別。

不只是消費。

他本來以為決策迴圈只出現在電商推薦場景。但他看清楚了之後發現不是——有交通路線推薦、有新聞內容推薦、有社交動態排序。不同類別的使用者,但模式一樣。都是某一天開始,行為變得高度一致。

他把地圖和行為類別圖層重疊在一起,盯著看了很久。

這不是在優化推薦。

這是在測試一件事:系統能在多大程度上,讓一個人在不知不覺中,反覆做同一個決定。

哲維把筆電蓋上了。

房間裡突然變得很安靜。冰箱在廚房那邊有微微的嗡嗡聲。窗外的巷子有摩托車的聲音經過,然後又沒了。

他又把筆電打開,看著那個蓋上去之前最後停留的畫面:地圖上散落的小點,每小點是一個被測試的人。紅色的點、藍色的點、綠色的點,代表不同的服務類別。它們散佈在整張地圖上,沒有群聚,沒有邏輯。

唯一共同的是:每一個點,都是某一天突然出現的。

他在備忘錄裡打了一行字:「這不是 bug。是 feature。」

然後他刪掉了。重新打了一行:「——看起來像 A/B test。但測試什麼?」

他存檔,關掉數據 dashboard。

拿起手機的時間是凌晨兩點十七分。他看到若晴的名字,光標在對話框裡閃了一下。他沒有點進去,把手機翻身放在床上。

天花板上那條裂紋的形狀,看起來像某種他看不懂的語系。他這樣想著,最後就睡著了。

5885 字 •