最近我重新投入了許多心力在創作,這主要歸功於大型語言模型(LLM)。我曾以為我喜歡程式設計,但後來發現我喜歡的是「創作」,而程式設計只是達成這個目標的一種方式。自從 LLM 在程式設計方面變得越來越強大,我便 nonstop 地利用它們來創作,而我們正處於一個全新未探索領域的開端,這點令人非常興奮。

目前關於 LLM 有許多爭論,但有幾位朋友詢問我的具體工作流程,所以我決定詳細寫下來,希望能幫助他們(以及你)比以往更輕鬆、快速且高品質地進行創作。

文末我也包含了一個真實的(附註解的)程式碼撰寫過程。如果你想跳過工作流程的細節,可以直接前往那裡。

有史以來第一次,大約在 Codex 5.2 發布時(感覺像是一個世紀以前),以及最近的 Opus 4.6,我驚訝地發現,我現在可以用 LLM 撰寫軟體,且缺陷率非常低,可能遠低於我手寫的程式碼,同時又不失對整個系統運作方式的理解。在此之前,程式碼在兩三天後很快就會變得難以維護,但現在我已經連續數週不間斷地進行幾個專案,程式碼行數已達數萬行,且每次變更都與第一次一樣可靠。

我也注意到我的工程技能並未變得毫無用處,只是轉移了方向:我不再需要知道如何正確編寫程式碼,但理解如何正確架構系統,以及如何做出正確的選擇來創建有用的東西,現在變得至關重要。

在我不了解底層技術的專案(例如行動應用程式)中,程式碼仍然很快就會變成糟糕選擇的集合。然而,在我熟悉所用技術的專案中(例如後端應用程式,但不一定是 Python),即使程式碼行數達到數萬行,這種情況也尚未發生。這很大程度上歸因於模型的進步,但我認為也有很大一部分是我改進了與模型互動的方式。

我注意到的一點是,不同的人從 LLM 獲得的結果差異很大,所以我懷疑你與它們溝通的方式會影響結果。因此,我將在這篇文章中深入探討細節,甚至發布實際的對話記錄,以便你能看到我開發的所有細節。

還有一點值得一提的是,我不知道模型未來會如何發展,但我注意到一個趨勢:在 LLM 的早期(GPT-2 比較有限,但從 davinci 開始),我必須審查每一行程式碼並確保其正確性。隨著後續幾代 LLM 的出現,這種檢查層級提升到函數層級,所以我不需要檢查程式碼,但需要檢查函數是否正確。現在,這主要是在「通用架構」層級,也許未來(明年)連這也不再需要。但目前為止,你仍然需要一個具備良好程式設計技能的人。

我最近建造了不少東西,我想在此列出其中一些,因為對 LLM 的一個常見批評是人們只用它們來寫玩具腳本。這些專案從日常使用的實用工具到藝術專案都有,但它們都是我每天都在使用、維護的真實專案:

我最近建造的最大項目是 OpenClaw 的替代品,它更注重安全性。我多年來一直想要一個 LLM 個人助理,終於透過這個項目實現了。在這裡,大多數人會說「但你無法讓 LLM 變得安全!」,這是一種誤解,安全是關於權衡的,而我的代理程式試圖做的是在給定的可用性下最大化安全性。我認為它做得非常成功,我已經使用它一段時間了,並且非常喜歡能夠精確地推理出它能做什麼、不能做什麼。

它管理我的日曆,並智能地決定我的可用性或任何衝突,為我進行研究,透過編寫程式碼來擴展自身功能,提醒我所有我過去會忘記的事情,並自主管理家務等。助理的好處很難解釋,因為它們沒有一個殺手級功能,但它們能緩解一千個小麻煩,而這些麻煩對每個人來說都不同。因此,試圖向某人解釋擁有助理有多好,最終會得到「但我不需要你需要的任何東西」的反應,這忽略了每個人都需要不同東西的觀點,而一個能夠存取工具並做出智能決策來解決問題的代理程式對任何人來說都是巨大的幫助。

我計劃很快更詳細地介紹這個項目,因為在設計它時遇到了一些非常有趣的挑戰,而且我喜歡我解決它們的方式。

也許我最近的命名不太出色,但這是一個記錄語音筆記的小掛件,它會轉錄語音,並可選擇性地將其 POST 到你選擇的 webhook。我讓它將語音筆記發送到我的 LLM,隨時隨地拿出這個小裝置,按下按鈕,錄下想法或提出問題,然後下次查看助理訊息時就能得到答案或待辦事項,這種感覺很棒。

這是一個簡單的東西,但它的實用性不在於它做了什麼,而在於它做的方式。它始終可用,始終可靠,並且使用起來毫無摩擦。

我也計劃寫一篇關於這個的介紹,但這個更像是一個藝術品:它是一個滴答作響的掛鐘,秒針的滴答聲不規則,但總能準確到分鐘(時間透過網路同步)。它有多種模式,一種模式的滴答聲間隔在 500 毫秒到 1500 毫秒之間變化,這令人愉悅又惱人。另一種模式的滴答聲比一秒略快,但會隨機暫停一秒,讓不知情的觀察者懷疑自己的理智。另一種模式以雙倍速度奔跑到 :59,然後在那裡停留三十秒,最後一種模式則是一個正常的時鐘,因為所有不規則的滴答聲讓我抓狂。

Pine Town 是一個異想天開的無限多人畫布,像一片草地,你可以在上面擁有自己的一小塊土地進行繪畫。大多數人畫的是……有問題的內容,但偶爾會有人畫出一些不錯的東西。有些畫作是真正的瑰寶,四處滾動看看人們的作品通常很有趣。

我用 LLM 完成了所有這些專案,甚至沒有讀過其中大部分的程式碼,但我仍然對每個專案的架構和內部運作非常熟悉。方法如下:

對於框架,我使用 OpenCode。我非常喜歡它的功能,但顯然還有很多其他選擇,我也曾與 Pi 有過不錯的經驗,但無論你使用哪個框架,它都需要讓你能夠:

根據你的專案和技術堆疊,可能還有其他不錯的功能,例如會話支援、工作樹管理等,這些都取決於你。我將解釋上述兩個要求以及它們為何必要。

你可以將一個特定的模型(例如 Claude Opus)視為一個人。當然,你可以從一個乾淨的上下文重新開始,但模型大多會保有之前的觀點/優勢/劣勢,並且很可能會同意自己。這意味著要求模型審查它剛寫的程式碼是相當無用的,因為它傾向於同意自己,但這也意味著讓不同的模型審查程式碼會帶來很大的改進。本質上,你獲得的是第二雙眼睛的審查。

不同的模型在這裡會有不同的優勢和劣勢。例如(這非常針對當前的模型),我發現 Codex 5.4 非常挑剔和迂腐。這不是我想要在編寫程式碼時的特質,但絕對是我在審查時想要的。Opus 4.6 的決策與我會做出的決策相關性很高,而 Gemini 3 Flash(是的,Flash!)甚至在提出其他模型未曾想到的解決方案方面表現出色。

每個人對哪個模型適合哪個工作都有不同的看法,而且模型會輪流使用(例如,我在 11 月份使用 Codex 作為我的主要模型,之後又切換回 Opus)。要獲得最佳結果,你需要混合使用它們。

我使用的流程由不同的代理程式組成,如果框架無法讓代理程式互相交流,你將會花費大量時間在 LLM 之間傳遞資訊。你可能想減少這種情況,所以這是一個非常有用的功能。

我的工作流程包含一個架構師、一個開發者,以及一到三個審核者,具體數量取決於專案的重要性。這些代理程式被配置為 OpenCode 代理程式(基本上是技能檔案,包含我希望每個代理程式如何運作的指令)。

我使用多個代理程式(而不是只用一個處理所有事情)有三個原因:

我不認為使用兩個具有相同模型和相同功能的代理程式有太大意義,因為我認為這就像一個人假裝戴著不同的帽子,但我沒有對此進行廣泛研究。

我也傾向於手動編寫技能檔案,因為我發現要求 LLM 編寫技能檔案並沒有真正幫助。這就像要求某人寫一份如何成為優秀工程師的說明,然後給他們自己的說明,並說「這就是如何成為優秀工程師,現在就去做吧」。這顯然不會讓他們變得更好,所以我試圖自己編寫說明。

如果你想親自嘗試,可以下載我的代理程式檔案。

架構師(目前是 Claude Opus 4.6)是我唯一互動的代理程式。這需要是一個非常強大的模型,通常是我能取得的最強大的模型。這個步驟不會消耗太多 token,因為它主要是聊天,但你需要它非常有條理。

我會告訴 LLM 我的主要目標(這將是一個非常具體的特徵或錯誤修復,例如「我想為 Stavrobot 添加帶有指數退避的重試機制,以便在 LLM 提供者離線時重試」),並與它交談,直到我確定它理解我的需求。這個步驟需要最多的時間,有時甚至長達半小時的來回溝通,直到我們確定所有目標、限制和方法的權衡,並就最終架構的外觀達成一致。最終會產生一個相當低層次的計劃,包含個別檔案和函數的詳細程度。例如,任務可能是「我將在該檔案的這兩個組件的這三個程式碼路徑中添加指數退避,因為沒有其他組件與 LLM 提供者通訊」。

我知道在這個步驟中,有些人更喜歡讓 LLM 將計劃寫入檔案,然後他們將反饋添加到該檔案中,而不是與 LLM 交談。這是一個個人偏好的問題,因為我可以看到兩種方法都同樣有效,所以如果這種方式更適合你,請隨意進行審查。個人而言,我更喜歡與 LLM 聊天。

澄清一下,在這個步驟中,我不僅僅是在提示,我是在 LLM 的幫助下塑造計劃。我仍然需要糾正 LLM 很多次,無論是因為它錯了,還是僅僅因為它沒有按照我想要的方式做事,這也是我的主要貢獻之一,也是我感到快樂的部分。這種方向讓我能夠稱這些專案為「我的」,因為如果其他人使用相同的 LLM,他們會得出不同的結果。

當我確信我們已經解決了所有問題(LLM 在這方面非常有幫助,會提出它還不知道的問題並給我選項)後,我終於可以批准計劃。我要求架構師在我實際說出「批准」這個詞之前不要開始任何事情,因為有些模型傾向於過於積極,一旦覺得自己明白了就開始實施,而我希望確保我對它是否理解感到自信。

然後,架構師會將工作分解成任務,並將每個任務寫成一個計劃檔案,通常比我們的聊天內容更詳細(且層級更低),然後調用開發者開始工作。這為開發者提供了具體的方向,並最大限度地減少了開發者可以做出的高層次選擇,因為這些選擇已經為它做好了。

開發者可以是一個較弱、更節省 token 的模型(我使用 Sonnet 4.6)。計劃不應給它太大的自由度,它的工作是嚴格執行計劃中的變更。完成後,它會回報給架構師,架構師再調用審核者來審查工作。

每個審核者將獨立查看計劃和剛實施的功能的 diff,並進行批評。在這個步驟中,我總是至少使用 Codex,有時會加入 Gemini,對於重要的專案,我還會加入 Opus。

這些反饋會回到架構師那裡,架構師判斷這些反饋是否應該被解決,或者是否足夠瑣碎可以忽略。我發現 Opus 在選擇正確的反饋來實施方面做得很好,有時會忽略一些反饋,因為它們過於迂腐(即難以實施且在實踐中不太可能成為問題)。顯然,當我使用「非常好」這樣的客觀評估時,我實際上是指「我非常同意它」。

這種工作方式意味著我仍然知道所有高於函數層級的決策,並可以在後續的運行中使用這些知識。我經常注意到 LLM 推薦的東西在其他程式碼庫中可能很好,但在我的程式碼庫中卻無法工作或不是最佳選擇,這表明 LLM 在研究程式碼時存在一些盲點。我經常會說「不,你應該使用 Y 來做這件事」,這時 LLM 就會意識到 Y 實際上存在於程式碼中,並且比它推薦的方式更好。

另一方面,當我對技術不夠熟悉,無法掌握架構時,我傾向於無法發現 LLM 做出的一些糟糕決策。這會導致 LLM 在這些糟糕決策的基礎上越建越多,最終陷入無法理清混亂的狀態。當你不斷告訴 LLM 程式碼不起作用,它卻說「我知道為什麼!讓我來修復它」並不斷讓事情變得更糟時,你就知道這種情況發生了。

這是我過去遇到過太多次的真實失敗模式,這也是我最終採用這種工作流程的原因。因此,即使我不熟悉特定技術,我也會盡量在規劃階段盡可能多地理解事物。如果我能很好地引導 LLM,就能節省以後很多麻煩。

這是一個真實會話的註解記錄,我在其中為 Stavrobot 添加了電子郵件支援。我已刪減了工具調用和冗長的內容,但對話和決策過程與實際發生的完全一致。

我首先告訴 LLM 我想實現什麼,這是一個非常高層次的目標。有時我會給它更多細節,特別是如果我已經有了實施想法。

機器人讀取程式碼並找到所有相關部分,然後提出一些問題。

在這個會話中,我只提出了一個還未完全想好的想法。LLM 透過提出具體問題來提供幫助,我決定實施的方向:

LLM 塑造了計劃,並增加了更多細節:

我回覆了一些我認為它遺漏的東西。這需要我對架構有深入了解,並遵循這個過程可以讓我了解中低層級的所有變更。

LLM 更新了計劃並提出任何最終問題。

有時我會想起一些事情,並在閱讀它的訊息之前告訴 LLM:

它透過納入我的擔憂並重複其訊息來適應。

我確實回去閱讀了它的訊息,因為它通常有很好的問題,我不想錯過回答任何一個。

LLM 需要我明確說出「批准」這個詞才能繼續。

LLM 在工作時我突然想起一件事,並暫停它來詢問:

LLM 編寫了計劃,調用了開發者、審核者,最終完成了。為了簡潔起見,我省略了所有後端的工具/代理程式調用。

我有一個想法,可以透過允許機器人讀取傳入的電子郵件而不配置 SMTP 伺服器來改善使用者體驗,以防使用者想轉發發票或行程計劃讓它讀取,但又不想讓機器人能夠發送電子郵件。

LLM 評估了工作量。如果是一個小變更,我通常會在此次會話中完成,否則我會將其寫入 GitHub issue 以供日後處理。

我對功能進行 QA 並回報問題:

LLM 前往修復問題。

在這裡我發現它錯過了一個更好的實現功能的方法,我建議它更改實現方式:

我對讓檢查通用化產生了疑慮,因為有特殊情況。

LLM 思考了一下,並提出了一個合理的建議。

我進行 QA 並再次檢查。我意識到電子郵件的處理方式與電話號碼略有不同,機器人現在會忽略我的自定義電子郵件地址。我與 LLM 討論了添加此功能:

LLM 誤解了我的意思,所以我用一個具體的用例來澄清:

我要求它確保小心處理一個注意事項。

並要求進行一些文件變更。

我要求進行澄清以避免潛在的陷阱:

會話繼續了一段時間,我進行了更多的 QA 回合,添加了電子郵件地址的萬用字元匹配,一個關於 SQLi 的問題,以及捕獲了子代理程式允許清單中遺漏的條目。對話大致與上述情況類似,我不是發現錯誤就是提出改進,與 LLM 一起完善,然後實施。

整個功能從開始到結束大約花費了一個小時,我對功能的良好運作感到滿意,因此結束了會話。

這就是我的基本設置概覽。它沒有什麼特別花哨的地方,但對我來說效果非常好,而且我對整個過程的可靠性感到非常滿意。Stavrobot 已經 24/7 全天候運行了近一個月,而且一直非常可靠。

如果你有任何反饋或只是想聊天,可以在 Bluesky 上找到我,或直接發送電子郵件給我。