Vai al contenuto principale

Chainlit: una guida con esempi pratici

Scopri cos'è Chainlit, come installarlo e come eseguirlo per creare interfacce interattive per applicazioni basate su LLM.
Aggiornato 29 set 2026  · 8 min leggi

Scopri con l'IA

ChatGPTClaudePerplexity

Chainlit è un potente framework open-source in Python che ti permette di creare interfacce interattive per le tue applicazioni basate su LLM con pochissimo codice e senza complicazioni di front-end.

In questo tutorial ti mostrerò:

  1. Come installare e configurare Chainlit.
  2. I concetti chiave, come azioni, ciclo di vita della chat e configurazioni.
  3. La creazione di due app di esempio: 
    • Un chatbot statico “Sorprendimi” con pulsanti
    • Un bot “Sorprendimi” alimentato da Ollama

Che cos'è Chainlit?

Chainlit ti aiuta a creare frontend per chatbot di AI, strumenti e workflow basati su LLM. Astrae la complessità del front-end e ti consente di concentrarti sulla logica in Python, offrendo al contempo il supporto per aggiungere pulsanti, slider, caricamento di file o perfino collegarti a strumenti usando il model context protocol (MCP).

Chainlit è ideale per:

  • Prototipare app basate su LLM
  • Creare strumenti interni
  • Costruire demo didattiche
  • Collegare i tuoi modelli a strumenti o API esterni

Componenti di Chainlit

Ogni app Chainlit si basa su alcune funzionalità essenziali:

  1. Hook del ciclo di vita della chat: ti permettono di controllare cosa accade nelle diverse fasi di una chat. Per esempio:
    • @cl.on_chat_start viene eseguito all'inizio della chat.
    • @cl.on_message viene eseguito quando l'utente invia un messaggio.
    • @cl.on_chat_end viene eseguito quando la chat termina.
  2. Azioni UI: Chainlit ti consente di aggiungere pulsanti con cl.Action e gestirli con @cl.action_callback. Sono perfetti per creare UI pulite e interattive senza richiedere input testuale dell'utente.
  3. Streaming dei messaggi: con LLM che supportano lo streaming di token, puoi trasmettere le risposte in tempo reale usando stream=True, rendendo l'app più dinamica e reattiva.
  4. Configurazione con config.toml: questo file ti permette di abilitare funzioni come la persistenza della chat, il caricamento dei file, la personalizzazione del tema e migliorie di usabilità—il tutto senza modificare il codice Python.

Spiegherò ogni concetto con un esempio pratico di codice, così potrai vedere esattamente come funziona e come integrarlo nelle tue app Chainlit. Partiamo dal primo passo.

Prerequisiti

Assicurati di avere installato Python 3.8+, poi installa Chainlit usando pip. Useremo anche Langchain per la demo con Ollama, quindi assicurati di installarla. Esegui il seguente comando nel terminale:

pip install chainlit langchain langchain-community

Capire le basi di Chainlit attraverso esempi

In questa sezione tratteremo i mattoni fondamentali di Chainlit, che costituiranno il cuore di qualsiasi progetto.

Hook del ciclo di vita della chat

Ogni volta che un utente si collega alla tua app Chainlit, viene creata una sessione di chat. Puoi intervenire nelle diverse fasi di quella sessione usando i decorator forniti da Chainlit. Questi includono:

Sviluppare con @cl.on_chat_start

Questo hook viene eseguito quando inizia una nuova sessione di chat. Puoi usarlo per salutare l'utente, mostrare un messaggio di benvenuto o inizializzare lo stato della sessione.

import chainlit as cl
@cl.on_chat_start
def on_chat_start():
    print("A new chat session has started!")

@cl.on_chat_start chainlit output

Sviluppare con @cl.on_message

Questo hook del messaggio viene eseguito quando l'utente invia un nuovo messaggio. Lo usiamo per elaborare l'input dell'utente, chiamare un LLM o restituire una risposta.

import chainlit as cl
@cl.on_message
async def on_message(msg: cl.Message):
    print("The user sent:", msg.content)
    await cl.Message(content=f"You said: {msg.content}").send()

@cl.on_message Output

Sviluppare con @cl.on_stop

L'hook on_stop viene eseguito quando l'utente clicca il pulsante stop (⏹) durante un'attività in corso. Serve per annullare operazioni di lunga durata o ripulire sessioni interrotte.

import chainlit as cl
import asyncio
@cl.on_chat_start
async def start():
    await cl.Message("Type anything and I'll pretend to work on it.").send()
@cl.on_message
async def on_message(msg: cl.Message):
    await cl.Message("Working on it... you can press Stop").send()
    try:
        # Simulate a long task
        await asyncio.sleep(10)
        await cl.Message("Task complete!").send()
    except asyncio.CancelledError:
        print("Task was interrupted!")
        # This is optional, just logs in the server
        raise
@cl.on_stop
async def on_stop():
    print("The user clicked Stop!")

Quando l'utente invia un messaggio, Chainlit simula un'attività con asyncio.sleep(10). Se l'utente clicca il pulsante stop (⏹), l'attività viene annullata e @cl.on_stop viene attivato per registrare l'interruzione.

@cl.on_stop output

Sviluppare con @cl.on_chat_end

Questo hook si attiva quando la sessione termina—se l'utente aggiorna, chiude la scheda o avvia una nuova sessione. Di solito si usa per registrare le disconnessioni o salvare lo stato.

import chainlit as cl
@cl.on_chat_start
async def on_chat_start():
    await cl.Message("Welcome! Feel free to leave anytime").send()
@cl.on_chat_end
async def on_chat_end():
    print("The user disconnected!")

Una volta aperto il localhost, puoi interagirci. Quando chiudi la scheda o la finestra del localhost, il terminale mostrerà quanto segue:

on_chat_end() chainlit output

Azioni UI (pulsanti)

Chainlit ti consente di aggiungere pulsanti interattivi direttamente nell'interfaccia del tuo chatbot. Ogni pulsante è definito come un'azione e collegato a una funzione di callback in Python. Invii i pulsanti come parte di un Messaggio usando l'argomento actions:

import chainlit as cl
@cl.on_chat_start
async def start():
    actions = [
        cl.Action(
            name="hello",
            label="👋 Say Hello",
            icon="smile",
            payload={"value": "hi"}
        )
    ]
    await cl.Message("Click a button!", actions=actions).send()

Ecco come puoi gestire il click su un pulsante:

@cl.action_callback("hello")
async def on_hello(action: cl.Action):
    await cl.Message("Hello there! 👋").send()

Il decorator @cl.action_callback("hello") dice a Chainlit di ascoltare i click su un pulsante con nome "hello". Al click, invia un messaggio amichevole all'utente nell'interfaccia della chat.

@cl.action_callback chainlit output

Suggerimento: puoi personalizzare il payload con qualsiasi dato tu voglia inviare al server.

Streaming dei messaggi 

Chainlit supporta lo streaming in tempo reale delle risposte degli LLM. Ciò significa che puoi inviare contenuti all'utente in modo incrementale man mano che vengono generati.

@cl.on_message
async def on_message(message: cl.Message):
    await cl.Message(content="Thinking...").send()
    async for chunk in llm.astream(message.content):
        await cl.Message(content=chunk, author="LLM", stream=True).send()

Vediamolo nel dettaglio:

  • Per prima cosa, mostra subito un messaggio "Thinking..." così l'utente sa che l'app sta lavorando.
  • Poi invia il messaggio dell'utente a un LLM compatibile con lo streaming.
  • Man mano che il modello genera l'output, trasmette ogni pezzo (chunk) all'interfaccia in tempo reale.
  • Il parametro stream=True fa sì che ogni chunk appaia progressivamente invece di attendere l'intera risposta.

Nota: funziona al meglio con modelli che supportano lo streaming.

Configurazione di Chainlit (config.toml)

Per sbloccare funzionalità potenti come persistenza della chat, caricamento dei file, theming e altro, puoi personalizzare la tua app Chainlit usando il file config.toml. Questo file si trova nella root della directory del progetto (nella cartella .chainlit) e ti permette di regolare il comportamento a runtime senza modificare il codice.

Persistenza

Questo parametro permette a Chainlit di mantenere la cronologia della chat e lo stato della sessione. Attiva l'hook @cl.on_chat_resume, risultando ideale per app in cui gli utenti potrebbero disconnettersi e tornare più tardi.

[persistence]
enabled = true

Caricamento dei file

Questa impostazione consente agli utenti di caricare file nell'interfaccia della chat. Puoi limitare i tipi di file consentiti e le dimensioni per garantire sicurezza e prestazioni.

[features.spontaneous_file_upload]
enabled = true
accept = ["*/*"] 
max_files = 5
max_size_mb = 500

Ecco alcuni tipi di file accettati da Chainlit.

# 1. Per tipi di file specifici:
    # accept = ["image/jpeg", "image/png", "application/pdf"]
# 2. Per tutti i file di un certo tipo:
    #    accept = ["image/*", "audio/*", "video/*"]
# 3. Per estensioni specifiche:
    #    accept = { "application/octet-stream" = [".xyz", ".pdb"] }

Questo ti consente di adattare gli upload per sicurezza, prestazioni o casi d'uso specifici del dominio.

Personalizzazione UI

Questa personalizzazione cambia il nome dell'assistente nel parametro UI e abilita la Chain of Thought (CoT) nella modalità di rendering, utile per ragionamenti step-by-step o debugging.

[UI]
name = "Assistant"
cot = "full"

Migliorie di usabilità

Queste migliorano l'esperienza utente facendo scorrere automaticamente in vista i nuovi messaggi e consentendo la modifica dei messaggi.

[features]
user_message_autoscroll = true
edit_message = true

Le migliorie di usabilità sopra permettono all'utente di abilitare l'autoscroll e la modifica dei messaggi nell'interfaccia.

Progetto: bot “Sorprendimi” (senza LLM)

Ora che conosciamo i componenti di base di Chainlit, realizziamo una semplice app basata su UI che usa pulsanti per mostrare curiosità predefinite o messaggi motivazionali per sviluppatori.

import chainlit as cl
import random
FUN_FACTS = [
    "💡 Did you know? Chainlit supports file uploads and custom themes!",
    "💡 You can add buttons, sliders, and images directly in your chatbot UI!",
    "💡 Chainlit supports real-time tool execution with LangChain and LLMs!",
    "💡 You can customize the look of your chatbot with just a CSS file!",
    "💡 Chainlit lets you connect to tools using Model Context Protocol (MCP)!"
]
SUPRISES = [
    "🎉 Surprise! You're doing great!",
    "🚀 Keep it up, you're making awesome progress!",
    "🌟 Fun fact: Someone out there just smiled because of you. Why not make it two?",
    "👏 Bravo! You just unlocked +10 imaginary developer XP!",
    "💪 Remember: Even bugs fear your debugging skills!"
]
@cl.on_chat_start
async def start():
    actions = [
        cl.Action(
            name="surprise_button",
            label="🎁 Surprise Me",
            icon="gift",
            payload={"value": "surprise"}
        ),
        cl.Action(
            name="fact_button",
            label="💡 Did You Know?",
            icon="lightbulb",
            payload={"value": "fact"}
        )
    ]
    await cl.Message(content="Choose an action:", actions=actions).send()
@cl.action_callback("surprise_button")
async def on_surprise(action: cl.Action):
    suprise = random.choice(SUPRISES)
    await cl.Message(content=suprise).send()
@cl.action_callback("fact_button")
async def on_fact(action: cl.Action):
    fact = random.choice(FUN_FACTS)
    await cl.Message(content=fact).send()

Il codice qui sopra definisce due liste: “FUN_FACTS” con consigli interessanti su Chainlit e “SUPRISES” con messaggi motivazionali.

  • Quando inizia una nuova chat, vengono mostrati due pulsanti: "Surprise Me" e "Did You Know?"—usando cl.Action. '
  • Cliccando "Surprise Me" si attiva @cl.action_callback("surprise_button"), che invia un messaggio sorpresa casuale.
  • Cliccando "Did You Know?" si attiva @cl.action_callback("fact_button")`, che invia una curiosità casuale.

Questo crea un semplice chatbot interattivo basato su pulsanti che non richiede LLM, perfetto per imparare come funzionano azioni e callback in Chainlit.

Per eseguire questa applicazione, lancia semplicemente il seguente comando nel terminale:

chainlit run main.py

Vedrai pulsanti interattivi nella UI che attivano curiosità o messaggi divertenti!

Surprise Me Bot (no LLM)

Progetto: bot “Sorprendimi” alimentato da Ollama

Ora automatizziamo il processo e generiamo i messaggi di sorpresa e curiosità usando un LLM locale tramite Ollama.

import chainlit as cl
from langchain_community.llms import Ollama
import random
llm = Ollama(model="mistral", temperature=0.7)  # Use any lightweight local model
# Reusable action buttons
def get_action_buttons():
    return [
        cl.Action(
            name="surprise_button",
            label="🎁 Surprise Me",
            icon="gift",
            payload={"value": "surprise"}
        ),
        cl.Action(
            name="fact_button",
            label="💡 Did You Know?",
            icon="lightbulb",
            payload={"value": "fact"}
        )
    ]

@cl.on_chat_start
async def start():
    await cl.Message(content="Choose an action below to see something fun:").send()
    await cl.Message(content="", actions=get_action_buttons()).send()
@cl.action_callback("surprise_button")
async def on_surprise(action: cl.Action):
    prompt = "Give a short, uplifting surprise message to a developer. Make it fun."
    try:
        surprise = llm.invoke(prompt).strip()
    except Exception:
        surprise = "🎉 Surprise! You're doing great!"
    await cl.Message(content=surprise).send()
    await cl.Message(content="", actions=get_action_buttons()).send()  
@cl.action_callback("fact_button")
async def on_fact(action: cl.Action):
    prompt = "Give a fun and helpful fact about LLMs or Chainlit."
    try:
        fact = llm.invoke(prompt).strip()
    except Exception:
        fact = "💡 Did you know? You can add sliders and buttons to Chainlit with just a few lines of code!"
    await cl.Message(content=fact).send()
    await cl.Message(content="", actions=get_action_buttons()).send()  

Questa app Chainlit integra un LLM locale (tramite Ollama con il modello Mistral) per generare dinamicamente risposte basate sulle interazioni dell'utente.

  • Definisce due pulsanti cl.Action—"Surprise Me" e "Did You Know?" usando una funzione riutilizzabile get_action_buttons().
  • All'inizializzazione della chat (@cl.on_chat_start) invia un messaggio con questi pulsanti interattivi.
  • Quando l'utente clicca il pulsante "Surprise Me", l'handler @cl.action_callback invia al LLM un prompt per un breve messaggio motivante per sviluppatori. La risposta viene ripulita con la funzione .strip() e rimandata in chat.
  • Allo stesso modo, cliccando "Did You Know?" il LLM viene invocato con un prompt che richiede una curiosità informativa su Chainlit o sugli LLM.
  • Se il LLM fallisce, vengono restituiti messaggi statici di fallback.
  • Dopo ogni interazione, i pulsanti vengono reinviati per mantenere il loop conversazionale.

Questo dimostra come combinare la UI di Chainlit con la generazione di contenuti basati su LLM, offrendo una base modulare ed estensibile per app di chat AI locali.

Esegui i seguenti comandi nel terminale:

ollama run mistral
chainlit run main.py

Ora hai un assistente AI locale e attivo che genera messaggi automatici.

Surprise Me Bot Powered by Ollama

Conclusione

Chainlit ha un grande potenziale per prototipare strumenti basati su chat, costruire assistenti e integrare output in tempo reale da LLM—il tutto senza toccare JavaScript. Per casi d'uso avanzati, dai un'occhiata al Chainlit Cookbook.

Per ampliare l'apprendimento con nuovi strumenti di AI, dai un'occhiata ai seguenti blog:


Aashi Dutt's photo
Author
Aashi Dutt
LinkedIn
Twitter

Sono una Google Developers Expert in ML (Gen AI), una Kaggle 3x Expert e una Women Techmakers Ambassador con oltre 3 anni di esperienza nel tech. Ho co-fondato una startup health-tech nel 2020 e sto conseguendo un master in informatica al Georgia Tech, con specializzazione in machine learning.

Argomenti
Intelligenza artificiale
AI generativa

Impara l'AI con questi corsi!

Corso

Deployment di AI in produzione con FastAPI

4 ore
5.6K
Sviluppa API con FastAPI per integrare modelli di AI e rispondere a esigenze reali.
Vedi i dettagliRight Arrow
Inizia Il Corso
Mostra altroRight Arrow
Correlato

blog

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

blog

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

Mostra AltroMostra Altro