Django創(chuàng)造者Simon Willison分享:我如何使用LLM幫我寫(xiě)代碼
近段時(shí)間,著名 AI 科學(xué)家 Andrej Karpathy 提出的氛圍編程(vibe coding)是 AI 領(lǐng)域的一大熱門(mén)話(huà)題。簡(jiǎn)單來(lái)說(shuō),氛圍編程就是鼓勵(lì)開(kāi)發(fā)者忘掉代碼,進(jìn)入開(kāi)發(fā)的氛圍之中。更簡(jiǎn)單地講,就是向 LLM 提出需求,然后「全部接受」即可。
當(dāng)然,這種使用 LLM 編程的方法過(guò)于簡(jiǎn)單粗暴,或許并不適合用來(lái)開(kāi)發(fā)一些更加復(fù)雜和精細(xì)的項(xiàng)目。近日,探索和發(fā)表數(shù)據(jù)的開(kāi)源工具 Datasette 的創(chuàng)造者、Web 應(yīng)用框架 Django 創(chuàng)造者之一、社交會(huì)議目錄 Lanyrd 的聯(lián)合創(chuàng)始人、著名編程技術(shù)博主 Simon Willison 分享了自己使用 LLM 輔助編程的體驗(yàn)。文中,他分享了不少自己積累的有用實(shí)踐和策略。機(jī)器之心編譯了這篇博客文章,希望能給開(kāi)發(fā)者讀者們帶來(lái)一些幫助。
Simon Willison
原文地址:https://simonwillison.net/2025/Mar/11/using-llms-for-code/
網(wǎng)絡(luò)上,很多開(kāi)發(fā)者在討論使用大型語(yǔ)言模型輔助編程,而其中不少開(kāi)發(fā)者都表示挺失望的。他們經(jīng)常會(huì)問(wèn)自己哪里做錯(cuò)了 —— 為什么有些人報(bào)告的結(jié)果如此出色,而他們自己的實(shí)驗(yàn)卻乏善可陳?
使用 LLM 編寫(xiě)代碼既困難又不直觀。需要付出巨大的努力才能弄清楚使用它們的利弊,而且?guī)缀鯖](méi)有什么指導(dǎo)可以幫助人們學(xué)會(huì)如何最好地使用它們。
如果有人告訴你使用 LLM 編碼很容易,那么他們(可能無(wú)意中)誤導(dǎo)了你。他們很可能偶然發(fā)現(xiàn)了有效的模式,但這些模式并不是每個(gè)人都能自然而然掌握的。
兩年多來(lái),LLM 代碼在輔助我寫(xiě)代碼方面表現(xiàn)很好。下面我將盡力將一些經(jīng)驗(yàn)和直覺(jué)傳授給你。
目錄:
- 設(shè)定合理的期望
- 考慮訓(xùn)練截止日期
- 上下文為王
- 讓它們提供選擇
- 告訴它們確切要做什么
- 你必須測(cè)試它寫(xiě)的內(nèi)容!
- 記住這只是一次對(duì)話(huà)
- 使用可以為你運(yùn)行代碼的工具
- 氛圍編程是一種很好的學(xué)習(xí)方式
- 使用 Claude Code 的一個(gè)詳細(xì)示例
- 做好讓人類(lèi)接管的準(zhǔn)備
- 最大的優(yōu)勢(shì)是開(kāi)發(fā)速度
- 使用 LLM 是對(duì)已有專(zhuān)業(yè)知識(shí)的放大
- 獎(jiǎng)勵(lì):回答有關(guān)代碼庫(kù)的問(wèn)題
設(shè)定合理的期望
不要去管?chē)@「AGI」的炒作 ——LLM 仍舊只是花哨的自動(dòng)補(bǔ)全。它們所做的只是預(yù)測(cè) token 序列 —— 但事實(shí)證明,寫(xiě)代碼的主要工作就是以正確的順序?qū)?token 串聯(lián)在一起,因此只要你給它們指示正確的方向,它們就會(huì)非常有用。
如果你認(rèn)為這項(xiàng)技術(shù)將完美地實(shí)現(xiàn)你的項(xiàng)目,而你不需要鍛煉任何技能,那你就等著失望吧。
相反,你應(yīng)該使用 LLM 來(lái)增強(qiáng)你的能力。我現(xiàn)在最喜歡的心理模式是將它們想象成一個(gè)過(guò)度自信的結(jié)對(duì)編程助理 —— 它們查找東西的速度快如閃電,可以隨時(shí)提供相關(guān)示例,并且可以毫無(wú)怨言地執(zhí)行繁瑣的任務(wù)。
過(guò)度自信很重要。它們絕對(duì)會(huì)犯錯(cuò)誤 —— 有時(shí)很細(xì)微,有時(shí)是大錯(cuò)。這些錯(cuò)誤可能與人類(lèi)錯(cuò)誤非常不一樣 —— 如果一個(gè)人類(lèi)合作者想象出了一個(gè)根本不存在的庫(kù),你會(huì)馬上就不再相信他了。不要把 LLM 當(dāng)人類(lèi)一樣看,這是一個(gè)陷阱。AI 犯的錯(cuò)誤并不能否定它的有用性。
當(dāng)與 LLM 一起工作時(shí),你經(jīng)常會(huì)發(fā)現(xiàn)它們無(wú)法做到的一些事情。記下這些事情 —— 它們是有用的教訓(xùn)!它們也是為未來(lái)儲(chǔ)備的寶貴例子 —— 一個(gè)強(qiáng)大的新模型的標(biāo)志是:它能解決以前的模型無(wú)法處理的任務(wù)。
考慮訓(xùn)練截止日期
任何模型都有一個(gè)關(guān)鍵特征:訓(xùn)練截止日期。也就是停止收集訓(xùn)練數(shù)據(jù)的日期。對(duì)于 OpenAI 的模型,這通常是 2023 年 10 月。Anthropic 和 Gemini 以及其它提供商可能有更近期的日期。
這對(duì)于編程來(lái)說(shuō)非常重要,因?yàn)檫@個(gè)時(shí)間會(huì)影響它們知道的庫(kù)。如果你使用的庫(kù)自 2023 年 10 月以來(lái)發(fā)生了重大變化,OpenAI 模型將不會(huì)知道!
我從 LLM 中獲得了足夠的價(jià)值,現(xiàn)在我在選擇庫(kù)時(shí)會(huì)特意考慮這一點(diǎn) —— 我會(huì)盡力堅(jiān)持使用具有良好穩(wěn)定性且足夠流行的庫(kù),這樣一來(lái),這些庫(kù)的許多示例都會(huì)在其訓(xùn)練數(shù)據(jù)中。我喜歡應(yīng)用無(wú)聊技術(shù)(boring technology)的原則 —— 在項(xiàng)目的獨(dú)特賣(mài)點(diǎn)上進(jìn)行創(chuàng)新,在其它所有方面堅(jiān)持使用經(jīng)過(guò)嘗試和測(cè)試的解決方案。
LLM 仍然可以幫助你處理訓(xùn)練數(shù)據(jù)之外的庫(kù),但你需要付出更多努力 —— 你需要在提示詞中向它們提供最新示例,說(shuō)明這些庫(kù)應(yīng)如何使用。
這就引出了使用 LLM 時(shí)最重要的事情:
上下文為王
要想讓 LLM 給出優(yōu)良的結(jié)果,很大一部分工作在于都可歸結(jié)為管理上下文,即當(dāng)前對(duì)話(huà)的一部分文本。
此上下文不僅僅是提供給 LLM 的提示詞:成功的 LLM 交互通常采用對(duì)話(huà)的形式,而其上下文包括當(dāng)前對(duì)話(huà)線(xiàn)程中存在的來(lái)自你的每條消息和來(lái)自 LLM 的每條回復(fù)。
當(dāng)你開(kāi)始新的對(duì)話(huà)時(shí),你會(huì)將該上下文重置為零。了解這一點(diǎn)很重要,因?yàn)閷?duì)于不再有用的對(duì)話(huà),通常的解決方法是將一切清除干凈并重新開(kāi)始。
一些 LLM 編程工具不僅僅適用于對(duì)話(huà)。例如,Claude Projects 允許你預(yù)先填充大量文本,包括最近的直接從 GitHub 庫(kù)導(dǎo)入代碼的功能 —— 我經(jīng)常使用這個(gè)功能。
Cursor 和 VS Code Copilot 等工具會(huì)自動(dòng)包含當(dāng)前編輯器會(huì)話(huà)和文件布局中的上下文,有時(shí)你可以使用 Cursor 的 @commands 等機(jī)制來(lái)提取其它文件或文檔。
我主要直接使用 ChatGPT 和 Claude 網(wǎng)頁(yè)版或應(yīng)用界面的原因之一是:它能讓我更容易準(zhǔn)確地了解上下文中的內(nèi)容。那些向我隱瞞上下文的 LLM 工具的效果更差。
另一個(gè)事實(shí)也可為你所用:之前的回復(fù)也是上下文的一部分。對(duì)于復(fù)雜的編程任務(wù),可以先嘗試讓 LLM 編寫(xiě)一個(gè)更簡(jiǎn)單的版本,檢查它是否有效,然后再迭代構(gòu)建更復(fù)雜的實(shí)現(xiàn)。
我在開(kāi)始新聊天時(shí),經(jīng)常會(huì)把現(xiàn)有代碼放入到上下文中,然后再與 LLM 一起合作以某種方式來(lái)修改它。
我最喜歡的代碼提示詞技術(shù)之一是放入幾個(gè)與我想要構(gòu)建的東西相關(guān)的完整示例,然后提示 LLM 將它們用作新項(xiàng)目的靈感。當(dāng)我在構(gòu)建我的 JavaScript OCR 應(yīng)用時(shí),我詳細(xì)地寫(xiě)了:該應(yīng)用應(yīng)結(jié)合 Tesseract.js 和 PDF.js—— 這兩個(gè)庫(kù)我過(guò)去曾使用過(guò),我可以在提示詞中提供有效示例。
讓它們提供選擇
我的大多數(shù)項(xiàng)目都是從一些開(kāi)放式問(wèn)題開(kāi)始的:我想做的事情是否可行?我可以用哪些潛在方式來(lái)實(shí)現(xiàn)它?哪些選項(xiàng)是最好的?
我會(huì)將 LLM 用作初始研究階段的一部分。
我會(huì)使用這樣的提示:「Rust 中有哪些 HTTP 庫(kù)可選?包括使用示例」或者「JavaScript 中有哪些有用的拖放庫(kù)?為我構(gòu)建一個(gè)展示每個(gè)庫(kù)的工件」(對(duì) Claude)。
訓(xùn)練截止時(shí)間在這里很重要,因?yàn)檫@意味著 LLM 不會(huì)建議使用較新的庫(kù)。通常這樣沒(méi)問(wèn)題 —— 我不想要最新的,我想要最穩(wěn)定的,以及存在時(shí)間足夠長(zhǎng)的,可以解決錯(cuò)誤的東西。
如果我要使用更新的東西,我會(huì)在 LLM 世界之外自己做研究。
開(kāi)始任何項(xiàng)目的最佳方式是使用原型來(lái)證明該項(xiàng)目的關(guān)鍵要求可以得到滿(mǎn)足。我經(jīng)常發(fā)現(xiàn),LLM 可以在我坐下來(lái)使用筆記本電腦的幾分鐘內(nèi)就讓我獲得那個(gè)可行的原型 —— 有時(shí)甚至在我使用手機(jī)工作時(shí)也可以。
告訴它們確切要做什么
一旦我完成了初步研究,我就會(huì)大幅改變模式。對(duì)于生產(chǎn)級(jí)代碼,我對(duì) LLM 的使用更加專(zhuān)制:我會(huì)把它當(dāng)作數(shù)字實(shí)習(xí)生,工作內(nèi)容是根據(jù)我的詳細(xì)指示來(lái)寫(xiě)代碼。
這里有個(gè)最近的例子:
我可以自己寫(xiě)這個(gè)函數(shù),但我需要花上十五分鐘來(lái)查找所有細(xì)節(jié),才能使代碼正常工作。Claude 在 15 秒內(nèi)就搞定了。
我發(fā)現(xiàn),對(duì)于我在這里使用的函數(shù)簽名,LLM 的響應(yīng)非常好。我的工作是作為函數(shù)設(shè)計(jì)者,LLM 負(fù)責(zé)根據(jù)我的規(guī)范構(gòu)建主體。
我經(jīng)常還會(huì)提出跟進(jìn)要求,比如「現(xiàn)在用 pytest 給我寫(xiě)測(cè)試」。再次強(qiáng)調(diào),選擇哪種技術(shù)完全由我決定 —— 我希望 LLM 能幫我省去錄入已經(jīng)存在于我腦子里的代碼的時(shí)間。
如果你對(duì)此的反應(yīng)是「輸入代碼肯定比輸入英文指令要快」,我只能告訴你,對(duì)我來(lái)說(shuō)已經(jīng)不是這樣了。代碼必須正確。而英語(yǔ)中存在大量捷徑、奇思妙想和拼寫(xiě)錯(cuò)誤,比如如果你記不住名字,你可以說(shuō)「使用那個(gè)流行的 HTTP 庫(kù)」。
優(yōu)秀的編程 LLM 非常擅長(zhǎng)填補(bǔ)空白。它們也遠(yuǎn)沒(méi)有我那么懶 —— 它們總是會(huì)記得捕捉可能的異常,添加準(zhǔn)確的文檔字符串,并用相關(guān)的類(lèi)型標(biāo)注代碼。
你必須測(cè)試它寫(xiě)的內(nèi)容!
有一件事是你絕對(duì)不能外包給機(jī)器的,那就是測(cè)試代碼是否真的有效。
作為軟件開(kāi)發(fā)者,你的責(zé)任是提供能有效工作的系統(tǒng)。如果你還沒(méi)有看到它運(yùn)行,那么它就不是一個(gè)有效的系統(tǒng)。你需要親手試試看。
這件事做起來(lái)可能沒(méi)多少趣味,但它一直是交付良好代碼的關(guān)鍵部分 —— 無(wú)論有沒(méi)有 LLM 參與其中。
記住這只是一次對(duì)話(huà)
如果我不喜歡 LLM 寫(xiě)的東西,可以馬上讓它重構(gòu),而它絕對(duì)不會(huì)抱怨!「將重復(fù)的代碼分解成一個(gè)函數(shù)」、「使用字符串操作方法而不是正則表達(dá)式」,甚至「寫(xiě)更好一點(diǎn)!」
LLM 第一次編寫(xiě)的代碼很少是最終的實(shí)現(xiàn),但它們可以為你重新輸入幾十次,而不會(huì)感到沮喪或無(wú)聊。
偶爾我會(huì)從我的第一個(gè)提示中獲得很好的結(jié)果 —— 我練習(xí)得越多,結(jié)果就越頻繁 —— 但我一直做好了需要后續(xù)跟進(jìn)的準(zhǔn)備。
我一直很好奇,這是否是人們錯(cuò)過(guò)的關(guān)鍵技巧之一 —— 糟糕的初始結(jié)果并不是失敗,而是一個(gè)起點(diǎn),基于此才能將模型推向你真正想要的方向。
使用可以為你運(yùn)行代碼的工具
現(xiàn)在越來(lái)越多的 LLM 編程工具能夠?yàn)槟氵\(yùn)行代碼。我對(duì)其中一些略微謹(jǐn)慎,因?yàn)殄e(cuò)誤的命令可能會(huì)造成真實(shí)的損害,所以我傾向于堅(jiān)持使用在安全沙箱中運(yùn)行代碼的工具。我現(xiàn)在最喜歡的包括:
- ChatGPT Code Interpreter,ChatGPT 可以直接在 OpenAI 管理的 Kubernetes 沙箱 VM 中編寫(xiě)并執(zhí)行 Python 代碼。這是完全安全的 —— 它甚至無(wú)法建立出站網(wǎng)絡(luò)連接,因此實(shí)際上可能發(fā)生的一切就是臨時(shí)文件系統(tǒng)被破壞然后重置。
- Claude Artifacts,Claude 可以為你構(gòu)建一個(gè)完整的 HTML+JavaScript+CSS Web 應(yīng)用,該應(yīng)用顯示在 Claude 界面中。這個(gè) Web 應(yīng)用顯示在一個(gè)非常封閉的 iframe 沙箱中 —— 這雖然極大地限制了它可以做的事情,但可以防止意外泄露你的私人 Claude 數(shù)據(jù)等問(wèn)題。
- ChatGPT Canvas 是一個(gè)較新的 ChatGPT 功能,具有與 Claude Artifacts 類(lèi)似的功能。我自己還沒(méi)有對(duì)此進(jìn)行足夠的探索。
如果你愿意更冒險(xiǎn)一點(diǎn):
- Cursor 有一個(gè)「Agent」功能可以做到這一點(diǎn),Windsurf 和越來(lái)越多的其它編輯器也是如此。我還沒(méi)有花足夠的時(shí)間研究這些,所以我不能提供相關(guān)推薦。
- Aider 是這些模式的領(lǐng)先開(kāi)源實(shí)現(xiàn),是 dogfooding 的一個(gè)很好的例子 ——Aider 的最新版本有 80% 以上是由 Aider 自己編寫(xiě)的。https://aider.chat/
- Claude Code 是 Anthropic 進(jìn)入這個(gè)領(lǐng)域的新成員。我將在稍后詳細(xì)介紹如何使用該工具。
這種在交互流程中運(yùn)行代碼的模式非常強(qiáng)大。我在選擇核心 LLM 編程工具時(shí),主要就是看它們是否可以安全地運(yùn)行和迭代我的代碼。
氛圍編程是一種很好的學(xué)習(xí)方式
Andrej Karpathy 一個(gè)多月前創(chuàng)造了氛圍編程(vibe coding)一詞:
Andrej 認(rèn)為這「對(duì)于一次性的周末項(xiàng)目來(lái)說(shuō)還不錯(cuò)」。這也是探索這些模型功能的絕佳方式 —— 而且真的很有趣。
學(xué)習(xí) LLM 的最佳方式就是玩它們。向它們拋出荒謬的想法,然后進(jìn)行氛圍編程,直到它們基本可以正常工作,這是一種真正有用的方法,可以讓你更快地對(duì)什么有效、什么無(wú)效形成直覺(jué)認(rèn)識(shí)
早在 Andrej 給它命名之前,我就已經(jīng)開(kāi)始進(jìn)行氛圍編程了!我的 simonw/tools GitHub 存儲(chǔ)庫(kù)有 77 個(gè) HTML+JavaScript 應(yīng)用和 6 個(gè) Python 應(yīng)用,每個(gè)應(yīng)用都是通過(guò)提示 LLM 構(gòu)建的。我從構(gòu)建這個(gè)集合中學(xué)到了很多東西,我以每周幾個(gè)新原型的速度向其中添加內(nèi)容:https://github.com/simonw/tools
你可以在 tools.simonwillison.net 上直接試用我的大部分工具 —— 這是這個(gè)庫(kù)的 GitHub Pages 發(fā)布版本。
使用 Claude Code 的一個(gè)詳細(xì)示例
在撰寫(xiě)本文時(shí),我想到了 tools.simonwillison.net/colophon 頁(yè)面 —— 我想要一個(gè)可以鏈接到的東西,以比 GitHub 更明顯的方式顯示我的每個(gè)工具的提交歷史記錄。
我決定利用這個(gè)機(jī)會(huì)展示我的 AI 輔助編程過(guò)程。
對(duì)于這個(gè)任務(wù),我使用了 Claude Code,因?yàn)槲蚁M軌蛑苯痈鶕?jù)我筆記本電腦上現(xiàn)有的工具庫(kù)運(yùn)行 Python 代碼。
在我的會(huì)話(huà)結(jié)束時(shí)運(yùn)行 /cost 命令,會(huì)向我顯示以下內(nèi)容:
其最初的項(xiàng)目從開(kāi)始到結(jié)束只花了我 17 分鐘多一點(diǎn)的時(shí)間,并且在調(diào)用 Anthropic 的 API 上僅花費(fèi)了 61 美分。
在這個(gè)過(guò)程中,我會(huì)確切地告訴模型我想要構(gòu)建什么。下面是我的提示詞序列,完整記錄在這里:https://gist.github.com/simonw/323e1b00ee4f8453c7834a7560eeafc1
首先,我要求 LLM 編寫(xiě)一個(gè)初始腳本來(lái)收集新頁(yè)面所需的數(shù)據(jù):
我真的沒(méi)有認(rèn)真考慮過(guò)上面的首個(gè)提示詞 —— 它更像是我在思考初始問(wèn)題時(shí)輸入到機(jī)器人中的意識(shí)流。
我檢查了初始結(jié)果并發(fā)現(xiàn)了一些問(wèn)題:
然后我改變了主意 —— 我也想要那些完整的提交消息:
像這樣提供示例是獲得你想要的確切內(nèi)容的絕佳捷徑。
請(qǐng)注意,我從未查看過(guò)在 gather_links.py 中編寫(xiě)的代碼!這是純粹的氛圍編程:我正在查看它在做什么,但我把實(shí)現(xiàn)細(xì)節(jié)完全留給了 LLM。
這個(gè) JSON 看起來(lái)還不錯(cuò),所以我指示 LLM:
Claude 知道 GitHub URL 的工作方式,因此告訴它提交的鏈接并提供庫(kù)名稱(chēng)就足夠了,它猜測(cè)這些提交 URL 是 https://github.com/simonw/tools/commit/fd9daf885c924ba277806b3440457d52b0ad90a8
我經(jīng)常發(fā)現(xiàn) Claude 在網(wǎng)頁(yè)設(shè)計(jì)方面有很好的默認(rèn)品味 —— 我只是說(shuō)了「頁(yè)面應(yīng)該適合移動(dòng)設(shè)備」,然后剩下的就交給它了。
Claude 不停地為我構(gòu)建不正確的頁(yè)面,所以我發(fā)出指令:
然后它自己修復(fù)了所有錯(cuò)誤,只剩下我決定要做的兩處更改:
整個(gè)項(xiàng)目就完成了!結(jié)果文件為 build_colophon.py,它生成的頁(yè)面看起來(lái)相當(dāng)不錯(cuò):
還有一項(xiàng)任務(wù):我需要將新的 colophon 作為我網(wǎng)站的一部分進(jìn)行部署,但我不想將新的 colophon.html 頁(yè)面簽入庫(kù)本身。我想要一個(gè)自定義的 GitHub Pages 構(gòu)建過(guò)程。
我啟動(dòng)了一個(gè)全新的 Claude Code 會(huì)話(huà),看看 Claude 是否也能做好這件事:
與第一次不同,這次我非常仔細(xì)地觀察了它在做什么 —— 我不知道如何以這種方式自定義 GitHub Pages 構(gòu)建,我想學(xué)習(xí)如何做到這一點(diǎn),并保持謹(jǐn)慎,因?yàn)樗赡軙?huì)產(chǎn)生幻覺(jué)并導(dǎo)致任務(wù)失敗。
它告訴我它想要?jiǎng)?chuàng)建這個(gè)文件并請(qǐng)求我的許可:
我想這是正確的?我很喜歡這個(gè)注釋「Need full history for git log in gather_links.py」—— 這是我很容易忽視的。
然后它說(shuō)它想將這些文件添加到 .gitignore—— 聽(tīng)起來(lái)是個(gè)好主意。
它輸出了對(duì)以上操作的總結(jié):
我查看了它的成本:
因此,使用 Claude API 花費(fèi)了 17 美分和 45 秒。(我分心了,因此總共花費(fèi)了 10 分鐘。)這里是完整記錄:https://gist.github.com/simonw/a560b07eef577e6183021d1ccaae7e07
這些代碼看起來(lái)不會(huì)不可逆地破壞任何東西,因此我將其 push 到了 GitHub,然后看看會(huì)發(fā)生什么。
……成功了!我的 colophon 頁(yè)面已上線(xiàn)。
有一個(gè)問(wèn)題。我在 GitHub Actions 運(yùn)行時(shí)觀察了它,發(fā)現(xiàn)有些不對(duì)勁:
我原本期待的是「Test」job,但為什么有兩個(gè)不同的部署?
我有一種預(yù)感,之前的默認(rèn) Jekyll 部署仍在運(yùn)行,而新的部署同時(shí)運(yùn)行 —— 新腳本完成得晚并覆蓋了原始腳本的結(jié)果,這純粹是時(shí)間上的運(yùn)氣。
是時(shí)候暫時(shí)放下 LLM 并閱讀一些文檔了!
我在 GitHub Pages 的使用自定義工作流中找到了這個(gè)頁(yè)面,但它沒(méi)有告訴我我需要知道的內(nèi)容。
出于另一個(gè)直覺(jué),我檢查了我的庫(kù)的 GitHub Pages 設(shè)置界面,發(fā)現(xiàn)了這個(gè)選項(xiàng):
我的倉(cāng)庫(kù)設(shè)置為「從分支部署」,所以我將其切換到「GitHub Actions」。
我手動(dòng)更新了我的 README.md,以在此提交中添加指向新 Colophon 頁(yè)面的鏈接,而這又觸發(fā)了另一次 build。
這次只運(yùn)行了兩個(gè) job,最終結(jié)果是正確部署的站點(diǎn):
(我后來(lái)發(fā)現(xiàn)了另一個(gè) bug—— 一些鏈接無(wú)意中在其 href= 中包含了 <br> 標(biāo)簽,我用另一個(gè) 11 美分的 Claude Code 會(huì)話(huà)修復(fù)了這個(gè)問(wèn)題。)
之后,我還通過(guò)新增 AI 生成描述工具進(jìn)一步改進(jìn)了這個(gè) colophon:https://simonwillison.net/2025/Mar/13/tools-colophon/
做好讓人類(lèi)接管的準(zhǔn)備
在這個(gè)例子中,我很幸運(yùn),因?yàn)樗兄谡f(shuō)明我的最后一點(diǎn):要做好接管的準(zhǔn)備。
LLM 無(wú)法取代人類(lèi)的直覺(jué)和經(jīng)驗(yàn)。我在 GitHub Actions 上花了足夠多的時(shí)間,我知道要尋找什么樣的東西。在這種情況下,比起繼續(xù)嘗試通過(guò)提示詞完成這個(gè)任務(wù),我介入并完成項(xiàng)目的速度更快。
最大的優(yōu)勢(shì)是開(kāi)發(fā)速度
我的新 colophon 頁(yè)面從構(gòu)思到完成、部署功能只花了我不到半個(gè)小時(shí)的時(shí)間。
我確信如果沒(méi)有 LLM 的幫助,我會(huì)花更長(zhǎng)的時(shí)間 —— 以至于我可能根本不會(huì)費(fèi)心去構(gòu)建它。
也因此,我非常關(guān)心我從 LLM 中獲得的生產(chǎn)力提升:它不是為了更快地完成工作,而是為了能夠交付我根本不想花時(shí)間的項(xiàng)目。
我在 2023 年 3 月寫(xiě)過(guò)一篇文章談到,AI 增強(qiáng)的開(kāi)發(fā)讓我對(duì)我的項(xiàng)目更加雄心勃勃。兩年后,這種影響沒(méi)有消退的跡象。
這也是加速學(xué)習(xí)新事物的好方法 —— 今天我講的是如何使用 Actions 自定義我的 GitHub Pages 構(gòu)建,這是我將來(lái)肯定會(huì)再次使用的東西。
事實(shí)上,LLM 能讓我更快地執(zhí)行我的想法,這意味著我可以實(shí)現(xiàn)更多的想法,這意味著我可以學(xué)到更多。
使用 LLM 是對(duì)已有專(zhuān)業(yè)知識(shí)的放大
其他人也能以同樣的方式做到這一點(diǎn)嗎?可能不會(huì)!我在這里的提示詞依賴(lài)于 25 年以上的專(zhuān)業(yè)編程經(jīng)驗(yàn),包括我之前對(duì) GitHub Actions、GitHub Pages、GitHub 本身以及我使用的 LLM 工具的探索。
我也知道這會(huì)起作用。我花了足夠多的時(shí)間使用這些工具,我相信使用從我的 Git 歷史記錄中提取的信息組裝一個(gè)新的 HTML 頁(yè)面完全在優(yōu)秀 LLM 的能力范圍內(nèi)。
我的提示詞反映了這一點(diǎn) —— 這里沒(méi)有什么特別新穎的東西,所以我口述了設(shè)計(jì),在它工作時(shí)測(cè)試了結(jié)果,偶爾推動(dòng)它修復(fù)錯(cuò)誤。
如果我試圖構(gòu)建一個(gè) Linux 內(nèi)核驅(qū)動(dòng)程序 —— 一個(gè)我?guī)缀跻粺o(wú)所知的領(lǐng)域 —— 我的過(guò)程將完全不同。
獎(jiǎng)勵(lì):回答有關(guān)代碼庫(kù)的問(wèn)題
如果你覺(jué)得使用 LLM 為你寫(xiě)代碼仍舊沒(méi)有吸引力,那么還有另一個(gè)用例可能會(huì)讓你覺(jué)得更有吸引力。
優(yōu)秀的 LLM 非常擅長(zhǎng)回答有關(guān)代碼的問(wèn)題。
這也是非常低風(fēng)險(xiǎn)的:最糟糕的情況是它們可能會(huì)出錯(cuò)。因此,你可能需要花一點(diǎn)時(shí)間才能弄清楚。與完全自己挖掘數(shù)千行代碼相比,這仍然可能會(huì)節(jié)省你的時(shí)間。
這里的技巧是將代碼提交給長(zhǎng)上下文模型中并開(kāi)始提問(wèn)。我目前最喜歡的模型是 gemini-2.0-pro-exp-02-05,這是 Google Gemini 2.0 Pro 的預(yù)覽版,目前可通過(guò)其 API 免費(fèi)使用。
我前幾天就用過(guò)這個(gè)技巧。當(dāng)時(shí)我正在嘗試一種對(duì)我來(lái)說(shuō)很新的工具 monolith,這是一個(gè)用 Rust 編寫(xiě)的 CLI 工具,它可以下載網(wǎng)頁(yè)及其所有依賴(lài)資產(chǎn)(CSS、圖像等)并將它們捆綁到一個(gè)存檔文件中。
我很好奇它是如何工作的,所以我將它克隆到了我的臨時(shí)目錄中并運(yùn)行了以下命令:
我在這里使用我自己的 files-to-prompt 工具(去年由 Claude 3 Opus 為我構(gòu)建)將庫(kù)中所有文件的內(nèi)容收集到一個(gè)流中。然后我將其導(dǎo)入我的 LLM 工具并告訴它(通過(guò) llm-gemini 插件)使用系統(tǒng)提示詞「architectural perspective as markdown」來(lái)調(diào)用 Gemini 2.0 Pro。
這給了我一份詳細(xì)的文檔,描述了該工具的工作原理 —— 哪些源文件做什么,以及最重要的是,它使用了哪些 Rust 包。我了解到它使用了 reqwest、html5ever、markup5ever_rcdom 和 cssparser,并且根本沒(méi)有評(píng)估 JavaScript,這是一個(gè)重要的限制。
我每周都會(huì)使用這個(gè)技巧幾次。這是開(kāi)始深入研究新代碼庫(kù)的好方法。