一句話說明

AI 應用的效能瓶頸通常在 LLM API 回應速度和 Token 成本,透過 Streaming、快取和模型選擇可以改善。

為什麼 AI 應用效能很重要

使用者對 AI 應用的等待容忍度大約是 3-5 秒。超過 10 秒沒有任何回應,大部分使用者會離開。但 LLM 的推論時間經常在 5-30 秒之間,取決於輸入長度和輸出長度。效能優化的目標是讓使用者在第一秒內看到回應開始產生。

Streaming Response

Streaming 是 AI 應用效能優化最重要的手段。傳統方式是等 LLM 產生完所有文字才一次回傳,Streaming 則是邊產生邊回傳。使用者在第一個 token 產生時(通常 0.5-2 秒)就能看到文字開始出現。

Server-Sent Events 實作

# FastAPI 範例
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import anthropic

app = FastAPI()
client = anthropic.Anthropic()

@app.post("/chat")
async def chat(request: ChatRequest):
    async def generate():
        with client.messages.stream(
            model="claude-sonnet-5",
            max_tokens=1024,
            messages=[{"role": "user", "content": request.prompt}]
        ) as stream:
            for text in stream.text_stream:
                yield f"data: {text}\n\n"
        yield "data: [DONE]\n\n"

    return StreamingResponse(generate(), media_type="text/event-stream")

前端用 EventSourcefetch 搭配 ReadableStream 接收。飛飛建議用 fetch + ReadableStream,因為 EventSource 只支援 GET 請求,而 AI 應用通常需要用 POST 傳送 prompt。

Prompt Caching

Claude 和 GPT 都支援 Prompt Caching。如果你的 System Prompt 很長(包含大量背景知識或指令),Prompt Caching 可以顯著降低成本和延遲。

Claude 的 Prompt Caching

Claude 的 cache 機制是在 message 中標記可快取的區塊。第一次呼叫會正常計費,後續相同的 cache 區塊會以折扣價計算。

response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "你是一個客服助手,以下是產品知識庫:...(很長的文字)...",
            "cache_control": {"type": "ephemeral"}
        }
    ],
    messages=[{"role": "user", "content": user_question}]
)

Cache 有效期是 5 分鐘(沒有新的請求就過期)。適合固定 System Prompt + 不同使用者問題的場景。

成本影響

以 Claude Sonnet 為例,快取讀取的成本大約是正常輸入 token 的 10%。如果你的 System Prompt 有 5000 個 token,每次呼叫省下的成本很可觀。一天 1000 次呼叫,一個月可以省下幾十到幾百美金。

語意快取

語意快取的概念是:如果兩個使用者問了意思相近的問題,第二個使用者可以直接拿到第一個使用者的回答,不需要再呼叫 LLM。

實作方式:

把每個問題用 Embedding 模型轉成向量。

查詢向量資料庫中是否有語意相似的問題(cosine similarity > 0.95)。

如果有,直接回傳快取的答案。如果沒有,呼叫 LLM 產生答案並存入快取。

import numpy as np

def get_cached_response(question, cache_db, threshold=0.95):
    question_embedding = get_embedding(question)
    results = cache_db.query(question_embedding, top_k=1)

    if results and results[0].score > threshold:
        return results[0].metadata["response"]
    return None

語意快取的限制:

對時效性內容不適用(「今天天氣如何」每次都不同)。

相似度閾值設太低會回傳不相關的答案。

回傳快取答案前要考慮使用者的上下文是否相同。

Token 成本估算

各模型的 Token 定價

模型 輸入(每百萬 Token) 輸出(每百萬 Token)
Claude Haiku 4.5 $0.80 $4.00
Claude Sonnet 5 $3.00 $15.00
Claude Opus 4 $15.00 $75.00
GPT-4o $2.50 $10.00
GPT-4o mini $0.15 $0.60

實際成本取決於你的使用模式。一個客服 Chatbot 每次對話平均 2000 token 輸入 + 500 token 輸出,用 Claude Haiku:

每次對話成本 = (2000 / 1M × $0.80) + (500 / 1M × $4.00)
            = $0.0016 + $0.002
            = $0.0036(約新台幣 0.12 元)

一天 500 次對話,一個月大約 $54 美金。

降低成本的方式

選擇合適的模型。不是所有任務都需要最大的模型。FAQ 回覆用 Haiku 就夠,複雜的技術分析再用 Sonnet 或 Opus。

縮短 System Prompt。把不必要的指令和背景資訊移除。很多 AI 應用的 System Prompt 有一半內容是冗餘的。

限制輸出長度。設定合理的 max_tokens。客服回覆不需要 4096 個 token。

用 Prompt Caching 減少重複的輸入 token 成本。

Batch API

如果你的 AI 任務不需要即時回應(例如每天凌晨處理昨天的客服對話摘要),可以用 Batch API。Batch API 的成本通常是即時 API 的一半,但回應時間可能需要數小時。

適合 Batch 處理的任務:大量文件摘要、歷史資料分析、定期報告生成、內容審核。

不適合 Batch 的任務:即時聊天、搜尋建議、表單驗證。

Rate Limiting 策略

AI 應用需要雙向的 Rate Limiting:

對使用者

防止單一使用者大量呼叫消耗 API 額度:

from slowapi import Limiter

limiter = Limiter(key_func=get_user_id)

@app.post("/chat")
@limiter.limit("20/hour")
async def chat(request: Request):
    ...

20 次/小時對一般使用者是合理的起點。企業用戶可以設更高的限制。

對上游 API

你的應用呼叫 LLM API 也有速率限制。Claude API 的速率限制依方案不同。超過限制會收到 429 錯誤。實作指數退避(exponential backoff):

import time

def call_with_retry(func, max_retries=3):
    for i in range(max_retries):
        try:
            return func()
        except RateLimitError:
            wait = 2 ** i
            time.sleep(wait)
    raise Exception("API rate limit exceeded after retries")

安全考量

快取的回應內容可能包含敏感資訊。如果你的 AI 應用處理不同使用者的不同權限資料,語意快取可能會把 A 使用者的回應提供給 B 使用者。快取策略要考慮使用者身份隔離。

Token 使用量的監控不只是成本問題。異常的 Token 消耗可能代表有人在濫用你的 API(例如用你的端點做 proxy 繞過 AI 服務商的使用政策)。設定 Token 使用量的告警。

Streaming Response 的安全:中間人如果攔截 streaming 資料,可以即時看到 AI 的回應內容。確保 streaming 端點使用 HTTPS。

知識檢測

讀完文章後,測試一下你對這個主題的理解。

常見問題

Streaming 和一般 Response 的成本一樣嗎?

一樣。Token 計費是按輸入和輸出的 token 數量,不是按請求方式。Streaming 只是改變了傳輸方式,不影響計費。

語意快取的命中率大概多少?

取決於你的應用場景。FAQ 類的客服 Chatbot 命中率可以到 30-50%。開放式對話的命中率通常低於 5%。命中率太低的話,維護快取的成本可能超過省下的 API 費用。

如何監控 Token 使用量?

Claude API 的每個回應都包含 usage 欄位,記錄了 input_tokensoutput_tokens。把這些數字記錄到資料庫或監控系統,設定每日和每月的用量告警。

有沒有免費的 AI API?

Google Gemini API 有免費方案(每分鐘 15 次請求)。Groq 提供限量免費的推論。Ollama 在本機跑模型不需要 API 費用,但需要自己的硬體資源。免費方案的資料使用政策通常比付費方案寬鬆,注意隱私問題。

Prompt Caching 和語意快取可以同時用嗎?

可以,兩者處理不同層級的問題。Prompt Caching 減少 System Prompt 的重複計算,語意快取減少重複問題的 API 呼叫。在 FAQ 類場景中同時使用效果最好。