成本優化
優化模型選擇、快取和 token 管理以提高效率。
你將學到什麼
大規模使用 AI 程式碼工具有實際的成本影響。每個 API 呼叫都會消耗 token,而 token 需要花錢。但成本優化不是把最便宜的模型用在所有事情上 --- 而是為每個任務使用正確的模型、保持上下文精簡,並避免不必要的工作。
完成後,你將了解:
- 什麼因素驅動 AI 輔助程式設計的成本
- 如何為每個任務選擇正確的模型
- 模型級聯模式
- Token 管理與上下文效率
- 減少冗餘工作的快取策略
問題是什麼
一個為每項任務都使用最強大模型的開發者 --- 包括簡單的檔案搜尋、列出目錄和讀取設定 --- 正在大幅超支。
考慮一個典型的會話:
任務分解:
5 次檔案搜尋 (簡單) ← Haiku 就能做到
3 次程式碼探索 (中等) ← Sonnet 最理想
1 次架構決策 (複雜) ← Opus 值得投資
10 次小型編輯 (簡單) ← Sonnet 處理得了
2 次測試調查 (中等) ← Sonnet 最理想
如果所有都用 Opus:
全部 21 個操作以最高成本運行 → 昂貴
如果匹配到正確的模型:
5 次 Haiku + 15 次 Sonnet + 1 次 Opus → 顯著更便宜
差異會隨著天數和週數累積。每月運行數百個會話的團隊,僅憑模型選擇就能看到數量級的成本差異。
如何運作
理解成本驅動因素
四個因素決定了 AI 程式設計會話的成本:
┌──────────────────────────────────────────────────┐
│ 成本驅動因素 │
│ │
│ 1. 輸入 TOKEN │
│ 發送給模型的所有內容: │
│ • 系統提示 + CLAUDE.md │
│ • 對話歷史 │
│ • 工具讀取的檔案內容 │
│ • 先前呼叫的工具輸出 │
│ │
│ 2. 輸出 TOKEN │
│ 模型生成的所有內容: │
│ • 推理和回應 │
│ • 工具呼叫參數 │
│ • 撰寫的程式碼 │
│ │
│ 3. 模型選擇 │
│ 每個 token 的價格因模型而異: │
│ • Haiku:最低成本 │
│ • Sonnet:中等成本 │
│ • Opus:最高成本 │
│ │
│ 4. API 呼叫次數 │
│ 每次工具使用 = 又一次來回: │
│ • 更多工具 = 更多呼叫 │
│ • 每次呼叫都重新發送完整上下文 │
│ • 減少不必要的呼叫可以省錢 │
│ │
└──────────────────────────────────────────────────┘
很多人忽略的關鍵細節:每次 API 呼叫都會發送輸入 token。 如果你的上下文是 50,000 個 token,而代理進行了 20 次工具呼叫,那就是 50,000 個輸入 token 發送了 20 次。精簡的上下文在每一次呼叫中都能帶來回報。
模型選擇策略
每個模型都有其最佳使用場景:
┌─────────────────────────────────────────────────┐
│ 模型選擇指南 │
│ │
│ HAIKU(快速,最低成本) │
│ ├── 檔案搜尋和探索 │
│ ├── 列出目錄內容 │
│ ├── 簡單的文字轉換 │
│ ├── 執行預定義的命令 │
│ ├── 讀取和摘要檔案 │
│ └── 跨程式碼庫的模式匹配 │
│ │
│ SONNET(平衡,中等成本) │
│ ├── 撰寫和修改程式碼 │
│ ├── 除錯和修復錯誤 │
│ ├── 重構現有程式碼 │
│ ├── 撰寫測試 │
│ ├── 程式碼審查和分析 │
│ └── 大多數日常程式設計任務 │
│ │
│ OPUS(強大,最高成本) │
│ ├── 架構決策 │
│ ├── 複雜的多檔案重構 │
│ ├── 解決微妙的 bug │
│ ├── 系統設計和規劃 │
│ ├── 必須正確的關鍵程式碼 │
│ └── 需要深度推理的任務 │
│ │
└─────────────────────────────────────────────────┘
模型級聯模式
不是事先選定一個模型,而是使用級聯:從最便宜的模型開始,只在需要時升級。
┌──────────────────────────────────────────────────┐
│ 模型級聯 │
│ │
│ 任務到達 │
│ │ │
│ ▼ │
│ 用 HAIKU 嘗試 │
│ │ │
│ ├── 成功? → 完成(最低成本) │
│ │ │
│ ▼ │
│ 結果品質足夠嗎? │
│ │ │
│ ├── 是 → 使用 Haiku 結果 │
│ │ │
│ ├── 否 → 升級到 SONNET │
│ │ │ │
│ │ ├── 成功? → 完成 │
│ │ │ │
│ │ ▼ │
│ │ 品質足夠嗎? │
│ │ │ │
│ │ ├── 是 → 使用 Sonnet 結果 │
│ │ │ │
│ │ └── 否 → 升級到 OPUS │
│ │ └── 使用 Opus 結果 │
│ │ │
│ └── 錯誤? → 分類並恢復 │
│ (見第 20 堂課) │
│ │
└──────────────────────────────────────────────────┘
實際上,你不會對每個任務單獨進行級聯。取而代之的是,根據任務類別預先分配模型。級聯是一種心智模型,用來決定哪些任務值得使用哪個模型。
Token 管理
保持上下文精簡可以降低每個後續 API 呼叫的成本。
┌──────────────────────────────────────────────────┐
│ Token 管理策略 │
│ │
│ 1. 針對性的檔案讀取 │
│ 壞的:「讀取 src/ 中的所有檔案」 │
│ → 50 個檔案,40,000 個 token │
│ 好的:「讀取 src/auth/middleware.ts」 │
│ → 1 個檔案,800 個 token │
│ │
│ 2. 具體的工具輸出 │
│ 壞的:搜尋 "config"(回傳 200 個結果) │
│ 好的:在 src/db/ 中搜尋 "databaseConfig" │
│ → 3 個相關結果 │
│ │
│ 3. 子代理隔離 │
│ 壞的:在主上下文中探索 │
│ → 20 次檔案讀取留在歷史中 │
│ 好的:產生探索子代理 │
│ → 只有摘要回傳給父代理 │
│ │
│ 4. 提前壓縮 │
│ 壞的:讓上下文自然填滿到 95% │
│ 好的:切換任務時使用 /compact │
│ → 主動釋放上下文 │
│ │
└──────────────────────────────────────────────────┘
快取策略
某些資訊會被重複讀取。快取可以減少冗餘的 token 消耗。
系統提示快取:
┌─────────────────────────────────────────────┐
│ │
│ 第一次呼叫: │
│ 系統提示(3000 token)→ 快取未命中 │
│ 以完整輸入費率計費 │
│ │
│ 後續呼叫(同一會話): │
│ 系統提示(3000 token)→ 快取命中 │
│ 以降低的快取費率計費 │
│ │
│ 節省:系統提示 + CLAUDE.md 在每次 │
│ 呼叫時都會發送,但第一次之後就被快取 │
│ │
└─────────────────────────────────────────────┘
額外的快取策略:
避免重複讀取未更改的檔案:
第一次讀取:cat src/config.ts → 500 token(必要)
第二次讀取:cat src/config.ts → 500 token(浪費!)
更好的做法:讀取一次,將資訊保留在對話中
批次相關的讀取:
壞的:讀取檔案 A、工具呼叫、讀取檔案 B、工具呼叫、讀取檔案 C
→ 3 次獨立的來回,上下文每次都在增長
好的:平行工具呼叫同時讀取檔案 A、B、C
→ 1 次來回,相同的上下文成本
精簡的 CLAUDE.md:
臃腫的:5000 token 的指令
精簡的:800 token 的必要指令
節省:4200 token x 會話中的每次 API 呼叫
子代理模型選擇
產生子代理時,將模型匹配到任務:
┌──────────────────────────────────────────────────┐
│ 子代理模型匹配 │
│ │
│ 探索任務 → Haiku │
│ 「找到所有測試檔案」 │
│ 「列出 API 路由」 │
│ 「搜尋 UserService 的使用處」 │
│ │
│ 實作任務 → Sonnet │
│ 「為 auth 模組撰寫單元測試」 │
│ 「將這個函式重構為使用 async/await」 │
│ 「為 API 路由加入錯誤處理」 │
│ │
│ 架構任務 → Opus │
│ 「設計多租戶的資料模型」 │
│ 「審查此遷移計畫的邊界案例」 │
│ 「評估這些方法之間的權衡」 │
│ │
└──────────────────────────────────────────────────┘
這個單一決策 --- 選擇子代理模型 --- 可以在探索密集的工作流中降低 50-70% 的成本,而品質沒有任何損失。
關鍵洞見
成本優化不是使用最便宜的模型。而是為每個任務使用正確的模型,這通常意味著混合使用不同價位的模型。
一個使用 Haiku 搜尋、Sonnet 寫程式碼、Opus 做架構決策的工作流,會產出與全部使用 Opus 相同品質的輸出 --- 但只需要一小部分的成本。
第二個洞見同樣重要:上下文大小是一個乘數。 因為完整的上下文在每次 API 呼叫時都會發送,將上下文從 50K 減少到 20K token 不是省了一次 30K token --- 而是在每次後續呼叫中都省了 30K token。在一個 30 次呼叫的會話中,就是省了 900K token。
這就是為什麼先前課程中的模式 --- 子代理隔離(第 4 堂課)、上下文壓縮(第 6 堂課)、針對性的工具使用 --- 不僅僅關乎品質。它們直接關乎成本。
實作範例
設定成本優化的工作流
以下是如何設定一個平衡成本和品質的工作流。
步驟 1:將任務分類
開始工作前,先在心中將任務排序:
功能:為應用程式新增搜尋功能
探索(Haiku):
- 找到現有的搜尋相關程式碼
- 列出資料庫表格
- 檢查 package.json 中有哪些搜尋函式庫
實作(Sonnet):
- 撰寫搜尋 API 端點
- 建立搜尋索引
- 建構搜尋 UI 元件
- 撰寫測試
架構(Opus):
- 決策:全文搜尋 vs. 模糊匹配 vs. 外部服務
- 設計搜尋索引結構
步驟 2:使用子代理進行探索
不要在主會話中探索:
# 在 CLAUDE.md 或你的提示中:
For exploration and search tasks, spawn a subagent
with model="haiku". Only use the main context for
implementation and decisions.
步驟 3:保持 CLAUDE.md 精簡
比較這兩種方法:
# 昂貴的 CLAUDE.md(2000 token):
This project is a web application built with React 18,
TypeScript 5.3, Tailwind CSS 3.4, Prisma ORM 5.x,
PostgreSQL 16, Redis 7.2 for caching...
[大量的工具描述、編碼標準、
部署程序、團隊慣例...]
# 精簡的 CLAUDE.md(400 token):
Tech: React 18, TypeScript, Tailwind, Prisma, PostgreSQL
Style: Prettier defaults, no semicolons
Test: Vitest, run with "pnpm test"
Build: "pnpm build", deploys via GitHub Actions
Key dirs: src/api/, src/components/, src/db/
精簡版本給了 Claude Code 有效工作所需的一切。詳細版本多了 1600 個 token,在每次 API 呼叫時都會重新發送。
步驟 4:監控和調整
追蹤你的使用模式:
每次會話後,記錄:
- 使用的總 token 數
- 多少用於探索 vs 實作
- 上下文膨脹發生在哪裡
- 哪些任務可以使用更便宜的模型
隨著時間,你會培養出直覺:
- 何時在會話中切換模型
- 你的提示需要多詳細
- 何時使用子代理 vs 直接工作
成本與品質的權衡
不是每個任務都應該為成本做優化。知道何時值得投資:
省錢的地方: 投資的地方:
├── 檔案搜尋 ├── 安全關鍵的程式碼
├── 目錄列表 ├── 資料遷移邏輯
├── 執行命令 ├── 架構決策
├── 簡單格式化 ├── 複雜除錯
├── 樣板程式碼生成 ├── 效能優化
└── 重複性編輯 └── API 設計
經驗法則:如果做錯的代價比做對的成本更高,就使用最好的模型。如果任務是機械性的且容易驗證,就使用最便宜的模型。
前後對比
| 未優化 | 成本優化後 |
|---|---|
| 所有事情用同一個模型 | 每個任務用正確的模型 |
| 大型 CLAUDE.md(2000+ token) | 精簡 CLAUDE.md(< 500 token) |
| 讀取目錄中的所有檔案 | 針對性的、具體的讀取 |
| 在主上下文中探索 | 透過 Haiku 子代理探索 |
| 上下文填滿,膨脹地重新發送 | 上下文保持精簡,每次呼叫成本更低 |
| 不意識到 token 成本 | 有意識的模型和上下文決策 |
下一堂課
第 22 堂課涵蓋人機協作(Human-in-the-Loop) --- 如何設計讓 AI 在例行任務上自主運行、但在關鍵決策時暫停等待人類批准的工作流,在速度和安全之間取得正確的平衡。