Karpathy Hermes 編碼指南
源自 Andrej Karpathy 的觀察 關於 LLM 編碼陷阱的行為指南,旨在減少常見的 LLM 編碼錯誤。
取捨抉擇: 這些指南傾向於謹慎勝於速度。對於瑣碎任務(如修正錯字、明顯的一行程式碼),請自行判斷 — 並非每次變更都需要完整嚴謹的流程。
何時載入此技能
在以下情況總是啟用:
- 撰寫新程式碼
- 編輯現有程式碼
- 審查程式碼
- 重構程式碼
- 規劃程式碼變更
僅在以下情況跳過:
- 用戶明確表示「趕快做就好」
- 純設定檔(YAML、JSON、env)
- 用戶已確認可丟棄的一次性原型
四項原則
1. 先思考再編碼
不要假設。不要隱藏困惑。將取捨攤開來講。
在實作任何東西之前:
- 明確陳述假設。 如果不確定,請提問。
- 有多種解讀方式? 請全部提出 — 不要默默選擇一種。
- 存在更簡單的方法? 說出來。在必要時提出異議。
- 有不清楚的地方? 停下。說明令人困惑之處。提問。
錯誤示範:
「我現在就來實作匯出功能。」 [在充滿假設的情況下繼續]
良好示範:
「在實作之前,我需要先釐清:
- 匯出所有用戶還是經過篩選的?(隱私影響)
- 檔案下載、API 端點,還是背景任務?
- 包含哪些欄位?有些可能很敏感。 您偏好哪種方式?」
測驗標準: 如果你正要寫程式碼,卻還沒有陳述你的假設,那你做錯了。
2. 簡潔至上
用最少的程式碼解決問題。不要寫任何投機性的東西。
規則:
- 不要實作未被要求的功能
- 不要為只使用一次的程式碼建立抽象層
- 不要加入未被要求的「彈性」或「可設定性」
- 不要為不可能發生的情境撰寫錯誤處理
- 如果你寫了 200 行,但其實 50 行就夠,重寫它
問問自己: 「資深工程師會說這個太複雜了嗎?」如果是,請簡化。
錯誤示範:
# 策略模式、抽象基礎類別、設定系統…
# 只為了一個折扣計算
class DiscountStrategy(ABC):
@abstractmethod
def calculate(self, amount: float) -> float:
pass
class PercentageDiscount(DiscountStrategy):
# 50 行以上
良好示範:
def calculate_discount(amount: float, percent: float) -> float:
return amount * (percent / 100)
何時增加複雜度: 只有當你真的需要它時。等到需求出現時再重構。
3. 精準修改
只觸碰你必須動的東西。只清理你自己造成的混亂。
編輯現有程式碼時:
- 不要「改善」相鄰的程式碼、註解或格式
- 不要重構沒有壞掉的東西
- 遵循現有風格,即使你個人偏好不同
- 如果你發現不相關的無用程式碼,提出來 — 但不要刪除它
當你的變更產生了孤兒(不再被使用的東西):
- 移除你的變更造成的未使用匯入/變數/函式
- 不要移除原本就存在的無用程式碼,除非被要求
測驗標準: 每一行被變更的程式碼都應該直接追溯到用戶的需求。
錯誤示範:
- def upload_file(file_path, destination):
+ def upload_file(file_path: str, destination: str) -> bool:
+ """Upload file to destination with logging."""
+ logger.info(f"Uploading {file_path} to {destination}")
try:
- with open(file_path, 'rb') as f:
+ with open(file_path, "rb") as f:
[新增了型別提示、文件字串、更改了引號風格 — 這些都沒有被要求]
良好示範:
+ import logging
+ logger = logging.getLogger(__name__)
+
def upload_file(file_path, destination):
+ logger.info(f'Starting upload: {file_path}')
try:
with open(file_path, 'rb') as f:
[只新增了被要求的東西:日誌記錄。保留了原有的風格。]
4. 目標驅動執行
定義成功標準。持續迴圈直到驗證通過。
將命令式的任務轉化為可驗證的目標:
| 與其這樣做... | 不如轉化為... |
|---|---|
| 「加入驗證」 | 「撰寫無效輸入的測試,然後讓它們通過」 |
| 「修正這個錯誤」 | 「撰寫一個能重現此錯誤的測試,然後讓它通過」 |
| 「重構 X」 | 「確保測試前後都通過」 |
| 「讓它動起來」 | 「定義『動起來』的意思,撰寫測試,驗證」 |
對於多步驟任務,請陳述簡短的計畫:
1. [步驟] → 驗證:[檢查項目]
2. [步驟] → 驗證:[檢查項目]
3. [步驟] → 驗證:[檢查項目]
明確的成功標準能讓你在沒有外部干預的情況下獨立執行迴圈。 模糊的標準(「讓它動起來」)會需要不斷澄清。
錯誤示範:
「我會審查驗證程式碼並進行改善。」 [在沒有明確標準的情況下開始改動]
良好示範:
「為了解決驗證問題,我需要設定成功標準。 問題:用戶在變更密碼後仍維持登入狀態。 計畫:
- 撰寫測試:變更密碼 → 舊 session 失效
- 實作修復
- 驗證測試通過 + 無回歸錯誤 從步驟 1 開始。」
與 Hermes 的整合
此技能可與其他 Hermes 技能搭配使用:
- [[test-driven-development]] — 與原則 4(目標驅動)搭配。TDD 就是驗證迴圈。
- [[systematic-debugging]] — 與原則 1(先思考再編碼)搭配。先除錯,再修復。
- [[writing-plans]] — 與原則 4 搭配。多步驟任務需要附帶驗證的計畫。
- [[requesting-code-review]] — 四項原則在審查時皆適用。
反模式速查表
| 原則 | 反模式 | 修正方式 |
|---|---|---|
| 先思考再編碼 | 默默假設格式、欄位、範圍 | 列出假設,請求釐清 |
| 簡潔至上 | 為單一函式使用策略模式 | 在需要複雜度之前只寫一個函式 |
| 精準修改 | 修正錯誤時順便重新格式化引號 | 只變更修復問題所需的行數 |
| 目標驅動 | 「我會審查並改善」 | 「寫測試 → 修復 → 驗證」 |
關鍵見解
引用自 Karpathy:
「LLM 在達成特定目標的迴圈中表現特別出色… 不要告訴它要做什麼,給它成功標準,然後看著它完成。
好的程式碼簡潔地解決今天的問題,而不是過早地解決明天的問題。」
如何判斷是否有效
如果你觀察到以下現象,表示這些指南正在發揮作用:
- diff 中不必要的更動減少了 — 只出現被要求的變更
- 因過度設計而重寫的情況減少了 — 程式碼第一次就寫得很簡單
- 釐清問題的提問在實作之前提出 — 而不是在犯錯之後
- 乾淨、簡潔的 PR — 沒有順便重構或「改善」
完整範例
請參閱 references/EXAMPLES.md 以取得每個原則的詳細前後對比範例。