Creare un chatbot con API LLM in Python: tutorial Claude
11/06/2026
Cosa costruiamo
In questo tutorial pratico realizziamo un chatbot da terminale in Python che dialoga con un modello LLM di Claude tramite le API ufficiali di Anthropic. Niente teoria astratta: partiamo da una singola chiamata e arriviamo, passo dopo passo, a un assistente completo.
Alla fine il tuo chatbot sapra’:
- mantenere la memoria della conversazione, ricordando i messaggi precedenti;
- fare streaming della risposta, stampandola parola per parola come una chat reale;
- gestire gli errori di rete e di quota senza crashare;
- tracciare token e costi di ogni messaggio in tempo reale.
E’ il classico progetto end-to-end che trasforma gli LLM da concetto a competenza spendibile: oggi saper integrare un modello via API e’ una delle skill piu’ richieste sul mercato.
Prerequisiti
- Python 3.9 o superiore installato (verifica con
python3 --version). - Conoscenza di base di funzioni, dizionari e cicli in Python.
- Una chiave API Anthropic, che ottieni dalla console su console.anthropic.com.
Una nota importante: la chiamata alle API e’ un servizio a consumo. Hai un piccolo credito iniziale, ma ogni richiesta ha un costo legato ai token. Per questo nel tutorial integriamo subito il monitoraggio della spesa.
Passo 1 — Ambiente e chiave API
Creiamo un ambiente virtuale isolato e installiamo l’unica dipendenza che ci serve, la libreria ufficiale anthropic.
python3 -m venv venv
source venv/bin/activate
pip install anthropic
Adesso impostiamo la chiave come variabile d’ambiente. Non scrivere mai la chiave nel codice: se finisce su Git, e’ compromessa. La libreria la legge in automatico dalla variabile ANTHROPIC_API_KEY.
export ANTHROPIC_API_KEY='la-tua-chiave-segreta'
Su Windows (PowerShell) usa $env:ANTHROPIC_API_KEY='...'. Per un progetto serio valuta un file .env con python-dotenv, ricordandoti di aggiungerlo a .gitignore.
Passo 2 — La prima chiamata alle API di Claude
Iniziamo dal minimo: una domanda, una risposta. Crea il file first_call.py.
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model='claude-sonnet-4-6',
max_tokens=300,
messages=[
{'role': 'user',
'content': 'Spiegami cosa e un LLM in due righe.'}
],
)
print(response.content[0].text)
print('Token:', response.usage.input_tokens,
'+', response.usage.output_tokens)
Eseguilo:
python first_call.py
Tre cose da capire qui. Il parametro model sceglie il modello: claude-sonnet-4-6 e’ un ottimo equilibrio tra qualita’ e costo; per risparmiare puoi passare a claude-haiku-4-5. Il parametro max_tokens e’ il tetto massimo di token della risposta, non un valore fisso. Infine response.content e’ una lista di blocchi: per il testo leggiamo response.content[0].text.
Passo 3 — Dare memoria alla conversazione
Le API LLM sono stateless: ogni chiamata e’ indipendente e il modello non ricorda nulla. La memoria la costruisci tu, inviando l’intera cronologia a ogni richiesta. Il trucco e’ una semplice lista di messaggi con ruoli alternati user e assistant.
messages = []
def ask(client, messages, user_text):
messages.append({'role': 'user', 'content': user_text})
response = client.messages.create(
model='claude-sonnet-4-6',
max_tokens=512,
messages=messages,
)
answer = response.content[0].text
messages.append({'role': 'assistant',
'content': answer})
return answer
Dopo ogni risposta aggiungiamo anche il testo del modello alla lista: cosi’ al turno successivo Claude vede tutto il contesto e puo’ rispondere a frasi come e quindi? capendo a cosa ti riferisci. Attenzione: piu’ lunga e’ la cronologia, piu’ token invii (e paghi) a ogni richiesta.
Passo 4 — Streaming delle risposte
Aspettare 5 secondi una risposta in silenzio e’ frustrante. Con lo streaming il testo appare a pezzi, appena il modello lo genera. La libreria offre un context manager dedicato e un iteratore comodo, text_stream.
with client.messages.stream(
model='claude-sonnet-4-6',
max_tokens=512,
messages=messages,
) as stream:
for chunk in stream.text_stream:
print(chunk, end='', flush=True)
print()
Il parametro flush=True forza la stampa immediata di ogni frammento. A streaming concluso possiamo recuperare il messaggio completo con stream.get_final_message(), che contiene anche i dati di utilizzo dei token: ci servira’ tra poco per calcolare i costi.
Passo 5 — Il chatbot completo: errori, token e costi
Mettiamo tutto insieme in chatbot.py. Questo file unisce memoria, streaming, gestione degli errori e calcolo della spesa in un ciclo interattivo.
import anthropic
MODEL = 'claude-sonnet-4-6'
MAX_TOKENS = 1024
# Prezzi indicativi in USD per milione di token.
# Verifica i valori aggiornati sulla pagina pricing.
PRICE_IN = 3.0 / 1_000_000
PRICE_OUT = 15.0 / 1_000_000
SYSTEM_PROMPT = (
'Sei un assistente tecnico in italiano. '
'Rispondi in modo chiaro e conciso.'
)
def stream_reply(client, messages):
print('Claude: ', end='', flush=True)
text = ''
with client.messages.stream(
model=MODEL,
max_tokens=MAX_TOKENS,
system=SYSTEM_PROMPT,
messages=messages,
) as stream:
for chunk in stream.text_stream:
print(chunk, end='', flush=True)
text += chunk
final = stream.get_final_message()
usage = final.usage
cost = (usage.input_tokens * PRICE_IN
+ usage.output_tokens * PRICE_OUT)
print(f'\n[token in={usage.input_tokens} '
f'out={usage.output_tokens} '
f'costo=${cost:.5f}]\n')
return text, cost
def main():
client = anthropic.Anthropic() # legge la chiave
messages = []
spent = 0.0
print('Chatbot Claude pronto. Scrivi esci per uscire.\n')
while True:
try:
user_input = input('Tu: ').strip()
except (EOFError, KeyboardInterrupt):
print('\nA presto!')
break
if not user_input:
continue
if user_input.lower() in ('esci', 'exit', 'quit'):
print(f'A presto! Costo sessione: ${spent:.4f}')
break
messages.append({'role': 'user',
'content': user_input})
try:
reply, cost = stream_reply(client, messages)
except anthropic.RateLimitError:
print('Troppe richieste: attendi e riprova.')
messages.pop()
continue
except anthropic.APIConnectionError:
print('Problema di rete: controlla la linea.')
messages.pop()
continue
except anthropic.APIStatusError as e:
print(f'Errore API ({e.status_code}): {e.message}')
messages.pop()
continue
messages.append({'role': 'assistant',
'content': reply})
spent += cost
if __name__ == '__main__':
main()
Avvialo con python chatbot.py e prova una conversazione:
Tu: Ciao, in due parole chi sei?
Claude: Sono Claude, un assistente AI.
[token in=26 out=11 costo=$0.00025]
Tu: esci
A presto! Costo sessione: $0.0003
Cosa abbiamo aggiunto
Il system prompt (parametro system) definisce personalita’ e regole del bot: e’ separato dai messaggi e vale per tutta la sessione. La gestione errori intercetta i tre casi piu’ frequenti: limite di richieste, problemi di rete e risposte di errore del server. Nota il messages.pop() dentro ogni except: se la chiamata fallisce, rimuoviamo il messaggio utente appena aggiunto, cosi’ la cronologia non resta sbilanciata con un turno senza risposta.
Errori comuni e trappole
- Chiave in chiaro nel codice. E’ l’errore numero uno. Usa sempre variabili d’ambiente o un file
.envignorato da Git. - Dimenticare di salvare la risposta in
messages. Senza il messaggioassistantin cronologia, il bot perde il filo e i ruoli si disallineano. - Ruoli non alternati. L’API richiede che i messaggi alternino
usereassistant. Dueuserdi fila generano un errore400. - Cronologia infinita. Conversazioni lunghe gonfiano i token di input a ogni chiamata. Imposta un limite e taglia i messaggi piu’ vecchi quando serve.
- Prezzi hardcoded. Le tariffe cambiano: tieni i valori in costanti e verificali sulla pagina pricing ufficiale di Anthropic.
Come estendere il progetto
Hai una base solida. Da qui puoi spingerti oltre:
- Salvare le conversazioni su file JSON per riprenderle in seguito.
- Limitare la finestra di contesto mantenendo solo gli ultimi N messaggi, per controllare i costi.
- Aggiungere i tool (function calling) per far chiamare al modello funzioni reali, come una ricerca o una query a un database.
- Passare a un’interfaccia web con FastAPI o Streamlit, riusando esattamente la stessa logica.
- Implementare il prompt caching per ridurre il costo dei prompt di sistema lunghi e ripetuti.
Conclusione
Hai costruito un chatbot Python funzionante che parla con un LLM di Claude, ricorda la conversazione, fa streaming e tiene sotto controllo errori e costi. Sono gli stessi mattoni con cui si costruiscono assistenti e agenti in produzione: cambia la scala, non i principi.
Se hai bisogno di portare un’idea basata su LLM dal prototipo al prodotto, con team che conoscono architettura, sicurezza e costi, parla con gli sviluppatori di Syrus Industry e trasforma il tuo progetto AI in software professionale.