目錄
你的 AI agent 上線了。功能很酷,但月底帳單讓你頭皮發麻。
這是 2025-2026 年 AI 工程師的新挑戰:LLM API 定價下降了,但 agent 的 token 使用量以倍數成長。一個「簡單的」工作流程代理人,每天可能跑出幾百美元的費用。
TL;DR
AI agent 費用暴增的三個根本原因:(1) 用了比需要更強(也更貴)的模型,(2) tool call 迴圈沒有深度限制導致無限呼叫,(3) 每輪對話都把整個歷史 context 傳進去造成 token 浪費。解法不是犧牲品質,而是對任務複雜度和模型能力做精準匹配。
前置條件
- 你有一個已部署或正在開發的 LLM-based agent
- 正在使用商業 API(OpenAI、Anthropic、Google、DeepSeek 等)
- 想在維持功能品質的前提下降低 token 使用量
步驟
步驟 1:評估每個任務的實際複雜度
第一步不是選模型,是分類你的 agent 任務。
| 任務類型 | 範例 | 需要的模型能力 |
|---|---|---|
| 結構化資料提取 | 從收據擷取金額、日期 | 低:規則化,格式固定 |
| 分類/路由 | 判斷這個 issue 應該給哪個 team | 低-中:需要理解,不需要推理 |
| 程式碼生成(複雜邏輯) | 實作一個演算法 | 高:需要多步推理 |
| 長文摘要 | 把 20 頁報告壓縮成重點 | 中:需要理解,不需要複雜推理 |
| 代理人規劃 | 分解任務、選擇工具、處理錯誤 | 高:需要可靠的工具使用能力 |
常見錯誤:把所有任務都丟給 Claude Opus 或 GPT-5,即使是「把這個 JSON 轉成表格」這種任務。
步驟 2:建立模型階層
依複雜度配置不同的模型:
# 範例:依任務類型路由到不同模型
MODELS = {
"classification": "claude-haiku-4-5", # 便宜,快
"extraction": "claude-haiku-4-5",
"summarization": "claude-sonnet-4-6", # 中等
"code_generation": "claude-sonnet-4-6",
"complex_planning": "claude-opus-4-6", # 保留給真正複雜的任務
}
def get_model_for_task(task_type: str) -> str:
return MODELS.get(task_type, "claude-sonnet-4-6")
成本參考(2026 年 5 月定價):
- Claude Haiku 4.5:~$0.08 / M input tokens
- Claude Sonnet 4.6:~$3 / M input tokens
- Claude Opus 4.6:~$15 / M input tokens
同樣的任務,Haiku 可能只花 Opus 費用的 0.5%。
步驟 3:控制 Tool Call 深度
沒有深度限制的 agent 在遇到問題時可能陷入無限 tool call 迴圈:
# 錯誤:沒有迭代上限
while not task_complete:
response = llm.call(tools=all_tools, messages=history)
handle_tool_calls(response)
# 正確:設定最大迭代數
MAX_ITERATIONS = 10
for i in range(MAX_ITERATIONS):
response = llm.call(tools=all_tools, messages=history)
if not response.tool_calls:
break # 沒有 tool call 表示任務完成
handle_tool_calls(response)
else:
# 超過上限,記錄並回傳部分結果
logger.warning(f"Agent hit max iterations for task: {task_id}")
每多一輪 tool call,就多一次 LLM 呼叫費用,加上整個 context 重新傳一遍的 token 費用。
步驟 4:精簡 Context 傳遞
每次 LLM 呼叫都把整個對話歷史傳進去是最大的 token 浪費來源之一。
策略一:滑動視窗
# 只保留最近 N 輪對話
def trim_history(messages: list, max_turns: int = 5) -> list:
system_messages = [m for m in messages if m["role"] == "system"]
conversation = [m for m in messages if m["role"] != "system"]
# 保留最後 max_turns * 2 條訊息(每輪一問一答)
recent = conversation[-(max_turns * 2):]
return system_messages + recent
策略二:壓縮中間 tool 結果
Tool call 的回傳資料常常很大(例如整個 API 回應),但 agent 只需要其中的關鍵欄位:
def compress_tool_result(tool_name: str, result: dict) -> str:
"""只保留 agent 需要繼續決策的關鍵資訊"""
if tool_name == "search_web":
# 只保留標題和摘要,不要全文
return "\n".join(
f"- {r['title']}: {r['snippet']}"
for r in result.get("results", [])[:3]
)
return str(result) # 其他 tool 的 fallback
步驟 5:快取重複呼叫
如果你的 agent 在不同任務中重複呼叫相同的工具(例如每次都重新取得使用者資料),加快取可以大幅降低費用:
import functools
@functools.lru_cache(maxsize=128)
def get_user_profile(user_id: str) -> dict:
"""快取使用者資料,避免重複 DB 查詢和 LLM 摘要"""
return db.get_user(user_id)
常見問題
Q:降到便宜的模型會不會讓 agent 變笨,導致更多錯誤和重試?
A:這取決於任務類型。對結構化提取和分類,Haiku 的準確率通常夠用。對需要多步推理的任務,強行降模型反而會因為重試增加總費用。先測試準確率,再做成本決策。
Q:如何衡量優化後的成本節省?
A:在每次 LLM 呼叫時記錄 token 用量:
response = client.messages.create(...)
logger.info({
"task_id": task_id,
"model": model,
"input_tokens": response.usage.input_tokens,
"output_tokens": response.usage.output_tokens,
"cost_usd": calculate_cost(model, response.usage)
})
建立每個任務類型的 token 基準,持續追蹤偏差。
參考資料
相關標籤
相關文章
為什麼你的 AI 代理越跑越笨?Context Rot 的原理與解法
AI 代理越做越差,根本原因不是模型變笨,而是 Context Window 裡累積的噪音讓訊號被稀釋——這個現象叫 Context Rot,解決方法是把 Context 當 RAM 管理,而不是永遠往裡面加東西。
AI 如何重塑人的思考方式:工具之外的認知轉變
AI 工具改變的不只是你做事的速度,而是你思考問題的方式——從「怎麼做」轉向「做什麼」和「判斷對不對」,這個轉變對工程師的長期影響值得認真思考。
長期免費使用 Codex、Hermes 等 AI Coding Agent:完整攻略
OpenAI Codex CLI 和多個 AI coding agent 工具都有免費方案,關鍵是了解各自的額度機制、如何組合使用以延長免費額度,以及什麼情境下值得付費。