0Pricing
AI Prompt Engineering · Lezione

Compromessi tra costi e latenza

Budget dei thinking token, costi di inferenza e strategie di routing ibride

Compromessi tra costi e latenza è una lezione AI Prompt Engineering gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Prompt Engineering, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Prompt Engineering include 4 lezioni in totale.

Il triangolo costi-qualità-latenza

Nella progettazione di sistemi LLM esiste un triangolo fondamentale: costo, qualità e latenza. In un dato momento, può ottimizzare al massimo due di questi tre fattori.

  • Costo ridotto + Qualità elevata = Lento (modelli di ragionamento, generazione lenta)
  • Costo ridotto + Latenza ridotta = Qualità inferiore (modelli piccoli e veloci)
  • Qualità elevata + Latenza ridotta = Costoso (modello di ragionamento con streaming)

Ogni scelta architetturale rappresenta un compromesso all'interno di questo triangolo.

Prezzi dei modelli di ragionamento

I token di ragionamento hanno un costo aggiuntivo, oltre ai token standard di input/output. Il costo di una chiamata a un modello di ragionamento include: token di input + token di ragionamento + token di output.

Rispetto ai modelli veloci e più piccoli: o3 è circa 20 volte più costoso di GPT-4o-mini per token; Claude Opus con il ragionamento esteso è circa 10-15 volte più costoso di Claude Haiku per token di output.

# Rough cost estimates (2025 pricing, may change)
# Source: provider pricing pages

PRICING = {
    # (input $/1M tokens, output $/1M tokens)
    'gpt-4o-mini':       (0.15,   0.60),
    'gpt-4o':            (2.50,  10.00),
    'o3-mini':           (1.10,   4.40),
    'o3':                (10.0,  40.00),
    'claude-haiku-4-5':  (0.25,   1.25),
    'claude-sonnet-4-5': (3.00,  15.00),
    'claude-opus-4-5':   (15.0,  75.00),
}

def estimate_cost(model, input_tokens, output_tokens, thinking_tokens=0):
    inp_price, out_price = PRICING[model]
    # Thinking tokens billed as output tokens
    total_out = output_tokens + thinking_tokens
    cost = (input_tokens / 1e6 * inp_price) + (total_out / 1e6 * out_price)
    return cost

# A single hard question with 8000 thinking tokens:
cost = estimate_cost('claude-opus-4-5', 500, 300, thinking_tokens=8000)
print(f'Cost per call: ${cost:.4f}')

Sovraccarico dei token di ragionamento

I token di ragionamento sono spesso molto più numerosi dei token di output. Una risposta concisa di 200 parole può basarsi su 5.000-15.000 token di ragionamento. Questi token costano quanto i token di output.

Ecco perché il moltiplicatore dei costi dei modelli di ragionamento dipende soprattutto dai token di ragionamento, non dalla lunghezza della risposta.

import anthropic

client = anthropic.Anthropic(api_key='sk-ant-...')

def analyze_token_breakdown(question, budget_tokens):
    response = client.messages.create(
        model='claude-opus-4-5',
        max_tokens=budget_tokens + 2000,
        thinking={'type': 'enabled', 'budget_tokens': budget_tokens},
        messages=[{'role': 'user', 'content': question}]
    )

    # Usage breakdown
    usage = response.usage
    print(f'Input tokens:  {usage.input_tokens:,}')
    print(f'Output tokens: {usage.output_tokens:,}')

    # Thinking tokens are in cache_creation_input_tokens on some APIs
    # or can be estimated from thinking block content length
    thinking_blocks = [b for b in response.content if b.type == 'thinking']
    est_thinking = sum(len(b.thinking.split()) * 1.3 for b in thinking_blocks)
    print(f'Est. thinking tokens: {int(est_thinking):,}')
    answer = next(b.text for b in response.content if b.type == 'text')
    print(f'Answer words: {len(answer.split())}')

analyze_token_breakdown(
    'Explain the trade-offs between REST and GraphQL APIs.',
    budget_tokens=5000
)

Latenza: cosa aspettarsi

Intervalli di latenza osservati per diverse configurazioni dei modelli, che variano significativamente in base al carico e alla difficoltà del problema:

  • Claude Haiku: 0,5-2 secondi
  • Claude Sonnet: 2-8 secondi
  • Claude Opus (senza ragionamento): 5-15 secondi
  • Claude Opus (ragionamento 5K): 15-40 secondi
  • Claude Opus (ragionamento 16K): 40-90 secondi
  • o3 (sforzo elevato): 30-120 secondi
import time
import anthropic

client = anthropic.Anthropic(api_key='sk-ant-...')

def benchmark_latency(prompt, model, budget_tokens=None):
    kwargs = {
        'model': model,
        'max_tokens': 2000,
        'messages': [{'role': 'user', 'content': prompt}]
    }
    if budget_tokens:
        kwargs['thinking'] = {'type': 'enabled', 'budget_tokens': budget_tokens}
        kwargs['max_tokens'] = budget_tokens + 2000

    start = time.time()
    response = client.messages.create(**kwargs)
    elapsed = time.time() - start
    answer = response.content[-1].text
    print(f'{model} (budget={budget_tokens}): {elapsed:.1f}s')
    return elapsed, answer

benchmark_latency('Name 3 planets', 'claude-haiku-4-5')
benchmark_latency('Solve x^2 - 5x + 6 = 0', 'claude-opus-4-5', 3000)
benchmark_latency('Design a fault-tolerant payment system', 'claude-opus-4-5', 10000)

Tempo al primo token con lo streaming

Sebbene la latenza totale dei modelli di ragionamento sia elevata, il tempo al primo token (TTFT) con lo streaming può essere molto inferiore: il modello inizia a trasmettere la risposta immediatamente dopo aver terminato il ragionamento. Mostri rapidamente qualcosa all'utente utilizzando lo streaming.

import anthropic
import time

client = anthropic.Anthropic(api_key='sk-ant-...')

def stream_with_timing(prompt):
    start = time.time()
    first_token_time = None
    full_text = ''

    with client.messages.stream(
        model='claude-opus-4-5',
        max_tokens=10000,
        thinking={'type': 'enabled', 'budget_tokens': 5000},
        messages=[{'role': 'user', 'content': prompt}]
    ) as stream:
        in_answer = False
        for text_chunk in stream.text_stream:
            if not in_answer:
                in_answer = True
                first_token_time = time.time() - start
                print(f'Time to first answer token: {first_token_time:.1f}s')
            full_text += text_chunk
            print(text_chunk, end='', flush=True)

    total_time = time.time() - start
    print(f'\nTotal time: {total_time:.1f}s')

stream_with_timing('List 5 key benefits of microservices.')

Il pattern architetturale ibrido

Un pattern pratico per la produzione consiste nell'utilizzare prima un modello standard veloce. Se il risultato è soddisfacente, lo verifichi con la metrica di qualità e lo restituisca immediatamente. In caso contrario, passi a un modello di ragionamento. In questo modo ottiene una latenza e un costo medi ridotti, mantenendo un'elevata accuratezza nei casi complessi.

import anthropic

client = anthropic.Anthropic(api_key='sk-ant-...')

def hybrid_query(question, quality_threshold=0.7):
    # Step 1: Try fast model first
    r_fast = client.messages.create(
        model='claude-haiku-4-5',
        max_tokens=300,
        messages=[{'role': 'user', 'content': question}]
    )
    fast_answer = r_fast.content[0].text

    # Step 2: Quick confidence check
    confidence_check = client.messages.create(
        model='claude-haiku-4-5',
        max_tokens=20,
        messages=[{
            'role': 'user',
            'content': (
                f'Q: {question}\nA: {fast_answer}\n'
                f'Rate answer quality 0.0-1.0. Number only:'
            )
        }]
    )
    try:
        quality = float(confidence_check.content[0].text.strip())
    except ValueError:
        quality = 0.5

    if quality >= quality_threshold:
        return fast_answer, 'fast'

    # Step 3: Escalate to reasoning model
    r_slow = client.messages.create(
        model='claude-opus-4-5',
        max_tokens=8000,
        thinking={'type': 'enabled', 'budget_tokens': 6000},
        messages=[{'role': 'user', 'content': question}]
    )
    return next(b.text for b in r_slow.content if b.type == 'text'), 'reasoning'

Costi su larga scala: facciamo i conti

I modelli di ragionamento che sembrano convenienti durante i test diventano costosi su larga scala. Proietti sempre i costi prima di scegliere un'architettura.

def project_monthly_cost(daily_queries, model_config):
    """
    Project monthly API costs for different configurations.
    model_config: dict with 'cost_per_query' key
    """
    monthly_queries = daily_queries * 30
    monthly_cost = monthly_queries * model_config['cost_per_query']

    print(f'Daily queries: {daily_queries:,}')
    print(f'Monthly queries: {monthly_queries:,}')
    print(f'Cost per query: ${model_config["cost_per_query"]:.4f}')
    print(f'Monthly cost: ${monthly_cost:,.2f}')
    return monthly_cost

# Compare configurations at 10,000 queries/day
configs = [
    {'name': 'All Haiku', 'cost_per_query': 0.0005},
    {'name': 'All Sonnet', 'cost_per_query': 0.015},
    {'name': 'All Opus+Thinking', 'cost_per_query': 0.85},
    {'name': 'Hybrid (90% Haiku, 10% Opus)', 'cost_per_query': 0.9*0.0005 + 0.1*0.85},
]

for config in configs:
    print(f'\n--- {config["name"]} ---')
    project_monthly_cost(10_000, config)

Caching dei prompt per ridurre i costi

Per le chiamate a modelli di ragionamento con prompt di sistema o contesti lunghi e ripetuti, utilizzi il caching dei prompt. I token memorizzati nella cache costano il 90% in meno di quelli non memorizzati. Questa strategia è particolarmente efficace quando lo stesso contesto esteso, come documenti o codice, viene inviato ripetutamente.

import anthropic

client = anthropic.Anthropic(api_key='sk-ant-...')

LONG_CONTEXT = 'A' * 50000  # Simulated large document

# With prompt caching: mark large context as cacheable
response = client.messages.create(
    model='claude-opus-4-5',
    max_tokens=10000,
    thinking={'type': 'enabled', 'budget_tokens': 6000},
    system=[
        {
            'type': 'text',
            'text': f'You are analyzing this document: {LONG_CONTEXT}',
            'cache_control': {'type': 'ephemeral'}  # Cache this prefix
        }
    ],
    messages=[{
        'role': 'user',
        'content': 'What are the main themes in this document?'
    }]
)

usage = response.usage
print(f'Cache read tokens: {getattr(usage, "cache_read_input_tokens", 0):,}')
print(f'Cache creation tokens: {getattr(usage, "cache_creation_input_tokens", 0):,}')
# Second call with same system content costs ~90% less on cached tokens

Elaborazione in batch per ottimizzare i costi

OpenAI e Anthropic offrono entrambe API batch con uno sconto del 50% per le richieste non sensibili al tempo. Se dispone di grandi volumi di query che possono attendere ore prima di ricevere una risposta, l'elaborazione in batch è l'opzione più conveniente.

import anthropic
import json

client = anthropic.Anthropic(api_key='sk-ant-...')

# Batch API: 50% cheaper, 24-hour turnaround
requests = [
    {
        'custom_id': f'query_{i}',
        'params': {
            'model': 'claude-opus-4-5',
            'max_tokens': 1024,
            'messages': [{'role': 'user', 'content': f'Analyze dataset row {i}'}]
        }
    }
    for i in range(100)  # 100 queries in one batch
]

# Submit batch
batch = client.messages.batches.create(requests=requests)
print(f'Batch ID: {batch.id}')
print(f'Status: {batch.processing_status}')
print(f'Requests: {batch.request_counts}')
# Poll batch.id for results when processing_status == 'ended'

Ottimizzazione del budget dei token

Imposti budget_tokens su un valore adeguato alla categoria del problema. Utilizzare un budget di 16K per un problema semplice spreca token e aumenta la latenza. Costruisca una tabella di consultazione del budget basata su livelli di difficoltà del problema.

BUDGET_LOOKUP = {
    'simple_math':        1000,   # Arithmetic, basic algebra
    'medium_code':        3000,   # Function implementation, debugging
    'complex_reasoning':  8000,   # System design, complex analysis
    'research_grade':    16000,   # Proofs, research-level problems
}

def budget_for_query(query):
    q_lower = query.lower()
    if any(kw in q_lower for kw in ['calculate', 'what is', 'how many', 'convert']):
        return BUDGET_LOOKUP['simple_math']
    elif any(kw in q_lower for kw in ['code', 'function', 'bug', 'implement']):
        return BUDGET_LOOKUP['medium_code']
    elif any(kw in q_lower for kw in ['design', 'architecture', 'analyze', 'strategy']):
        return BUDGET_LOOKUP['complex_reasoning']
    else:
        return BUDGET_LOOKUP['medium_code']  # Safe default

print(budget_for_query('What is 15% of 340?'))       # 1000
print(budget_for_query('Implement a trie in Python')) # 3000
print(budget_for_query('Design a CDC pipeline'))      # 8000

Definizione degli SLA per le applicazioni LLM

Prima di scegliere tra modelli standard e modelli di ragionamento, definisca i requisiti del Service Level Agreement (SLA) della sua applicazione:

  • Latenza P50: esperienza utente tipica
  • Latenza P99: esperienza utente nel caso peggiore
  • Budget dei token: costo massimo per query utente
  • Soglia minima di qualità: accuratezza minima accettabile sul set di test

I modelli di ragionamento violano facilmente gli SLA di latenza P99 delle applicazioni interattive. Conosca i suoi vincoli prima di definire l'architettura.

Verifica: costi dei modelli di ragionamento

Qual è il principale fattore che determina i costi elevati dei modelli di ragionamento rispetto ai modelli standard?

Riepilogo: compromessi tra costi e latenza

I modelli di ragionamento sono costosi: i token di ragionamento vengono fatturati come token di output e possono essere da 10 a 50 volte più numerosi della risposta visibile. La latenza varia da 15 a 120 secondi per i problemi complessi. Riduca l'impatto con: il pattern ibrido, che utilizza prima un modello veloce e passa a un modello di ragionamento solo quando la confidenza è bassa; il caching dei prompt per i contesti estesi ripetuti, con uno sconto del 90% sui token memorizzati; l'API batch per i carichi offline, con uno sconto del 50%; e un dimensionamento adeguato di budget_tokens in base alla difficoltà del problema. Su larga scala, anche piccoli costi per query si moltiplicano fino a produrre fatture mensili elevate. Proietti sempre i costi prima di impegnarsi in un'architettura.

Domande Frequenti

La lezione «Compromessi tra costi e latenza» è gratuita?

Sì — il testo completo di «Compromessi tra costi e latenza» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Prompt Engineering, passa a CoddyKit PRO. Il corso AI Prompt Engineering include 4 lezioni in totale.

Cosa imparerò in «Compromessi tra costi e latenza»?

Budget dei thinking token, costi di inferenza e strategie di routing ibride Eserciti AI Prompt Engineering con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare AI Prompt Engineering?

Non è richiesta alcuna esperienza precedente. AI Prompt Engineering su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Compromessi tra costi e latenza»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione AI Prompt Engineering?

Sì. Ogni lezione AI Prompt Engineering include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Differenze tra i modelli di reasoning
  2. Prompt efficaci per il ragionamento esteso
  3. Quando usare modelli di reasoning o standard
  4. Compromessi tra costi e latenza
← Torna a AI Prompt Engineering