如果有一天,一段由 AI 編程工具寫的純粹程式碼——沒有神經網路,沒有梯度下降,沒有任何「訓練」——卻在經典遊戲裡打出了理論最高分,在機器人控制裡跑出了媲美深度強化學習(Deep RL)的成績,你會怎麼解釋這件事?
這不是科幻設定,而是 OpenAI 研究工程師翁家翌(Jiayi Weng)最近在一篇部落格文章裡記錄的真實實驗。他本來只是想為遊戲測試寫幾條便宜的小規則,結果弄出了一套連他自己都感到震撼的東西。他因此重新審視了一種長期被低估的方法——啟發式規則(heuristics),認為它可能正在迎來屬於自己的時代。
手寫規則本身不是新東西。專家系統幾十年前就有了,問題也是老問題:今天加一條規則修好 A,明天發現 B 壞了,後天再打補丁,最後沒人敢動了。規模一大,維護成本就把人壓垮。翁家翌的核心觀察是:程式開發代理(coding agent)改變的正是這條成本曲線。當代理能夠自動讀取日誌、看回放、改程式碼、跑測試、記錄實驗,一套手寫規則系統就第一次有了持續生長的可能——原來只能當補丁用的東西,現在開始值得長期擁有了。
這也直接觸碰到了持續學習(Continual Learning)的老問題。神經網路的災難性遺忘,根源在於舊能力只能靠參數隱式保存,新數據一來就容易被沖掉。而在他提出的啟發式學習(Heuristic Learning)框架裡,舊能力可以直接寫進回歸測試、固定種子(seed)的回放和明確的失敗記錄,歷史是顯式的、可讀的、可重構的。這不是解決了遺忘問題,而是把「防遺忘」變成一個更工程化的問題來處理。
當然,翁家翌也指出了這套方法的邊界:程式碼的表達能力終究有限,複雜感知和長程泛化還是神經網路的主場。他認為更有前景的方向是兩者結合——用啟發式系統(Heuristic System)快速處理線上數據、積累可回歸的經驗,再週期性地把這些經驗內化進神經網路。
他把這個願景總結成一句話:凡是可以被持續迭代的,都開始能被解決。這和之前幾輪範式轉移的邏輯一脈相承——從預訓練(pretrain)到 RLHF,再到大型強化學習(large-scale RL),每一步都是把「可驗證」的邊界往外推了一圈。啟發式學習,或許是下一圈。
翁家翌是 OpenAI 後訓練(Post-training)RL 基礎設施的核心工程師之一。2022 年加入 OpenAI 時,他的面試官正是 John Schulman。此後,他主導搭建了 OpenAI 後訓練階段的核心 RL 基礎設施,這套系統支撐著 GPT 系列在 RLHF、對齊與推理優化階段的訓練迭代。
以下是翁家翌的部落格《Learning Beyond Gradients》原文,機器之心經授權轉載:
原文連結:https://trinkle23897.github.io/learning-beyond-gradients/
持續學習一直難以被解決,主要卡在神經網路的災難性遺忘:學了新東西,舊能力就容易被沖掉。那如果不把目光只放在神經網路權重上,還有沒有其他解決方案?
隨著大型語言模型(LLM)代理變強,程式開發的速度和品質都在提升。但我最近更在意的是另一個現象:程式開發代理不訓練新網路、不更新權重,只是持續看失敗、改程式碼、加測試、看回放,也能把一套程式系統越養越強。
這讓我重新看待啟發式規則,也就是手寫規則和程式策略。過去很多啟發式規則不是沒用,而是沒人養得起;程式開發代理改變的是這條維護成本曲線。於是,過去只能當一次性補丁的規則,開始變成值得長期擁有的程式碼。
凡是可以被持續迭代的,都開始能被解決。這也是持續學習一直想要解決的問題。它會是繼預訓練、RLHF、大型強化學習/RLVR 之後的下一個範式嗎?
異常現象
在業餘時間維護 EnvPool 的時候,我想用一個便宜一點的策略來測試遊戲環境正確性,不然每次持續整合(CI)都跑神經網路,很費測試資源。
一開始的問題只是:
能不能寫一些便宜、可複現、比隨機強很多的啟發式規則,專門把環境跑到有資訊量的狀態?
我試著使用 codex(gpt-5.4)寫一個基於規則的版本,完全不依賴神經網路。沒想到弄了幾下,結果比我預期離譜很多:
一個打磚塊遊戲 Atari Breakout,策略從 387 -> 507 -> 839 -> 864,最後打到理論最高分;
一個仿真四足機器人關節控制任務 MuJoCo Ant,純 Python 程式策略先學會節律步態,再接上短視窗模型規劃,最後上了 6000+ 分,進入常見 Deep RL 結果的量級;
一個仿真機器人跑步任務 MuJoCo HalfCheetah,靠可解釋的步態/姿態規則和線上規劃,迭代到 5 局複測均值 11836.7,也進入了常見 Deep RL 結果的量級;
一整套 Atari 57 個遊戲,一共跑了 57 個遊戲 x 2 種輸入 x 3 次運行 = 342 條開發代理(coding-agent)搜尋軌跡,表現有好有壞;但在固定環境互動步數下,中位數 HNS 遊戲得分在 1M 環境步附近已經遠高於 PPO 這類 Deep RL 演算法的曲線。
這些結果第一次見到十分震撼,更讓我在意的是:codex 沒有訓練神經網路,它在維護一套還能繼續生長的軟體系統。
Breakout 策略到最後遠遠超過一句「球在左邊就往左」。這個策略長出來的是動作探測、狀態讀取、球和擋板檢測、落點預測、卡住循環檢測、回歸測試、影片回放和實驗記錄。Ant 策略也超過一條步態公式,裡面有節律控制、姿態回饋、接觸資訊、短視窗模型展開。
於是我意識到有必要在這裡創造一個新的概念:這裡被更新的對象已經不只是策略函數,而是一套帶有記憶、回饋入口和回歸機制的軟體系統。
啟發式學習(Heuristic Learning)
在接著和 codex 交流了一陣子之後,我想把這個過程定義為啟發式學習(HL):
HL 的主體由程式碼構成;
它和今天常見的 Deep RL 實踐共享狀態、動作、回饋、更新的閉環;但更新對象從神經網路參數換成了軟體結構;
它的回饋由開發代理消化,可以來自環境獎勵、測試案例(testcase)、日誌、影片、回放、人類回饋;
它的更新不走反向傳播;開發代理直接修改策略(policy)、狀態檢測器、測試、配置或者記憶體(memory);
HL 是學習和更新的過程;被 HL 長期維護的對象稱之為啟發式系統(Heuristic System,HS);
HS 超過一個孤立的 policy.py:它至少包含程式策略、狀態表示、回饋入口、實驗記錄、回放或測試、記憶體,以及由開發代理執行的更新機制。單條規則不夠,規則、回饋、歷史和下一輪更新全部接起來,才稱之為 HS。
列一個表就是:
啟發式學習相比 Deep RL 有很多良好的性質:
可解釋性(Explainability):神經網路很難解釋,HL 的程式碼策略可以翻譯成人話;
樣本效率(Sample Efficiency):一次有效程式碼更新可以直接跳到新策略,不用調學習率慢慢爬;
可回歸/可驗證(Regression-testable):舊能力可以變成測試、重播(replay)、黃金案例(golden case);
可約束過擬合:程式碼啟發式規則也會過擬合到種子、環境細節或測試漏洞,但簡化、回歸和多種子檢查可以形成一種工程正則化;
可以避免一部分災難性遺忘(Catastrophic Forgetting):舊能力不用全靠模型自己記住,可以被寫進規則集和測試裡。
重點在於,有一類原來因為維護成本太高而不值得寫的啟發式規則,現在突然可能值得長期擁有了。
為什麼啟發式學習以前沒發展起來
如果說 HL 的前身是專家系統、規則系統,那麼在開發代理沒發展起來之前,這玩意的維護成本十分高昂。
人類手工維護啟發式規則很容易變成這樣:
今天加一條規則修 case A。明天發現 case B 被修壞了。後天再加一個 if。大後天沒人敢刪了。
問題不在啟發式規則沒用,在沒人力能養得起。之前人力維護專家系統,有點像工業革命前手工紡紗:規模一大,穩定性和維護成本就壓死人。紡織機改變的是產能曲線;開發代理改變的是啟發式規則的維護曲線。它像一條可以輸送智力的營養管道,可以持續澆灌一個 HS,讓它自己迭代進化。
目前常見的代理式回饋閉環主要是:
功能請求 -> 代理寫程式碼 -> 過 test -> 人類給一點回饋 -> 下一輪補丁但隨著大型語言模型能力提升,人類介入次數會逐漸變少,這個回饋循環就有機會在某些邊界明確的系統裡自動閉合,從而能夠實現自動化用 HL 批量生產 HS:
環境回饋 / 測試失敗 / 日誌異常-> 開發代理讀上下文(context)-> 修改 policy / test / memory-> 重新運行-> 把結果寫回 trials 和 summary-> 下一輪繼續
啟發式學習怎麼做持續學習
神經網路裡的災難性遺忘,是新數據把參數往新任務推,舊能力被覆蓋掉。HL 也會忘,例如:
新規則修好了一個失敗模式,同時破壞舊場景;
新記憶體把代理反覆帶到錯誤方向;
新測試太窄,導致策略學會鑽空子;
新補丁改了公共介面,舊呼叫方悄悄壞掉;
規則越堆越多,最後代理自己也維護不動。
所以 HL 不會自動解決持續學習。它把「防遺忘」變成了更工程化的東西。
在 HL 裡,舊能力可以被固化成:
回歸測試;
固定種子的重播;
黃金軌跡(golden trace);
失敗影片;
版本差異(diff);
明確寫下來的失敗方向。
與神經網路把經驗壓進權重完全不一樣:HL 的歷史是顯式、可讀、可刪、可重構的。它負責「記住」,也負責把一堆局部補丁壓縮成更簡單的表示。
(只增長不壓縮的 HS,最後一定會變成屎山程式碼。它會「記住」很多東西,但記住的方式太差,導致誰也不敢動,從而腐化)
所以一個健康的 HS 至少需要兩個操作維持:
吸收回饋:把新失敗、新日誌、新獎勵寫回系統。
壓縮歷史:把一堆局部補丁折回更簡單、更可維護的表示。
這就把持續學習從「怎麼更新參數」變成了「怎麼維護一個持續吸收回饋的軟體系統」。
啟發式系統的複雜度
此處定義耦合複雜度為開發代理能維護多複雜的策略來支援 HL。展開說,就是一次更新必須同時照顧多少相互牽連的狀態、規則、測試、回饋和歷史。
這個量不能按程式碼行數算。一個 500 行策略,如果模組邊界清楚、測試完整、狀態可複現,可能很好維護;一個 80 行策略,如果每行都互相牽制、沒有日誌、沒有回放,也可能是個定時炸彈,一碰就崩。
朝程式碼一側看,耦合複雜度受模組邊界、介面穩定性、測試覆蓋、日誌觀測性、回滾成本和狀態可複現性限制。好的模組化會把全局耦合切成局部耦合,從而降低耦合複雜度;好的測試能讓開發代理不必每次在腦子裡模擬整個系統。
朝開發代理一側看,能接受多少耦合複雜度,取決於模型能力、上下文長度、記憶體品質、工具品質、整體迭代速度。更強的模型能夠同時處理更多相互作用;更長的上下文能讓它少丟線索;記憶體可以把跨輪次迭代經驗留下;搜尋、定位、運行、回放這些工具能夠把一部分認知負擔搬到外部。
把這兩側放一起,可以得到一組判斷:
回饋越清楚,單位代理智力能維護的耦合複雜度越高;
同等工具和回饋下,模型能力越強,能處理的耦合複雜度越高;
模組化、測試、回放會把一部分耦合複雜度轉移到環境裡;
記憶體和工具會提高代理的有效上下文;
只增長不壓縮的 HS 會讓耦合複雜度持續上升,直到超過維護能力。
Breakout 策略能走到 864 的滿分,有規則簡單的一面,也有失敗可以影片回放、局部複現、回歸驗證的一面。Ant 複雜得多,但它可以拆成節律、姿態、接觸、殘差 MPC 這些模組。
Montezuma 是一個很好的反例。Atari57 裡有一條無人值守的記錄到了 400 分,但那條路線由 86 個宏動作組成,基本是開迴路執行。這個例子說明,有些環境需要更強的程式形態,比如可組合宏動作、可恢復搜尋狀態、長期記憶體。普通的 if else 不能解決所有問題。
下一個範式?
目前的範式轉移是從最開始的預訓練,到 RLHF,再變成大型強化學習/RLVR。凡是可以驗證的,都開始能被解決。
線上學習(Online Learning)和持續學習可以被當前 RLVR 生產出來的代理式程式開發,透過啟發式學習的方式部分解決。從這個願景出發,我願稱其為下一個範式:凡是可以被持續迭代的,都開始能被解決。
為什麼說是部分解決?因為啟發式學習並不能做所有神經網路能做到的事情。它受制於程式碼的表達能力,比如複雜感知和長程泛化。比如在我目前認知範圍內,我想不出有個代理能搓出一個純 Python 程式碼、不用神經網路去解決 ImageNet。
於是問題在於如何結合神經網路和 HL,同時解決線上學習和持續學習。最有希望的方向是:用 HL 處理線上數據快速生成線上經驗,把線上經驗內化成可訓練、可回歸、可篩選的數據,再週期性更新神經網路。
以機器人為例,如果套用 System 1/2 的術語,一個可能的分工形態如下:
專用、淺層神經網路(NN):當作 System 1 的一部分,快、便宜,負責感知、分類、物體狀態估計;
HL:也可以當作 System 1 的一部分,負責最新數據處理、規則、測試、回放、記憶體、安全邊界、局部恢復;
大型語言模型(LLM)代理:作為 System 2,負責給 HL 提供回饋、改進數據,並週期性提取 HL 生成的數據來更新自身。
這套東西可以繼續拆成層級結構:
關節級 HL -> 肢體級 HL -> 全身平衡 HL -> 任務級 HL低層負責安全和低延遲控制,中層負責步態和接觸,高層負責任務、恢復和長期記憶。開發代理不一定直接「懂得走路」,它更像插進系統裡的更新管線:持續把失敗影片、感測器串流、仿真結果、測試結果餵進系統,再把回饋改寫成程式碼、參數、保護規則和記憶體。
大型語言模型代理可以共享,也可以相互隔離在機器人體內自行學習。這裡的問題是:HL 提供的特定數據分布如何才能不讓大型語言模型的週期性更新崩潰。這是一個經典的後訓練問題,已經有很多成熟經驗,由於某些原因在這裡就不展開了。
代理式程式開發改變了寫程式碼速度,也改寫了哪些程式碼值得被長期擁有。
過去很多啟發式規則看起來沒有前途,原因常常落在維護成本上;它們本身未必太弱。開發代理改變的是這條維護成本曲線。規則、測試、日誌、記憶體和補丁原來只是散落的工程材料,現在開始可以組成一個會持續更新的啟發式系統,能夠真正解決線上學習和持續學習所未能解決的問題。
歡迎來到下一個範式!
附錄:實驗過程和複現入口
完整成品倉庫(artifact repo)在 https://github.com/Trinkle23897/learning-beyond-gradients。下面命令預設你已經 clone 了這個倉庫,並在倉庫根目錄執行;GitHub Pages 只展示文章和必要靜態檔案,完整腳本、CSV、影片和實驗材料都在倉庫裡。
以下實驗中 codex 模型版本均為 gpt-5.4,最新版本模型尚未測試。以下實驗報告均由 codex 自行攥寫。
A.1 實驗過程簡述
重現入口:heuristic_pong.py。
python heuristic_pong.py \--policy ram \--episodes 1 \--seed 0
預期輸出應包含 episode=0 score=21.0 與 mean=21.000。
Breakout 864
重現入口:heuristic_breakout.py。
rm -f /tmp/repro_breakout_864.jsonl /tmp/repro_breakout_864.csvpython heuristic_breakout.py \--policy ram \--episodes 1 \--seed 0 \--max-steps 108000 \--deadband 3 \--chase-lead-steps 6 \--tunnel-offset 0 \--launch-offset 24 \--fast-ball-min-vy 3 \--fast-low-ball-lead-steps 3 \--stuck-trigger-steps 1024 \--stuck-switch-steps 256 \--stuck-offset 12 \--stuck-release-horizon-steps 8 \--brick-balance-deadzone 0.01 \--brick-balance-bias-min-score 432 \--late-game-paddle-lag-px 2 \--late-game-lag-ball-y 170 \--trial-name repro_breakout_864 \--log-path /tmp/repro_breakout_864.jsonl \--summary-path /tmp/repro_breakout_864.csv
預期輸出應包含 score=864.0 與 mean=864.000。
Ant 預設 MPC 策略
重現入口:heuristic_ant.py、ant_envpool.xml。
rm -f /tmp/repro_ant_6146_eval5.jsonl /tmp/repro_ant_6146_eval5.csvpython heuristic_ant.py \--policy mpc \--episodes 5 \--seed 0 \--max-steps 1000 \--mujoco-xml-path ant_envpool.xml \--trial-name repro_ant_6146_eval5 \--log-path /tmp/repro_ant_6146_eval5.jsonl \--summary-path /tmp/repro_ant_6146_eval5.csv
我在本機重跑時數值為 mean=6005.521、min=5776.805、max=6146.208。
HalfCheetah staged-tree MPC
重現入口:heuristic_halfcheetah_v5.py。
python heuristic_halfcheetah_v5.py \--policy mpc-staged-tree-asym-pd-cpg \--eval-episodes 5 \--eval-seed 100
我在本機重跑時,5 局平均分數為 11836.693。
Montezuma 400 分重播
重現入口:heuristic_montezuma_400_policy.py。
python heuristic_montezuma_400_policy.py \--metadata-out /tmp/repro_montezuma_400.json
預期輸出應包含 "score": 400.0 與 "env_steps": 1769。此為邊界案例,切勿將其視為通用的 Montezuma 策略。
© THE END
轉載請聯繫本公眾號獲得授權
投稿或尋求報導:liyazhou@jiqizhixin.com