Zmniejsz koszty LLM: strategie optymalizacji tokenów

Zredukuj koszty LLM o 80% dzięki inteligentnej optymalizacji tokenów

Page content

Optymalizacja tokenów to kluczowe umiejętności, które oddzielają kosztowne aplikacje LLM od doświadczeń zużycia budżetu.

Z uwagi na to, że koszty API rosną liniowo wraz z użyciem tokenów, zrozumienie i wdrażanie strategii optymalizacji może zmniejszyć koszty o 60–80%, jednocześnie zachowując jakość.

inteligentna architektura

Zrozumienie ekonomiki tokenów

Przed optymalizacją należy zrozumieć, jak działają tokeny i ceny w różnych dostawcach LLM.

Podstawy tokenów

Tokeny to podstawowe jednostki przetwarzane przez LLM – w przybliżeniu odpowiadają 4 znakom lub 0,75 słowom w języku angielskim. Ciąg “Hello, world!” zawiera około 4 tokeny. Różne modele używają różnych tokenizatorów (GPT używa tiktoken, Claude używa własnego), więc liczba tokenów może się nieznacznie różnić między dostawcami.

Porównanie modeli ceny

Ceny OpenAI (stan na 2025):

  • GPT-4 Turbo: $0,01 wejście / $0,03 wyjście na 1000 tokenów
  • GPT-3.5 Turbo: $0,0005 wejście / $0,0015 wyjście na 1000 tokenów
  • GPT-4o: $0,005 wejście / $0,015 wyjście na 1000 tokenów

Ceny Anthropic:

  • Claude 3 Opus: $0,015 wejście / $0,075 wyjście na 1000 tokenów
  • Claude 3 Sonnet: $0,003 wejście / $0,015 wyjście na 1000 tokenów
  • Claude 3 Haiku: $0,00025 wejście / $0,00125 wyjście na 1000 tokenów

Aby uzyskać szczegółowe porównanie dostawców LLM w chmurze, w tym szczegółowe ceny, funkcje i przypadki użycia, sprawdź nasz dedykowany przewodnik.

Główne spostrzeżenie: Tokeny wyjściowe kosztują 2–5 razy więcej niż tokeny wejściowe. Ograniczanie długości wyjścia ma znaczny wpływ na koszty.

Inżynieria promptów dla wydajności

Efektywna inżynieria promptów znacząco zmniejsza zużycie tokenów bez utraty jakości.

1. Eliminacja nadmiarowości

Zły przykład (127 tokenów):

Jestes pomocnym asystentem. Proszę pomóż mi z poniższym zadaniem.
Chciałbym, abyś przeanalizował poniższy tekst i podał mi
podsumowanie. Oto tekst, który chciałbym podsumować:
[tekst]
Proszę podaj skrócony podsumowanie głównych punktów.

Optymalizowany (38 tokenów):

Podsumuj kluczowe punkty:
[tekst]

Zysk: 70% zmniejszenie liczby tokenów, identyczna jakość wyjścia.

2. Użycie strukturalnych formatów

Formaty JSON i strukturalne wyjścia zmniejszają marnotrawstwo tokenów z powodu rozbudowanego języka naturalnego.

Zamiast:

Proszę wyodrębnić imię, wiek i zawód osoby z tego tekstu
i sformatuj odpowiedź jasno.

Użyj:

Wyodrębnij do JSON: {imie, wiek, zawód}
Tekst: [wejście]

3. Optymalizacja uczenia z kilkoma przykładami

Przykłady z kilkoma przykładami są potężne, ale drogie. Optymalizuj, stosując:

  • Użyj minimalnej liczby przykładów (1–3 zazwyczaj wystarczających)
  • Zachowuj przykłady skrócone – usuń zbędne słowa
  • Udostępniaj wspólne prefiksy – zmniejsz powtarzane instrukcje
# Optymalizowany prompt z kilkoma przykładami
prompt = """Kategoryzuj nastrój (poz/neg):
Tekst: "Świetny produkt!" -> poz
Tekst: "Zdenerwowany" -> neg
Tekst: "{wejście}" ->"""

Aby uzyskać więcej wzorców optymalizacji Pythona i skrótów składniowych, zobacz nasz cheatsheet Pythona.

Strategie cacheowania kontekstu

Cacheowanie kontekstu to najbardziej skuteczna optymalizacja dla aplikacji z powtarzającym się statycznym treścią.

Jak działa cacheowanie kontekstu

Dostawcy takie jak OpenAI i Anthropic cacheują prefiksy promptów, które pojawiają się w wielu żądaniach. Zacheowane części kosztują o 50–90% mniej niż normalne tokeny.

Wymagania:

  • Minimalna długość cacheowalnego treści: 1024 tokeny (OpenAI) lub 2048 tokeny (Anthropic)
  • TTL cache: 5–60 minut w zależności od dostawcy
  • Treść musi być identyczna i pojawiać się na początku promptu

Przykład implementacji

from openai import OpenAI

client = OpenAI()

# Systemowy prompt cacheowany w wielu żądaniach
SYSTEM_PROMPT = """Jestes AI obsługującym klienta dla TechCorp.
Zasady firmy:
[Długie dokumenty zasad - 2000 tokenów]
"""

# To jest automatycznie cacheowane
response = client.chat.completions.create(
    model="gpt-4-turbo",
    messages=[
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": "Jak zwrócić produkt?"}
    ]
)

# Następne wywołania w czasie trwałości cacheu używają zacheowanego systemowego promptu
# Płacąc tylko za wiadomość użytkownika + wyjście

Wpływ w praktyce: Aplikacje z bazami wiedzy lub długimi instrukcjami widzą zmniejszenie kosztów o 60–80%.

Strategia wyboru modelu

Użycie odpowiedniego modelu dla każdego zadania jest kluczowe dla optymalizacji kosztów.

Drabinka modeli

  1. GPT-4 / Claude Opus – złożone rozumowanie, kreatywne zadania, krytyczna dokładność
  2. GPT-4o / Claude Sonnet – zrównoważona wydajność / koszt, ogólny cel
  3. GPT-3.5 / Claude Haiku – proste zadania, klasyfikacja, ekstrakcja
  4. Dostosowane mniejsze modele – specjalistyczne powtarzające się zadania

Wzorzec routingu

def route_request(task_complexity, user_query):
    """Routuj do odpowiedniego modelu na podstawie złożoności"""
    
    # Prosta klasyfikacja – użyj Haiku
    if task_complexity == "prosta":
        return call_llm("claude-3-haiku", user_query)
    
    # Średnia – użyj Sonnet
    elif task_complexity == "średnia":
        return call_llm("claude-3-sonnet", user_query)
    
    # Złożone rozumowanie – użyj Opus
    else:
        return call_llm("claude-3-opus", user_query)

Przypadek studium: Chatbot obsługujący klienta, który kieruje 80% zapytań do GPT-3.5 i 20% do GPT-4 zmniejszył koszty o 75% w porównaniu do użycia GPT-4 dla wszystkiego.

Przetwarzanie wsadowe

Dla prac niezależnych od czasu, przetwarzanie wsadowe oferuje 50% zniżki od większości dostawców.

OpenAI API wsadowy

from openai import OpenAI
client = OpenAI()

# Utwórz plik wsadowy
batch_requests = [
    {"custom_id": f"request-{i}", 
     "method": "POST",
     "url": "/v1/chat/completions",
     "body": {
         "model": "gpt-3.5-turbo",
         "messages": [{"role": "user", "content": query}]
     }}
    for i, query in enumerate(queries)
]

# Wyślij wsadowe (50% zniżka, przetwarzanie 24h)
batch = client.batches.create(
    input_file_id=upload_batch_file(batch_requests),
    endpoint="/v1/chat/completions",
    completion_window="24h"
)

Przypadki użycia:

  • Etykietowanie i anotacja danych
  • Generowanie treści dla blogów/SEO
  • Generowanie raportów
  • Przetwarzanie wsadowe tłumaczeń
  • Generowanie syntetycznych danych

Techniki kontroli wyjścia

Ponieważ tokeny wyjściowe kosztują 2–5 razy więcej, kontrolowanie długości wyjścia jest krytyczne.

1. Ustaw maksymalną liczbę tokenów

response = client.chat.completions.create(
    model="gpt-4",
    messages=messages,
    max_tokens=150  # Twardy limit zapobiega niekontrolowanym kosztom
)

2. Użyj sekwencji zatrzymania

response = client.chat.completions.create(
    model="gpt-4",
    messages=messages,
    stop=["END", "\n\n\n"]  # Zatrzymaj przy znacznikach
)

3. Wymagaj skróconych formatów

Dodaj instrukcje takie jak:

  • “Odpowiedz w mniej niż 50 słowach”
  • “Podaj tylko punkty”
  • “Zwróć tylko JSON, bez wyjaśnień”

Strumieniowanie dla lepszej UX

Choć strumieniowanie nie zmniejsza kosztów, poprawia wrażenie wydajności i umożliwia wczesne zakończenie.

stream = client.chat.completions.create(
    model="gpt-4",
    messages=messages,
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        token = chunk.choices[0].delta.content
        print(token, end="")
        
        # Wczesne zakończenie, jeśli odpowiedź wychodzi poza ścieżkę
        if undesired_pattern(token):
            break

Optymalizacja RAG

Generacja wzbogacana przez odzyskiwanie (RAG) dodaje kontekst, ale nieoptymalizowany RAG marnotrawi tokeny.

Efektywny wzorzec RAG

def optimized_rag(query, vector_db):
    # 1. Pobierz odpowiednie fragmenty
    chunks = vector_db.search(query, top_k=3)  # Nie zbyt wiele
    
    # 2. Skompresuj fragmenty – usuń nadmiary
    compressed = compress_chunks(chunks)  # Własna kompresja
    
    # 3. Obcięcie do limitu tokenów
    context = truncate_to_tokens(compressed, max_tokens=2000)
    
    # 4. Strukturalny prompt
    prompt = f"Kontekst:\n{context}\n\nQ: {query}\nA:"
    
    return call_llm(prompt)

Techniki optymalizacji:

  • Użyj segmentacji semantycznej (nie stałej wielkości)
  • Usuń formatowanie markdown z pobranych fragmentów
  • Zaimplementuj ponowne rangowanie, aby uzyskać najbardziej relevantne treści
  • Rozważ sumaryzację fragmentów dla dużych dokumentów

Caching odpowiedzi

Cacheuj identyczne lub podobne żądania, aby uniknąć całkowicie wywołań API.

Implementacja z Redis

import redis
import hashlib
import json

redis_client = redis.Redis()

def cached_llm_call(prompt, model="gpt-4", ttl=3600):
    # Utwórz klucz cache z promptu + modelu
    cache_key = hashlib.md5(
        f"{model}:{prompt}".encode()
    ).hexdigest()
    
    # Sprawdź cache
    cached = redis_client.get(cache_key)
    if cached:
        return json.loads(cached)
    
    # Wywołaj LLM
    response = call_llm(model, prompt)
    
    # Zapisz wynik w cache
    redis_client.setex(
        cache_key, 
        ttl, 
        json.dumps(response)
    )
    
    return response

Caching semantyczny: Dla podobnych (nieidentycznych) zapytań, użyj wektorowych embeddingów, aby znaleźć zapisane odpowiedzi.

Monitorowanie i analizy

Śledź użycie tokenów, aby zidentyfikować możliwości optymalizacji.

Kluczowe metryki

class TokenTracker:
    def __init__(self):
        self.metrics = {
            'total_tokens': 0,
            'input_tokens': 0,
            'output_tokens': 0,
            'cost': 0.0,
            'requests': 0
        }
    
    def track_request(self, response, model):
        usage = response.usage
        self.metrics['input_tokens'] += usage.prompt_tokens
        self.metrics['output_tokens'] += usage.completion_tokens
        self.metrics['total_tokens'] += usage.total_tokens
        self.metrics['cost'] += calculate_cost(usage, model)
        self.metrics['requests'] += 1
    
    def report(self):
        return {
            'avg_tokens_per_request': 
                self.metrics['total_tokens'] / self.metrics['requests'],
            'total_cost': self.metrics['cost'],
            'input_output_ratio': 
                self.metrics['input_tokens'] / self.metrics['output_tokens']
        }

Alerty kosztowe

Ustaw alerty, gdy użycie przekracza próg:

def check_cost_threshold(daily_cost, threshold=100):
    if daily_cost > threshold:
        send_alert(f"Koszt dzienny ${daily_cost} przekroczony ${threshold}")

Zaawansowane techniki

1. Modele kompresji promptów

Użyj dedykowanych modeli do kompresji promptów:

  • LongLLMLingua
  • AutoCompressors
  • Uczone tokeny kompresji

Te modele mogą osiągnąć 10x współczynnik kompresji, jednocześnie zachowując 90%+ wydajność zadania.

2. Dekodowanie spekulacyjne

Uruchom mały model obok dużego modelu, aby przewidzieć tokeny, zmniejszając wywołania dużego modelu. Zwykle 2–3x przyspieszenie i zmniejszenie kosztów dla podobnej jakości.

3. Kwantyzacja

Dla modeli samodzielnie hostowanych, kwantyzacja (4-bit, 8-bit) zmniejsza pamięć i obliczenia:

  • 4-bit: ~75% zmniejszenie pamięci, minimalna utrata jakości
  • 8-bit: ~50% zmniejszenie pamięci, znikoma utrata jakości

Jeśli uruchamiasz LLM lokalnie, Ollama oferuje świetną platformę do wdrażania modeli z kwantyzacją z minimalną konfiguracją. Dla wyboru sprzętu i testów wydajności, nasze porównanie NVIDIA DGX Spark vs Mac Studio vs RTX-4080 pokazuje rzeczywistą wydajność na różnych konfiguracjach sprzętu uruchamiających duże modele z kwantyzacją.

Lista sprawdzania optymalizacji kosztów

  • Profiluj obecne użycie tokenów i koszty na endpoint
  • Audytuj prompty na nadmiarowość – usuń zbędne słowa
  • Wdroż cacheowanie kontekstu dla treści statycznych > 1K tokenów
  • Ustaw routing modeli (małe dla prostych, duże dla złożonych)
  • Dodaj ograniczenia max_tokens do wszystkich żądań
  • Wdroż cacheowanie odpowiedzi dla identycznych zapytań
  • Użyj API wsadowego dla prac niezależnych od czasu
  • Włącz strumieniowanie dla lepszej UX
  • Optymalizuj RAG: mniej fragmentów, lepsze rangowanie
  • Monitoruj za pomocą śledzenia tokenów i alertów kosztowych
  • Rozważ dostosowanie dla powtarzających się zadań
  • Ocenić mniejsze modele (Haiku, GPT-3.5) dla klasyfikacji

Przypadek studium w praktyce

Scenariusz: Chatbot obsługujący klienta, 100K żądań/miesiąc

Przed optymalizacją:

  • Model: GPT-4 dla wszystkich żądań
  • Średnia liczba tokenów wejściowych: 800
  • Średnia liczba tokenów wyjściowych: 300
  • Koszt: 100K × (800 × 0,00003 + 300 × 0,00006) = $4200/miesiąc

Po optymalizacji:

  • Routing modeli: 80% GPT-3.5, 20% GPT-4
  • Cacheowanie kontekstu: 70% promptów zacheowane
  • Kompresja promptów: 40% zmniejszenie
  • Cacheowanie odpowiedzi: 15% stopień trafienia

Wyniki:

  • 85% żądań uniknęło GPT-4
  • 70% korzyści z zniżki cacheu kontekstu
  • 40% mniej tokenów wejściowych
  • Efektywny koszt: $780/miesiąc
  • Zysk: 81% ($3420/miesiąc)

Przydatne linki

Podsumowanie

Optymalizacja tokenów przekształca ekonomikę LLM z prohibitwnie drogiej w trwałą skalowalność. Poprzez wdrażanie kompresji promptów, cacheowania kontekstu, inteligentnego wyboru modeli i cacheowania odpowiedzi, większość aplikacji osiąga zmniejszenie kosztów o 60–80% bez kompromitacji jakości.

Zacznij od szybkich zwycięstw: audytuj swoje prompty, włącz cacheowanie kontekstu i kieruj proste zadania do mniejszych modeli. Śledź swoje użycie tokenów religijnie – to, co jest mierzone, jest optymalizowane. Różnica między kosztowną aplikacją LLM a drogą jest nie technologia – to strategia optymalizacji.

Powiązane artykuły