Torna al blog

Per iniziareGuida

Prima richiesta a CheapTokens in Python con requests, senza SDK

Uno script Python di 20 righe con solo requests: un chat completion, un timeout, gestione degli errori HTTP e la stampa di risposta, finish_reason e usage.

Di CheapTokens TeamPubblicato il 4 min di lettura

Script Python che chiama l'endpoint chat completions di CheapTokens con requests
In questa pagina
  1. Lo script completo
  2. Cosa fa ogni riga
  3. Leggere la risposta
  4. Quando non funziona
  5. Quanto costa una chiamata
  6. Da dove andare da qui

Non hai bisogno del pacchetto openai per parlare con un'API compatibile con OpenAI. Una chiamata requests.post, una chiave Bearer e un corpo JSON sono sufficienti, e vedi esattamente cosa passa sulla rete. Questa guida costruisce quello script per CheapTokens (https://api.cheaptokens.dev/v1/chat/completions) e termina con la stampa della risposta, finish_reason e dell'utilizzo dei token.

È adatto se sei su una macchina bloccata dove è installato solo requests, se un piccolo cron job non dovrebbe tirare dentro un SDK, o se vuoi semplicemente capire cosa fa l'SDK per te. La guida alla prima richiesta copre le vie SDK, curl e Node; questa è quella in puro Python.

Lo script completo#

Metti prima la tua chiave in una variabile d'ambiente (vedi come memorizzare in sicurezza una chiave API), poi salva questo come ask.py:

python
import os
import requests

url = "https://api.cheaptokens.dev/v1/chat/completions"
headers = {"Authorization": f"Bearer {os.environ['CHEAPTOKENS_API_KEY']}"}
payload = {
    "model": "deepseek-ai/DeepSeek-V4-Flash-0731",
    "messages": [
        {"role": "user", "content": "Explain what a token is in two sentences."}
    ],
    "max_tokens": 200,
}

try:
    r = requests.post(url, headers=headers, json=payload, timeout=30)
    r.raise_for_status()
except requests.exceptions.Timeout:
    raise SystemExit("No reply within 30 seconds - try again or raise the timeout")
except requests.exceptions.HTTPError as e:
    raise SystemExit(f"HTTP {e.response.status_code}: {e.response.text}")

data = r.json()
choice = data["choices"][0]
print(choice["message"]["content"])
print("finish_reason:", choice["finish_reason"])
print("usage:", data["usage"])

Esegui python ask.py. L'id del modello è l'id completo del gateway, deepseek-ai/DeepSeek-V4-Flash-0731; se non sei sicuro di cosa mettere, elenca i modelli con GET /v1/models. Per provare un altro modello, sostituisci con zai-org/GLM-5.3-Flash e non cambiare altro: un saldo copre tutti i modelli.

Il percorso di una richiesta: chiave, POST, raise_for_status, choices, usage
Una richiesta dal tuo script alla risposta stampata

Cosa fa ogni riga#

Ecco le cinque idee su cui si basa lo script. Il Quickstart di requests (documentazione viva, verificata il 2 novembre 2026) spiega la maggior parte di esse, e il riferimento Chat Completions di OpenAI definisce i campi della risposta.

Flashcard

Cinque cose nello script

Il terzo punto è quello che la gente salta. Uno script che si blocca per sempre in un cron job è molto peggio di uno che fallisce rumorosamente dopo 30 secondi.

Leggere la risposta#

Una risposta riuscita è JSON. Le parti che ti interessano, secondo il riferimento Chat Completions:

  • choices[0].message.content è il testo. Può essere null, quindi non chiamare metodi di stringa su di esso alla cieca.
  • choices[0].finish_reason dice perché il modello si è fermato: stop (ha finito), length (il limite max_tokens l'ha interrotto), tool_calls, content_filter.
  • usage.prompt_tokens, usage.completion_tokens e usage.total_tokens sono ciò per cui paghi: input, output e la loro somma.

La risposta ha questa forma (i numeri sono segnaposto):

json
{
  "choices": [
    {
      "message": {"role": "assistant", "content": "A token is a small piece of text..."},
      "finish_reason": "stop"
    }
  ],
  "usage": {"prompt_tokens": 18, "completion_tokens": 52, "total_tokens": 70}
}
Provalo tu stessoProvalo: imposta max_tokens a 5 ed esegui di nuovo lo script. Cosa dice finish_reason?Mostra risposta

Dice length: il modello è stato fermato dal tuo limite max_tokens, quindi la risposta finisce a metà frase. Alza il limite e ottieni di nuovo stop. La storia completa è in Risposta AI troncata? Correggi finish_reason "length".

Quando non funziona#

Lo script trasforma la maggior parte dei fallimenti in una riga di output. Ecco cosa significa di solito ciascuno:

Abbina le coppie

Abbina ogni messaggio alla sua causa abituale

  • HTTP 401La chiave manca, è scritta male o non è quella che volevi inviare
  • HTTP 404Il percorso URL o l'id del modello è sbagliato
  • requests.exceptions.TimeoutNessun byte è arrivato entro il timeout
  • KeyError: 'CHEAPTOKENS_API_KEY'La variabile d'ambiente non è impostata in questo terminale

Per i corpi di errore effettivi e un controllo passo passo di chiave, URL di base e id del modello, usa Errore API 401 o 404: chiave, URL di base o id del modello sbagliati. Due insidie minori: se vedi KeyError: 'choices', hai analizzato un corpo di errore come successo, il che significa che raise_for_status() è stato saltato. E se la tua macchina ha un file ~/.netrc, requests può usare le sue credenziali invece dell'header Authorization che hai impostato.

Quanto costa una chiamata#

Con i numeri segnaposto della risposta sopra (circa 18 token in, 52 out), una chiamata a DeepSeek-V4-Flash costa $0.0000055. È un numero che non riesci a percepire, quindi ingrandiscilo. Diciamo che il tuo script riassume 1.000 ticket di supporto al giorno, circa 800 token in e 300 out ciascuno:

Modello Per richiesta 1000 richieste OpenRouter, 1000 richieste
GLM-5.3-Flash $0.000028 $0.028 $0.0517
DeepSeek-V4-Flash $0.000042 $0.042 $0.098
MiniMax-M2.7 $0.000085 $0.085 $1.02

800 token di input e 300 token di output per richiesta. I prezzi per 1M di token sono attuali e cambiano insieme alle nostre tariffe; la colonna OpenRouter mostra i prezzi di riferimento per lo stesso carico di lavoro.

I prezzi sono fissi per modello, senza ore di punta, quindi lo stesso script costa lo stesso alle 3 di notte e a mezzogiorno. I prezzi attuali per modello sono sulla pagina dei prezzi, e la documentazione elenca gli endpoint.

Da dove andare da qui#

Una volta che funziona, i prossimi passi abituali sono un ciclo su molti input, un retry su 429 (vedi 429 Too Many Requests: retry con backoff), o la stessa chiamata con lo streaming. Se preferisci non gestire HTTP da solo, la via SDK è a un cambio di base_url di distanza.