Nel campo in continua evoluzione dell’elaborazione del linguaggio naturale (NLP), la capacità di rappresentare il testo in un formato comprensibile per le macchine è fondamentale. Gli incorporamenti di testo, noti anche come word embedding, sono una tecnica chiave che consente ai computer di “comprendere” il significato e le relazioni tra le parole. In sostanza, gli incorporamenti di testo trasformano le parole, le frasi o interi documenti in vettori numerici densi, catturando le loro proprietà semantiche e sintattiche. Questa rappresentazione vettoriale consente ai modelli di apprendimento automatico di elaborare e analizzare il testo in modo più efficiente ed efficace, aprendo la strada a una vasta gamma di applicazioni NLP. Per raggiungere questo obiettivo, gli incorporamenti di testo convertono il testo in vettori numerici che gli algoritmi di apprendimento automatico possono elaborare. Ciò consente ai computer di analizzare le relazioni tra le parole e comprenderne il significato semantico, aprendo nuove possibilità per l’analisi e l’interpretazione del linguaggio.

Gli incorporamenti di testo “embedding” sono delle rappresentazioni numeriche che trasformano parole o frasi in rappresentazioni numeriche in un iperpiano di “ n dimensioni” e permettono di individuare le relazioni semantiche tra parole.
Di seguito si riporta un video della piattaforma Embedding Projector, uno strumento di visualizzazione interattivo sviluppato da Google che permette di esplorare queste rappresentazioni vettoriali ad alta dimensionalità in spazi più comprensibili come 2D o 3D. Questo potente strumento consente ai ricercatori e agli sviluppatori di visualizzare, analizzare e comprendere meglio le relazioni semantiche catturate dagli embeddings, facilitando l’identificazione di pattern, cluster e outlier nei dati. Attraverso tecniche come PCA, t-SNE o UMAP, l’Embedding Projector offre una finestra intuitiva nel complesso mondo degli spazi vettoriali multidimensionali, rendendo più accessibile l’esplorazione delle strutture semantiche latenti nel linguaggio.
Un concetto chiave alla base degli incorporamenti di testo è l’ipotesi distribuzionale, che afferma che le parole con significati simili tendono a comparire in contesti simili. Ad esempio, le parole “re” e “regina”, pur non essendo sinonimi, condividono un contesto simile legato alla regalità e alla monarchia. Gli incorporamenti di testo mirano a catturare questa similarità semantica rappresentando queste parole con vettori vicini nello spazio vettoriale. Sfruttando questa intuizione, i modelli di incorporamento analizzano grandi quantità di dati testuali per apprendere le relazioni tra le parole e codificarle in vettori. Tecniche come la riduzione della dimensionalità sulla matrice di co-occorrenza delle parole aiutano a creare rappresentazioni più compatte ed efficienti, riducendo la complessità computazionale e i requisiti di memoria. Queste tecniche di riduzione della dimensionalità permettono di poter visualizzare gli incorporamenti di testo in spazio a due e tre dimensioni, compressibili dall’occhio umano.
Questi vettori sono posizionati in uno spazio vettoriale multidimensionale, dove la distanza e la direzione tra i vettori riflettono la similarità e le relazioni semantiche tra le parole corrispondenti.
Un’intuizione chiave degli incorporamenti di testo è che consentono di eseguire operazioni matematiche sul testo, preservando le relazioni semantiche. Ad esempio, l’operazione vettoriale “re – uomo + donna” potrebbe risultare in un vettore molto vicino all’incorporamento per “regina”, catturando la relazione analogica tra queste parole.
Di seguito si trova un video Google Cloud Tech che è davvero eccezionale! Spiega in modo semplice e coinvolgente cosa sono gli embedding, rendendo questo argomento affascinante e accessibile a tutti!
Risorse cosigliate
Se sei affascinato dall’idea di esplorare i concetti straordinari che si celano dietro agli Embedding, non perdere l’occasione di guardare il video del corso di Google: Machine Learning Crash Course
Machine Learning Crash Course di Google Developers
Rappresenta una risorsa preziosa per una rapida introduzione al machine learning di Google, comprende una serie di video animati, visualizzazioni interattive ed esercitazioni pratiche.
Link al corso: Embedding – Machine Learning
Come si possono applicare gli embedding?

- Ricerca semantica: Gli incorporamenti consentono di trovare documenti e informazioni simili in base al significato, andando oltre la semplice corrispondenza delle parole chiave. Ad esempio, Google Search utilizza gli incorporamenti per comprendere l’intento dietro le query di ricerca e fornire risultati più pertinenti. Invece di cercare solo le pagine web che contengono le parole chiave esatte, Google analizza il significato della query e restituisce i risultati che corrispondono a quel significato, anche se utilizzano parole diverse.
- Classificazione del testo: Gli incorporamenti possono essere utilizzati per classificare il testo in diverse categorie, come l’analisi del sentiment, il rilevamento di argomenti e la classificazione dello spam. Ad esempio, le aziende possono utilizzare gli incorporamenti per analizzare il sentiment dei commenti dei clienti sui social media o per classificare le e-mail come spam o non spam.
- Clustering del testo: Gli incorporamenti possono essere utilizzati per raggruppare documenti simili in base al loro contenuto semantico. Ad esempio, un’organizzazione di notizie potrebbe utilizzare gli incorporamenti per raggruppare articoli su argomenti simili, anche se utilizzano parole chiave diverse.
- Traduzione automatica: Gli incorporamenti possono migliorare la qualità della traduzione automatica catturando le relazioni semantiche tra le parole in lingue diverse.
- Sistemi di raccomandazione: Gli incorporamenti possono migliorare i sistemi di raccomandazione analizzando la cronologia degli acquisti e il comportamento di navigazione, fornendo suggerimenti semanticamente correlati.
- Rilevamento delle anomalie: Gli incorporamenti possono migliorare consentire di analizzare la struttura sottostante dei dati e distinguere tra anomalie reali e variazioni normali.
- Question answering: Gli incorporamenti possono essere utilizzati per trovare risposte precise a domande specifiche, identificando i passaggi di testo più rilevanti. Ad esempio, un chatbot di assistenza clienti potrebbe utilizzare gli incorporamenti per trovare le risposte alle domande degli utenti in una knowledge base.
- Generazione di testo: Gli incorporamenti possono essere utilizzati come input per modelli di generazione di testo, consentendo la creazione di testo coerente e creativo. Ad esempio, gli incorporamenti possono essere utilizzati per generare descrizioni di prodotti, articoli di notizie o persino sceneggiature.
Fonte: https://www.deeplearning.ai/
Corso consigliato: Understanding and Applying Text Embeddings di www.deeplearning.ai creato in collaborazione con Google
Cenni sull’evoluzione degli Embedding
Nel corso degli anni, sono state sviluppate diverse tecniche per generare incorporamenti di testo, ognuna con i propri punti di forza e di debolezza.
Prima dell’avvento di tecniche più avanzate, metodi come Bag-of-Words (BoW) e Term Frequency-Inverse Document Frequency (TF-IDF) venivano utilizzati per rappresentare il testo. Tuttavia, questi metodi presentano delle limitazioni significative. BoW, ad esempio, crea vettori basati sulla frequenza delle parole in un documento, ma non tiene conto dell’ordine delle parole o delle relazioni semantiche tra di esse. TF-IDF, pur migliorando BoW considerando la rarità delle parole nel corpus, soffre ancora di problemi simili. Questi metodi tradizionali spesso comportano la creazione di vettori ad alta dimensionalità con molti zeri, il che li rende computazionalmente intensivi e meno efficienti per l’analisi del testo su larga scala.
Word2Vec e GloVe.
Di seguito, si riportano alcune delle tecniche più diffuse:
Word2Vec 1 e GloVe
Word2Vec 1 e GloVe sono due modelli classici di incorporamento di parole che hanno segnato un passo avanti significativo nell’NLP. Word2Vec utilizza una rete neurale superficiale con due architetture principali: Continuous Bag-of-Words (CBOW) e Skip-gram. CBOW prevede una parola target in base alle parole circostanti, mentre Skip-gram prevede le parole circostanti in base a una parola target. GloVe, d’altra parte, si basa su una tecnica di fattorizzazione di matrici che analizza le statistiche di co-occorrenza delle parole in un corpus. Entrambi i modelli producono vettori di parole che catturano le relazioni semantiche, consentendo operazioni vettoriali come l’analogia (“re” – “uomo” + “donna” ≈ “regina”).
Tuttavia, Word2Vec e GloVe presentano alcune limitazioni. In primo luogo, sono modelli a senso unico, il che significa che generano un singolo vettore per parola, indipendentemente dal contesto. Questo può essere problematico per parole polisemiche con significati multipli. In secondo luogo, non gestiscono efficacemente le parole fuori vocabolario (OOV), ovvero parole che non sono presenti nel vocabolario di addestramento.
FastText
FastText (10), sviluppato da Facebook AI Research, affronta alcune delle limitazioni di Word2Vec, come la gestione delle parole fuori vocabolario. Invece di considerare le parole come unità atomiche, FastText rappresenta ogni parola come una somma di vettori di n-grammi di caratteri. Questo approccio consente a FastText di generare incorporamenti anche per parole rare o OOV, sfruttando le informazioni sui sotto-componenti delle parole. FastText è particolarmente efficace per lingue con morfologie ricche, dove le parole possono avere diverse forme flessive. È importante notare che, sebbene Word2Vec e GloVe siano spesso citati come le principali tecniche di incorporamento basate sulla previsione, FastText rientra anch’esso in questa categoria.
BERT, RoBERTa, XLNet
L’architettura Transformer ha rivoluzionato il campo dell’NLP, consentendo la creazione di modelli di incorporamento contestuale. BERT (Bidirectional Encoder Representations from Transformers), RoBERTa e XLNet sono esempi di modelli basati su Transformer che generano incorporamenti di parole dipendenti dal contesto. A differenza di Word2Vec e GloVe, che producono incorporamenti statici, questi modelli considerano l’intero contesto di una parola, sia a sinistra che a destra, per generare un vettore. Questo approccio consente di catturare significati più sfumati e relazioni complesse tra le parole, migliorando la comprensione del linguaggio da parte delle macchine.
Incorporamenti di Testo Pre-addestrati
Gli incorporamenti di testo pre-addestrati, come quelli generati da Word2Vec, GloVe e BERT, svolgono un ruolo fondamentale nello sviluppo di modelli linguistici più avanzati. Questi incorporamenti servono come base per modelli come BERT e GPT, consentendo loro di beneficiare della conoscenza acquisita durante la fase di pre-addestramento su enormi quantità di dati testuali (4). L’utilizzo di incorporamenti pre-addestrati può accelerare il processo di addestramento e migliorare le prestazioni dei modelli in una varietà di attività NLP.
Sentence-BERT Sentence-BERT (SBERT) (17) è un modello specializzato per la generazione di incorporamenti a livello di frase. SBERT adatta l’architettura BERT aggiungendo strutture di rete siamese e tripletta, consentendo di mappare frasi in uno spazio vettoriale dove la similarità semantica è rappresentata dalla distanza tra i vettori. SBERT è particolarmente efficiente per attività di Similarità Semantica Testuale (STS), come la ricerca di frasi simili o la parafrasi (18). A differenza di BERT, che richiede il confronto di ogni possibile coppia di frasi, Sentence-BERT mappa le frasi in uno spazio vettoriale a dimensione fissa, consentendo il confronto diretto di più frasi contemporaneamente. Questo rende Sentence-BERT significativamente più efficiente dal punto di vista computazionale per le attività STS, soprattutto quando si ha a che fare con un gran numero di frasi
Qual è la frontiera attuale?
La frontiera attuale della ricerca si sta spingendo verso paradigmi avanzati: embedding multimodali che integrano comprensione testuale e visiva, rappresentazioni neurosimboliche che combinano apprendimento statistico e ragionamento simbolico, e sistemi di continuous learning capaci di adattarsi dinamicamente a nuovi domini e contesti.
Gli embedding multimodali sono rappresentazioni vettoriali che integrano informazioni da diverse modalità, come testo, immagini e video, in uno spazio semantico comune. Questo consente di confrontare elementi differenti e apre la strada a nuove applicazioni di ricerca.
In pratica, trasformano dati di vari tipi in vettori numerici, permettendo di calcolarne la somiglianza. Ad esempio, un modello può creare un vettore per un’immagine e uno per la sua descrizione testuale, mantenendoli vicini nello spazio vettoriale a indicare somiglianza.
Di seguito si riportano alcuni tra i modelli più conosciuti
Esempi di modelli e tecnologie:
- CLIP (Contrastive Language-Image Pretraining):Un modello famoso per il suo lavoro nel campo degli embedding multimodali, sviluppato da OpenAI.
- Jina CLIP:Modelli migliorati di CLIP, con funzionalità di recupero multilingue e supporto per risoluzioni di immagine più elevate.
- Vertex AI di Google Cloud:Offre funzionalità avanzate per generare embedding multimodali, adatti per diverse applicazioni azienedali.
In questo interessante video di Google Cloud Tech , è possibile esplorare il potere dei modelli di embedding multimodali, rivelando le loro incredibili applicazioni nel mondo reale con i modelli di AI generativa di Google.
Risorse consigliate:
Applicazioni degli embedding con le API di Google Vertex AI
In questa sezione si descrive come implementare un modulo per l’inizializzazione e l’utilizzo del servizio di Text Embeddings di Vertex AI di Google Cloud. Questo modulo ha l’obiettivo di dimostrare come generare rappresentazioni vettoriali di testo (embedding) e come utilizzarle per analisi semantiche avanzate con Vertex AI.
Gli obiettivi principali del modulo sono:
- Configurare l’ambiente di sviluppo con Vertex AI e le librerie necessarie
- Generare embedding vettoriali da parole singole e frasi complete
- Analizzare la similarità semantica tra diversi testi attraverso il confronto degli embedding
- Dimostrare la differenza tra embedding basati sulla media delle parole e embedding contestuali di frasi
Il modulo illustra due approcci fondamentali per la generazione di embedding:
– Embedding di parole singole: trasformazione di parole in vettori
– Embedding di frasi: generazione di rappresentazioni vettoriali che preservano il contesto e l’ordine delle parole
Il modulo fornisce le basi sperimentali per implementare funzionalità di ricerca semantica, classificazione e clustering testuale con i modelli di Embedding di Google Vertex AI.
La comprensione di questi concetti è essenziale per lo sviluppo di applicazioni di elaborazione del linguaggio naturale che richiedono una profonda comprensione semantica del testo.
Applicare il modello di incorporamento di testo
Gli incorporamenti vettoriali forniscono un metodo per trasformare parole, frasi e altri dati in rappresentazioni numeriche che ne racchiudono il significato semantico e le associazioni.

Fonte: https://www.graft.com/blog/open-source-text-embedding-models
Questo esempio di codice permette di creare un incorporamento di testo di alcune parole contenute in una lista.
Lista delle parole = “algoritmo”, “rete neurale”, “datacenter”, “sensore”, “interfaccia”, “prototipo”, “digitale”, “virtuale”, “criptovaluta”, “banda larga”, “rivoluzionario”, “creativo”, “sostenibile”, “adattivo”, “trasformativo”, “agile”, “scalabile”, “visionario”, “strategico”, “disruptive”
L’API Text Embeddings di Vertex AI è uno strumento fondamentale per trasformare il testo in vettori numerici, catturando con precisione il significato semantico e il contesto delle parole. Queste rappresentazioni vettoriali sono progettate per cogliere il significato e il contesto delle parole stesse, consentendo la creazione di modelli che facilitano l’elaborazione del linguaggio naturale in diverse applicazioni, come la ricerca semantica, il clustering e la classificazione.
Di seguito si riporteranno degli esempi di codice in Python, sviluppato considerando la documentazione dell’API di Text Embedding di Vertex AI.
Incorporamento di testo di una lista di parole
Per generare incorporamenti di una lista di parole e analizzare le somiglianze semantiche all’interno di una matrice di similarità, è fondamentale comprendere come tali tecniche consentano di identificare facilmente le parole affini in base al loro significato. Questo approccio offre strumenti per esplorare le relazioni tra le parole, facilitando una maggiore comprensione del contesto e dell’uso linguistico; inoltre, è cruciale per la progettazione di sistemi RAG efficaci, poiché consente di ottimizzare le interazioni e migliorare la rilevanza delle risposte generate.
Il seguente esempio è replicabile su Google Colaboratory
Colab è un servizio di Jupyter Notebook in hosting che non richiede alcuna configurazione per essere utilizzato e fornisce accesso gratuito alle risorse di calcolo, comprese GPU e TPU.
Colab è particolarmente adatto all’apprendimento automatico, alla scienza dei dati e alla formazione.
STEP1: Configurare l’ambiente Python, installando le librerie necessarie, effettuando l’autenticazione e caricando le credenziali di accesso al progetto creato in Google Vertex AI.
#Installare l'SDK Vertex AI per Python
!pip show google-cloud-aiplatform
# @title Autenticazione
import sys
if "google.colab" in sys.modules:
import IPython
app = IPython.Application.instance()
app.kernel.do_shutdown(True)
import sys
if "google.colab" in sys.modules:
from google.colab import auth
auth.authenticate_user()
# @title Definire il progetto associato a Google Vertex AI
PROJECT_ID = "PROJECT_ID" # @param {type:"string"}
LOCATION = "REGION" # @param {type:"string"}
from google.cloud import aiplatform
aiplatform.init(project=PROJECT_ID, location=LOCATION)STEP 2: Applicare il modello di embedding
# @title Trasformare un eleco di parole in vettori numerici
from vertexai.language_models import TextEmbeddingModel, TextEmbeddingInput
# Lista di venti termini comuni relativi alla tecnologia
LISTA_PAROLE = [
"algoritmo", "rete neurale", "datacenter", "sensore", "interfaccia", "prototipo", "digitale", "virtuale", "criptovaluta", "banda larga", "rivoluzionario",
"creativo", "sostenibile", "adattivo", "trasformativo", "agile", "scalabile", "visionario", "strategico", "disruptive"
]
MODEL = "text-multilingual-embedding-002" # @param ["gemini-embedding-001","text-embedding-005", "text-multilingual-embedding-002", "textembedding-gecko@003", "textembedding-gecko-multilingual@001"]
TASK = "SEMANTIC_SIMILARITY" # @param ["RETRIEVAL_QUERY", "RETRIEVAL_DOCUMENT", "SEMANTIC_SIMILARITY", "CLASSIFICATION", "CLUSTERING", "QUESTION_ANSWERING", "FACT_VERIFICATION", "CODE_RETRIEVAL_QUERY"]
TITLE = None # @param {type:"string"} # Aggiunto parametro TITLE per coerenza, anche se usato solo con RETRIEVAL_DOCUMENT
# Istanziare il modello
embedding_model = TextEmbeddingModel.from_pretrained(MODEL)
NUM_PAROLE_DA_VISUALIZZARE = 5 # @param {type:"integer"}
NUM_VALORI_ICORPORAMNETO = 10 # @param {type:"integer"}
# Generare un'incorporazione di parole
# Creare una lista di oggetti TextEmbeddingInput, gestendo condizionalmente il parametro title
embedding_inputs = []
for parola in LISTA_PAROLE:
if TASK == "RETRIEVAL_DOCUMENT":
# Include title only if TASK is RETRIEVAL_DOCUMENT
embedding_inputs.append(TextEmbeddingInput(text=parola, task_type=TASK, title=TITLE))
else:
# Exclude title for other tasks
embedding_inputs.append(TextEmbeddingInput(text=parola, task_type=TASK))
embedding = embedding_model.get_embeddings(embedding_inputs)
#L'oggetto restituito è un elenco con un singolo oggetto TextEmbedding per ogni parola nella lista.
#Il campo TextEmbedding.values memorizza le incorporazioni in un elenco Python.
# Stampare informazioni per ciascun embedding generato (limitato da NUM_PAROLE_DA_VISUALIZZARE)
print(f"Generati {len(embedding)} embeddings per {len(LISTA_PAROLE)} parole.")
print("-" * 30)
if embedding: # Assicurati che l'elenco non sia vuoto
# Iterare solo fino al numero specificato di parole da visualizzare
for i, emb in enumerate(embedding[:NUM_PAROLE_DA_VISUALIZZARE]):
# Assicurati di non superare l'indice della lista originale delle parole
if i < len(LISTA_PAROLE):
word = LISTA_PAROLE[i]
vector = emb.values
print(f"Parola: '{word}'")
print(f" Lunghezza = {len(vector)}")
print(f" Primi {NUM_VALORI_ICORPORAMNETO} valori = {vector[:NUM_VALORI_ICORPORAMNETO]}")
print("-" * 30)
else:
# Questo caso non dovrebbe verificarsi se NUM_PAROLE_DA_VISUALIZZARE
# non supera la lunghezza di embedding, ma è una precauzione.
break
else:
print("Nessun embedding generato per la lista di parole.")
Output dei primi 10 valori della vettorializzazione delle prime 5 parole
# Output
Generati 20 embeddings per 20 parole.
------------------------------
Parola: 'algoritmo'
Lunghezza = 768
Primi 10 valori = [0.026081064715981483, -0.025825606659054756, 0.016669943928718567, 0.0129399998113513, 0.05186998099088669, 0.043555017560720444, 0.060335922986269, 0.06001272425055504, -0.0006582607747986913, -0.002974875969812274]
------------------------------
Parola: 'rete neurale'
Lunghezza = 768
Primi 10 valori = [-0.05132479593157768, -0.00343142356723547, 0.025114450603723526, -0.030568841844797134, 0.08088871091604233, 0.0460718497633934, 0.06899718940258026, 0.041629355400800705, -0.037336260080337524, 0.0011259093880653381]
------------------------------
Parola: 'datacenter'
Lunghezza = 768
Primi 10 valori = [0.059829626232385635, -0.04276513680815697, 0.012132694013416767, 0.022198665887117386, 0.018857905641198158, 0.05009336769580841, 0.0754488930106163, 0.07150093466043472, 0.05510862544178963, -0.010431251488626003]
------------------------------
Parola: 'sensore'
Lunghezza = 768
Primi 10 valori = [-0.03875970467925072, -0.030892126262187958, -0.007774360477924347, -0.011211755685508251, 0.10428448021411896, 0.02040928043425083, 0.05300946533679962, 0.08032511174678802, -0.025467265397310257, -0.014852229505777359]
------------------------------
Parola: 'interfaccia'
Lunghezza = 768
Primi 10 valori = [0.01992962695658207, 0.002713253954425454, 0.04323243722319603, 0.0002527496835682541, 0.024960432201623917, 0.025631487369537354, 0.08235741406679153, 0.04506294056773186, 0.006448426283895969, -0.03974509611725807]
------------------------------


È evidente che ogni parola può essere convertita in un vettore numerico di 768 dimensioni, il quale racchiude il suo significato semantico. Questa rappresentazione consente di confrontare i vettori, permettendo di verificare se il significato semantico di due parole sia affine.
Di seguito, si illustreranno alcuni esempi pratici che mostrano in modo coinvolgente il processo di confronto della similarità tra le parole della lista con l’ausilio di una matrice di similarità, evidenziando l’importanza di questi strumenti nell’analisi dei dati linguistici, e la relativa organizzazione dei termini in cluster.
Questa organizzazione non solo facilita la comprensione delle relazioni tra le parole, ma permette anche di individuare modelli ricorrenti e tendenze fondamentale per la progettazione di sistemi RAG efficaci.
In oltre in questa sezione si descriverà come inserire un task per analizzare i risultati del raggruppamento in cluster, utilizzando un LLM per spiegare i risultati. Questo approccio offre una visione approfondita e analitica dei dati elaborati, consentendo agli utenti di applicare queste informazioni in contesti automatizzati.
Calcolo della similarità tra due vettori
Per verificare se due ebbendins (incorporamenti di testo) sono simili, si possono usare tre metodi principali: il metodo della distanza euclidea, che misura la distanza lineare tra i punti; il metodo della distanza di Manhattan, che somma le differenze assolute delle coordinate; e il metodo del coseno, che calcola l’angolo tra i due vettori per valutare la loro correlazione. Esistono molte metriche per stimare la similarità dei vettori. La scelta della metrica dipende dai vettori stessi e dal metodo di training del codificatore della rete neurale. Le metriche comuni includono il prodotto scalare e la somiglianza del coseno, insieme alla distanza euclidea e alla distanza di Manhattan.
Tipi di metriche comunemente utilizzate:
- Prodotto scalare: https://en.wikipedia.org/wiki/Dot_product
- Distanza euclidea: https://en.wikipedia.org/wiki/Euclidea_distance
- Distanza di manhattan: https://en.wikipedia.org/wiki/Taxicab_geometry
- Somiglianza del coseno: https://en.wikipedia.org/wiki/Cosine_similarity
La metrica più comune nei modelli di apprendimento per similarità è la metrica coseno.
A, B, C, rappresentano gli incorporamenti di testo riportati su due dimesioni dopo l’applicazione di tecniche di riduzione della dimensionalità come la Principal Component Analysis (PCA).

Fonte: https://qdrant.tech/documentation/concepts/search/
Calcolare la similarità (somiglianza) tra due frasi come un numero compreso tra 0 e 1.
0 = Bassa similarità
1 = Alta similarità
Creare una matrice di similarità
Per spiegare come creare una matrice di similarità, faremo riferimento alla lista di parole utilizzata nell’esempio precedente, illustrando le modalità di calcolo della similarità tra gli incorporamenti.
STEP 1: Configurare il modello
# @title Setup model embedding per il confornto di parole
TEXT = "\"algoritmo\", \"rete neurale\", \"datacenter\", \"sensore\", \"interfaccia\", \"prototipo\", \"digitale\", \"virtuale\", \"criptovaluta\", \"banda larga\", \"rivoluzionario\", \"creativo\", \"sostenibile\", \"adattivo\", \"trasformativo\", \"agile\", \"scalabile\", \"visionario\", \"strategico\", \"disruptive\"" # @param {type:"string"}
MODEL = "text-multilingual-embedding-002" # @param ["gemini-embedding-001","text-embedding-005", "text-multilingual-embedding-002"]
TASK = "SEMANTIC_SIMILARITY" # @param ["RETRIEVAL_QUERY", "RETRIEVAL_DOCUMENT", "SEMANTIC_SIMILARITY", "CLASSIFICATION", "CLUSTERING", "QUESTION_ANSWERING", "FACT_VERIFICATION", "CODE_RETRIEVAL_QUERY"]
OUTPUT_DIMENSIONALITY = 768 # @param [1, 768, "None"] {type:"raw", allow-input:true}
STEP 2: Preparazione dei dati
# @title Preparazione dei dati
import re
# Dividi la stringa TEXT in base a virgole o punti.
# re.split() dividerà la stringa e includerà i delimitatori nel risultato se racchiusi tra parentesi.
# Qui vogliamo solo i segmenti tra i delimitatori.
# Il pattern r'[,\.]+' cerca una o più virgole o punti come separatori.
segments = re.split(r'[,\.]+', TEXT)
# Processa ogni segmento per creare la lista di parole/frasi
LISTA_PAROLE = []
for segment in segments:
# Rimuovi spazi bianchi iniziali e finali da ciascun segmento
cleaned_segment = segment.strip()
# Aggiungi il segmento pulito alla lista se non è vuoto
if cleaned_segment:
# Se il segmento inizia e finisce con virgolette doppie, eliminale
if cleaned_segment.startswith('"') and cleaned_segment.endswith('"'):
# Rimuovi le virgolette doppie iniziali e finali
processed_segment = cleaned_segment[1:-1]
LISTA_PAROLE.append(processed_segment)
else:
# Altrimenti, aggiungi il segmento così com'è
LISTA_PAROLE.append(cleaned_segment)
# Visualizza la lista di parole/frasi estratte
print("Lista di parole/frasi estratte:")
print(LISTA_PAROLE)STEP 3: Generazione degli embedding di ogni parola
# @title Generazione degli embedding
from vertexai.language_models import TextEmbeddingModel, TextEmbeddingInput
from typing import List, Union # Import necessary typing hints
# Definizione dei parametri (copiate dalla cella precedente per rendere questa cella autonoma)
MODEL = "text-multilingual-embedding-002" # @param ["gemini-embedding-001","text-embedding-005", "text-multilingual-embedding-002", "textembedding-gecko@003", "textembedding-gecko-multilingual@001"]
TASK = "SEMANTIC_SIMILARITY" # @param ["RETRIEVAL_QUERY", "RETRIEVAL_DOCUMENT", "SEMANTIC_SIMILARITY", "CLASSIFICATION", "CLUSTERING", "QUESTION_ANSWERING", "FACT_VERIFICATION", "CODE_RETRIEVAL_QUERY"]
TITLE = None # @param {type:"string"} # Aggiunto parametro TITLE per coerenza, anche se usato solo con RETRIEVAL_DOCUMENT
# Caricare il modello di incorporazione
embedding_model = TextEmbeddingModel.from_pretrained(MODEL)
# Creare un elenco di oggetti TextEmbeddingInput con l'hint di tipo esplicito
embedding_inputs: List[TextEmbeddingInput] = [] # Explicit type hint
for parola in LISTA_PAROLE:
# Creare TextEmbeddingInput, includendo title solo se il task è RETRIEVAL_DOCUMENT
if TASK == "RETRIEVAL_DOCUMENT":
embedding_inputs.append(TextEmbeddingInput(text=parola, task_type=TASK, title=TITLE))
else:
embedding_inputs.append(TextEmbeddingInput(text=parola, task_type=TASK))
# Ottenere le incorporazioni per tutte le parole
# Aggiungi un hint di tipo al parametro per aiutare il type checker,
# anche se la lista è già stata tipizzata sopra.
# Utilizza un cast esplicito per soddisfare il type checker
from typing import cast # Import cast
embeddings = embedding_model.get_embeddings(
texts=cast(List[str | TextEmbeddingInput], embedding_inputs) # Cast the list
)
# Estrarre i valori di incorporazione
word_embeddings = [embedding.values for embedding in embeddings]
# Print verification information
print(f"Generated {len(word_embeddings)} word embeddings.")
if word_embeddings:
print(f"Dimensionality of the first embedding: {len(word_embeddings[0])}")STEP 4: Calcolo della matrice di similarità
Per creare una matrice di similarità, è fondamentale calcolare la similarità coseno tra ogni coppia di embedding di parole. Questo compito implica l’importazione della funzione necessaria, la conversione degli embeddings in un array NumPy e l’applicazione del calcolo della somiglianza tra le incorporazioni generate.
#@title Calcolo della matrice di similarità
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# Convert the list of word embeddings to a NumPy array
word_embeddings_array = np.array(word_embeddings)
# Calculate the cosine similarity matrix
similarity_matrix = cosine_similarity(word_embeddings_array)
# Print the resulting similarity matrix
print("Cosine Similarity Matrix:")
print(similarity_matrix)Output di una parte della matrice
Cosine Similarity Matrix:
[[1. 0.59928397 0.59695674 0.63780305 0.64382455 0.71677957
0.69054893 0.6243309 0.62892947 0.5951024 0.6226948 0.68234821
0.58396994 0.70499693 0.62016568 0.64131245 0.63428697 0.64739358
0.71783934 0.57608394]
[0.59928397 1. 0.60687559 0.73421993 0.63532134 0.5931054
0.62964563 0.64320696 0.56981787 0.63120851 0.60552687 0.6216694
0.59839509 0.63115825 0.62153644 0.53320037 0.58411495 0.59623283
0.60383143 0.57196145]
[0.59695674 0.60687559 1. 0.58358493 0.61543417 0.5778606
0.66323401 0.59760651 0.58859453 0.57305702 0.51775159 0.56911203
0.55877115 0.60399307 0.57706056 0.57615636 0.6262123 0.56147332
0.59498185 0.6112978 ]
... Output trocanto per visualizzazioneSTEP 5: Visualizzazione matrice di similarità
Generare una mappa di calore per visualizzare la matrice di similarità utilizzando matplotlib e seaborn.
# @title Visualizzazione matrice di similarità
import matplotlib.pyplot as plt
import seaborn as sns
# Create a heatmap of the similarity matrix
plt.figure(figsize=(12, 10))
sns.heatmap(similarity_matrix, annot=True, xticklabels=LISTA_PAROLE, yticklabels=LISTA_PAROLE, cmap='viridis', fmt=".2f")
plt.title("Matrice di similarità coseno delle parole")
plt.show()


Output matrice di similarità

Analisi dei dati risultati
La matrice di similarità risultante è stata visualizzata come una mappa di calore, con le etichette delle parole sugli assi e i punteggi di somiglianza annotati sulle celle.
- La matrice di somiglianza e la mappa di calore forniscono una rappresentazione visiva delle relazioni semantiche tra le parole del testo originale, dove valori più alti indicano una maggiore somiglianza.
- Un’ulteriore analisi potrebbe prevedere il raggruppamento di parole simili in base ai punteggi di somiglianza per identificare temi o concetti all’interno del testo.
Questa matrice visualizza quanto sono concettualmente simili tra loro diverse parole del mondo tecnologico. Un punteggio alto (giallo) indica una forte somiglianza semantica, mentre un punteggio basso (viola scuro) indica una relazione più debole.
Questa matrice è particolarmente interessante perché mette a confronto termini tecnologici concreti (come datacenter, sensore) con una serie di aggettivi e concetti astratti (come visionario, disruptive) che sono diventati il linguaggio comune dell’innovazione e del business.
La caratteristica più evidente è il grande blocco di colori caldi (giallo/verde) in basso a destra. Questo blocco rappresenta un gruppo semantico molto coeso di “buzzword” o aggettivi usati per descrivere strategie e visioni aziendali. Le correlazioni più forti sono al suo interno:
- Visionario & Creativo (0.78): La correlazione più alta del cluster. Essere visionari è visto come un atto intrinsecamente creativo.
- Visionario & Strategico (0.75): Una visione deve essere supportata da una strategia.
- Disruptive, Rivoluzionario & Trasformativo: Questi tre termini sono quasi intercambiabili, con punteggi reciproci molto alti (0.72 – 0.74). Indicano un cambiamento radicale dello status quo.
- Adattivo, Agile & Scalabile: Un altro sottogruppo molto forte. Descrivono la capacità di un sistema o di una strategia di crescere e cambiare in modo flessibile.
AdattivoeScalabilehanno un punteggio di 0.71.
I termini “Ponte” che uniscono tecnica e strategia
Alcuni termini tecnici non sono isolati, ma funzionano come un collegamento diretto al mondo astratto del business.
- Scalabile: È la parola “ponte” per eccellenza. Ha una natura duplice: è una caratteristica tecnica di un sistema (
datacenter,algoritmo) ma anche un obiettivo di business fondamentale. Infatti, si lega bene sia adatacenter(0.63) sia astrategico(0.75) eadattivo(0.71). - Algoritmo: Si collega in modo sorprendentemente forte al cluster astratto, in particolare con
strategico(0.72) evisionario(0.75). Questo suggerisce che, nel linguaggio comune, un “algoritmo” non è solo un pezzo di codice, ma uno strumento per realizzare una visione strategica. - Digitale: Funziona come un attivatore di cambiamento. Le sue correlazioni più alte, dopo
virtuale(0.73), sono contrasformativo(0.66) erivoluzionario(0.66), catturando perfettamente l’idea di “trasformazione digitale”.
Clustering semantico
Proseguendo con l’analisi precedente, facciamo ora un passo avanti introducendo come effettuare un processo di clustering semantico, sfruttando le capacità di un modello LLM avanzato come Gemini 1.5 Flash. Questo esempio più sofisticato ci permette di capire come classificare e raggruppare automaticamente parole con significati affini, partendo da un semplice elenco di termini tecnologici.
L’idea di base è quella di applicare un algoritmo di clustering sugli embedding (o incorporazioni semantiche) di ciascuna parola.
Possiamo immaginare gli embedding come delle coordinate che posizionano ogni termine in uno “spazio del significato”: parole concettualmente vicine, come “dottore” e “infermiere”, si troveranno in punti molto prossimi tra loro in questo spazio.
Questo approccio rappresenta un “blocco di costruzione” (building block) fondamentale, poiché illustra un processo chiave per classificare e raggruppare testi, frasi e singole parole non in base a semplici parole chiave, ma al loro significato più profondo. Tale tecnica può essere utilizzata per una vasta gamma di applicazioni pratiche, come:
- Analizzare e categorizzare grandi volumi di feedback dei clienti o di recensioni.
- Organizzare automaticamente archivi di documenti e articoli.
- Identificare trend emergenti e argomenti di discussione sui social media.
- Potenziare motori di ricerca che comprendono l’intento dell’utente anziché limitarsi a una corrispondenza letterale delle parole.
In sostanza, trasformiamo le parole in punti misurabili nello spazio per scoprire, in modo del tutto automatico, le strutture e i gruppi tematici nascosti al loro interno, e interroghiamo un modello LLM come Gemini 1.5 Flash per inferire le caratteristiche e le peculiarità dei clusters individuati.
STEP 1: Verificare la presenza della matrice degli incorporamenti e la sua dimensione
# @title Verificare l'esistenza e la forma della variabile `word_embeddings_array
if 'word_embeddings_array' in locals() and word_embeddings_array is not None:
print("word_embeddings_array è disponibile e contiene dati.")
print("Shape of word_embeddings_array:")
print(word_embeddings_array.shape)STEP 2: Scelta e applicazione dell’algoritmo di clustering
In questo caso si è scelto di utilizzare un K-Means e applicarlo agli embedding delle parole, un metodo particolarmente efficace per raggruppare dati testuali in cluster significativi. Attraverso il clustering, si possono identificare categorie linguistiche e tendenze nell’uso delle parole, frasi o testi, rendendo così possibile la creazione di modelli predittivi più accurati e pertinenti. Inoltre, l’implementazione di K-Means offre l’opportunità di lavorare con grandi volumi di dati, ottimizzando il processo di analisi e migliorando l’efficacia degli algoritmi di machine learning e dei sitemi RAG.
# @title Scelta e applicazione dell'algoritmo di clustering
# Selezionare un algoritmo di clustering (ad esempio, K-Means) e applicarlo agli embedding delle parole.
# Sarà necessario decidere il numero di cluster desiderato.
from sklearn.cluster import KMeans
import numpy as np
# Applicare l'algoritmo di clustering KMeans alle incorporazioni di parole per raggruppare le parole simili.
# Inizializzare l'oggetto KMeans
# Decidere 5 cluster in base al numero di parole e ai potenziali gruppi tematici.
kmeans = KMeans(n_clusters=5, random_state=42, n_init=10) # Set n_init explicitly
# Applicare il clustering KMeans alle incorporazioni di parole e ottenere le etichette dei cluster.
cluster_labels = kmeans.fit_predict(word_embeddings_array)
# Memorizzare le etichette dei cluster risultanti
# (Già memorizzate nella variabile cluster_labels)
# Print the cluster labels to verify
print("Cluster Labels:")
print(cluster_labels)Output: lista delle etichette dei Clusters
Cluster Labels:
[2 0 2 0 0 1 2 2 2 4 1 1 3 3 1 3 3 1 1 1]STEP 2: Assegnazione delle parole ai cluster
# @title Assegnazione delle parole ai cluster
# Creare un elenco di tuple che abbinano ogni parola all'etichetta del cluster e stampare l'elenco.
clustered_words = []
# Iterare simultaneamente l'elenco di parole e le etichette dei cluster
for word, label in zip(LISTA_PAROLE, cluster_labels):
# Aggiungere all'elenco una tupla della parola e della sua etichetta di cluster
clustered_words.append((word, label))
# Stampa l'elenco delle parole raggruppate
print("Parole con le etichette dei cluster assegnate:")
print(clustered_words)Output clustered words
Words with their assigned cluster labels:
[('algoritmo', np.int32(2)), ('rete neurale', np.int32(0)), ('datacenter', np.int32(2)), ('sensore', np.int32(0)), ('interfaccia', np.int32(0)), ('prototipo', np.int32(1)), ('digitale', np.int32(2)), ('virtuale', np.int32(2)), ('criptovaluta', np.int32(2)), ('banda larga', np.int32(4)), ('rivoluzionario', np.int32(1)), ('creativo', np.int32(1)), ('sostenibile', np.int32(3)), ('adattivo', np.int32(3)), ('trasformativo', np.int32(1)), ('agile', np.int32(3)), ('scalabile', np.int32(3)), ('visionario', np.int32(1)), ('strategico', np.int32(1)), ('disruptive', np.int32(1))]STEP 3: Visualizzazione dei risultati del clustering
# @title Visualizzazione dei risultati del clustering
# Creare un dizionario per memorizzare le parole raggruppate in base all'etichetta del cluster.
clusters_dict = {}
# Iterate through the clustered_words list
for word, label in clustered_words:
# Se l'etichetta del cluster non è già una chiave del dizionario, aggiungerla con una lista vuota come valore
if label not in clusters_dict:
clusters_dict[label] = []
# Aggiungere la parola all'elenco corrispondente alla sua etichetta di cluster
clusters_dict[label].append(word)
# Stampa il dizionario risultante
print("Parole raggruppate per cluster:")
for cluster_label, words_in_cluster in clusters_dict.items():
print(f"Cluster {cluster_label}: {words_in_cluster}")
Output parole raggruppate per cluster
Parole raggruppate per cluster:
Cluster 2: ['algoritmo', 'datacenter', 'digitale', 'virtuale', 'criptovaluta']
Cluster 0: ['rete neurale', 'sensore', 'interfaccia']
Cluster 1: ['prototipo', 'rivoluzionario', 'creativo', 'trasformativo', 'visionario', 'strategico', 'disruptive']
Cluster 4: ['banda larga']
Cluster 3: ['sostenibile', 'adattivo', 'agile', 'scalabile']Il risultato del processo di clusterig è il seguente:
Cluster 0: rete neurale, sensore, interfaccia.
Cluster 1: prototipo, rivoluzionario, creativo, trasformativo, visionario, strategico, disruptive.
Cluster 2: algoritmo, datacenter, digitale, virtuale, criptovaluta.
Cluster 3: sostenibile, adattivo, agile, scalabile.
Cluster 4: banda larga.
È davvero straordinario e affascinante come l’algoritmo riesca a raggruppare con maestria termini e parole, rivelando significati e concetti simili che si collegano in perfetta armonia!
Inferenza con LLM
In questa sezione, integriamo l’analisi di clustering semantico dell’esempio precedente con l’inferenza tramite un Large Language Model (LLM). Questa integrazione automatizza il processo di analisi, rendendolo più accessibile e scalabile per analisi aziendali ricorrenti, consentendo di ottenere nuove intuizioni e prospettive interessanti.
SPEP 1: Formattare i risultati del clustering in una stringa di testo strutturata per il prompt di LLM
# @title Formattare i risultati del clustering in una stringa di testo strutturata per il prompt di LLM.
# Formattare i risultati del clustering (elenco dei cluster e delle parole in ciascuno) in una stringa di testo chiara e strutturata che possa essere utilizzata come parte del prompt per l'LLM.
clustering_results_text = "Risultati del Clustering:\n"
# Iterare attraverso il dizionario clusters_dict
for cluster_label, words_in_cluster in clusters_dict.items():
# Formatta le parole nel cluster corrente in una singola stringa, separata da virgole
words_str = ", ".join(words_in_cluster)
# Aggiungere una stringa formattata a clustering_results_text
clustering_results_text += f"Cluster {cluster_label}: {words_str}\n"
# Stampare la variabile clustering_results_text per verificare la formattazione dell'output
print(clustering_results_text)Output contesto per LLM
Risultati del Clustering:
Cluster 2: algoritmo, datacenter, digitale, virtuale, criptovaluta
Cluster 0: rete neurale, sensore, interfaccia
Cluster 1: prototipo, rivoluzionario, creativo, trasformativo, visionario, strategico, disruptive
Cluster 4: banda larga
Cluster 3: sostenibile, adattivo, agile, scalabileSTEP 2: Definire il prompt dinamico per il modello LLM
# @title Definire il prompt dinamico per il modello LLM
# Creare un prompt che istruisca l'LLM a generare un riepilogo dei risultati del clustering, inclusi i risultati chiave e potenziali insight o passi successivi, basandosi esclusivamente sull'input fornito.
llm_prompt = f"""Agisci come un analista di dati che riassume i risultati di un'analisi di clustering.
Basati *solamente* sul seguente input per generare un riepilogo.
Includi i risultati chiave del clustering e risultati.
Fornisci il riepilogo in italiano.
Input:
{clustering_results_text}
Riepilogo dell'analisi di clustering:
"""
# Print the prompt to verify its content
print(llm_prompt)Output prompt dinamico per l’LLM
Agisci come un analista di dati che riassume i risultati di un'analisi di clustering.
Basati *solamente* sul seguente input per generare un riepilogo.
Includi i risultati chiave del clustering e risultati.
Fornisci il riepilogo in italiano.
Input:
Risultati del Clustering:
Cluster 2: algoritmo, datacenter, digitale, virtuale, criptovaluta
Cluster 0: rete neurale, sensore, interfaccia
Cluster 1: prototipo, rivoluzionario, creativo, trasformativo, visionario, strategico, disruptive
Cluster 4: banda larga
Cluster 3: sostenibile, adattivo, agile, scalabileSTEP 3: Istanziare il modello generativo e inviare il prompt per generare l’analisi automatica
# @title Istanziare il modello generativo e inviare il prompt per generare l'analisi automatica
# Scegliere un modello LLM appropriato (ad esempio, un modello di generazione di testo da Vertex AI) e inviare il prompt con l'input preparato.
from vertexai.generative_models import GenerativeModel
from IPython.display import display
from IPython.display import Markdown
# Importare la libreriaper formattare markdowen
# Istanziare un GenerativeModel con il nome del modello specificato
# Assicurarsi che il nome del modello sia appropriato per la regione del progetto e per i modelli disponibili.
try:
llm_model = GenerativeModel("gemini-2.5-flash")
except Exception as e:
print(f"Could not load model gemini-2.5-flash: {e}")
llm_model = None # Impostare su Nessuno se il caricamento del modello non riesce
# Controllare se il modello è stato caricato con successo prima di procedere
if llm_model:
# Assumendo che clustering_results_text e llm_prompt siano disponibili dai passi precedenti
# Inviare il prompt all'LLM e ottenere la risposta generata.
try:
response = llm_model.generate_content(llm_prompt)
llm_summary_text = response.text
except Exception as e:
llm_summary_text = f"Errore nella generazione della risposta dall'LLM: {e}"
else:
llm_summary_text = "Nessun modello LLM appropriato disponibile per la generazione del riepilogo."
# Memorizzare il testo generato in llm_summary_text (già fatto sopra)
# Stampare il testo di riepilogo generato per la verifica (opzionale, ma utile)
print("\nGenerated LLM Summary:")
print("----------------------")
display(Markdown(llm_summary_text))
print("----------------------")

Output analisi LLM
Generated LLM Summary:
Riepilogo dell’analisi di clustering:
Il processo di clustering ha identificato 5 distinti raggruppamenti di termini, ciascuno rappresentante un tema concettuale. I cluster sono i seguenti:
- Cluster 2: Tecnologie Digitali Core e Infrastruttura Questo cluster raggruppa termini legati all’infrastruttura tecnologica fondamentale e ai concetti emergenti nel panorama digitale, inclusi:
algoritmo, datacenter, digitale, virtuale, criptovaluta. - Cluster 0: Intelligenza Artificiale e Interazione Hardware/Software Questo gruppo comprende parole chiave che delineano l’ambito dell’Intelligenza Artificiale (AI) e i suoi punti di contatto con il mondo fisico e l’interazione:
rete neurale, sensore, interfaccia. - Cluster 1: Innovazione, Visione e Strategia Questo cluster è caratterizzato da termini che evocano l’impulso al cambiamento, alla creatività e alla crescita strategica:
prototipo, rivoluzionario, creativo, trasformativo, visionario, strategico, disruptive. - Cluster 4: Connettività Questo cluster, sebbene di dimensioni ridotte, si concentra su un concetto chiave dell’infrastruttura di rete:
banda larga. - Cluster 3: Attributi di Resilienza e Efficienza Questo gruppo raggruppa qualità essenziali per sistemi e processi moderni, focalizzandosi su adattabilità, crescita e sostenibilità:
sostenibile, adattivo, agile, scalabile.
Risultati Chiave e Conclusioni:
L’analisi di clustering ha rivelato che i termini si aggregano attorno a temi ben definiti che spaziano dalle basi tecnologiche e infrastrutturali (Cluster 2 e 4), alle frontiere dell’Intelligenza Artificiale e dell’IoT (Cluster 0), ai driver di innovazione e trasformazione strategica (Cluster 1), fino alle qualità intrinseche di resilienza e adattabilità richieste dai sistemi e dalle soluzioni moderne (Cluster 3).
Questa segmentazione suggerisce una prospettiva olistica che abbraccia sia la componente abilitante della tecnologia sia la visione strategica e la flessibilità operativa necessarie per affrontare le sfide e le opportunità nel contesto analizzato. Il cluster sull’innovazione (Cluster 1) emerge come particolarmente ricco di termini che esprimono un forte orientamento al futuro e al cambiamento, mentre il cluster sugli attributi (Cluster 3) sottolinea l’importanza di qualità “non funzionali” ma cruciali per il successo a lungo termine.
L’analisi dei cluster ha rivelato l’efficacia del modello LLM nel raggruppare termini, identificando cinque cluster chiave: Tecnologie Digitali, Intelligenza Artificiale, Innovazione, Connettività e Resilienza.
Questi esempi e applicazioni costituiscono un punto di partenza essenziale per il mondo industriale e aziendale; infatti, lo sviluppo di queste tecnologie non solo facilita il progresso, ma apre anche porte inimmaginabili all’innovazione, rispondendo così con efficacia alle sfide future del settore digitale.
Similarità tra FAQ e policy aziendali
In questa sezione si illustra come creare un meccanismo fondamentale per la ricerca di informazioni aziendali, sottolineando l’importanza di calcolare e visualizzare la matrice di similarità tra due dizionari di dati testuali: uno per le domande FAQ e l’altro per i titoli/abstract delle policy aziendali. Apprendere questi concetti è essenziale per un analista al fine di progettare sistemi di recupero efficienti ed efficaci.
Definire i dizionari delle FAQ
Di seguito è riportato il codice per definire i dizionari delle FAQ e uno per i titoli e gli abstract delle policy aziendali. Per garantire una gestione efficace delle informazioni, è fondamentale strutturare questi dizionari in modo chiaro e accessibile, consentendo agli utenti di navigare facilmente tra le diverse sezioni e trovare rapidamente le risposte desiderate.
# @title Definire i dizionari delle FAQ e uno per i titoli/abstract delle Policy aziendali
# Definire il dizionario per le domande frequenti FAQ
faq_questions = {
'faq_1': 'Come posso richiedere un rimborso per un acquisto?',
'faq_2': 'Quali sono i metodi di pagamento accettati?',
'faq_3': 'Come posso tracciare il mio ordine?',
'faq_4': 'Qual è la politica di reso?',
'faq_5': 'Come posso contattare il servizio clienti?'
}
# Definire il dizionario per i titoli e gli abstract delle politiche.
policy_titles = {
'policy_a': 'Termini e Condizioni del Servizio',
'policy_b': 'Informativa sulla Privacy',
'policy_c': 'Politica di Spedizione',
'policy_d': 'Politica sui Resi e Rimborsi',
'policy_e': 'Politica sull\'Utilizzo dei Cookie'
}
# Stampa i dizionari da verificare
print("FAQ Questions:")
print(faq_questions)
print("\nPolicy Titles:")
print(policy_titles)Output
FAQ Questions:
{'faq_1': 'Come posso richiedere un rimborso per un acquisto?', 'faq_2': 'Quali sono i metodi di pagamento accettati?', 'faq_3': 'Come posso tracciare il mio ordine?', 'faq_4': 'Qual è la politica di reso?', 'faq_5': 'Come posso contattare il servizio clienti?'}
Policy Titles:
{'policy_a': 'Termini e Condizioni del Servizio', 'policy_b': 'Informativa sulla Privacy', 'policy_c': 'Politica di Spedizione', 'policy_d': 'Politica sui Resi e Rimborsi', 'policy_e': "Politica sull'Utilizzo dei Cookie"}Creare un elenco di testi di domande frequenti
Una volta crearti i dizionari bisogna creare una lista di testi delle domande frequenti e dei titoli delle policy. Questo passaggio sarà utile per creare gli incorporamenti di testo di ogni stringa.
# @title Creare un elenco di testi di domande frequenti
# Creare due liste di testi, una per le domande FAQ e una per i titoli delle policy, estraendo i valori dai rispettivi dizionari. Mantenere l'ordine per poter associare gli embedding agli ID originali.
faq_texts = list(faq_questions.values())
# Create a list of policy title texts
policy_texts = list(policy_titles.values())
# Optional: Print the lists to verify
print("FAQ Texts:")
print(faq_texts)
print("\nPolicy Texts:")
print(policy_texts)Output
FAQ Texts:
['Come posso richiedere un rimborso per un acquisto?', 'Quali sono i metodi di pagamento accettati?', 'Come posso tracciare il mio ordine?', 'Qual è la politica di reso?', 'Come posso contattare il servizio clienti?']
Policy Texts:
['Termini e Condizioni del Servizio', 'Informativa sulla Privacy', 'Politica di Spedizione', 'Politica sui Resi e Rimborsi', "Politica sull'Utilizzo dei Cookie"]Generare gli embeding di testo
Eseguiti i passaggi precedenti, siamo pronti per effettuare gli incorporamenti.
Questa cella di codice trasforma i testi delle FAQ e delle policy in rappresentazioni vettoriali dense che possono essere utilizzate per calcolare la similarità semantica.
# @title Generazione degli embedding
# Generare le incorporazioni per i testi delle FAQ e delle politiche utilizzando il modello di incorporazione di Vertex AI.
# Utilizzare il modello di embedding di Vertex AI per generare gli embedding per ogni testo nelle due liste create al passo precedente.
# Specificare il tipo di task appropriato (probabilmente "RETRIEVAL_QUERY" per le domande e "RETRIEVAL_DOCUMENT" per le policy, o un altro task pertinente come "SEMANTIC_SIMILARITY").
from vertexai.language_models import TextEmbeddingModel, TextEmbeddingInput
from typing import List, Union # Import necessary typing hints
MODEL = "text-multilingual-embedding-002" # @param ["gemini-embedding-001","text-embedding-005", "text-multilingual-embedding-002", "textembedding-gecko@003", "textembedding-gecko-multilingual@001"]
OUTPUT_DIMENSIONALITY = 768 # @param [1, 768, "None"] {type:"raw", allow-input:true}
# Load the embedding model
embedding_model = TextEmbeddingModel.from_pretrained(MODEL)
# Create a list of TextEmbeddingInput objects for FAQ texts
# Use "RETRIEVAL_QUERY" for questions
faq_embedding_inputs: List[TextEmbeddingInput] = [TextEmbeddingInput(text=text, task_type="RETRIEVAL_QUERY") for text in faq_texts] # Added explicit type hint
# Create a list of TextEmbeddingInput objects for policy texts
# Use "RETRIEVAL_DOCUMENT" for policies
policy_embedding_inputs: List[TextEmbeddingInput] = [TextEmbeddingInput(text=text, task_type="RETRIEVAL_DOCUMENT") for text in policy_texts] # Added explicit type hint
# Get embeddings for FAQ texts
faq_embeddings_result = embedding_model.get_embeddings(faq_embedding_inputs, output_dimensionality=OUTPUT_DIMENSIONALITY)
# Get embeddings for policy texts
policy_embeddings_result = embedding_model.get_embeddings(policy_embedding_inputs, output_dimensionality=OUTPUT_DIMENSIONALITY)
# Extract the embedding values
faq_embeddings = [embedding.values for embedding in faq_embeddings_result]
policy_embeddings = [embedding.values for embedding in policy_embeddings_result]
# Print verification information
print(f"Generated {len(faq_embeddings)} FAQ embeddings.")
if faq_embeddings:
print(f"Dimensionality of the first FAQ embedding: {len(faq_embeddings[0])}")
print(f"\nGenerated {len(policy_embeddings)} policy embeddings.")
if policy_embeddings:
print(f"Dimensionality of the first policy embedding: {len(policy_embeddings[0])}")Output:
Generated 5 FAQ embeddings.
Dimensionality of the first FAQ embedding: 768
Generated 5 policy embeddings.
Dimensionality of the first policy embedding: 768Calcolo della similarità e visualizzazione della matrice
Questo blocco di celle ci permette di calcolare la matrice di similarità tra le domande frequenti (FAQ) e le policy aziendali e successivamente di visualizzarla per mostrare quali FAQ sono più simili a quali policy.
# @title Calcolo della matrice di similarità FAQ / Policy azinedali
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# Convert the list of FAQ embeddings to a NumPy array
faq_embeddings_array = np.array(faq_embeddings)
# Convert the list of policy embeddings to a NumPy array
policy_embeddings_array = np.array(policy_embeddings)
# Calculate the cosine similarity matrix between FAQ and policy embeddings
cross_similarity_matrix = cosine_similarity(faq_embeddings_array, policy_embeddings_array)
# Print the resulting cross-similarity matrix
print("Cross-Similarity Matrix (FAQ vs Policy):")
print(cross_similarity_matrix)
# @title Estrarre le chiavi dal dizionario faq_questions
# Estrarre le chiavi ID dai due dizionari originali per usarle come etichette sugli assi della matrice di similarità.
# Estrarre le chiavi dai dizionari faq_questions e policy_titles e memorizzarle in elenchi da utilizzare come etichette nella visualizzazione della matrice di similarità.
faq_labels = list(faq_questions.keys())
# Estrarre le chiavi dal dizionario policy_titles
policy_labels = list(policy_titles.keys())
# Stampare gli elenchi per verificare
print("FAQ Labels:")
print(faq_labels)
print("\nPolicy Labels:")
print(policy_labels)
# @title Visualizzazione della matrice di similarità
import matplotlib.pyplot as plt
import seaborn as sns
# Create a figure for the heatmap
plt.figure(figsize=(10, 8))
# Generate the heatmap of the cross-similarity matrix
sns.heatmap(cross_similarity_matrix, annot=True, xticklabels=policy_labels, yticklabels=faq_labels, cmap='viridis', fmt=".2f")
# Add a title to the heatmap
plt.title("Matrice di similarità FAQ vs Policy")
# Show the heatmap
plt.show()




Output
#Output 1
Cross-Similarity Matrix (FAQ vs Policy):
[[0.62612563 0.60274245 0.62922628 0.6966778 0.60005592]
[0.64500092 0.59464261 0.62922644 0.64135078 0.61754487]
[0.63520649 0.61662513 0.67022879 0.61387803 0.61450759]
[0.65585409 0.63384104 0.70182276 0.83364487 0.64279147]
[0.66184442 0.63631851 0.6162395 0.64364437 0.62723338]]
#Output 2
FAQ Labels:
['faq_1', 'faq_2', 'faq_3', 'faq_4', 'faq_5']
Policy Labels:
['policy_a', 'policy_b', 'policy_c', 'policy_d', 'policy_e']
# Output 3

Analisi dei risultati
In questo esempio Invece di analizzare le parole chiave, abbiamo usato l’AI per “leggere” e comprendere il significato profondo di ogni singola FAQ e policy. Questo ci ha permesso di misurare la somiglianza semantica tra ogni domanda e ogni documento, creando una mappa di correlazioni.
L’analisi ha prodotto una mappa chiara, presentata sotto forma di una heatmap, che rivela a colpo d’occhio quali FAQ sono più strettamente correlate a specifiche policy.
Questo insight è fondamentale perché ci permette di:
- Sviluppare sistemi di Q&A automatici più precisi, che indirizzano immediatamente i clienti verso la policy corretta.
- Migliorare la scopribilità e l’organizzazione delle nostre policy interne.
- Identificare lacune dove le domande dei clienti non trovano una risposta chiara nelle policy esistenti, suggerendo aree per l’aggiornamento dei contenuti.
Calcolo della matrice di Ranking tra FAQ e Policy aziendali
Per concludere in modo pratico questo caso d’uso, il passo finale consiste nel trasformare la nostra mappa di correlazioni in una lista chiara e azionabile.
Procederemo calcolando una matrice di Punteggio e Ranking, che ci permetterà di valutare e classificare l’importanza di ogni singola corrispondenza. Successivamente, visualizzeremo solo le migliori corrispondenze, eliminando il “rumore” e mettendo in evidenza i collegamenti più forti e significativi. Per ogni singola FAQ, identifichiamo e isoliamo la policy che ha ottenuto il punteggio di somiglianza più alto.
# @title Calcolo del ranking
# Genera una matrice di classificazione basata sulla matrice di somiglianza incrociata precedentemente calcolata tra gli embedding delle FAQ e gli embedding delle politiche aziendali
# La matrice di classificazione deve mostrare per ogni FAQ (etichettata dal suo ID) le politiche (etichettate dal loro ID) ordinate in base al loro punteggio di similarità in ordine decrescente.
import numpy as np
# Inizializza una lista vuota per memorizzare gli indici classificati per ogni FAQ
ranked_indices = []
# Iterare su ogni riga (FAQ) della matrice cross_similarità
for row in cross_similarity_matrix:
# Ottenere gli indici che ordinano la riga in ordine decrescente
# argsort() restituisce indici in ordine crescente, quindi lo invertiamo [::-1]
sorted_row_indices = np.argsort(row)[::-1]
# Aggiungere gli indici ordinati all'elenco
ranked_indices.append(sorted_row_indices)
# Convertire l'elenco di array in un singolo array numpy
ranked_indices = np.array(ranked_indices)
# Stampa l'array di indici classificati
print("Ranked Indices (Policy indices sorted by similarity for each FAQ):")
# @title Creazione della matrice di ranking
# Creare una nuova struttura dati che mostri per ogni FAQ le policy ordinate per similarità (dal più alto al più basso), possibilmente includendo anche i punteggi di similarità ordinati.
# Creare un DataFrame pandas per visualizzare la matrice di classificazione, mappando gli indici classificati alle etichette delle politiche e includendo facoltativamente i punteggi di similarità.
import pandas as pd
# Creare un elenco per contenere i dati della classifica DataFrame
ranking_data = []
# Iterazione di ogni FAQ e dei corrispondenti indici di politica classificata
for i, faq_label in enumerate(faq_labels):
# Ottenere gli indici classificati per la FAQ attuale
current_ranked_indices = ranked_indices[i]
# Ottenere i punteggi di somiglianza per la FAQ corrente
current_similarity_scores = cross_similarity_matrix[i]
# Creare un elenco per le informazioni sulla classifica delle FAQ correnti
faq_ranking = {}
faq_ranking['FAQ ID'] = faq_label
# Iterare gli indici classificati per ottenere le politiche e i punteggi classificati.
for rank, policy_index in enumerate(current_ranked_indices):
policy_id = policy_labels[policy_index]
similarity_score = current_similarity_scores[policy_index]
# Formatta l'output per mostrare sia l'ID della politica che il punteggio
faq_ranking[f'Rank {rank + 1}'] = f'{policy_id} ({similarity_score:.4f})'
# Aggiungere le informazioni di classifica per la FAQ corrente all'elenco dei dati
ranking_data.append(faq_ranking)
# Creare il DataFrame pandas dai dati della classifica
ranking_df = pd.DataFrame(ranking_data)
# Impostare la colonna "ID FAQ" come indice
ranking_df.set_index('FAQ ID', inplace=True)
# Stampa la classifica DataFrame
print("Ranking Matrix (FAQ vs Ranked Policies by Similarity):")
display(ranking_df)
Output:
Ranked Indices (Policy indices sorted by similarity for each FAQ):
[[3 2 0 1 4]
[0 3 2 4 1]
[2 0 1 4 3]
[3 2 0 4 1]
[0 3 1 4 2]]
Scoprire le Policy aziendali più rilevanti per le FAQ
A questo punto, il nostro obiettivo è eliminare il “rumore” e mettere in evidenza solo il risultato del ranking. La visualizzazione finale sarà un output pulito che mostra, in modo diretto e semplice, esattamente quale FAQ ha la sua correlazione più alta con una specifica policy.
Questo ci fornirà un output pulito che mostra esattamente quale FAQ ha la correlazione più alta con una specifica policy, offrendo una base solida per l’implementazione pratica di un sistema di Q&A o per l’ottimizzazione dei contenuti.
# @title Visualizzazione delle migliori corrispondenze
# Per ogni domanda FAQ, trovare la policy con il punteggio di similarità più alto e visualizzare la coppia FAQ-Policy con il punteggio corrispondente.
# Iterare la matrice di somiglianza incrociata, trovare l'indice del punteggio di somiglianza massimo per ogni riga di FAQ e utilizzare l'etichetta e il punteggio del criterio corrispondente per visualizzare la migliore corrispondenza per ogni FAQ
import numpy as np
print("Migliori corrispondenze FAQ - Policy (con testo completo):")
print("---------------------------------------------------------")
# Assicurarsi che i dizionari faq_questions e policy_titles siano disponibili dalle celle precedenti.
# Iterare ogni FAQ (riga nella matrice di somiglianza)
for i, faq_label in enumerate(faq_labels):
# Ottenere i punteggi di somiglianza per la FAQ corrente
similarity_scores = cross_similarity_matrix[i]
# Trova l'indice del massimo punteggio di somiglianza per questa FAQ.
best_match_policy_index = np.argmax(similarity_scores)
# Ottenere l'etichetta (ID) della politica con la migliore corrispondenza
best_match_policy_label = policy_labels[best_match_policy_index]
# Ottenere il punteggio di somiglianza più alto
best_similarity_score = similarity_scores[best_match_policy_index]
# --- Aggiunte per includere il testo completo ---
# Ottenere il testo completo per la FAQ corrente utilizzando la sua etichetta (ID)
faq_text = faq_questions.get(faq_label, "Testo FAQ non trovato") # Usare .get() per un accesso sicuro
# Ottenere il testo completo per la migliore politica di corrispondenza usando la sua etichetta (ID)
policy_text = policy_titles.get(best_match_policy_label, "Testo Policy non trovato") # Usare .get() per un accesso sicuro
# ------------------------------------------------
# Stampa l'ID della FAQ, il suo testo, l'ID della politica che corrisponde meglio, il suo testo e il punteggio.
print(f"FAQ ID: {faq_label}")
print(f"Testo FAQ: {faq_text}")
print(f"Miglior Policy ID: {best_match_policy_label}")
print(f"Testo Policy: {policy_text}")
print(f"Punteggio: {best_similarity_score:.4f}")
print("---") # Separatore per chiarezza
print("---------------------------------------------------------")Output:
Migliori corrispondenze FAQ - Policy (con testo completo):
---------------------------------------------------------
FAQ ID: faq_1
Testo FAQ: Come posso richiedere un rimborso per un acquisto?
Miglior Policy ID: policy_d
Testo Policy: Politica sui Resi e Rimborsi
Punteggio: 0.6967
---
FAQ ID: faq_2
Testo FAQ: Quali sono i metodi di pagamento accettati?
Miglior Policy ID: policy_a
Testo Policy: Termini e Condizioni del Servizio
Punteggio: 0.6450
---
FAQ ID: faq_3
Testo FAQ: Come posso tracciare il mio ordine?
Miglior Policy ID: policy_c
Testo Policy: Politica di Spedizione
Punteggio: 0.6702
---
FAQ ID: faq_4
Testo FAQ: Qual è la politica di reso?
Miglior Policy ID: policy_d
Testo Policy: Politica sui Resi e Rimborsi
Punteggio: 0.8336
---
FAQ ID: faq_5
Testo FAQ: Come posso contattare il servizio clienti?
Miglior Policy ID: policy_a
Testo Policy: Termini e Condizioni del Servizio
Punteggio: 0.6618
---
---------------------------------------------------------Estrarre informazioni da documenti aziendali tramite similarità semantica
Il primo passaggio da effettuare per creare sistemi RAG aziendali è mappare i processi e i corpus delle Policy Aziendali sottostanti, espressi ed inespressi.
Questo processo non solo aiuta a identificare le linee guida e le best practice esistenti, ma consente anche di evidenziare eventuali lacune o aree di miglioramento. Inoltre, una mapping accurato permette di allineare i diversi dipartimenti e garantire che tutti gli aspetti delle politiche siano ben compresi e applicati in modo coerente, facilitando una maggiore efficienza operativa e una compliance più robusta.
Si presuppone di avere una lista di FAQ con le relative risposte per ogni caso d’uso e dipartimento analizzato; se così non fosse, sarebbe necessario crearla.
Definizione del corpus aziendale
Il primo processo da effettuare è elaborare le Policy aziendali in modo che siano compatibili con un LLM e concatenabili in prompt o incapsulate in variabili e file di testo. Inoltre, è fondamentale garantire che le informazioni siano strutturate in maniera chiara e accessibile per facilitare ulteriori elaborazioni e analisi.
Di seguito si illustra il processo in modo semplificato ma strategicamente operativo.
Si ricorda che i dati degli esempi sono sintetici. Le informazioni fornite hanno unicamente uno scopo illustrativo e non devono essere interpretate come dati reali.
# @title Definizione del corpus aziendale
# Definire una variabile stringa multilinea per il corpus aziendale
# Dimostrare la potenza degli embedding per la creazione di sistemi RAG (Retrieval Augmented Generation) per la ricerca di informazioni in testi aziendali,
corporate_corpus = """
La nostra politica di reso prevede che i prodotti possano essere restituiti entro 30 giorni dall'acquisto, a condizione che siano in condizioni originali e con la prova d'acquisto. I rimborsi verranno elaborati entro 7-10 giorni lavorativi.
Per contattare il servizio clienti, è possibile chiamare il numero verde 800-123-456 dal lunedì al venerdì, dalle 9:00 alle 18:00, oppure inviare una email a supporto@azienda.it.
Offriamo diverse opzioni di spedizione, inclusa la spedizione standard (3-5 giorni lavorativi) e la spedizione espressa (1-2 giorni lavorativi). I costi di spedizione variano in base alla destinazione e al peso del pacco.
Accettiamo i principali metodi di pagamento, tra cui carte di credito (Visa, Mastercard, American Express), PayPal e bonifico bancario. Tutti i pagamenti sono processati in modo sicuro.
I nostri termini e condizioni del servizio descrivono i diritti e gli obblighi dell'utente nell'utilizzo dei nostri prodotti e servizi. Si prega di leggere attentamente questo documento prima di procedere.
Questa informativa sulla privacy spiega come raccogliamo, utilizziamo e proteggiamo i dati personali dei nostri utenti. Ci impegniamo a garantire la massima riservatezza e sicurezza delle informazioni.
Il nostro nuovo prodotto, lo "SmartWidget Pro", è un dispositivo innovativo dotato di intelligenza artificiale e connettività avanzata. È progettato per semplificare le attività quotidiane e migliorare l'efficienza.
Per l'installazione dello SmartWidget Pro, seguire attentamente le istruzioni fornite nel manuale utente. Assicurarsi che il dispositivo sia collegato a una rete Wi-Fi stabile durante il processo di configurazione iniziale.
In caso di problemi tecnici con lo SmartWidget Pro, consultare la sezione risoluzione dei problemi nel manuale o contattare il supporto tecnico specializzato.
Utilizziamo i cookie per migliorare l'esperienza di navigazione sul nostro sito web e per raccogliere dati statistici anonimi sull'utilizzo. È possibile gestire le preferenze dei cookie tramite le impostazioni del browser.
"""
# Print the content of the corporate_corpus variable
print("Contenuto del corpus aziendale:")
print(corporate_corpus)Output:
Corpus Policy aziendale
Contenuto del Corpus Aziendale:
La nostra politica di reso prevede che i prodotti possano essere restituiti entro 30 giorni dall’acquisto, a condizione che siano in condizioni originali e con la prova d’acquisto. I rimborsi verranno elaborati entro 7-10 giorni lavorativi.
Per contattare il servizio clienti, è possibile chiamare il numero verde 800-123-456 dal lunedì al venerdì, dalle 9:00 alle 18:00, oppure inviare una email a supporto@azienda.it.
Offriamo diverse opzioni di spedizione, inclusa la spedizione standard (3-5 giorni lavorativi) e la spedizione espressa (1-2 giorni lavorativi). I costi di spedizione variano in base alla destinazione e al peso del pacco.
Accettiamo i principali metodi di pagamento, tra cui carte di credito (Visa, Mastercard, American Express), PayPal e bonifico bancario. Tutti i pagamenti sono processati in modo sicuro.
I nostri termini e condizioni del servizio descrivono i diritti e gli obblighi dell’utente nell’utilizzo dei nostri prodotti e servizi. Si prega di leggere attentamente questo documento prima di procedere.
Questa informativa sulla privacy spiega come raccogliamo, utilizziamo e proteggiamo i dati personali dei nostri utenti. Ci impegniamo a garantire la massima riservatezza e sicurezza delle informazioni.
Il nostro nuovo prodotto, lo “SmartWidget Pro”, è un dispositivo innovativo dotato di intelligenza artificiale e connettività avanzata. È progettato per semplificare le attività quotidiane e migliorare l’efficienza.
Per l’installazione dello SmartWidget Pro, seguire attentamente le istruzioni fornite nel manuale utente. Assicurarsi che il dispositivo sia collegato a una rete Wi-Fi stabile durante il processo di configurazione iniziale.
In caso di problemi tecnici con lo SmartWidget Pro, consultare la sezione risoluzione dei problemi nel manuale o contattare il supporto tecnico specializzato.
Utilizziamo i cookie per migliorare l’esperienza di navigazione sul nostro sito web e per raccogliere dati statistici anonimi sull’utilizzo. È possibile gestire le preferenze dei cookie tramite le impostazioni del browser.
Una volta pre-processato il documento ed estratto il corpus delle policy aziendali, ti consigliamo di suddividere i documenti in segmenti o “chunk” più piccoli. Il passo successivo consiste nel generare un embedding per ciascun chunk utilizzando un modello di embedding. Infine, è importante memorizzare i chunk e i loro embedding in una struttura dati, come una lista, un database vettoriale in memoria o un DataFrame pandas, in modo da creare una base di conoscenza ricercabile e facilmente accessibile.
In questa sezione di codice si divide il corpus aziendale in pezzi, e per ogni pezzo si genera un embedding usando il modello Vertex AI specificando il tipo di task, e si memorizzano per comodità gli embedding in un elenco.
# @title Creazione della base di conoscenza (knowledge base)
# Dividere i documenti del corpus in segmenti o "chunk" più piccoli, generare un embedding per ciascun chunk utilizzando un modello di embedding di Vertex AI e memorizzare i chunk e i loro embedding in una struttura dati
# (ad esempio, una lista, un database vettoriale in memoria o un DataFrame pandas) che fungerà da base di conoscenza ricercabile.
from vertexai.language_models import TextEmbeddingModel, TextEmbeddingInput
import re
# 1. Dividere la stringa corporate_corpus in una lista di stringhe più piccole (chunk)
# Dividere per paragrafi (supponendo che i paragrafi siano separati da due o più newline)
chunks = re.split(r'\n\s*\n', corporate_corpus.strip())
# Rimuovere tutte le stringhe vuote che potrebbero risultare dalla suddivisione
chunks = [chunk.strip() for chunk in chunks if chunk.strip()]
# 2. Inizializzare il modello di embedding di Vertex AI
# Utilizzare le variabili MODEL e TASK definite nelle celle precedenti.
embedding_model = TextEmbeddingModel.from_pretrained(MODEL)
# 3. Per ogni chunk, generare l'embedding
# Creare un elenco di oggetti TextEmbeddingInput per ogni pezzo
chunk_embedding_inputs = [TextEmbeddingInput(text=chunk, task_type="RETRIEVAL_DOCUMENT") for chunk in chunks]
# Ottenere le incorporazioni per tutti i chunk
# Usare la variabile OUTPUT_DIMENSIONALITY definita nelle celle precedenti
chunk_embeddings_result = embedding_model.get_embeddings(chunk_embedding_inputs, output_dimensionality=OUTPUT_DIMENSIONALITY)
# Estrarre i valori di incorporazione
chunk_embeddings = [embedding.values for embedding in chunk_embeddings_result]
# 4. Creare una struttura dati per memorizzare i chunk e i loro embedding
# 5. Popolare la struttura dati
knowledge_base = []
for chunk, embedding in zip(chunks, chunk_embeddings):
knowledge_base.append({'text': chunk, 'embedding': embedding})
# 6. Stampare la lunghezza della lista di chunk e la dimensionalità del primo embedding
print(f"Numero di chunk creati: {len(chunks)}")
if chunk_embeddings:
print(f"Dimensionalità del primo embedding: {len(chunk_embeddings[0])}")
# Opzionale: Stampare le prime voci della base di conoscenza per verificarle.
print("\nPrime voci della base di conoscenza:")
for entry in knowledge_base[:2]:
print("--- Chunk ---")
print(entry['text'])
print("--- Embedding Dimensionality ---")
print(len(entry['embedding']))
print("---")Output:
Per semplicità si visualizzano i primi due chunk della base di conoscenza creata.
Numero di chunk creati: 10
Dimensionalità del primo embedding: 768
Prime voci della base di conoscenza:
--- Chunk ---
La nostra politica di reso prevede che i prodotti possano essere restituiti entro 30 giorni dall'acquisto, a condizione che siano in condizioni originali e con la prova d'acquisto. I rimborsi verranno elaborati entro 7-10 giorni lavorativi.
--- Embedding Dimensionality ---
768
---
--- Chunk ---
Per contattare il servizio clienti, è possibile chiamare il numero verde 800-123-456 dal lunedì al venerdì, dalle 9:00 alle 18:00, oppure inviare una email a supporto@azienda.it.
--- Embedding Dimensionality ---
768
---Simulare una domanda e recuperare le informazioni semanticamente rilevanti
Domanda dell'utente: Come posso chiedere un rimborso per il mio acquisto?
# @title Simulazione di una query utente
# Definire una variabile stringa per la query dell'utente
user_query = "Come posso chiedere un rimborso per il mio acquisto?" # @param {"type":"string"}
# Stampa la query dell'utente per verificarne il contenuto
print("User Query:")
print(user_query)
# @title Generazione dell'embedding della query
# 1. Importare TextEmbeddingInput e TextEmbeddingModel (già importati nelle celle precedenti).
# from vertexai.language_models import TextEmbeddingInput, TextEmbeddingModel
# 2. Inizializzare il modello di incorporazione (già inizializzato nelle celle precedenti)
# embedding_model = TextEmbeddingModel.from_pretrained(MODEL)
# 3. Creare un oggetto TextEmbeddingInput per la user_query
# Usare "RETRIEVAL_QUERY" come tipo di task per la query dell'utente
query_embedding_input = TextEmbeddingInput(text=user_query, task_type="RETRIEVAL_QUERY")
# 4. Generare l'incorporazione per la query
# Utilizzare la OUTPUT_DIMENSIONALITY definita nelle celle precedenti.
query_embeddings_result = embedding_model.get_embeddings([query_embedding_input], output_dimensionality=OUTPUT_DIMENSIONALITY)
# 5. Estrarre i valori di incorporazione
user_query_embedding = query_embeddings_result[0].values
# 6. Stampa la dimensionalità dell'incorporamento della query
print(f"Dimensionalità dell'embedding della query utente: {len(user_query_embedding)}")
# @title Recupero dei chunk rilevanti
# Confrontare l'embedding della query con gli embedding di tutti i chunk nella base di conoscenza e identificare i chunk più simili alla query (ad esempio, utilizzando la similarità coseno).
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# Convertire l'elenco dei chunk embeddings in un array NumPy
chunk_embeddings_array = np.array(chunk_embeddings)
# Convertire l'embedding della query utente in un array NumPy e rimodellarlo
user_query_embedding_array = np.array(user_query_embedding).reshape(1, -1)
# Calcolare la somiglianza del coseno tra l'incorporamento della query dell'utente e tutti gli incorporamenti dei chunk
similarity_scores = cosine_similarity(user_query_embedding_array, chunk_embeddings_array)[0]
# Ottenere gli indici dei chunk ordinati per punteggio di somiglianza in ordine decrescente
ranked_chunk_indices = np.argsort(similarity_scores)[::-1]
# Definire il numero di top k chunk da recuperare (ad esempio, 3)
top_k = 3
# Selezionare i primi k indici di chunk
top_k_chunk_indices = ranked_chunk_indices[:top_k]
# Stampa i punteggi di somiglianza e i primi k indici per la verifica
print("Cosine Similarity Scores (Query vs Chunks):")
print(similarity_scores)
print(f"\nTop {top_k} Chunk
Output:
# Simulazione di una query utente
User Query:
Come posso chiedere un rimborso per il mio acquisto?
# Generazione dell'embedding della query
Dimensionalità dell'embedding della query utente: 768
# Recupero dei chunk rilevanti
Cosine Similarity Scores (Query vs Chunks):
[0.76977757 0.70099548 0.63983967 0.63674064 0.65781946 0.61323987
0.59545833 0.56050322 0.66342832 0.62252781]
Top 3 Chunk Indices (ranked by similarity):
[0 1 8]
# Selezionare i migliori k chunk dalla base di conoscenza usando gli indici top_k_chunk
Top 3 Retrieved Chunks:
----------------------------
Chunk 1 (Index: 0):
La nostra politica di reso prevede che i prodotti possano essere restituiti entro 30 giorni dall'acquisto, a condizione che siano in condizioni originali e con la prova d'acquisto. I rimborsi verranno elaborati entro 7-10 giorni lavorativi.
---
Chunk 2 (Index: 1):
Per contattare il servizio clienti, è possibile chiamare il numero verde 800-123-456 dal lunedì al venerdì, dalle 9:00 alle 18:00, oppure inviare una email a supporto@azienda.it.
---
Chunk 3 (Index: 8):
In caso di problemi tecnici con lo SmartWidget Pro, consultare la sezione risoluzione dei problemi nel manuale o contattare il supporto tecnico specializzato.
---
----------------------------Risposta generata dall’LLM in base ai risultati recuperati
Si seguito si riporta la risposta alla domanda dell’utente in base ai risultati recuperati dal processo RAG e inseriti come CONTESTO per rispondere all’utente.
# @title Presentazione dei risultati recuperati
# Iterare i pezzi recuperati e stampare il loro contenuto testuale insieme ai punteggi di somiglianza.
# Assicurarsi che i pezzi recuperati, i top_k_chunk_indices e i similarity_scores siano disponibili dai passi precedenti.
print("Chunk di testo più rilevanti recuperati (con punteggio di similarità):")
print("-------------------------------------------------------------------")
# Iterate through the retrieved_chunks list
for i, chunk_info in enumerate(retrieved_chunks):
# Get the original index of the chunk to access the similarity score
original_index = top_k_chunk_indices[i]
# Get the similarity score for this chunk
similarity_score = similarity_scores[original_index]
# Print the chunk text
print(f"Chunk {i+1} (Punteggio: {similarity_score:.4f}):")
print(chunk_info['text'])
print("---") # Separator for clarity
print("-------------------------------------------------------------------")
# @title Integrazione con modello linguistico (opzionale)
# Utilizzare un modello linguistico di grandi dimensioni (LLM) per generare una risposta basata solo sul contenuto dei chunk recuperati.
# Importa il modello LLM necessario e costruisce il prompt che include la domanda dell'utente e i chunk recuperati, quindi genera e stampa la risposta dell'LLM.
from vertexai.generative_models import GenerativeModel
# 1. Importare il modello linguistico desiderato da Vertex AI.
# Utilizzando un modello adatto per la generazione del testo, ad esempio gemini-2.5-flash
# Assicurarsi che il nome del modello sia appropriato per la regione del progetto e per i modelli disponibili.
llm_model = GenerativeModel("gemini-2.5-flash")
# Combinare il testo dei pezzi recuperati in un'unica stringa
retrieved_context = "\n\n".join([chunk['text'] for chunk in retrieved_chunks])
# 2. Costruire un prompt per il LLM che includa la domanda originale dell'utente e i chunk recuperati.
# Specificare chiaramente che l'LLM deve basare la sua risposta *solo* sul contenuto fornito nei chunk.
prompt = f"""Basati *solamente* sul seguente contesto per rispondere alla domanda dell'utente.
Se la risposta non è presente nel contesto, rispondi che non hai informazioni a riguardo basate sul contesto fornito.
Contesto:
{retrieved_context}
Domanda dell'utente:
{user_query}
Risposta:
"""
# 3. Inviare la richiesta all'LLM e ottenere la risposta generata.
try:
response = llm_model.generate_content(prompt)
llm_response_text = response.text
except Exception as e:
llm_response_text = f"Errore nella generazione della risposta dall'LLM: {e}"
# 4. Stampare la risposta generata dall'LLM.
print("\nRisposta generata dall'LLM (basata sui chunk recuperati):")
print("----------------------------------------------------------")
print(llm_response_text)
print("----------------------------------------------------------")



Output:
Chunk di testo più rilevanti recuperati (con punteggio di similarità):
---------------------------------------------------------
Chunk 1 (Punteggio: 0.7698): La nostra politica di reso prevede che i prodotti possano essere restituiti entro 30 giorni dall'acquisto, a condizione che siano in condizioni originali e con la prova d'acquisto. I rimborsi verranno elaborati entro 7-10 giorni lavorativi.
Chunk 2 (Punteggio: 0.7010): Per contattare il servizio clienti, è possibile chiamare il numero verde 800-123-456 dal lunedì al venerdì, dalle 9:00 alle 18:00, oppure inviare una email a supporto@azienda.it.
Chunk 3 (Punteggio: 0.6634): In caso di problemi tecnici con lo SmartWidget Pro, consultare la sezione risoluzione dei problemi nel manuale o contattare il supporto tecnico specializzato.
---------------------------------------------------------Domanda Utente:
Come posso chiedere un rimborso per il mio acquisto?
Risposta generata dall'LLM (basata sui chunk recuperati):
---------------------------------------------------------
Per chiedere un rimborso per il tuo acquisto, puoi contattare il servizio clienti.
È possibile:
* Chiamare il numero verde **800-123-456** dal lunedì al venerdì, dalle 9:00 alle 18:00.
* Inviare una email a **supporto@azienda.it**.
Ricorda che i prodotti possono essere restituiti entro 30 giorni dall'acquisto, a condizione che siano in condizioni originali e con la prova d'acquisto. I rimborsi verranno elaborati entro 7-10 giorni lavorativi.
---------------------------------------------------------Il codice implementato rappresenta il cuore di un sistema RAG (Retrieval-Augmented Generation). La prima sezione del codice, dedicata alla presentazione dei risultati recuperati, illustra la fase di recupero (retrieval), dove i pezzi di testo più rilevanti vengono estratti da una base di conoscenza esterna.
La stampa dei punteggi di similarità, ottenuti confrontando la domanda dell’utente con i vari “pezzi” di dati, dimostra la capacità del sistema di identificare le informazioni più vicine semanticamente all’input dell’utente, un passaggio cruciale per garantire la pertinenza della risposta.
La seconda parte del codice si concentra sulla fase di aumento (augmentation). Qui, il contesto recuperato viene integrato in un prompt specifico e passato a un modello linguistico di grandi dimensioni (LLM), in questo caso Gemini. Questo processo assicura che l’LLM generi la sua risposta basandosi esclusivamente sul contesto fornito, prevenendo le cosiddette “allucinazioni” (ovvero la creazione di informazioni false o non supportate) e migliorando notevolmente l’accuratezza e l’affidabilità. Questa integrazione di recupero e generazione è fondamentale per costruire sistemi di intelligenza artificiale più precisi ed efficienti, poiché limita il modello a un set di dati rilevante e verificabile, rendendo le risposte non solo corrette ma anche trattabili.
Combinando le sezioni di codice precedente è possibile creare un sistema di recupero delle informazioni automatico che riporta i Chunk delle Policy con il punteggio di similarità più rilevante per rispondere in modo sicuro alle domande dell’utente, creando risposte alle FAQ più comuni in modo da verificare il contesto della risposta ed eliminando possibili allucinazioni.
