Gli assistenti virtuali o chatbot sono diventati una componente importante delle strategie digitali di aziende, organizzazioni e servizi pubblici. Non si tratta più soltanto di chatbot capaci di rispondere a qualche domanda predefinita, ma di sistemi progettati per comprendere il linguaggio naturale, raccogliere informazioni, gestire richieste articolate e interagire con applicazioni e servizi esterni.
La diffusione dell'intelligenza artificiale generativa ha ulteriormente accelerato questa evoluzione. Oggi un assistente virtuale può consultare documentazione, recuperare informazioni da un database o interrogare API (RAG - Retrieval augmented generation), accompagnare un utente in una procedura amministrativa e mantenere il contesto di una conversazione articolata in più passaggi. Il problema, tuttavia, non è soltanto generare una risposta plausibile. In un'applicazione reale bisogna anche garantire che il sistema esegua le operazioni corrette, rispetti le regole aziendali e gestisca in maniera affidabile le informazioni ricevute.
Nel panorama degli assistenti virtuali, Rasa occupa una posizione particolare. Per anni è stato uno dei framework open source più interessanti per sviluppare chatbot e applicazioni conversazionali con Python, offrendo agli sviluppatori un controllo diretto sulla comprensione del linguaggio naturale, sulla gestione delle conversazioni e sull'integrazione con i sistemi aziendali.
Quando parliamo di Rasa in questa guida, ci riferiamo precisamente al progetto Rasa Open Source, disponibile nel repository ufficiale RasaHQ/rasa su GitHub. È il framework storico distribuito con licenza Apache 2.0, che permette di realizzare assistenti conversazionali senza dipendere necessariamente da piattaforme proprietarie o servizi cloud esterni.
È importante fare subito una distinzione: negli ultimi anni Rasa ha attraversato una trasformazione significativa. L'azienda ha progressivamente spostato la propria attenzione verso soluzioni commerciali per la realizzazione di agenti AI, introducendo nuove architetture basate sui modelli linguistici, strumenti per la gestione dei flussi conversazionali e ambienti dedicati allo sviluppo di assistenti più evoluti. La documentazione attuale presenta prodotti e tecnologie come Rasa Platform, CALM e Mantle, che non devono essere confusi con il framework open source storico.
Anche il repository Rasa Open Source ha cambiato posizione all'interno di questo ecosistema: il progetto è ancora disponibile, conserva la propria licenza open source, ma è stato dichiarato in maintenance mode. Questo significa che possiamo continuare a studiarlo, installarlo e utilizzarlo, ma non dobbiamo aspettarci lo stesso ritmo di sviluppo e innovazione che caratterizza una piattaforma attivamente evoluta. È una differenza importante, soprattutto quando si sceglie una tecnologia da adottare in un nuovo progetto.
In questa guida mi concentrerò quindi su Rasa Open Source, analizzandone l'architettura, gli strumenti e le tecniche necessarie per costruire un assistente conversazionale con Python. Vedremo come progettare un dataset, definire le intenzioni degli utenti, riconoscere le entità, gestire il contesto e realizzare azioni personalizzate. Dedicheremo inoltre spazio alla generazione automatica dei dati di addestramento con modelli linguistici come Mistral e all'utilizzo di spaCy per l'elaborazione del testo.
Non ignoreremo però l'evoluzione del prodotto. Ricostruiremo il passaggio dal modello tradizionale basato su NLU e gestione del dialogo alle architetture più recenti che integrano LLM e logiche conversazionali deterministiche. In questo modo sarà possibile comprendere non soltanto come funziona Rasa, ma anche perché oggi il suo ecosistema è molto diverso da quello che molti sviluppatori hanno conosciuto negli anni precedenti.
Introduzione a Rasa Open Source: cos'è e come funziona
Rasa Open Source è un framework Python per lo sviluppo di assistenti virtuali e applicazioni conversazionali. La sua architettura tradizionale è progettata per separare due responsabilità fondamentali:
- comprendere ciò che l'utente sta chiedendo
- decidere quale risposta o operazione eseguire.
Queste responsabilità sono tradizionalmente associate a due componenti: Natural Language Understanding (NLU) e Dialogue Management.
Il componente NLU analizza i messaggi ricevuti e cerca di individuare l'intenzione comunicativa dell'utente, oltre a estrarre le informazioni significative presenti nella frase. Il Dialogue Management utilizza invece queste informazioni, insieme allo stato della conversazione, per determinare il comportamento successivo dell'assistente.
La distinzione è importante perché comprendere una richiesta e sapere cosa fare per soddisfarla sono due problemi differenti.
Immaginiamo un assistente virtuale utilizzato da un'azienda di trasporti. Un utente scrive: «Vorrei prenotare un viaggio da Roma a Milano per venerdì». Il sistema NLU deve riconoscere che l'utente vuole effettuare una prenotazione e individuare le informazioni presenti nel messaggio: città di partenza, destinazione e data del viaggio. Il gestore della conversazione deve poi verificare quali dati sono disponibili, controllare se manca qualche informazione e stabilire quale passaggio eseguire per completare la prenotazione.

In Rasa Open Source questo comportamento viene costruito attraverso dati di addestramento, configurazioni YAML e codice Python. Lo sviluppatore definisce le intenzioni riconoscibili, le entità da estrarre, le regole conversazionali e le azioni che l'assistente può eseguire.
L'obiettivo non è semplicemente generare una risposta plausibile, ma realizzare un sistema capace di seguire un comportamento progettato e verificabile. Questa caratteristica ha reso Rasa particolarmente interessante per applicazioni aziendali nelle quali la conversazione deve rispettare procedure precise, interrogare servizi esterni o interagire con database e applicazioni esistenti.
È utile precisare che Rasa Open Source 3.x non deve essere interpretato come la semplice somma di due prodotti indipendenti chiamati Rasa NLU e Rasa Core. Si tratta di componenti funzionali integrate nello stesso framework, con una pipeline di elaborazione del linguaggio e un sistema di gestione del dialogo coordinati.
Gli elementi fondamentali di Rasa
Per comprendere il funzionamento del framework dobbiamo conoscere alcuni concetti che ritroveremo continuamente durante lo sviluppo.
Intents: rappresentano le intenzioni espresse dall'utente. Una frase come «Vorrei conoscere gli orari di apertura» può essere associata all'intento ask_hours.
Entities: sono le informazioni specifiche contenute nel messaggio. Nel caso di una prenotazione possono essere una data, una località, un prodotto o il numero di persone.
Slots: rappresentano la memoria operativa della conversazione. Consentono di conservare informazioni raccolte durante i diversi passaggi, evitando di chiedere continuamente all'utente dati che ha già fornito.
Responses: sono le risposte che l'assistente può restituire, definite attraverso configurazioni e varianti testuali.
Stories: descrivono sequenze di interazione che permettono al sistema di apprendere i percorsi conversazionali previsti.
Rules: definiscono comportamenti che devono essere eseguiti quando si verificano determinate condizioni.
Actions: rappresentano le operazioni che l'assistente può eseguire. Possono essere semplici risposte oppure funzioni Python capaci di interrogare servizi esterni, recuperare informazioni e modificare lo stato della conversazione.
Questi elementi costituiscono la base sulla quale costruire un assistente virtuale personalizzato.
Comprensione del linguaggio naturale: intent ed entities
Il primo compito di un chatbot intelligente consiste nel comprendere cosa vuole l'utente. In Rasa questa attività viene svolta attraverso il riconoscimento degli intent e l'estrazione delle entities.
Un intent identifica la finalità comunicativa, mentre un'entità contiene un'informazione specifica che può essere utilizzata per eseguire un'operazione.
Consideriamo un assistente virtuale per una pizzeria. Potremmo avere due intent principali:
order_pizza: l'utente vuole ordinare una pizza.ask_hours: l'utente vuole conoscere gli orari di apertura.
Nel primo caso il sistema deve anche riconoscere il tipo di pizza richiesto. Possiamo quindi definire un'entità chiamata pizza_type.
Un esempio di configurazione NLU per Rasa 3.x è il seguente:
version: "3.1"
nlu:
- intent: order_pizza
examples: |
- Voglio ordinare una pizza
- Posso avere una pizza Margherita?
- Vorrei una Quattro formaggi
- Mi preparate una pizza Diavola?
- intent: ask_hours
examples: |
- A che ora aprite?
- Quali sono gli orari di apertura?
- Quando chiudete?
- Siete aperti questa sera?La sintassi utilizzata per indicare un'entità è particolarmente importante. La parte racchiusa tra parentesi quadre rappresenta il valore individuato nella frase, mentre il testo tra parentesi tonde identifica il tipo di entità.
In questo modo Rasa può imparare che parole differenti, come Margherita, Diavola e Quattro formaggi, appartengono alla stessa categoria informativa.
La qualità degli esempi è determinante. Non basta inserire una singola frase per ogni intento e aspettarsi che il modello riconosca automaticamente tutte le possibili formulazioni. Bisogna prevedere sinonimi, variazioni linguistiche, errori di digitazione e costruzioni sintattiche differenti.
La gestione della conversazione: stories, rules e slots
Riconoscere correttamente un intento non significa aver risolto il problema. Un assistente deve anche sapere come proseguire l'interazione. La gestione del dialogo è affidata ai componenti che analizzano lo stato della conversazione e determinano quale azione eseguire successivamente.
In Rasa Open Source 3.x le stories rappresentano sequenze di eventi che descrivono percorsi conversazionali. Attraverso gli esempi forniti durante l'addestramento, il sistema apprende quali azioni sono appropriate nelle diverse situazioni.
Un esempio:
version: "3.1"
stories:
- story: ordine pizza
steps:
- intent: order_pizza
- action: utter_ask_pizza_type
- intent: inform
- action: utter_confirm_orderIn questo scenario l'utente manifesta l'intenzione di ordinare una pizza. L'assistente chiede quale tipo desidera, riceve una risposta e conferma l'ordine.
Le stories non sono l'unico strumento disponibile. Le rules permettono di definire comportamenti deterministici, particolarmente utili quando una determinata condizione deve produrre sempre la stessa azione.
Gli slots, invece, permettono di conservare le informazioni raccolte. Se l'utente comunica la città di partenza e successivamente indica la destinazione, l'assistente può mantenere entrambi i valori durante la conversazione.
È un aspetto fondamentale per realizzare procedure articolate, perché consente di separare la raccolta delle informazioni dalla loro elaborazione.
Progettare un dataset efficace per Rasa
La qualità di un assistente virtuale dipende in larga misura dai dati utilizzati per addestrarlo. Il dataset non è un semplice insieme di frasi, ma una rappresentazione strutturata delle interazioni che il sistema deve imparare a riconoscere e gestire. Ogni esempio, ogni intento, ogni entità e ogni sequenza conversazionale contribuisce a definire il comportamento atteso del chatbot.
La progettazione deve quindi iniziare dall'analisi del dominio applicativo. Prima di scrivere gli esempi è necessario comprendere quali utenti utilizzeranno il sistema, quali operazioni dovranno eseguire e quali informazioni saranno necessarie per completare le richieste.
Un assistente destinato a un sito di e-commerce avrà esigenze differenti rispetto a un chatbot utilizzato per fornire informazioni sui servizi di un'amministrazione pubblica.
Nel primo caso potremmo avere intent relativi agli ordini, ai pagamenti, alle spedizioni e ai resi. Nel secondo potremmo dover gestire richieste relative agli uffici, agli orari, ai documenti e alle procedure amministrative.
La progettazione degli intent deve evitare sia un'eccessiva frammentazione sia una classificazione troppo generica. Se due richieste hanno significati differenti, inserirle nello stesso intento può compromettere la precisione del sistema. Al contrario, creare decine di intent quasi identici rende più difficile l'addestramento e la manutenzione.
Raccolta e preparazione dei dati
Prima di addestrare Rasa bisogna costruire un dataset che rappresenti il modo in cui gli utenti si rivolgono realmente all'assistente. È una fase più importante di quanto possa sembrare: un modello può essere configurato correttamente, utilizzare una buona pipeline NLU e ottenere comunque risultati deludenti se viene addestrato su esempi poco rappresentativi.
Immaginiamo di voler realizzare un assistente per un sito web. Se decidiamo di gestire richieste come informazioni sugli orari, prenotazioni e assistenza tecnica, dobbiamo raccogliere frasi che esprimano questi intenti in modi differenti. Un utente potrebbe scrivere "A che ora chiudete?", un altro "Siete ancora aperti?" e un altro ancora "Vorrei sapere gli orari di apertura". Sono formulazioni diverse, ma esprimono sostanzialmente la stessa intenzione.
Per questo motivo non è sufficiente preparare una singola frase per ogni intent. Servono esempi vari, con costruzioni grammaticali differenti, sinonimi, abbreviazioni e formulazioni più vicine al linguaggio quotidiano. In caso contrario, Rasa rischia di riconoscere soltanto le richieste che assomigliano molto a quelle presenti nel dataset.
Quando disponibili, utilizzerei conversazioni reali provenienti da sistemi di assistenza, email, moduli di contatto o registrazioni delle interazioni con gli utenti. In alternativa, è possibile creare manualmente gli esempi e utilizzare un modello linguistico per generare parafrasi e nuove formulazioni. Queste ultime, però, non andrebbero inserite automaticamente: devono essere controllate, perché frasi apparentemente simili possono esprimere intenzioni differenti.
Una volta raccolti gli esempi, bisogna associarli agli intent corretti, individuare le eventuali entità e rimuovere duplicati, dati personali e contenuti che non contribuiscono all'addestramento. È altrettanto importante mantenere una distribuzione ragionevole degli esempi tra i diversi intent, evitando che alcune categorie siano rappresentate da centinaia di frasi e altre da pochissimi casi.
Il dataset finale non deve essere necessariamente enorme. Deve soprattutto essere coerente, vario e rappresentativo delle richieste che l'assistente dovrà affrontare. Preferisco partire da un insieme più contenuto ma verificato, ampliandolo progressivamente sulla base degli errori emersi durante i test, piuttosto che accumulare migliaia di frasi generate automaticamente senza sapere quanto siano effettivamente utili.
Generare automaticamente intent e risposte con un LLM
Nella costruzione dei miei dataset ho seguito una strada diversa dal classico lavoro di annotazione manuale: partire dai contenuti già pubblicati sui siti web e trasformarli automaticamente in materiale utilizzabile per l'addestramento.
Ho partecipato allo sviluppo di un sistema che lavora su più domini, collegato a un orchestratore incaricato di recuperare ed estrarre documenti da CMS appartenenti a clienti differenti. In questo modo è possibile raccogliere informazioni provenienti da fonti diverse, senza dover intervenire manualmente su ogni singola pagina.
Il vantaggio è evidente quando si lavora con siti aziendali che contengono decine o centinaia di pagine. Informazioni sui servizi, procedure, condizioni commerciali, modalità di pagamento e recapiti sono già disponibili, ma sono organizzate per essere lette da una persona, non per diventare esempi di addestramento per un assistente conversazionale.
Per risolvere questo problema ho utilizzato Mistral, affidandogli il compito di analizzare i documenti estratti e generare coppie di domande e risposte coerenti con il contenuto originale.
Il modello riceve il testo di una pagina e un'istruzione precisa: individuare le informazioni rilevanti, formulare possibili domande che un utente potrebbe porre e costruire risposte basate esclusivamente sulle informazioni presenti nel documento. Questo ultimo aspetto è fondamentale: non voglio che il modello completi le informazioni mancanti con supposizioni o conoscenze generiche.
Il primo passaggio consiste quindi nel definire un prompt sufficientemente preciso:
Estrai coppie domanda-risposta dal testo seguente.
Rispondi esclusivamente con un array JSON.
Ogni elemento deve contenere i campi question e answer.
Non aggiungere informazioni che non siano presenti nel testo.
TESTO:
I nostri tempi di spedizione variano tra 2 e 5 giorni lavorativi.
Le spedizioni verso Milano richiedono in media 3 giorni.
Accettiamo pagamenti con carta, bonifico bancario e PayPal.
Il pagamento alla consegna non è disponibile.Il modello restituisce un risultato di questo tipo:
[
{
"question": "Quali sono i tempi di spedizione?",
"answer": "I tempi di spedizione variano tra 2 e 5 giorni lavorativi."
},
{
"question": "Quanto tempo ci vuole per spedire a Milano?",
"answer": "Le spedizioni verso Milano richiedono in media 3 giorni."
},
{
"question": "Quali metodi di pagamento accettate?",
"answer": "Accettiamo carta, bonifico bancario e PayPal."
},
{
"question": "Posso pagare alla consegna?",
"answer": "Il pagamento alla consegna non è disponibile."
}
]A questo punto abbiamo già una prima base di conoscenza organizzata.
Possiamo automatizzare anche la generazione dei nomi degli intent utilizzando Python e le stopword italiane di NLTK:
import re
from nltk.corpus import stopwords
stop_words = set(stopwords.words("italian"))
def make_intent_name(question):
question = question.lower()
question = re.sub(r"[^\w\s]", "", question)
words = question.split()
words = [word for word in words if word not in stop_words]
return "_".join(words[:5])La funzione rimuove la punteggiatura, elimina le parole grammaticali più comuni e costruisce un identificativo in formato snake_case. Per esempio, la domanda «Quali sono i tempi di spedizione?» può diventare tempi_spedizione.
Il passaggio successivo consiste nella generazione delle parafrasi. Per ogni domanda possiamo chiedere a Mistral di produrre tre o più formulazioni alternative mantenendo invariato il significato.
Per esempio:
Per la domanda seguente genera tre variazioni linguistiche.
Mantieni invariato il significato.
DOMANDA:
Quali metodi di pagamento accettate?Potremmo ottenere:
intent: pagamento_metodi
examples:
- Quali metodi di pagamento accettate?
- Che tipi di pagamento posso usare?
- Come posso pagare?
- Che opzioni di pagamento offrite?Questi esempi saranno successivamente trasformati nel formato NLU di Rasa.
È importante non confondere la quantità con la qualità. Generare cento parafrasi quasi identiche non significa ottenere un dataset migliore. Le frasi devono rappresentare variazioni linguistiche realmente plausibili e devono essere controllate prima dell'addestramento.
Inoltre, le risposte generate dal modello devono essere confrontate con il contenuto originale: un modello linguistico può introdurre dettagli non presenti nella documentazione. In un assistente aziendale, un'informazione inventata sui tempi di consegna o sulle condizioni di pagamento può diventare un problema concreto.
Estrazione delle entità con spaCy
Dopo aver identificato gli intent, dobbiamo occuparci delle informazioni contenute nelle frasi. Per questa attività possiamo utilizzare spaCy, una libreria Python dedicata all'elaborazione del linguaggio naturale che mette a disposizione modelli pre-addestrati per il riconoscimento delle entità.
L'obiettivo è individuare informazioni come località, organizzazioni, date, orari e importi economici, associando ciascun valore alla relativa categoria.
Installiamo spaCy e il modello linguistico italiano:
pip install spacy
python -m spacy download it_core_news_smPossiamo quindi costruire una funzione per analizzare le frasi e raccogliere le entità individuate:
import spacy
from collections import defaultdict
nlp = spacy.load("it_core_news_sm")
ENTITY_LABEL_MAP = {
"GPE": "location",
"LOC": "location",
"ORG": "organization",
"DATE": "date",
"TIME": "time",
"MONEY": "amount"
}
def extract_entities(sentences):
extracted = []
entities_by_intent = defaultdict(set)
for sentence in sentences:
doc = nlp(sentence["text"])
entities = []
for ent in doc.ents:
label = ENTITY_LABEL_MAP.get(ent.label_)
if not label:
continue
entities.append({
"entity": label,
"value": ent.text
})
entities_by_intent[sentence["intent"]].add(label)
extracted.append({
"intent": sentence["intent"],
"original_text": sentence["text"],
"entities": entities
})
return extracted, entities_by_intentPossiamo verificare il funzionamento utilizzando alcune frasi di esempio:
sentences = [
{
"intent": "richiesta_spedizione",
"text": "Quanto tempo ci mette la spedizione a Milano?"
},
{
"intent": "richiesta_pagamento",
"text": "Posso pagare con bonifico bancario entro il 15 maggio?"
},
{
"intent": "richiesta_saldo",
"text": "Quanto devo pagare se l'importo è di 50 euro?"
}
]
extracted, entities_by_intent = extract_entities(sentences)
for item in extracted:
print(f"Intent: {item['intent']}")
print(f"Frase: {item['original_text']}")
for entity in item["entities"]:
print(f"Entità: {entity['value']} - Tipo: {entity['entity']}")
print()Il risultato atteso è l'individuazione di informazioni come Milano, 15 maggio e 50 euro, associate rispettivamente alle categorie location, date e amount, quando riconosciute dal modello.
A tal proposito, ho preparato un notebook su Google Colab che costruisce da zero un modello spaCy completo e personalizzato per l’italiano: oltre al riconoscimento delle entità (NER) include lemmatizzazione, segmentazione delle frasi, etc.
Organizzare il progetto: i file YAML di Rasa
Un progetto Rasa utilizza diversi file di configurazione che separano i dati di addestramento, le informazioni sul dominio e la logica conversazionale.
Il file nlu.yml contiene gli esempi utilizzati per riconoscere intent ed entities. Il file stories.yml descrive i percorsi conversazionali, mentre rules.yml contiene le regole che determinano comportamenti specifici.
Il file domain.yml definisce invece il dominio applicativo, ovvero l'insieme degli elementi che l'assistente conosce e può utilizzare: intent, entità, slots, risposte, azioni e form.
Un esempio semplificato:
version: "3.1"
intents:
- order_pizza
- ask_hours
- inform
entities:
- pizza_type
slots:
pizza_type:
type: text
mappings:
- type: from_entity
entity: pizza_type
responses:
utter_ask_pizza_type:
- text: "Quale pizza desideri?"
utter_confirm_order:
- text: "Perfetto, abbiamo ricevuto il tuo ordine."
actions:
- action_get_pizza_menuLa separazione tra questi file non è un dettaglio puramente organizzativo. Permette di mantenere il progetto comprensibile anche quando il numero di intent, percorsi e funzionalità aumenta.
Un chatbot aziendale può iniziare con pochi intent, ma nel tempo può arrivare a gestire decine di procedure differenti. Una struttura ordinata riduce la complessità delle modifiche e rende più semplice individuare eventuali problemi.
Sviluppare azioni personalizzate con Python
Le risposte statiche non sono sufficienti quando l'assistente deve interagire con sistemi esterni. Pensiamo a un chatbot per un negozio online: quando l'utente chiede informazioni sul menu dei prodotti, non vogliamo necessariamente restituire una risposta scritta in precedenza. Potremmo invece interrogare un'API REST e recuperare i dati aggiornati.
Rasa permette di farlo attraverso le Custom Actions, funzioni Python che vengono eseguite dal server delle azioni quando il sistema decide di richiamarle.
Un esempio:
import requests
from typing import Any, Text
from rasa_sdk import Action, Tracker
from rasa_sdk.executor import CollectingDispatcher
class ActionGetPizzaMenu(Action):
def name(self) -> Text:
return "action_get_pizza_menu"
def run(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: dict
) -> list:
response = requests.get(
"https://api.pizzashop.com/menu",
timeout=10
)
response.raise_for_status()
menu = response.json()
dispatcher.utter_message(
text=f"Ecco il menu: {menu}"
)
return []In questo esempio la custom action invia una richiesta HTTP a un servizio esterno, recupera il menu e restituisce il risultato all'utente. In un'applicazione reale dovremmo aggiungere una gestione appropriata degli errori, validare la struttura della risposta e formattare i dati in modo leggibile.
Il vantaggio è evidente: il chatbot non è più limitato alle informazioni inserite durante l'addestramento, ma può accedere a dati aggiornati e interagire con il software aziendale.
Possiamo quindi collegare Rasa a CRM, gestionali, database, sistemi di prenotazione, servizi di autenticazione e applicazioni sviluppate internamente.
Personalizzazione e miglioramento continuo
Uno degli aspetti più importanti nello sviluppo di un assistente virtuale è la capacità di adattarlo alle esigenze del contesto applicativo. La personalizzazione non consiste semplicemente nel modificare il tono delle risposte. Significa progettare correttamente il comportamento del sistema, decidere quali informazioni conservare, stabilire quando richiedere ulteriori dati e definire quali operazioni possono essere eseguite.
I domain file, gli slots, le stories, le rules e le custom actions permettono di costruire un'esperienza conversazionale coerente con le esigenze dell'organizzazione.
Anche il dataset deve essere aggiornato nel tempo. Le persone possono utilizzare espressioni differenti per comunicare la stessa intenzione, possono cambiare le procedure aziendali e possono emergere nuove richieste che non erano state previste durante la progettazione iniziale.
Per questo motivo il ciclo di sviluppo non termina con il primo addestramento. Bisogna analizzare le conversazioni, individuare gli errori di classificazione, verificare il riconoscimento delle entità e correggere i percorsi conversazionali che non producono il risultato desiderato.
La qualità di un assistente virtuale si misura soprattutto nella sua capacità di gestire le situazioni reali, comprese quelle che non erano state previste durante la progettazione.
Test e valutazione del chatbot
Un progetto Rasa deve essere sottoposto a verifiche periodiche. Non è sufficiente controllare che il chatbot risponda correttamente a qualche domanda durante lo sviluppo. Occorre valutare la capacità di riconoscere gli intent, estrarre le entità e seguire i percorsi conversazionali previsti.
Rasa mette a disposizione strumenti per addestrare i modelli e valutare le prestazioni attraverso dati di test separati da quelli utilizzati per il training.
Tra gli aspetti da monitorare troviamo la precisione e il richiamo nella classificazione degli intent, le prestazioni nell'estrazione delle entità e la corretta esecuzione delle azioni.
È altrettanto importante verificare i casi di fallback, ovvero le situazioni in cui il sistema non riesce a comprendere una richiesta. Un assistente ben progettato deve sapere quando non dispone di informazioni sufficienti e deve poter chiedere chiarimenti o trasferire la richiesta a un operatore. La fase di test deve comprendere anche scenari con informazioni incomplete, risposte inattese, cambi di argomento e interruzioni della procedura.
Un sistema che funziona soltanto quando l'utente segue esattamente il percorso previsto non è ancora un assistente conversazionale affidabile.
Le alternative open source a Rasa
Rasa non è l'unico strumento disponibile per sviluppare chatbot e assistenti virtuali. L'ecosistema offre diverse piattaforme e librerie, ciascuna con caratteristiche e approcci differenti. La scelta dipende dal linguaggio di programmazione utilizzato, dalla complessità delle conversazioni, dalle competenze del team e dal livello di controllo richiesto sull'infrastruttura.
Botpress: progettazione visuale e sviluppo conversazionale
Botpress è una piattaforma dedicata alla realizzazione di chatbot e assistenti conversazionali, con un'interfaccia visuale che permette di progettare flussi e integrare servizi esterni.
È particolarmente interessante per chi preferisce costruire le conversazioni attraverso strumenti visuali anziché definire ogni comportamento direttamente nel codice.
Nel valutarlo bisogna però distinguere tra il prodotto Botpress attualmente distribuito e le precedenti versioni open source. Non è corretto considerare automaticamente l'attuale piattaforma cloud equivalente a una soluzione liberamente installabile e gestibile su un proprio server.
Per un progetto che richiede piena autonomia sull'infrastruttura, è quindi necessario verificare licenza, disponibilità del codice e condizioni di deployment della specifica versione scelta.
DeepPavlov: NLP e modelli linguistici
DeepPavlov è un framework open source dedicato all'elaborazione del linguaggio naturale e allo sviluppo di sistemi conversazionali.
È particolarmente interessante per chi vuole lavorare direttamente con modelli NLP, classificazione del testo, riconoscimento delle entità e question answering.
La versione DeepPavlov 1.0 si basa su PyTorch e Transformers, offrendo un'architettura modulare e configurabile.
Rispetto a Rasa, l'approccio è maggiormente orientato alla costruzione e all'utilizzo di componenti NLP. È quindi una soluzione da considerare quando la priorità è sperimentare con modelli linguistici e pipeline di elaborazione personalizzate.
Microsoft 365 Agents SDK: l'evoluzione dell'ecosistema Microsoft
Il Microsoft Bot Framework è stato per anni una delle piattaforme più conosciute per lo sviluppo di chatbot multipiattaforma.
Tuttavia, nel dicembre 2025 Microsoft ha concluso il supporto del Bot Framework SDK, che è stato successivamente archiviato su GitHub. Non è quindi opportuno presentarlo come una soluzione attualmente mantenuta per i nuovi progetti.
Il successore indicato da Microsoft è il Microsoft 365 Agents SDK, disponibile per C#, JavaScript e Python.
Questa distinzione è importante: il nuovo SDK non deve essere confuso con il precedente Bot Framework. Si tratta di un'evoluzione dell'ecosistema Microsoft orientata allo sviluppo di agenti e all'integrazione con i servizi della piattaforma.
Per chi lavora in ambienti Microsoft e deve realizzare agenti integrati con Teams e altri servizi aziendali, rappresenta un'opzione da valutare.
OpenDialog: progettazione delle esperienze conversazionali
OpenDialog è una piattaforma orientata alla progettazione e alla gestione di esperienze conversazionali complesse.
Il suo approccio pone particolare attenzione alla struttura del dialogo, al contesto e all'integrazione tra interfaccia conversazionale e sistemi applicativi.
La piattaforma si è evoluta nel tempo verso la gestione di agenti AI, includendo funzionalità per l'integrazione di modelli linguistici, la consultazione di documenti e l'utilizzo di API.
È una soluzione interessante per progetti nei quali la conversazione non rappresenta soltanto un'interfaccia di assistenza, ma diventa parte integrante di un processo aziendale.
Anche in questo caso bisogna verificare le condizioni di licenza dei singoli componenti prima di considerarla completamente equivalente a un framework open source installabile senza vincoli.
ChatterBot: una libreria Python per chatbot semplici
ChatterBot è una libreria Python pensata per realizzare chatbot attraverso un approccio relativamente semplice.
Può essere utilizzata per prototipi, applicazioni didattiche e progetti nei quali non è necessario costruire una complessa architettura di gestione delle conversazioni.
La sua semplicità rappresenta il principale vantaggio, ma anche il limite. Non offre lo stesso livello di controllo e di articolazione delle funzionalità disponibili in Rasa.
È comunque una soluzione da conoscere per chi vuole sperimentare rapidamente con lo sviluppo di chatbot in Python.
Cognitor: un approccio proprietario alla comprensione del linguaggio
Tra le alternative a Rasa inserisco anche Cognitor, un mio progetto che rappresenta un approccio differente alla realizzazione di assistenti virtuali. Invece di affidarsi a un framework già strutturato, l'idea è sviluppare e controllare direttamente i componenti dedicati alla comprensione del linguaggio naturale, alla classificazione degli intent e alla gestione delle richieste.
Questo tipo di soluzione richiede naturalmente un maggiore lavoro di progettazione e sviluppo, ma offre anche una libertà più ampia nella scelta delle architetture, nella preparazione dei dataset e nell'addestramento dei modelli. È un percorso interessante soprattutto quando si vogliono sperimentare soluzioni specifiche, mantenere il controllo sulla pipeline NLU e non dipendere completamente dalle astrazioni offerte da un framework esterno.
Il confronto con Rasa diventa quindi interessante proprio su questo punto: Rasa mette a disposizione un ecosistema già organizzato per gestire intent, entità, conversazioni e azioni personalizzate; Cognitor permette invece di intervenire direttamente sui meccanismi che rendono possibile la comprensione delle richieste. Non è necessariamente una scelta migliore in assoluto, ma un approccio alternativo per chi vuole costruire un sistema conversazionale partendo dai propri requisiti tecnici.
Rasa o un'alternativa? Come scegliere il framework
La scelta del framework non dovrebbe essere determinata soltanto dalla popolarità di una piattaforma o dal numero di funzionalità pubblicizzate. Bisogna partire dal problema che vogliamo risolvere.
Rasa è particolarmente interessante quando abbiamo bisogno di un assistente personalizzato, con una logica di conversazione strutturata, integrazioni applicative e controllo sul comportamento del sistema.
DeepPavlov è più orientato alla sperimentazione e all'utilizzo di componenti NLP avanzati. Botpress può risultare interessante quando la progettazione visuale è un requisito importante. OpenDialog si concentra sulla gestione delle esperienze conversazionali e degli agenti aziendali, mentre ChatterBot può essere sufficiente per applicazioni molto semplici.
Il Microsoft 365 Agents SDK, invece, rappresenta una strada differente per chi lavora già nell'ecosistema Microsoft e vuole sviluppare agenti integrati con i suoi servizi.
La valutazione deve comprendere anche aspetti meno evidenti durante la fase iniziale: manutenzione, aggiornamenti, licenze, disponibilità dei componenti, gestione dei dati e possibilità di migrare verso altre tecnologie.
Un chatbot può iniziare come un piccolo progetto sperimentale e diventare successivamente un servizio utilizzato da centinaia o migliaia di persone. Scegliere una piattaforma soltanto perché permette di realizzare velocemente un prototipo può comportare costi e difficoltà quando il sistema dovrà essere mantenuto e ampliato.
Conclusioni
Rasa rappresenta uno strumento importante nell'ecosistema dell'intelligenza artificiale. La sua architettura permette di sviluppare assistenti virtuali personalizzati, integrando comprensione del linguaggio naturale, gestione del dialogo e logica applicativa.
Il vero lavoro, però, non consiste soltanto nell'installare il framework e scrivere qualche configurazione YAML. La parte più delicata è progettare un dataset coerente, individuare correttamente gli intent, riconoscere le entità e costruire percorsi capaci di gestire le esigenze reali degli utenti.
L'integrazione con strumenti come LLM e spaCy permette di automatizzare alcune attività e ridurre il lavoro necessario per preparare i dati, ma non elimina la necessità di verificare ciò che viene generato. L'intelligenza artificiale può accelerare la costruzione di un progetto, non sostituire le decisioni architetturali e il controllo della qualità.
Personalmente considero particolarmente interessante l'approccio che mantiene separati il riconoscimento della richiesta e l'esecuzione delle operazioni. Un modello può interpretare il linguaggio dell'utente, ma le regole applicative devono continuare a essere governate da una logica verificabile. È una distinzione fondamentale quando un assistente deve interagire con dati aziendali, procedure amministrative o servizi che producono conseguenze concrete.
Rasa, insieme alle alternative disponibili, dimostra che lo sviluppo di assistenti virtuali non deve necessariamente passare attraverso piattaforme proprietarie e servizi completamente gestiti da terzi. Con le competenze tecniche adeguate è possibile costruire sistemi autonomi, personalizzabili e integrati con la propria infrastruttura.
La differenza tra un chatbot che risponde e un assistente virtuale che risolve davvero un problema si trova proprio qui: nella qualità dei dati, nella progettazione della conversazione e nella capacità di trasformare una richiesta in un'operazione corretta.
