\n\n\n\n Il mio Fuzzy Matching in Python per un miglior NLU del bot - AI7Bot \n

Il mio Fuzzy Matching in Python per un miglior NLU del bot

📖 12 min read2,262 wordsUpdated Apr 3, 2026

Ciao a tutti, sono Marcus di ai7bot.com. Oggi è il 27 marzo 2026 e ultimamente ho affrontato qualcosa di piuttosto specifico nei miei progetti di bot: far sì che i bot sembrino meno… beh, bot. Più come se *capissero* veramente quello che stai dicendo, anche quando sei un po’ confuso con le parole. Dimentica per un attimo quei servizi NLU costosi e fancy. Sto parlando di qualcosa di molto più concrete e, francamente, spesso trascurato: fuzzy matching con Python. In particolare, come utilizzarlo efficacemente all’interno dei tuoi bot di Telegram per gestire input degli utenti che non sono perfettamente puliti.

Tutti noi abbiamo costruito bot che si aspettano un comando preciso o una parola chiave specifica. E quando l’utente scrive “puoi aiutarmi a impostare un nuovo utente” invece di “imposta utente”, il bot fissa il vuoto. O peggio, fornisce un generico messaggio “non capisco”. Questo è un modo rapido per frustrate gli utenti e far sentire il tuo bot stupido. Ho recentemente vissuto questa esperienza di persona mentre costruivo un piccolo bot di supporto interno per la startup di un amico. Avevano bisogno che rispondesse a domande comuni, ma il team continuava a digitare variazioni delle domande. “Come posso reimpostare la mia password?” è diventato “aiuto reset password” o “password dimenticata”. Il mio bot iniziale stava fallendo spettacolamente.

Quindi, oggi voglio entrare nel merito di come puoi utilizzare la libreria fuzzywuzzy di Python per aggiungere uno strato di comprensione simile a quella umana ai tuoi bot di Telegram senza bisogno di un motore NLU completo. Non si tratta di apprendimento profondo o linguistica complessa; si tratta di un confronto di stringhe pratico che fa una grande differenza nell’esperienza dell’utente.

Il Problema: I Bot Sono Troppo Letterali

Il mio primo bot di Telegram per quella startup era un semplice gestore di comandi. Se qualcuno digitava `/faq`, elencava le FAQ. Se digitavano `/support`, collegava alla pagina di supporto. Per domande specifiche, avevo gestori come questo:


@bot.message_handler(func=lambda message: message.text and "reset password" in message.text.lower())
def handle_reset_password(message):
 bot.reply_to(message, "Per reimpostare la tua password, visita il nostro portale su example.com/reset.")

Sembra a posto, giusto? Tranne, come ho menzionato, gli utenti non digitano sempre “reset password”. Scrivono “ho bisogno di reimpostare la mia password”, “ho dimenticato la mia password”, “aiuto password”, “come posso avere una nuova password?”. Il mio bot, benedetto sia, catturava solo l’esatta frase. Era un incubo di usabilità. Il mio amico mi ha chiamato, leggermente infastidito, dicendo: “Marcus, il tuo bot capisce solo robot, non umani!” Aveva ragione.

Questo abbinamento rigido e letterale è un comune punto debole. Noi, come sviluppatori, spesso progettiamo per l’input ideale, ma gli utenti raramente lo forniscono. Digitano in modo conversazionale, fanno errori di battitura, utilizzano sinonimi. E i nostri bot devono essere pronti per questo.

Entra in Gioco il Fuzzy Matching con fuzzywuzzy

È qui che entrano in gioco librerie come fuzzywuzzy. È una libreria Python che implementa il calcolo della distanza di Levenshtein, che misura sostanzialmente quante modifiche devi apportare a una stringa per arrivare a un’altra. Minore è il numero, più simili sono. fuzzywuzzy ti fornisce poi un punteggio da 100.

Pensala così: “mela” e “aple” sono molto vicine. “Mela” e “banana” non lo sono. fuzzywuzzy può dirti *quanto* sono vicine.

Prima di tutto, devi installarla:


pip install fuzzywuzzy python-Levenshtein

Hai bisogno di python-Levenshtein per prestazioni migliori, poiché fuzzywuzzy lo utilizza se disponibile.

Concetti di Fuzzy Matching di Base

Ci sono alcune funzioni core che utilizzerai da fuzzywuzzy.fuzz:

  • fuzz.ratio(string1, string2): Calcola un semplice rapporto di somiglianza.
  • fuzz.partial_ratio(string1, string2): Utile quando una stringa è molto più lunga dell’altra ma contiene una sottostringa simile. Ad esempio, “reset password” e “ho dimenticato la mia password, puoi aiutarmi a reimpostarla?”
  • fuzz.token_sort_ratio(string1, string2): Ordina le parole in entrambe le stringhe in ordine alfabetico prima di confrontarle. Questo aiuta con parole riordinate, come “password reset” vs. “reset password”.
  • fuzz.token_set_ratio(string1, string2): Simile a token_sort_ratio ma gestisce meglio le parole duplicate e comuni. Spesso è la scelta più sicura per input conversazionali.

Diamo un’occhiata ad alcuni rapidi esempi nell’interprete Python:


from fuzzywuzzy import fuzz

# Rapporto semplice
print(fuzz.ratio("reset password", "password reset")) # Output: 95
print(fuzz.ratio("reset password", "reset passwrd")) # Output: 94
print(fuzz.ratio("reset password", "forgot password")) # Output: 62

# Rapporto parziale (ottimo per frasi più lunghe)
print(fuzz.partial_ratio("Ho bisogno di reimpostare la mia password", "reset password")) # Output: 100

# Rapporto di ordinamento delle parole (gestisce l'ordine delle parole)
print(fuzz.token_sort_ratio("reset password", "password reset")) # Output: 100

# Rapporto set di parole (spesso il migliore per input conversazionali)
print(fuzz.token_set_ratio("Come posso reimpostare la mia password?", "aiuto reset password")) # Output: 90
print(fuzz.token_set_ratio("Dove si trova il FAQ?", "link FAQ")) # Output: 67

Nota come token_sort_ratio e token_set_ratio diano punteggi più alti quando le parole sono riordinate o quando una frase è un sottoinsieme dell’altra, che è esattamente ciò di cui abbiamo bisogno per l’input degli utenti.

Integrando il Fuzzy Matching in un Bot di Telegram

Ora, passiamo alla pratica. Come implementiamo questo nel nostro bot di Telegram? L’idea è di definire un elenco di frasi “canoniche” o attese per ogni azione. Poi, quando un utente invia un messaggio, lo confrontiamo con tutte queste frasi canoniche e scegliamo quella con il punteggio di somiglianza più alto, se supera una certa soglia.

Ecco un esempio semplificato utilizzando la libreria python-telegram-bot (anche se il concetto si applica a qualsiasi framework di bot di Telegram).

Passo 1: Definisci la Tua Mappa delle Intenzioni

Invece di codificare “reset password” in un gestore di messaggi, creeremo un dizionario che associa un’“intenzione” (cosa vuole fare l’utente) a un elenco di frasi che la attivano.


INTENT_PHRASES = {
 "reset_password": [
 "reset password",
 "ho dimenticato la mia password",
 "come reimpostare la password",
 "cambiare password",
 "ottenere nuova password"
 ],
 "contact_support": [
 "contattare supporto",
 "parlare con un umano",
 "ho bisogno di aiuto",
 "team di supporto",
 "problema tecnico"
 ],
 "view_faq": [
 "faq",
 "domande frequenti",
 "domande comuni",
 "fare una domanda"
 ]
}

# Associare intenzioni a funzioni gestore
INTENT_HANDLERS = {} # Populate this later

Passo 2: Crea una Funzione di Fuzzy Matching

Questa funzione prenderà il messaggio dell’utente e restituirà l’intenzione migliore e il suo punteggio.


from fuzzywuzzy import fuzz
from fuzzywuzzy import process

def get_best_intent(user_message, intent_map, threshold=70):
 best_match_intent = None
 best_score = 0

 # Colleziona tutte le possibili frasi dalla mappa delle intenzioni
 all_phrases = []
 for intent, phrases in intent_map.items():
 for phrase in phrases:
 all_phrases.append((phrase.lower(), intent)) # Memorizza la frase e la sua intenzione

 # Usa process.extractOne per efficienza
 # Restituisce (phrasing_match, punteggio, indice_nella_lista_delle_scelte)
 # Adatteremo un po' poiché dobbiamo mappare di nuovo alle nostre intenzioni
 
 # Iteriamo manualmente per chiarezza, oppure usiamo process.extract con un punteggio personalizzato
 # Per semplicità, creeremo un elenco piatto di tutte le frasi “trigger”
 # e poi mapperemo di nuovo all'intento.

 flat_trigger_phrases = [phrase for sublist in intent_map.values() for phrase in sublist]

 # process.extractOne restituisce (match_string, score)
 # Questo abbina il user_message alla nostra lista piatta di frasi trigger
 best_phrase_match, score = process.extractOne(
 user_message.lower(), 
 flat_trigger_phrases, 
 scorer=fuzz.token_set_ratio # Spesso il migliore per l'input generale
 )

 if score >= threshold:
 # Ora, trova a quale intenzione appartiene questo best_phrase_match
 for intent_name, phrases_list in intent_map.items():
 if best_phrase_match in [p.lower() for p in phrases_list]:
 best_match_intent = intent_name
 best_score = score
 break # Trovata l'intenzione, non serve controllare altre frasi
 
 return best_match_intent, best_score

Una nota veloce su process.extractOne: è progettata per trovare la corrispondenza migliore per una stringa all’interno di un elenco di scelte. È più efficiente rispetto a fare un ciclo su tutto da solo. Il mio esempio qui sopra mostra come utilizzarla creando un elenco piatto di tutte le frasi trigger e poi mappando la corrispondenza migliore di nuovo alla sua intenzione originale.

Passo 3: Implementa il Gestore di Messaggi del Bot

Ora, modifica il gestore di messaggi principale del tuo bot per utilizzare questa logica.


import telebot # Assuming pyTelegramBotAPI
# from telegram.ext import Updater, MessageHandler, Filters # If using python-telegram-bot

# Inizializza il tuo bot (sostituisci con il tuo token effettivo)
bot = telebot.TeleBot("YOUR_TELEGRAM_BOT_TOKEN")

# Definisci i gestori per ogni intento
def handle_reset_password_intent(message):
 bot.reply_to(message, "Nessun problema! Per reimpostare la tua password, visita il nostro portale sicuro su example.com/reset. Se hai bisogno di ulteriore assistenza, contatta il supporto IT.")

def handle_contact_support_intent(message):
 bot.reply_to(message, "Capisco che hai bisogno di parlare con qualcuno. Puoi contattare il nostro team di supporto via email a [email protected] o chiamarci al 1-800-BOT-HELP durante l'orario lavorativo.")

def handle_view_faq_intent(message):
 bot.reply_to(message, "Certo, ecco le nostre Domande Frequenti: example.com/faq. Fammi sapere se hai una domanda specifica!")

# Popola la mappa INTENT_HANDLERS
INTENT_HANDLERS = {
 "reset_password": handle_reset_password_intent,
 "contact_support": handle_contact_support_intent,
 "view_faq": handle_view_faq_intent
}

@bot.message_handler(func=lambda message: True) # Cattura tutti i messaggi
def handle_all_messages(message):
 user_text = message.text
 if not user_text:
 return

 best_intent, score = get_best_intent(user_text, INTENT_PHRASES, threshold=75) # Regola la soglia se necessario

 if best_intent and best_intent in INTENT_HANDLERS:
 INTENT_HANDLERS[best_intent](message)
 else:
 bot.reply_to(message, "Non sono sicuro di aver capito. Puoi provare a riformulare o a fare una domanda diversa? Puoi anche digitare 'help' per le opzioni.")

bot.polling()

Cosa succede qui? Quando un utente invia un messaggio, la nostra funzione handle_all_messages lo intercetta. Poi passa il testo del messaggio a get_best_intent. Se viene trovato un intento adatto (punteggio sopra 75 in questo caso), viene chiamata la funzione di gestione corrispondente. Altrimenti, il bot dà un messaggio di fallback educato.

Ho impostato la soglia a 75 dopo alcuni esperimenti. Se è troppo bassa, il bot potrebbe fraintendere troppo spesso. Se è troppo alta, diventa di nuovo troppo rigido. Questo è un valore che vorrai regolare per il tuo specifico bot e i suoi utenti.

Uno Scenario Pratico: Il Comando “Aiuto”

Diciamo che un utente digita “Ho bisogno di assistenza per favore.”

  • user_message: “Ho bisogno di assistenza per favore.”
  • get_best_intent verifica contro INTENT_PHRASES.
  • Trova “ho bisogno di aiuto” in contact_support, e fuzz.token_set_ratio("Ho bisogno di assistenza per favore", "ho bisogno di aiuto") potrebbe restituire un punteggio di, ad esempio, 85.
  • Poiché 85 > 75 (la nostra soglia), l’intento "contact_support" viene restituito.
  • Il bot chiama quindi handle_contact_support_intent(message).

Questo è un modo molto più efficace di gestire le variazioni rispetto alla semplice corrispondenza di stringhe.

Considerazioni e Regolazioni Avanzate

Regolazione della Soglia

Questo è cruciale. Una soglia di 70-80 è spesso un buon punto di partenza per token_set_ratio. Testa ampiamente con input reali degli utenti o variazioni simulate per trovare il punto ottimale. Se è troppo bassa otterrai falsi positivi; se è troppo alta perderai il vantaggio della corrispondenza fuzzy.

Gestire Più Corrispondenze Potenziali

E se due intenti avessero punteggi simili? Ad esempio, “reimposta password” e “password dimenticata” sono simili. Potresti voler introdurre un meccanismo di risoluzione dei pareggi o, per punteggi molto vicini, chiedere all’utente di chiarire:


"Hai inteso reimpostare la tua password o contattare il supporto?"

fuzzywuzzy.process.extract (senza il “One”) può restituire un elenco delle migliori N corrispondenze, il che potrebbe essere utile qui.

Preprocessing dell’Input Utente

Prima della corrispondenza fuzzy, considera alcune operazioni di preprocessing di base:

  • Converti in minuscolo: user_message.lower() (già presente negli esempi).
  • Rimuovi la punteggiatura: Usa str.translate e string.punctuation.
  • Rimuovi le comuni parole vuote (ad es., “a”, “il”, “è”) se non hanno significato per i tuoi intenti. Fai attenzione, poiché a volte le parole vuote sono importanti per il contesto.

Combinare con Corrispondenze Esatte

Per comandi critici, potresti comunque voler effettuare prima un controllo di corrispondenza esatta. Ad esempio, se un utente digita `/admin`, vuoi gestirlo esattamente prima che la corrispondenza fuzzy cerchi di collegarlo a “aggiungi nuovo utente” a causa di “admi”.

Prestazioni

Per bot con un numero molto elevato di intenti o frasi di attivazione, chiamare ripetutamente funzioni di corrispondenza fuzzy può diventare lento. Tuttavia, per la maggior parte dei bot di piccole e medie dimensioni (centinaia di frasi), fuzzywuzzy con python-Levenshtein è solitamente sufficientemente veloce. Se riscontri colli di bottiglia nelle prestazioni, potresti considerare soluzioni NLU più avanzate o preindicizzare le tue frasi.

Riflessioni Utili

  1. Non fare affidamento esclusivamente sulla corrispondenza di stringhe esatte: Gli utenti sono disordinati. Il tuo bot deve essere perdonante.
  2. Usa fuzzywuzzy (o librerie simili): È un modo veloce ed efficace per aggiungere uno strato di “comprensione” al tuo bot senza ricorrere al NLU completo.
  3. Prioritizza fuzz.token_set_ratio: Per input conversazionali, è spesso la scelta più solida poiché gestisce bene l’ordine delle parole e i sottoinsiemi.
  4. Definisci frasi “canoniche” chiare: Anche con la corrispondenza fuzzy, è fondamentale fornire al tuo bot buoni esempi di ciò che deve cercare.
  5. Regola la tua soglia: Sperimenta con la soglia del punteggio di similitudine (ad es., 70-85) per trovare il giusto equilibrio per la tolleranza del tuo bot all’ambiguità.
  6. Implementa un fallback delicato: Avere sempre un messaggio di “non capisco” che guidi l’utente su cosa fare dopo.

Aggiungere la corrispondenza fuzzy al bot di supporto del mio amico ha fatto una grande differenza. Le lamentele “Marcus, il tuo bot capisce solo i robot!” sono cessate, e il bot è diventato effettivamente uno strumento utile per il loro team. È una tecnica relativamente semplice, ma il suo impatto sull’esperienza utente è enorme. Provala nel tuo prossimo progetto di bot Telegram e fammi sapere come va nei commenti!

🕒 Published:

💬
Written by Jake Chen

Bot developer who has built 50+ chatbots across Discord, Telegram, Slack, and WhatsApp. Specializes in conversational AI and NLP.

Learn more →
Browse Topics: Best Practices | Bot Building | Bot Development | Business | Operations
Scroll to Top