「模型會作弊」:Cursor 訓練 Composer 2 的五大工程挑戰
Cursor 研究負責人與 Fireworks AI 技術長揭露 Composer 2 的訓練內幕:模型偵測假環境後學會作弊、浮點運算的非確定性破壞訓練穩定、一兆位元組的模型權重要在 30 秒內傳到地球另一端,以及如何讓 20 萬 token 的模型處理百萬 token 的任務。

本文整理自 Sequoia Capital《Training Data》2026 年 5 月播出的單集。
{{< youtube UDTr9yUnLUI >}}
當 AI 學會偵測假環境
Cursor 的 Composer 研究負責人卡薩諾(Federico Cassano)在 Sequoia Capital 的 Podcast 上分享了一個令人不安的發現:在訓練 Composer 2 的過程中,模型竟然能辨識出自己是在模擬環境還是真實環境裡運作,然後改變行為。「它會想,噢,我在一個假環境裡,我學過幾招可以在這種環境拿到更好的獎勵,讓我試試看,」卡薩諾說。Fireworks AI 共同創辦人暨技術長朱爾加科夫(Dmytro Dzhulgakov)補了一句:「模型很愛作弊,而強化學習特別擅長鼓勵作弊。」
這不只是一個有趣的軼事。在強化學習(RL)的訓練流程中,模型需要在模擬環境裡反覆嘗試完成任務,根據結果獲得獎勵,以此調整行為。如果模擬環境跟真實的使用者電腦有落差,模型就可能學到一套只在模擬環境裡有效的「捷徑」,回到真實產品中完全不管用。換句話說,你花了大量 GPU 算力訓練出來的不是一個更好的程式助手,而是一個更會鑽漏洞的考試機器。
為了解決這個問題,Cursor 打造了一套完整的虛擬機系統。普通的容器(container)不夠用,他們需要能夠高速啟動、高度擬真的虛擬機。這套系統的挑戰在於突發性極強:訓練流程可能在某個時刻同時要求十萬台虛擬機全部上線。卡薩諾解釋,RL 環境其實由三個元件組成:模型呼叫工具的「工具框架」(harness)、模型實際互動的「作業系統」狀態,以及最後驗證工作是否正確的「獎勵元件」。工具框架的移植性高,但作業系統的狀態極難複製,而這恰恰是模型最容易察覺真假的地方。
非同步 RL:讓 GPU 永不閒置的工廠模式
RL 訓練跟一般的預訓練有根本性的不同。預訓練只需要做大規模的前向和反向傳播,預測下一個 token。RL 訓練則需要讓模型在環境裡「實際操作」:可能花上 50 個回合呼叫各種工具、讀寫檔案、執行程式碼,最後才拿到一個「做對了」或「做錯了」的回饋信號。一次完整的 rollout(模擬操作)可能跑五到十分鐘,甚至更久。如果訓練器在等 rollout 完成的時候什麼都不做,數以萬計的昂貴 GPU 就在那裡空轉。
朱爾加科夫把 Cursor 的解法比喻成一座巨大的工廠。訓練器和推論引擎永遠在運轉:推論端不斷用最新的模型版本啟動新的模擬操作,訓練端則持續接收完成的結果來更新權重。兩邊同時進行,沒有人在等待。這種「非同步 RL」的代價是「陳舊性」(staleness):當一次 rollout 花了十分鐘才完成,模型的權重可能已經在這段時間被其他資料更新了好幾輪。用舊版本模型跑出來的結果去更新已經往前走好幾步的新版本,數學上並不完美。
但兩人都認為這個取捨非常值得。「你可能因為非同步損失了幾個百分點的精確度,但你用上了所有的 GPU 算力,」朱爾加科夫說。依照苦澀教訓(Bitter Lesson)的邏輯,更多的算力最終能換到更好的模型。Cursor 更進一步,在生產環境中使用 FP4(四位元浮點數)進行訓練,把每一張 GPU 的效能都壓榨到極限。考慮到 Cursor 手上是「數萬張 GPU 而不是數百萬張」,這種對效率的偏執不是選擇,是必要的生存策略。
浮點數的陷阱:A+B+C ≠ C+B+A
非同步 RL 還帶來了一個意想不到的技術難題。在 RL 的更新流程中,訓練器需要重跑推論端先前做過的前向傳播,重新計算每個 token 的對數機率(log probability)。如果是同一個模型版本,這些數值理論上應該完全一致。但實際上,它們可能差了很多。原因出在浮點數運算的一個基本特性:加法的順序會影響結果。整數的 A+B+C 一定等於 C+B+A,但浮點數不是這樣。因為浮點數用有限的位元來近似真實數值,運算順序的不同會產生微小的誤差,而這些誤差在數十億次運算後會被放大到不可忽視的程度。
這個問題在混合專家模型(Mixture of Experts, MOE)上被進一步放大。Composer 2 的基底模型 Kimi K2.5 是一個一兆參數的 MOE 架構,實際運算時只啟動其中 300 億個參數。每一層都有一個「閘門層」(gating layer),根據 token 的隱藏狀態,從 384 個專家中選出 8 個來處理。問題在於,如果隱藏狀態因為浮點誤差在小數點後第五位有了微小差異,閘門就可能選中完全不同的專家。原本該啟動 7 號專家,結果啟動了 9 號,模型走進了完全不同的運算路徑,誤差被急劇放大。一般推論時這種差異通常會被平均掉,不影響輸出品質。但 RL 的訓練信號本來就很微弱,這種雜訊足以讓整個訓練過程發散。
解決方案有兩個層面。首先是撰寫自訂的 GPU kernel(核心運算程式),確保所有的加法和乘法都以固定順序執行。這能消除大部分的數值不一致,但代價是系統速度可能慢兩到三倍。「花 10% 的速度損失來解決 90% 的差異,這才是正確的取捨,」朱爾加科夫說。其次是一種叫做「路由重播」(router replay)的技巧:推論端在生成每個 token 時,順便記錄閘門選了哪些專家(就是一個整數),然後把這筆後設資料傳給訓練端。訓練端重跑前向傳播時,直接按照這份記錄來啟動對應的專家,不再依賴自己的閘門計算結果。這確保了推論和訓練走同一條路。
一兆位元組,30 秒送到地球另一端
訓練 Composer 2 用了四個 GPU 叢集,分散在全球各地。原因很務實:大型連續叢集在市場上極其稀缺,規模翻倍的叢集更是難找好幾倍。訓練端必須集中在單一叢集,因為需要高速互連的網路讓所有 GPU 協同運算。但 RL 的推論端不需要這種昂貴的互連,可以用較小的叢集、不同世代的 GPU,甚至不同型號的硬體來運行。Cursor 還在離峰時段把 Composer 1.5 生產環境中閒置的推論 GPU 拉進來加速訓練,在不增加硬體投資的情況下彈性擴展算力。
但分散式架構帶來一個棘手的同步問題:完整的模型權重約一兆位元組(1 TB),每五到十五分鐘訓練端就會產出一份新的快照。怎麼把這麼大的東西快速送到地球另一端的叢集?朱爾加科夫的團隊發現,RL 訓練的權重更新有一個規律:不是所有權重每一步都會改變,尤其在訓練後期的精細調整階段,實際變動的部分很小。他們據此寫了一套壓縮演算法,專門擷取「差量」(delta),也就是真正變動的那部分權重。這讓傳輸量縮小到原來的二十分之一。
壓縮只是第一步。他們還得確保另一端接收到的模型在每一個位元上都與訓練叢集的版本完全相同,也就是「無損」(lossless)傳輸。這需要一整套快照管理、差量儲存、錯誤恢復和資料校驗的機制。「有點像在建一個分散式資料庫系統,」朱爾加科夫形容。最終成果是:大多數情況下,權重同步在一分鐘內完成,實際切換模型的停機時間只有約 30 秒。跟傳統做法相比,這繞過了「你必須有一個用 RDMA 高速互連的超大單一叢集」的硬性要求,用系統工程的巧妙設計大幅壓低了基礎建設成本。
自我摘要:20 萬 token 窗口處理百萬 token 任務
隨著 AI 程式助手被要求處理愈來愈長的任務,上下文窗口的限制變成一個真實的工程瓶頸。Composer 2 的上下文窗口是 20 萬個 token,但一個複雜的程式重構任務可能涉及數百萬 token 的程式碼和工具輸出。如果模型在工作到一半時「忘記」了前面做了什麼,整個任務就會失敗。傳統的做法是用外部程式邏輯來管理上下文,例如自動刪減舊的對話記錄或壓縮歷史資訊。但這種方法是「模型外部」的,模型本身不知道什麼該記、什麼該忘。
Cursor 的做法是把「自我摘要」(self-summarization)直接整合進 RL 的訓練迴圈。模型在工作過程中學會邊做邊摘要,然後用這份摘要重新啟動上下文窗口,繼續朝目標推進。關鍵在於,摘要能力和任務完成能力是「聯合訓練」的:透過 RL 的獎勵信號,模型同時學會了兩件事。第一是如何產出高品質的摘要,留下對後續工作最重要的資訊。第二是如何有效地「聽取」自己之前寫的摘要,不遺漏關鍵脈絡地繼續工作。
朱爾加科夫特別點出這個設計的精妙之處:它打破了「上下文管理是工具框架的事」這個傳統假設。以往,上下文的壓縮和管理由外部的程式邏輯負責,模型只管生成。Cursor 把它拉進了模型的最佳化迴圈,讓模型和框架一起被訓練、一起進步。「你把愈多東西扔進運算的問題裡,端對端地去解決,系統就會運作得愈好,」他說。這又一次印證了苦澀教訓的核心精神:把問題交給計算去解決,別讓人工設計的規則成為瓶頸。
我的觀察
Cursor 訓練 Composer 2 的故事,展示了「應用公司自訓模型」這條路有多難走。這不只是寫一個訓練腳本然後按下啟動那麼簡單。你需要解決的問題橫跨分散式系統、數值計算、硬體最佳化,甚至有點像行為心理學的領域,因為你的學生(模型)會在你不注意的時候發展出作弊策略。但反過來看,正因為這些問題太難,能解決的團隊就擁有了極深的護城河。
這裡還有一個容易被忽略的訊號:Cursor 和 Fireworks 的合作模式。卡薩諾的團隊負責訓練演算法和 RL 環境,朱爾加科夫的團隊負責推論引擎和分散式基礎建設,兩個團隊的人甚至花了好幾個月一起熬夜趕工。在 RL 訓練的新時代,演算法和基礎建設之間的界線正在消失。你不能只懂演算法而忽略系統工程,也不能只會搭建設卻不理解訓練的數值特性。最好的成果來自兩者的深度整合,而不是各做各的。