我對生成式 AI 的態度非常反感。然而,在過去一個月裡,我使用生成式編碼工具完成了一個專案。它確實有效,但我討厭這樣做的過程。
先說明我的心情:我對使用生成模型的感受非常複雜。如果你現在想叫我怪物或偽君子,我理解。我正在處理這些矛盾,並完全承認我可能做了錯誤的選擇。
我的日常工作已轉型為「AI 安全專家」,不僅負責測試 AI 應用,還要成為其運作專家。我希望能在這些應用部署前盡力讓它們更安全,並對過於危險的想法大聲說「不」。但這一切都離不開對這些工具的深入使用與了解。
我也清楚這些工具帶來的社會與環境傷害,甚至知道使用它們會對認知造成危害(後面會談到)。我不想用它們,但我必須理解它們。如果這讓你看我不順眼,那就算了。
我一直在將 The Taggart Institute 從兩個商業平台 Teachable 和 Discord 遷移出來,過程中需要將新選擇的論壇軟體 Discourse 改造成類似學習管理系統。Discourse 是論壇軟體,功能強大且管理起來有趣。它大致能滿足我們的學習平台需求,除了有一項功能難以複製:課程完成證書。雖然我們政策是尊重自我評估,但學習社群仍渴望有證書。LinkedIn 是我們主要的新學員來源,而 LinkedIn 用戶總喜歡分享成就。
我認為 LinkedIn 就像數位冥河,靈魂們爭先恐後地攀爬、抓住船隻,希望能獲得救贖。但既然大家都在地獄,不如互相扶持。
Teachable 現在價格昂貴,且越來越多 AI 功能,還有一個我暫時不能透露的嚴重安全問題(敬請期待!),它有一個非常完善的證書產生器。這是我放棄它的唯一安慰。市面上沒有現成方案完全符合我的需求,但這也給了我機會打造自己的證書產生器,甚至可能開源成為任何人都能用的公開驗證證書解決方案。
挑戰是:我已經忙於工作、遷移任務和一個新專案,最重要的是,我的空閒時間極少,因為我想當一個好爸爸,陪伴我那個了不起的幼兒。我無法像以前那樣日夜編碼,這就是人生。
所以,一方面我必須理解生成式 AI 編碼工具,另一方面我需要這個缺失的功能來完成遷移。我決定用 Claude Code 來嘗試開發這個專案。
我想,如果成功,我就有了證書解決方案;如果失敗,至少我會更了解這項技術及其影響。
結果是:它成功了。就我所知,安全性也還不錯。但天啊,用這種方式開發非常痛苦,雖然比自己全部寫程式快。
我的想法很簡單:一個 webhook 攔截器接收課程完成資訊(學生姓名、電子郵件、課程名稱),生成帶有唯一且可驗證 ID 的 PDF 證書。證書會寄給使用者,且內含 QR 碼連結到應用程式上的驗證頁面。這可以是簡單的 Python Flask 應用呼叫 shell 腳本,也可以複雜到我最後做的樣子。但我必須承認,模型在規劃過程中提出的便利建議相當吸引人,所以我決定照做。如果我後來討厭它,隨時可以砍掉重練。
開始這場冒險前,我盡量閱讀關於使用 AI 編碼工具的「最佳實踐」。我刻意避免用「vibe coding」這詞,因為我追求的不是那種隨性編碼。事實上,我得到的最重要建議是:盡可能讓模型保持專注並在預期範圍內運作。這不只是寫提示語,更是設計讓模型輸出有明確成功或失敗標準,並能追蹤自身進度與外部上下文。
Claude Code 有個「計劃模式」,這是 Anthropic 官方認為最適合用來開發新專案的方式。模型不直接寫程式碼,而是先寫計劃,這計劃成為半永久上下文,引導後續修改。每個新功能我都是這樣開始。我還讓模型輸出計劃到外部 Markdown 檔案備查(因為上下文會隨時間消失)。我也維護一個 TASKS.md 追蹤已完成與待完成功能。事實上,我在這專案中幾乎所有實際敲鍵盤時間都花在 Markdown 語法上。我很愛 Markdown,但寫給模型看而非人類,感覺不太好。
毫不意外,我選擇用 Rust 開發,不只是因為我喜歡 Rust。我熟悉這語言,能更容易發現錯誤、反模式和程式味道。更重要的是,我希望 Rust 內建的安全機制(型別安全、編譯時檢查、嚴謹測試)能幫助模型保持正軌。前端用 Svelte,一方面我一直想做 Svelte 專案,另一方面它的 HTML 類語法比 React 或 Next.js 更易除錯。
PDF 產生是我最喜歡的部分。我用 Typst 模板,透過 Typst API 生成 PDF,方便日後更換模板。我也漸漸成為 Typst 迷。
模型/編碼代理用的是 Claude Code 搭配 Sonnet 4.6。我試過 Ollama 和開源模型,但想體驗那些誓言這技術將革命化工作的開發者的感受。
為了最大化確定性,開發過程採用測試驅動開發(TDD)。從 Markdown 計劃檔開始,模型先產生定義功能的測試,再逐一實作。每輪編碼後執行 cargo check 和 cargo test 確認編譯與測試通過。我審查模型產生的每行程式碼。初稿幾乎不需改動。當然,這不是複雜應用,只是基本 CRUD 加上一些特殊需求。但包含認證與資料處理都必須正確。
初稿完成後,我檢視整個應用,列出改進與變更任務。這份 TODO.md 成為模型新計劃上下文的起點。
意外的是,當文件中的項目被處理,模型會更新檔案,打勾並記錄實作細節。這不是我指示的,但我很喜歡這行為,因為它創造了責任軌跡。
所有功能運作後,我清空上下文,給模型新指令。這次不再當軟體開發者,而是安全審計員與安全程式碼專家,找出漏洞並建議修補。結果寫入 FINDINGS.md,延續「計劃、文件、執行、記錄」模式。
你真正想知道的是:結果如何?感覺如何?
這裡我們要成熟地接受一些看似矛盾的想法。我會談什麼有效、什麼無效,以及感受。我不會支持這技術,也不會輕描淡寫它的法律與倫理問題。我對它對社會的危害立場未變,但對它在軟體開發能力的理解改變了。我不認為快速產出程式碼值得付出一切,就像蠟果一樣。
但它確實有效。程式碼已上線,為 TTI 發放證書。我對程式碼庫的直接修改僅限於優化。核心邏輯從一開始就穩固,我相信這既得益於 Rust 的安全機制,也得益於模型能力。
你可以在這裡查看程式碼。我故意把連結放在這裡,讓有興趣的讀者更容易找到。
我最後完成的應用比我自己寫的更健全、功能更豐富。不得不承認這點。審計日誌、GDPR 資料刪除、加密驗證上傳、可選的 HMAC 來驗證 webhook——這些我可能不會為小型證書產生工具花心思,但它們讓工具更通用,也讓我在這次擺脫託管服務的遷移中更安心。
放棄 Teachable 和 Discord 意味著我也承擔了他們原本處理的法律合規責任。模型在計劃中提出這些考量並不討厭。由於模型的隨機性,它的輸出可能激發你不會想到的想法。這不代表它「好」,只是使用時可能發生的事。別誤會我在為它辯護。
用 Claude Code 循環開發程式碼的感受?痛苦至極。
我討厭這種寫軟體的方式。先不談結果,過程令人難受。大部分時間我都在閱讀建議的程式碼變更,然後按 1 鍵接受,幾乎總是接受。我就像荷馬的喝水鳥。
很想按 2 鍵:「是的,這次會話接受所有變更。」為什麼不呢?如果你都手動接受,這有什麼壞處?
壞處是?壞處是?壞處是?壞處是?
沒錯,這就是你會栽跟頭的原因。一旦你停止嚴格審查模型輸出,出錯機率幾乎是 100%。「人類在迴路中」是必要的,但現有流程讓人想跳出迴路,這很危險。放手讓它跑的誘惑無時無刻不在,我甚至沒有老闆催促我交付程式碼。
雖然我讀每個建議變更,但深入了解程式碼庫更具挑戰。自己寫新應用時,我腦中建構一座精巧的紙牌屋,交織著想法與目標的輕盈結構。這是我用程式碼講述的故事,最終也是與使用者分享的故事。
這次,我是觀眾而非作者。必須倒退著理解程式碼,仔細閱讀結構。這對於大型團隊或接手別人寫的程式碼的開發者很常見,但我經驗不多,感覺有點尷尬。
尷尬,但不是不可能。我透過仔細閱讀程式碼、相關函式庫文件和建議變更,對程式碼非常熟悉。但這種安全感來自人類的自律。很可能(甚至很可能)有人會走捷徑,信任模型做對的事。
那條路通往瘋狂。這流程缺乏真正系統性的安全措施,不是踩到耙子,而是踩到布滿地雷的耙子。
大型公司已在處理因魯莽使用這些工具而產生的程式碼問題。
模型會幻覺嗎?會,但很少且會自我修正。有幾次它為某些函式庫的結構體捏造方法。但 Rust 的 LSP 伺服器錯誤訊息和編譯檢查迫使模型重新檢查,最終正確實作。我沒介入,平均每個問題花約五分鐘。
有一次在修安全漏洞時,模型的程式碼引入一個不明顯的拒絕服務(DoS)漏洞。從部署角度看很明顯,但程式碼本身不易察覺。這就是為什麼仔細閱讀每個變更很重要。指出問題後,模型產生的程式碼既修補了安全問題,也避免了 DoS。
我很慶幸做了安全審計階段(從一開始就計劃好)。模型發現了幾個嚴重漏洞——大部分我已察覺,但不是全部。最可怕的是模板管理系統的路徑遍歷漏洞,以及 Typst 模板注入問題,雖然無法執行程式碼,但可能導致 DoS。
我也承認初版 Argon2 雜湊函式有時間側信道漏洞。錯誤密碼失敗很快,正確密碼花較長時間。修正方法是使用恆定時間檢查。這是模型在程式碼中發現的,我自己不會察覺,因為不熟悉 Argon2。雖然我可能不會選它當雜湊演算法,但這反映我還是新手密碼學者。總之,審計讓程式碼更安全。這很難接受,但表示不論技術倫理問題,這些工具在安全領域有其價值。
它們找到的 CVE 漏洞是真實的。它們能做某些靜態分析,且透過代理流程也能做動態分析。這不新鮮,但速度與徹底性能提升應用安全。關鍵是決定交給模型什麼、鎖定自動化什麼、留給人類專家什麼。
知道這些後,開發流程中省略安全審計合理或負責任嗎?我不確定。
再說一次,我知道這會被誤解,我不是為這技術的負面外部性辯護。危害遠大於利益。我只是說,在軟體開發這個領域,這東西確實有效。
我從這過程學了很多,且感到非常不舒服。但忽視這種不適沒幫助。讓我們面對它。
那些大肆宣揚近期模型能力的人有道理:它有效。這專案三週完成。相比之下,我之前做的 Ringspace 專案,規模相近,花了我約六個月的夜晚和清晨,還沒算日常工作和當爸爸的責任。沒有這工具,我不可能做得這麼好或這麼快。其他開發者也指出,這就是現在出現的幫助。
我不完全同意 Mike Masnick 對這技術民主化力量的樂觀看法。我不認為技術能輕易與其來源或企業控制分開。但我的證書應用 CertGen 現在存在了。沒有像 Claude Code 這樣的工具,它不可能存在。開源界尤其需要正視這點,因為目前開發者飢餓且自我耗盡的狀況不可持續。我們必須面對這問題。我還不確定結果如何,任何說自己知道的人都是在說謊、愚蠢或狂熱。
「有效」只限於編碼任務。我沒有證據,也似乎沒人有,這技術能在法律、醫療或其他高度人性化、主觀的職業中達到同樣成功。
如果生成模型在所有領域失敗率都高,反對理由會簡單得多。但在這特定領域,大型語言模型似乎找到成功利基。這也是 OpenAI 轉向企業與編碼工具的原因。編碼助理廣泛採用,也是管理層命令的結果。
我轉向生成模型不只是實驗,更是出於無奈。我需要不存在的程式碼。沒人會幫我寫,也不該期待有人幫忙。過去我會拼湊快速且粗糙的解決方案,可能犧牲身心健康完成。這次,我有了另一選擇。在這有限範圍內,模型對我、TTI 社群和家人都有益。這不否定技術的危險外部性,但我作為個人只能承擔部分責任。
我很幸運能做這選擇。不是每個人都有這種特權。我不願譴責那些接受幫助、履行照顧責任的人。只要這些模型讓人能建構美好事物,且不過度痛苦,我們必須正視這價值。這是好處,但不消除隨之而來的傷害。
編程代理可能有效,但有很多錯誤可能發生。維持模型正軌所需的護欄無法擴展。流程中依賴生成輸出越多,錯誤與災難性失敗風險越高。任何涉及這些模型的流程都必須盡量確保確定性並減少模型變異。
就我看,這也是為什麼我認為 Rust 非常適合這類開發(甚至是必需)。Rust 嚴謹的安全機制能幫助模型保持正軌。其他語言也有類似安全機制,但我認為沒有一個像 Rust 那麼嚴格。
但即便如此,錯誤累積的方式讓這成為危險的提案。這專案小,運作良好,但更大、更複雜的專案可能讓模型崩潰。且隨著專案規模增加,審查變更更困難也更重要。
這些工具有個根本問題,任何部署策略都無法解決:工具需要專業知識來驗證,但使用它會削弱專業知識並阻礙成長。怎麼成為專家?沒有捷徑,只有持續努力與奉獻。有人說過,偉大作家先學規則,再用新穎方式打破它們。
但新手開發者如果每天工作只是照顧模型,怎麼學規則?怎麼累積讓人類在迴路中成為有效防護的寶貴經驗?
我在這過程中無聊到快哭,意識到如果軟體開發變成這樣,不只會是糟糕職業,還會吞噬新血。
我沒有解決方案。只要工具存在,就會成為短視組織的快速廉價答案。沒有政策或程序能阻止過度依賴。它的存在本身就是誘惑。
我讓這東西進入腦中,現在它一直存在。每當有新專案想法,腦中就有聲音告訴我,讓模型做會簡單多少,快多少。只要用提示描述目標就能放手。
我不想放手,但我承認這種誘惑的力量。親身感受更堅定我相信這些模型是成癮物質。它們以有害人類繁榮的方式改變認知。換句話說,雖然產出多,但它們奪走了我們重要的東西。
也許只有我這樣想。我寫程式多年,深愛創作的掙扎。我想繼續寫,即使慢、即使不完美。我想繼續寫程式。但我懷疑不是每個人都這麼想。他們錯了嗎?還是不同人能從同一任務找到不同價值?社會又該如何對待喜歡舊方式的人?
如果能消滅這技術,我會。經驗雖讓我了解模型能力,但沒改變我認為它害大於利的信念。然而,我沒計畫如何摧毀生成式 AI。我不認為這技術能被放回盒子。一年後它可能不再同樣形式,不再普及或受歡迎,但它會存在。
在軟體開發領域,它的存在根本改變了行業本質。我們必須學會在有人選擇使用這些工具的世界共存,無論是否負責任。能分辨兩者嗎?能否拒絕所有非人類手寫的程式碼?如果能,合理嗎?
我也不知道怎麼處理製造我電腦的礦物所帶來的破壞性採礦。這些人類傷害幾乎肯定比盜用著作權嚴重,但我樂於忽視。我提這點不是輕忽錯誤,而是承認所有科技都染血。我不知道如何完全脫離這系統,讓雙手乾淨。我不認為有人能在這互聯時代做到。
也許你不願跨過的界線是知識產權盜竊。這是合理界線!但我不確定這必須是每個人的界線。我不認為個人使用這些工具就成了怪物。
我雖然害怕這技術的後果,但更害怕意識形態純潔的後果。人們常因立場變成神聖事業、旗幟、排斥異己的群體。純潔是危險的概念——歷史上比技術改變勞動力更危險。純潔是用來分裂勞動者的武器(見美國 1865 年至今的種族與階級衝突)。
真正的怪物不是模型,而是賦予它生命的操控者。戰鬥不該是被技術威脅的勞動者間的爭鬥,而是想工作、創造、生活與繁榮的勞動者,對抗只想靠這技術致富的精英。如果生成模型是怪物——我仍深信如此——它的主人就是我們的敵人。
我厭倦了因工具互相拆台。我厭倦了在科技各角落奔波,證明我多關心科技倫理。我想把時間與精力用在為我關心的人打造未來。我不喜歡這工具,真心相信它對社會有害。我仍認為它成癮;仍認為它出錯的機率遠高於成功。我找到一個它成功的特定場景。
這次探索讓我理解為何有人會用生成模型完成特定目標,以及它們如何成功。我不認為譴責使用者對任何人或任何你熱衷的事業有幫助。
這些模型和使用它們的人一樣,不是單一事物。它們在不同光線、角度下呈現不同面貌:危險、驚人、誘惑、有效、有益、腐敗——還有更多。我們當然都是罪人。我在這世界生存的唯一方式是團結,以恩慈和理解伸出援手給不與我同見、不同作的人。這比憤怒與譴責難多了。這也是我確信這是正確做法的部分原因。伸出手比握拳打人感覺好太多。
我會再用這工具寫程式嗎?我真的不想。如果用,一定會明確標示,並遵守我學到且持續學習的安全原則。但我不會因為這選擇而否定或責備任何人。