Kostnadsminimering för LLM-system: Vart pengarna faktiskt går
Använd tokens där de verkligen gör skillnad.
LLM-kostnader skalar linjärt med användningen. Ett system som bearbetar 10 000 förfrågningar per dag till $0,01 per förfrågan kostar $100 dagligen — $365 per år. Vid enterprise-skala blir det över $10 000.
Kostnadsminimering handlar inte om att skära ner på kvalitet. Det handlar om att spendera tokens där det räcker.
Varje token du slösar är en token du hade kunnat spendera på ett bättre svar.

Tokenbudgetering
Det enklaste sättet att kontrollera kostnader är att sätta gränser. Per session, per uppgift eller per dag.
Strategi 1: Budget per session
Budget per session är rakt fram:
class SessionBudget:
def __init__(self, budget_tokens: int = 10000):
self.budget = budget_tokens
self.used = 0
def allocate(self, tokens: int) -> bool:
if self.used + tokens <= self.budget:
self.used += tokens
return True
return False
def remaining(self) -> int:
return self.budget - self.used
Strategi 2: Budget per uppgift
Budget per uppgift är mer användbar. Olika uppgifter kräver olika mängd kontext:
task_budgets:
classify:
max_tokens: 100
model: qwen2.5-1.5b
summarize:
max_tokens: 500
model: qwen2.5-7b
code_review:
max_tokens: 2000
model: qwen2.5-coder-7b
reason:
max_tokens: 4000
model: qwen2.5-32b
Strategi 3: Adaptiva budgetar
Adaptiva budgetar justeras baserat på vad som faktiskt händer. Om klassificeringsuppgifter konsekvent använder 80 tokens, sluta allokera 100:
class AdaptiveBudget:
def __init__(self):
self.task_history = {}
def allocate(self, task_type: str) -> int:
if task_type in self.task_history:
return int(self.task_history[task_type] * 1.5)
return 1000
def record(self, task_type: str, tokens_used: int):
if task_type not in self.task_history:
self.task_history[task_type] = tokens_used
else:
self.task_history[task_type] = (
0.9 * self.task_history[task_type] + 0.1 * tokens_used
)
Den exponentiella rörliga genomsnittet (vikt 0,9) betyder att senare användning väger tyngre än historik. Justera vikten baserat på hur volatila dina arbetsbelastningar är.
API vs lokal inferens
Lokal inferens är billigare i stor skala. Jämviktspunkten beror på din hårdvara och API-tariffer.
| Modell | API ($/M tokens) | Lokal kostnad/timme | Jämvikt |
|---|---|---|---|
| GPT-4o | $2,50 / $10,00 | — | N/A |
| Claude Sonnet 4 | $3,00 / $15,00 | — | N/A |
| Qwen2.5-72B | $0,50 / $2,00 | ~$0,50 | ~4 timmar/dag |
| Qwen2.5-32B | $0,30 / $1,20 | ~$0,20 | ~2 timmar/dag |
| Qwen2.5-7B | $0,10 / $0,40 | ~$0,05 | ~1 timme/dag |
Hårdvarumatematiken:
| Hårdvara | Uppföljning | Månadsl elm | Jämvikt vs API |
|---|---|---|---|
| RTX 3090 (beg) | $600 | $15 | ~4 månader |
| RTX 4090 | $1 500 | $20 | ~6 månader |
| RTX 5080 | $1 000 | $18 | ~5 månader |
| DGX Spark | $2 000 | $30 | ~8 månader |
Vid måttlig användning — en timme eller mer per dag — betalar lokal inferens sig själv. Vid hög användning är besparingarna dramatiska. Haken är den initiala kapitalinvesteringen. En RTX 5080 kostar $1 000. En API-räkning kan du pausa. Hårdvara kan du inte.
Återfallstrategier
När din föredragna modell är för dyr eller för långsam, fall tillbaka på något billigare. Nyckeln är att veta när kvaliteten är “tillräckligt bra”.
Strategi 1: Återfall baserat på kvalitet
Återfall baserat på kvalitet testar modeller tills utdata uppfyller en tröskel:
class QualityFallback:
def __init__(self, quality_threshold: float = 0.8):
self.threshold = quality_threshold
self.models = [
{"model": "claude-sonnet-4", "cost": 0.015},
{"model": "qwen2.5-72b", "cost": 0.002},
{"model": "qwen2.5-32b", "cost": 0.001},
{"model": "qwen2.5-7b", "cost": 0.0004},
]
def route(self, prompt: str) -> str:
for model_config in self.models:
result = self.call_model(model_config["model"], prompt)
if self.evaluate_quality(result) >= self.threshold:
return result
return self.call_model(self.models[0]["model"], prompt)
Problemets kärna ligger i utvärderingen i sig. Hur mäter du kvalitet utan att anropa en annan modell? Vissa system använder en liten klassificerare. Andra använder heuristiska kontroller — längd, struktur, förekomst av nyckelord. Inget av dessa är perfekt.
Strategi 2: Återfall baserat på latens
Återfall baserat på latens är enklare. Rutt till den snabbaste modellen som uppfyller din tidsbudget:
class LatencyFallback:
def __init__(self, max_latency: float = 5.0):
self.max_latency = max_latency
self.models = [
{"model": "qwen2.5-1.5b", "latency": 0.5},
{"model": "qwen2.5-7b", "latency": 2.0},
{"model": "qwen2.5-32b", "latency": 10.0},
{"model": "claude-sonnet-4", "latency": 5.0},
]
def route(self, prompt: str) -> str:
for model_config in sorted(self.models, key=lambda x: x["latency"]):
if model_config["latency"] <= self.max_latency:
return self.call_model(model_config["model"], prompt)
return self.call_model(self.models[0]["model"], prompt)
Cachelagring
Cachelagring är den mest underskattade kostnadsminimeringen. Identiska promptar händer oftare än du tror — klassificeringsförfrågningar, FAQ-stilfrågor, upprepade verktygsanrop.
Strategi 1: Promptcachelagring
Exakt promptcachelagring är enkel:
import hashlib
class PromptCache:
def __init__(self, max_size: int = 1000):
self.cache = {}
self.max_size = max_size
def get(self, prompt: str) -> str | None:
key = hashlib.sha256(prompt.encode()).hexdigest()
return self.cache.get(key)
def set(self, prompt: str, response: str):
key = hashlib.sha256(prompt.encode()).hexdigest()
if len(self.cache) >= self.max_size:
self.cache.pop(next(iter(self.cache)))
self.cache[key] = response
Strategi 2: Semantisk cachelagring
Semantisk cachelagring är mer användbar. Den fångar promptar som är olika men betyder samma sak:
from sentence_transformers import SentenceTransformer
class SemanticCache:
def __init__(self, similarity_threshold: float = 0.95):
self.model = SentenceTransformer('all-MiniLM-L6-v2')
self.cache = {}
self.threshold = similarity_threshold
def get(self, prompt: str) -> str | None:
prompt_embedding = self.model.encode([prompt])[0]
for cached_prompt, cached_response in self.cache.items():
cached_embedding = self.model.encode([cached_prompt])[0]
similarity = self.cosine_similarity(
prompt_embedding, cached_embedding
)
if similarity >= self.threshold:
return cached_response
return None
def set(self, prompt: str, response: str):
self.cache[prompt] = response
Tröskeln spelar roll. 0,95 är aggressivt — endast mycket lika promptar matchas. 0,85 är mer benådig men riskerar att returnera felaktiga svar. Mät din missrate och justera.
Svarscachelagring för vanliga frågor är också värt det. Om användare ställer “vad är vädret” eller “vilket är klockan” upprepade gånger, cachem mönstret, inte bara den exakta prompten:
class ResponseCache:
def __init__(self):
self.common_queries = {
"what is the weather": "Check weather API",
"what is the time": "Check system time",
"who is the president": "Check current president",
}
def get(self, query: str) -> str | None:
query_lower = query.lower()
for common_query, response in self.common_queries.items():
if common_query in query_lower:
return response
return None
Detta är inte sofistikerat, men det fungerar. Vanliga frågor är vanliga av en anledning.
När optimering hjälper
Optimering spelar roll när du bearbetar höga volymer, kör blandade arbetsbelastningar, eller betalar API-kostnader som staplas upp.
Det spelar ingen roll när du prototyperar, använder en enda modell, eller bearbetar låga volymer. Komplexiteten med budgetering, återfall och cachelagring är inte värd det för ett system som gör 100 förfrågningar per dag.
Få den grundläggande flödet att fungera först. Lägg till optimering när räkningen kommer.
Avvägningar
| Strategi | Kostnad | Kvalitet | Komplexitet |
|---|---|---|---|
| Ingen optimering | Högst | Konsistent | Lägsta |
| Tokenbudgetering | Medel | Variabel | Medel |
| Återfallsmodeller | Låg-Medel | Variabel | Medel |
| Cachelagring | Lägst | Hög (för cacheträffar) | Medel |
| Hybrid | Optimerad | Optimerad | Högst |
Produktionssystem kör oftast hybrid. Budgetera per session, fall tillbaka på kvalitet eller latens, cachem vad du kan. Komplexiteten är verklig, men besparingarna är det också.
Relaterat
- Modellrutningsstrategier — kapacitetsbaserad, kostnadsmedveten, latensmedveten routing
- LLM-vägspärrar i praktiken — inputvalidering, outputfiltrering, säkerhet
- Systemdesign för multimodellsystem — arkitektur för flera modeller
- LLM-arkitektur — systemdesignpelare: routing, kostnad, vägspärrar och orkestrering