Per chi sviluppa applicazioni e soluzioni AI, l’assemblaggio di prompt in combinazine con tools è un nuovo e affacinante linguaggio di programmazione, dove la logica si fonde con l’ingegneria dei processi e l’analisi del significato semantico
L’assemblaggio di prompt, in combinazione con i tool, rappresenta il passaggio cruciale dal costruire con semplici mattoncini LEGO, alla progettazione di modelli LEGO Technic realmente funzionanti.
In questa metafora, i prompt restano i mattoncini di base, ma i tool di esecuzione sono i pezzi che fanno la differenza: motori, ingranaggi e sensori che danno vita alla creazione. Il focus, quindi, non è più sull’arte di assemblare una struttura statica (la “descrizione”), ma sulla progettazione di un sistema integrato che compie un’azione.
I nuovi modelli di ragionamento, rappresentano un notevole avanzamento nelle prestazioni, nelle capacità di codifica e nella controllabilità. Tuttavia, per sfruttare appieno il loro potenziale, è essenziale superare le tecniche di prompting tradizionali e abbracciare approcci in linea con la logica di programmazione.
Questo articolo intende esplorare le metodologie di prompt engineering con maggiore impatto concreto sui risultati, almeno dal un punto di vista dell’autore, tale da dare dei consigli per l’applicazione per la progettazione e creazione di modelli di analisi avanzati con ausilio di LLM.
Perché effettuare esperimenti con code execution
Per comprendere il potenziale di questo approccio, pensiamo a un LLM con capacità di esecuzione di codice come a una scatola di LEGO infinita e tecnologicamente avanzata. Interrogare un modello con un prompt tradizionale è come seguire le istruzioni per costruire un modello predefinito: il risultato sarà funzionale, ma limitato. La vera innovazione, invece, nasce dalla sperimentazione.

È esattamente ciò che è accaduto nel processo creativo che ha portato alle immagini di questo articolo. Siamo partiti da un’idea base (“un astronauta che gioca con i LEGO sulla Luna”) e, attraverso un dialogo iterativo, l’abbiamo trasformata. Ogni prompt successivo non era una semplice domanda, ma un esperimento: “Cosa succede se aumentiamo la luce? E se cambiamo l’inquadratura in un primo piano? E se la creazione prendesse vita?”. Alcuni tentativi hanno funzionato magnificamente, altri meno, ma ogni passo è stato un atto di progettazione attiva e scoperta.
Questo processo stimola un autentico pensiero progettuale. Invece di limitarsi a chiedere una soluzione, si inizia a “costruire” il ragionamento del modello, testando diverse combinazioni di logica e codice, proprio come si assemblano i mattoncini per scoprire nuove forme e strutture. Sperimentare con questi strumenti non significa solo trovare risposte, ma imparare a porre domande migliori, a prototipare soluzioni in tempo reale e a scoprire percorsi algoritmici inaspettati ed eleganti, trasformando un problema complesso in un entusiasmante cantiere di innovazione.
In questo articolo, esploreremo diversi esperimenti finalizzati a mettere in luce come un modello LLM possa trasformarsi in un potente strumento di problem-solving quantitativo. Grazie alla sua abilità di generare ed eseguire codice all’interno di un ambiente sicuro (sandbox), l’LLM è in grado di affrontare e risolvere problemi complessi. Partendo dalla semplice descrizione testuale di un problema, dimostra la capacità non solo di comprenderne le sfide, ma anche di tradurle in programmi eseguibili altamente efficaci.
Negli esempi seguenti utilizzeremo come LLM Google Gemini e, nello specifico, il meccanismo di Code Execution del modello.

Note sull’API dei esecuzione del codice di Google Gemini
L’API Gemini fornisce uno strumento di esecuzione del codice che consente al modello di generare ed eseguire codice Python. Il modello può quindi apprendere in modo iterativo dai risultati dell’esecuzione del codice fino a ottenere un output finale. Puoi utilizzare l’esecuzione di codice per creare applicazioni che sfruttano il ragionamento basato sul codice. Ad esempio, puoi utilizzare l’esecuzione del codice per risolvere equazioni o elaborare testo. Puoi anche utilizzare le librerie incluse nell’ambiente di esecuzione del codice per eseguire attività più specializzate. Gemini è in grado di eseguire codice solo in Python. Puoi comunque chiedere a Gemini di generare codice in un’altra lingua, ma il modello non può utilizzare lo strumento di esecuzione del codice per eseguirlo.
Consideriamo ad esempio un’azienda manifatturiera che desidera ottimizzare la produzione: l’LLM, dopo aver analizzato il quesito contenente i dati di input riguardanti la produzione, costi, prezzi e vincoli, formula autonomamente un modello di programmazione lineare e genera il codice Python necessario per risolverlo. L’esecuzione del codice nella sandbox consente al modello di ottenere risultati concreti, determinati secondo regole matematiche e privi di allucinazioni, presentando chiaramente il piano di produzione ottimale, il profitto massimo e un’analisi completa sull’utilizzo delle risorse.
Questa esperienza evidenzia come gli LLM, attraverso l’esecuzione controllata di codice, siano in grado di affrontare quesiti complessi con calcoli e analisi rigorosi, aprendo così nuovi orizzonti per l’automazione dei processi decisionali in ambiti diversi.
È fondamentale sottolineare che in questa tipologia di esperimenti, il modello LLM non esegue direttamente i calcoli per trovare la soluzione al problema di ottimizzazione. Il suo ruolo principale è quello di interpretare la richiesta, formulare il modello matematico, e generare il codice Python che implementa tale modello utilizzando la libreria scipy.optimize.
Come il modello LLM determina la soluzione?
La soluzione al problema viene ottenuta dall’esecuzione del codice Python generato dall’LLM in una sandbox, che a sua volta si appoggia alle funzionalità di calcolo della libreria scipy.optimize, una libreria specializzata in risoluzione di problemi lineari per risolvere il problema.

In altre parole, l’LLM agisce come un “traduttore” e un “orchestratore”, trasformando la richiesta in un programma eseguibile e delegando l’effettiva risoluzione del problema al codice generato.
Successivamente, l’LLM interpreta i risultati ottenuti dall’esecuzione del codice e li presenta in un formato comprensibile all’utente.
Questo processo evidenzia una distinzione cruciale: l’LLM è responsabile della comprensione e della strutturazione del problema, mentre il codice generato si occupa dell’elaborazione dei dati e del calcolo della soluzione.
Questa distinzione è fondamentale per comprendere i limiti e le potenzialità dell’approccio. L’LLM non “comprende” la soluzione nel senso matematico del termine, ma è in grado di utilizzare il codice come uno strumento per ottenere risposte a quesiti complessi, aprendo nuove possibilità per l’interazione tra intelligenza artificiale e problem-solving quantitativo.

Configurare un workflow automatico
Di seguito si riporta un passaggio semplificato su come creare un workflow di analisi per automatizzare la risoluzione di un quesito aziendale, utilizzando il linguaggio naturale o concatenando stringhe di form attraverso la chiamata a funzione del modello LLM di Gemini 2.5 per risolvere un quesito di ottimizzazione della produzione in un’azienda manifatturiera. Viene presentato il setup iniziale e una possibile configurazione basata di un Task di analisi. Si considera che gli output dei Task possono essere concatenati per creare processi di analisi anche molto complessi.
Il codice seguente è scritto in linguaggio Python ed è compatibile con Google Colaboratory. Pertanto, è sufficiente creare un nuovo foglio in Google Colab, ottenere un’API KEY di Google Gemini, copiare e incollare il codice, inserire la API KEY nel segreto del modulo o nella cella specifica ed eseguire le celle.
I quesiti degli esempi, seppur verosimili, sono sintetici, creati per scoprire e descrivere le complesse dinamiche del fenomeno in esame. Essi offrono spunti di riflessione e stimolano la curiosità intellettuale, permettendo così di approfondire la comprensione e facilitare l’apprendimento.
Setup
# @title Installare le librerie
%pip install -U -q 'google-genai>=1.2.0'
!pip install reportlab
# @title Configurare la chiave API
from google.colab import userdata
# Prova a ottenere la chiave API dai segreti Colab.
try:
GOOGLE_API_KEY = userdata.get('GOOGLE_API_KEY')
print("Chiave API caricata nel Secret Colab.")
except KeyError:
# Se la chiave non è presente in secrets, utilizzare un modulo Colab.
print("Chiave API non trovata nei segreti Colab. Inseriscila qui sotto:")
GOOGLE_API_KEY = "" # @param {type:"string"}
if GOOGLE_API_KEY:
print("Chiave API inserita tramite modulo.")
else:
print("Inserisci la tua chiave API nel campo del modulo.")
# @title Inizializzare il client SDK
# Con il nuovo SDK ora è sufficiente inizializzare un client con la chiave API (o OAuth se si utilizza Vertex AI). Il modello è ora impostato in ogni chiamata.
from google import genai
client = genai.Client(api_key=GOOGLE_API_KEY)
# @title Scegli un modello Gemini da utilizzare
MODEL_ID = "gemini-2.0-flash" # @param ["gemini-1.5-flash-8b","gemini-1.5-flash-002","gemini-2.0-flash-lite","gemini-2.0-flash", "gemini-2.5-pro"] {"allow-input":true}Questo codice, come i successivi, si riferisce a un’elaborazione e integrazione avanzata di notebook di Google Research. per l’esecuzione del codice. I modelli disponibili di LLM utilizzati si basano sui modelli della famiglia di Google Gemini 2.5.
Creare una funzione di utilità
Questo blocco di codice definisce una funzione di utilità chiamata display_code_execution_result. Questa funzione è progettata per visualizzare in modo strutturato i diversi tipi di output che possono derivare dall’esecuzione del codice tramite l’API Gemini.
# @title Definire una funizione di utilità
from IPython.display import Image, Markdown, Code, HTML
def display_code_execution_result(response):
for part in response.candidates[0].content.parts:
if part.text is not None:
display(Markdown(part.text))
if part.executable_code is not None:
code_html = f'<pre style="background-color: #282c34; color: white;">{part.executable_code.code}</pre>'
display(HTML(code_html))
if part.code_execution_result is not None:
display(Markdown(part.code_execution_result.output))
if part.inline_data is not None:
display(Image(data=part.inline_data.data, width=800, format="png"))
display(Markdown("---"))Questa funzione prende la risposta complessa dell’API Gemini (che può includere codice, output e immagini) e la presenta in un formato più leggibile e organizzato.
Risolvere un task di analisi: Stimare la produzione ottimale
TASK 1 – Applicare code_execution in uno STEP singolo (singola chiamata)
In questo blocco di codice è presente la configurazione per effettuare una chiamata al modello LLM, utilizzando una query che contiene il quesito da risolvere.
Quesito: Richiesta di ottimizzazione della produzione di zaini da montagna.
Ottimizzazione della produzione di Zaini da Montagna per “Adventure Gear S.r.l.”
Scenario: “Adventure Gear S.r.l.”, un’azienda specializzata nella produzione di attrezzatura per l’outdoor, produce due modelli di zaini da montagna: il “Trekker 35” (uno zaino da escursionismo di media capacità) e l’“Alpinist 60” (uno zaino da spedizione di alta capacità).
Dati Chiave:
- Trekker 35:
- Richiede 1.2 metri di tessuto tecnico impermeabile (Tipo A) e 0.5 metri di tessuto resistente all’abrasione (Tipo B).
- Necessita di 0.8 ore di lavoro nel reparto di cucitura e assemblaggio.
- Prezzo di vendita: 80 €/unità.
- Alpinist 60:
- Richiede 1.8 metri di tessuto tecnico impermeabile (Tipo A) e 1.0 metri di tessuto resistente all’abrasione (Tipo B).
- Necessita di 1.5 ore di lavoro nel reparto di cucitura e assemblaggio.
Vincoli Settimanali:
- Disponibilità Tessuto Tipo A: 600 metri.
- Disponibilità Tessuto Tipo B: 400 metri.
- Capacità Reparto Cucitura e Assemblaggio: 300 ore.
Vincoli di Domanda (Stime Realistiche):
- Domanda massima settimanale Trekker 35: 250 unità. * Domanda massima settimanale Alpinist 60: 180 unità.
Richiesta: Utilizzando la programmazione lineare, determina la quantità ottimale di “Trekker 35” e “Alpinist 60” da produrre settimanalmente per massimizzare il profitto totale.
Fornisci:
- La quantità ottimale di “Trekker 35” da produrre.
- La quantità ottimale di “Alpinist 60” da produrre. 3. Il profitto massimo settimanale ottenibile.
- Un’analisi dell’utilizzo delle risorse (Tessuto Tipo A, Tessuto Tipo B, Ore di cucitura e assemblaggio) con la soluzione ottimale, evidenziando eventuali colli di bottiglia o risorse sottoutilizzate.
Librerie Python Utili: scipy.optimize (funzione linprog)
# @title Applicare `code_execution` in un sigollo STEP (sigola chiamata)
# Quando si avvia il modello, passare `code_execution` come `tool` per indicare al modello che è consentito generare ed eseguire codice.
from google.genai import types
query = "**Ottimizzazione della produzione di Zaini da Montagna per \"Adventure Gear S.r.l.\"** **Scenario:** \"Adventure Gear S.r.l.\", un'azienda specializzata nella produzione di attrezzatura per l'outdoor, produce due modelli di zaini da montagna: il \"Trekker 35\" (uno zaino da escursionismo di media capacità) e l'\"Alpinist 60\" (uno zaino da spedizione di alta capacità). **Dati Chiave:** * **Trekker 35:** * Richiede 1.2 metri di tessuto tecnico impermeabile (Tipo A) e 0.5 metri di tessuto resistente all'abrasione (Tipo B). * Necessita di 0.8 ore di lavoro nel reparto di cucitura e assemblaggio. * Prezzo di vendita: 80 €/unità. * **Alpinist 60:** * Richiede 1.8 metri di tessuto tecnico impermeabile (Tipo A) e 1.0 metri di tessuto resistente all'abrasione (Tipo B). * Necessita di 1.5 ore di lavoro nel reparto di cucitura e assemblaggio. * Prezzo di vendita: 120 €/unità. **Vincoli Settimanali:** * Disponibilità Tessuto Tipo A: 600 metri. * Disponibilità Tessuto Tipo B: 400 metri. * Capacità Reparto Cucitura e Assemblaggio: 300 ore. **Vincoli di Domanda (Stime Realistiche):** * Domanda massima settimanale Trekker 35: 250 unità. * Domanda massima settimanale Alpinist 60: 180 unità. **Richiesta:** Utilizzando la programmazione lineare, determina la quantità ottimale di \"Trekker 35\" e \"Alpinist 60\" da produrre settimanalmente per massimizzare il profitto totale. Fornisci: 1. La quantità ottimale di \"Trekker 35\" da produrre. 2. La quantità ottimale di \"Alpinist 60\" da produrre. 3. Il profitto massimo settimanale ottenibile. 4. Un'analisi dell'utilizzo delle risorse (Tessuto Tipo A, Tessuto Tipo B, Ore di cucitura e assemblaggio) con la soluzione ottimale, evidenziando eventuali colli di bottiglia o risorse sottoutilizzate. **Librerie Python Utili:** `scipy.optimize` (funzione `linprog`)" #@param {type:"string"}
prompt = f"\"{query} Generate ed eseguite il codice per il calcolo e assicuratevi di ottenere tutti i risutltati richiesti. Restituisci la risposta in lingia italiana\"\"\""
response = client.models.generate_content(
model=MODEL_ID,
contents=prompt,
config = types.GenerateContentConfig(
tools=[types.Tool(
code_execution=types.ToolCodeExecution()
)]
)
)
display_code_execution_result(response)



Output automatico del modello
Ok, analizzerò il problema di ottimizzazione della produzione di zaini e utilizzerò la programmazione lineare per trovare la soluzione ottimale. Tradurrò il problema in un modello matematico, utilizzerò la libreria scipy.optimize per risolverlo e presenterò i risultati in italiano, includendo l’analisi dell’utilizzo delle risorse.
Ecco il modello matematico:
Variabili di decisione:
- x = quantità di “Trekker 35” da produrre
- y = quantità di “Alpinist 60” da produrre
Funzione obiettivo (massimizzare il profitto):
- Profitto = 80x + 120y
Vincoli:
- Tessuto Tipo A: 1.2x + 1.8y <= 600
- Tessuto Tipo B: 0.5x + 1.0y <= 400
- Reparto Cucitura: 0.8x + 1.5y <= 300
- Domanda Trekker 35: x <= 250
- Domanda Alpinist 60: y <= 180
- Non negatività: x >= 0, y >= 0
Ora utilizzerò scipy.optimize.linprog per risolvere questo problema.
Codice eseguito automaticamente
import numpy as np
from scipy.optimize import linprog
# Coefficienti della funzione obiettivo (da minimizzare il negativo del profitto)
c = [-80, -120]
# Coefficienti dei vincoli (lato sinistro)
A = [
[1.2, 1.8], # Tessuto Tipo A
[0.5, 1.0], # Tessuto Tipo B
[0.8, 1.5], # Reparto Cucitura
[1, 0], # Domanda Trekker 35
[0, 1] # Domanda Alpinist 60
]
# Limiti dei vincoli (lato destro)
b = [600, 400, 300, 250, 180]
# Limiti delle variabili (non negatività)
x0_bounds = (0, None)
x1_bounds = (0, None)
# Risolvi il problema di programmazione lineare
res = linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds], method='highs')
# Estrai i risultati
x = res.x[0]
y = res.x[1]
profitto = -res.fun
print(f'Quantità ottimale di Trekker 35: {x}')
print(f'Quantità ottimale di Alpinist 60: {y}')
print(f'Profitto massimo settimanale: {profitto}')
# Analisi dell'utilizzo delle risorse
tessuto_a_utilizzato = 1.2 * x + 1.8 * y
tessuto_b_utilizzato = 0.5 * x + 1.0 * y
ore_cucitura_utilizzate = 0.8 * x + 1.5 * y
print(f'Tessuto Tipo A utilizzato: {tessuto_a_utilizzato} metri')
print(f'Tessuto Tipo B utilizzato: {tessuto_b_utilizzato} metri')
print(f'Ore di cucitura utilizzate: {ore_cucitura_utilizzate} ore')Quantità ottimale di Trekker 35: 250.0 Quantità ottimale di Alpinist 60: 66.66666666666667 Profitto massimo settimanale: 28000.0 Tessuto Tipo A utilizzato: 420.0 metri Tessuto Tipo B utilizzato: 191.66666666666669 metri Ore di cucitura utilizzate: 300.0 ore
Ecco i risultati dell’ottimizzazione della produzione di zaini:
- Quantità ottimale di “Trekker 35” da produrre: 250 unità.
- Quantità ottimale di “Alpinist 60” da produrre: Circa 66.67 unità. Poiché non è possibile produrre una frazione di zaino, si dovrebbe arrotondare a 66 o 67 unità, valutando l’impatto sul profitto e sui vincoli. Per semplicità, manterrò il valore non arrotondato per l’analisi.
- Profitto massimo settimanale ottenibile: 28000 €.
- Analisi dell’utilizzo delle risorse:
- Tessuto Tipo A: Utilizzati 420 metri (disponibilità totale: 600 metri). Rimangono quindi 180 metri di tessuto Tipo A non utilizzati.
- Tessuto Tipo B: Utilizzati circa 191.67 metri (disponibilità totale: 400 metri). Rimangono quindi circa 208.33 metri di tessuto Tipo B non utilizzati.
- Reparto Cucitura e Assemblaggio: Utilizzate 300 ore (capacità totale: 300 ore). Il reparto di cucitura e assemblaggio è completamente utilizzato, rappresentando un collo di bottiglia.
Di seguito sono riportate le conclusioni del modello, risultanti dalla rielaborazione dell’esecuzione del codice tramite il Code del modello e non dall’inferenza del modello LLM.
La soluzione ottimale prevede di produrre il massimo numero possibile di “Trekker 35” (250 unità) e circa 66.67 unità di “Alpinist 60”. Il reparto di cucitura e assemblaggio rappresenta un collo di bottiglia, in quanto viene utilizzato al 100%. Il tessuto Tipo A e il tessuto Tipo B non sono completamente utilizzati, il che suggerisce che si potrebbe aumentare la produzione, se la capacità del reparto di cucitura fosse maggiore. Arrotondare la produzione di Alpinist 60 a 66 o 67 unità impatterà leggermente il profitto e l’utilizzo dei tessuti. Bisognerebbe valutare la soluzione arrotondata e verificare che rispetti i vincoli.

Configurare un Agente di esecuzione di codice
È possibile creare un agente specializzato nell’esecuzione di codice utilizzando le istruzioni di sistema e il tool di code execution. Questo permette di avere conversazioni a più turni con il modello (chat). La caratteristica distintiva di questo agente è la sua capacità di generare, eseguire codice Python e rispondere basandosi esclusivamente sui risultati di tale esecuzione, piuttosto che sull’inferenza diretta del modello LLM. È possibile impostare le istruzioni di sistema per orientare ulteriormente il comportamento del modello per specifiche attività.
Configurare l’agente di calcolo
# @title Configura le istruzioni
from google.genai import types
system_instruction="""
Sei uno sviluppatore di software esperto e un valido assistente di programmazione.
Sei in grado di generare codice di alta qualità in qualsiasi linguaggio di programmazione.
Utilizza SEMPRE il tools Code Execution per risolvere il problema
Qunado possibile e se richiesto crea grafici fotmattandoli in modo eleganete
Rispondi SEMPRE in italiano
"""
chat = client.chats.create(
model=MODEL_ID,
config=types.GenerateContentConfig(
system_instruction=system_instruction,
tools=[types.Tool(
code_execution=types.ToolCodeExecution()
)]
)
)Integrazione query singola
Analizza questi dati di vendita mensili [gennaio: €125k, febbraio: €98k, marzo: €156k, aprile: €89k, maggio: €178k] e calcola trend, crescita e anomalie. Visualizza i valori su un grafico a barre.
# @title Query
QUERY_UTENTE = "Analizza questi dati di vendita mensili [gennaio: €125k, febbraio: €98k, marzo: €156k, aprile: €89k, maggio: €178k] e calcola trend, crescita e anomalie." # @param {"type":"string"}
response = chat.send_message(QUERY_UTENTE)
display_code_execution_result(response)Output

Il grafico a barre fornisce una chiara rappresentazione delle vendite per ciascun mese. L’analisi delle variazioni percentuali rivela mesi di crescita significativa (Marzo e Maggio) e un mese di calo significativo (Aprile). Un’analisi più approfondita potrebbe esaminare le cause di queste fluttuazioni.



L’analisi è stata effettuata eseguendo il codice prodotto dal LLM e eseguito dal tool di esecuzione del codice.
Integrazione query multi turno
In questo caso, si può arricchire il thread dei messaggi integrando query multi-turno per affinare e potenziare l’analisi precedente.
Query 1:
Ora segmenta i dati per identificare quali mesi sono sotto/sopra la media e calcola l’impatto economico delle performance negative.
Query 2:
Crea un forecast per i prossimi 3 mesi basato sui trend identificati e suggerisci azioni correttive specifiche.
# @title Integrazione query multi turno
QUERY_UTENTE_1 = "Ora segmenta i dati per identificare quali mesi sono sotto/sopra la media e calcola l'impatto economico delle performance negative." # @param {"type":"string"}
response_1 = chat.send_message(QUERY_UTENTE_1)
QUERY_UTENTE_2 = "Crea un forecast per i prossimi 3 mesi basato sui trend identificati e suggerisci azioni correttive specifiche." # @param {"type":"string"}
response_2 = chat.send_message(QUERY_UTENTE_2)
display_code_execution_result(response_1)
display_code_execution_result(response_2)Output:
Previsioni (Scenario 1: Regressione Lineare): Mese 6: €158300.00 Mese 7: €168000.00 Mese 8: €177700.00
Previsioni (Scenario 2: Media Mobile Semplice): Mese 6: €133500.00 Mese 7: €133500.00 Mese 8: €133500.00
Interpretazione delle Previsioni:
- Scenario 1 (Regressione Lineare): Prevede una continua crescita, con vendite che raggiungono circa €177.700 nel mese 8. Questo scenario assume che il trend leggermente crescente continuerà.
- Scenario 2 (Media Mobile): Prevede vendite stabili a €133.500 per i prossimi 3 mesi. Questo scenario assume che le performance recenti (Aprile e Maggio) siano più indicative del futuro.
Suggerimenti per azioni correttive (e Preventive):
Indipendentemente dallo scenario che si rivelerà più accurato, è fondamentale analizzare le cause delle fluttuazioni mensili e agire di conseguenza. Ecco alcune azioni:
- Analisi Approfondita dei Mesi con Performance Negative (Febbraio e Aprile):
- Cause Interne: Rivedere le strategie di marketing e vendita, eventuali problemi operativi, gestione delle scorte, prezzi, etc. Sono state lanciate promozioni inefficaci? Ci sono stati problemi di produzione o consegna?
- Cause Esterne: Analizzare fattori esterni come la concorrenza, cambiamenti nel mercato, eventi economici, stagionalità (anche se difficile da valutare con pochi dati), etc.
- Capitalizzare sui mesi con erformance Positive (Marzo e Maggio):
- Identificare i fattori di successo: Cosa ha funzionato bene in questi mesi? Quali strategie o iniziative hanno contribuito all’aumento delle vendite?
- Replicare e scalare: Cercare di replicare e scalare i fattori di successo per migliorare le performance degli altri mesi.
- Azioni correttive specifiche (Esempi):
- Febbraio e Aprile (Performance Negative):
- Rilanciare campagne di marketing: Creare promozioni mirate e campagne di marketing per stimolare la domanda.
- Migliorare l’esperienza del cliente: Raccogliere feedback dai clienti e implementare miglioramenti nel servizio clienti, nel processo di acquisto, etc.
- Gestione delle scorte: Assicurarsi di avere scorte adeguate per soddisfare la domanda, evitando rotture di stock.
- Marzo e Maggio (Performance Positive):
- Offrire Incentivi: Proporre incentivi per acquisti di gruppo o ripetuti per aumentare le vendite a carrello
- Eventi Esclusivi: Incontri o workshop in presenza o digitali per creare community ed engagement
- Febbraio e Aprile (Performance Negative):
- Monitoraggio continuo e aggiustamenti: Monitorare attentamente le performance di vendita mensili e confrontarle con le previsioni. Essere pronti ad aggiustare le strategie in base ai risultati effettivi. Raccogliere dati più granulari (settimanali, giornalieri) se possibile, per una maggiore reattività.
- Raccolta di Dati: Raccogliere più dati possibili sulle vendite (e sui fattori che le influenzano) per migliorare la precisione delle previsioni future.
Importante: Queste sono solo alcune idee di azioni correttive. Le azioni più appropriate dipenderanno dalle specifiche circostanze dell’azienda e dai risultati dell’analisi approfondita. Data la limitata quantità di dati, è essenziale essere cauti nell’interpretazione delle previsioni e concentrarsi sull’analisi delle cause delle fluttuazioni e sull’implementazione di azioni mirate.
Infine, con più dati storici, si potrebbe usare un modello di previsione più sofisticato (es. ARIMA, Prophet, reti neurali) per ottenere previsioni più accurate e tenere conto di stagionalità e altri fattori complessi.




Caso d’uso 1: Ottimizzare la produzione aziendale
Questo caso d’uso illustra come utilizzare il LLM di Google Gemini e il tool di code execution per risolvere un problema (verosimile) di ricerca operativa, in particolare l’ottimizzazione della produzione di un’azienda manifatturiera specializzata nella produzione di complementi d’arredo.
Quesito di analisi
Legno Veneto S.r.l. produce due tipi di tavoli: “Tavolo Rustico Tradizionale” e “Tavolo Moderno Essenziale”. Per la produzione, l’azienda utilizza legno di rovere e ore di lavoro, entrambi con disponibilità limitata. Inoltre, la domanda di mercato per ciascun tipo di tavolo è anch’essa limitata, considerando i seguenti dati:
Dati di produzione e vendita:
| Prodotto | Legno (m³) | Ore Lavoro | Costo (€) | Prezzo (€) |
|---|---|---|---|---|
| Tavolo Rustico Tradizionale | 1.2 | 8 | 300 | 700 |
| Tavolo Moderno Essenziale | 0.8 | 5 | 200 | 550 |
Vincoli operativi (Prossimo Mese):
- Legno di Rovere: <= 150 m³
- Ore di Lavoro: <= 800 ore
- Domanda Tavolo Rustico: <= 80 unità
- Domanda Tavolo Moderno: <= 120 unità
Richiesta: Qual è la quantità ottimale di ciascun tipo di tavolo che “Legno Veneto S.r.l.” dovrebbe produrre il prossimo mese per massimizzare il profitto totale, rispettando i vincoli di risorse e di domanda?
Istruzioni
- Elabora il quesito
- Genera ed esegui un codice
- Rispondi solo in base all’esecuzione del codice
- Fornisci:
- Il piano di produzione ottimale (quantità di Tavoli Rustici e Tavoli Moderni).
- Il profitto massimo previsto.
- Un’analisi dell’utilizzo delle risorse (legno di rovere e ore di lavoro) con la soluzione ottimale.
- Un analisi strategica della soluzione
Suggerimenti:
- Definire le variabili decisionali: x1 (numero di Tavoli Rustici) e x2 (numero di Tavoli Moderni).
- Formulare la funzione obiettivo (massimizzare il profitto).
- Formulare i vincoli come disequazioni lineari.
Output del processo di analisi
Attenzione!!! L’output seguente è la rielaborazione da parte del modello LLM del risultato dell’algoritmo di calcolo generato e eseguito dallo strumento Code Execution.
Piano di produzione ottimale: Tavoli Rustici: 25 Tavoli Moderni: 120 Profitto massimo previsto: 52.000 €
Utilizzo delle risorse: Legno di Rovere utilizzato: 126 m³ Ore di Lavoro utilizzate: 800 ore
Risposta:
- Piano di produzione ottimale:
- Tavoli Rustici Tradizionali: 25 unità
- Tavoli Moderni Essenziali: 120 unità
- Profitto massimo previsto: 52.000 €
- Utilizzo delle risorse:
- Legno di Rovere utilizzato: 126 m³
- Ore di Lavoro utilizzate: 800 ore
Analisi Strategica:
La soluzione ottimale prevede di produrre 25 tavoli rustici e il massimo possibile di tavoli moderni (120 unità), sfruttando completamente la capacità produttiva in termini di ore di lavoro. L’utilizzo del legno di rovere è inferiore alla disponibilità massima, il che indica che questo vincolo non è stringente come quello delle ore di lavoro.
Implicazioni:
- Efficienza: L’azienda dovrebbe concentrarsi sulla produzione di tavoli moderni, che generano un profitto elevato e saturano la domanda.
- Capacità produttiva: Le ore di lavoro sono un fattore limitante. Valutare l’assunzione di personale aggiuntivo o l’ottimizzazione dei processi produttivi per aumentare la capacità.
- Marketing e Vendite: La domanda per i tavoli rustici è inferiore alla capacità produttiva potenziale. Si potrebbe valutare di intensificare gli sforzi di marketing per aumentare la domanda di questo tipo di tavolo oppure analizzare la possibilità di introdurre nuovi prodotti simili ai tavoli moderni per sfruttare al meglio la capacità produttiva.
- Negoziazione fornitori: Considerato che il legno non è un vincolo stringente, l’azienda potrebbe concentrarsi sulla negoziazione di prezzi migliori per le materie prime, soprattutto in relazione al costo del lavoro.
In sintesi, la “Legno Veneto S.r.l.” dovrebbe concentrarsi sulla produzione dei tavoli moderni, cercare di aumentare la propria capacità produttiva, valutare strategie per incrementare la domanda di tavoli rustici e monitorare attentamente i costi delle risorse per massimizzare il profitto.
Codice del modello di analisi
In questa sezione di codice, esploreremo come creare un’interfaccia intuitiva per inserire il quesito di analisi, memorizzandolo e e comporre un prompt per l’invio della richiesta al modello LLM, LLM comprensiva del Tool Code Execution per la generazione del codice di risoluzione.
Inoltre viene visualizzato a schermo l’utilizzo di Token che ha usato il modello per risolvere il quesito.
Si ricorda che la risposta del modello si basa sul risultato dell’esecuzione del codice generato in una sandbox. Il codice generato diventa contesto per il LLM, che lo rielabora semanticamente e crea un output in linguaggio naturale, come si può verificare dalle immagini allegate. In questo caso, l’LLM funge da interprete della domanda e programmatore del codice; il risultato non viene inferito dall’LLM, ma è il frutto di un algoritmo basato su regole deterministiche.
Questo codice crea una cella in Google dove è possibile inviare la risposta al modello per la risoluzione con il tool Code con Execution. Il codice è valido per tutti i seguenti casi d’uso.
# @title Risolvere un quesito azinedale con Code Execution
import ipywidgets as widgets
from IPython.display import display, Markdown, HTML
from IPython.display import display
from google.genai import types
import time
# Import Output from ipywidgets
from ipywidgets import Output # Importing Output class from ipywidgets
# --- Funzioni ---
def salva_quesito(b):
global quesito
quesito = textarea.value
with output_caricamento: # Redirect output to output_caricamento
display(HTML('<p style="font-size:16px;">Quesito salvato.</p>')) # Display as HTML
def visualizza_domanda(b):
display(Markdown(quesito))
# --- Funzioni aggiuntive ---
output_caricamento = Output() # Crea un'istanza di Output
def mostra_caricamento():
"""Visualizza il messaggio di caricamento."""
with output_caricamento: # Usa output_caricamento come contesto
display(HTML('<p style="font-size:16px;">Elaborazione in corso, attendere prego...</p>'))
output_caricamento.clear_output(wait=True) # Cancella l'output precedente
def nascondi_caricamento():
"""Nasconde il messaggio di caricamento e mostra messaggio di completamento."""
with output_caricamento:
output_caricamento.clear_output(wait=True)
display(HTML('<p style="font-size:16px;">Elaborazione completata.</p>'))
# --- Modifica della funzione invia_quesito ---
def invia_quesito(b):
global quesito
mostra_caricamento() # Mostra il messaggio di caricamento
prompt = f"\"{quesito}.\n Generate ed eseguite il codice per il calcolo e assicuratevi di ottenere tutti i risutltati richiesti. Restituisci la risposta in lingia italiana\"\"\""
try:
response = client.models.generate_content(
model=MODEL_ID,
contents=prompt,
config=types.GenerateContentConfig(
tools=[types.Tool(code_execution=types.ToolCodeExecution)]
)
)
display_code_execution_result(response)
finally: # Assicurati che il messaggio venga nascosto anche in caso di errore
nascondi_caricamento() # Nascondi il messaggio di caricamento e mostra messaggio di completamento
# Stampa informazioni sui token utilizzati
print("\n-------------------- Utilizzo dei Token --------------------")
print(f"Token prompt: {response.usage_metadata.prompt_token_count}")
print(f"Token risposta: {response.usage_metadata.candidates_token_count}")
print(f"Token totali: {response.usage_metadata.prompt_token_count + response.usage_metadata.candidates_token_count}")
# --- Widget ---
# Variabile per memorizzare il quesito
quesito = ""
# Titolo
titolo = widgets.HTML(value='<h2 style="float: left;">Descrizione del quesito da risolvere</h2>')
# Textarea per il quesito
textarea = widgets.Textarea(
placeholder='Inserisci il tuo quesito qui...',
layout=widgets.Layout(width='100%', height='400px')
)
# Pulsante Salva
salva_button = widgets.Button(description='Salva')
salva_button.on_click(salva_quesito)
# Pulsante Visualizza domanda
visualizza_domanda_button = widgets.Button(description='Visualizza domanda')
visualizza_domanda_button.on_click(visualizza_domanda)
# Pulsante Invia a Gemini
invia_button = widgets.Button(description='Invia a Gemini')
invia_button.on_click(invia_quesito)
# --- Visualizzazione ---
display(titolo)
display(textarea)
display(salva_button)
display(visualizza_domanda_button)
display(invia_button)
display(output_caricamento)
Output:




Caso d’uso 2: Analisi break even point
L’utente definisce un quesito di business specifico e quantificabile, in questo caso l’analisi del punto di pareggio, fornendo tutti i dati numerici necessari (costi fissi, costi variabili, prezzo di vendita).
LLM non calcola la risposta. Traduce il problema in codice Python, lo esegue per ottenere i risultati numerici e utilizza le librerie appropriate per generare una visualizzazione grafica dei dati.
Quesito di analisi
Analisi del punto di pareggio
Un’azienda manifatturiera sta introducendo una nuova linea di prodotto e necessita di un’analisi del punto di pareggio.
Dati:
Costo Fisso Totale Annuo: 75.000 € Costo Variabile per Unità Prodotta: 15 € Prezzo di Vendita per Unità: 40 € Richiesta:
Calcoli richiesti:
Punto di Pareggio in Unità: Calcola il numero di unità da vendere per coprire tutti i costi (fissi e variabili) e raggiungere un profitto pari a zero. Punto di Pareggio in Valore (Fatturato): Calcola il valore delle vendite (in euro) necessario per raggiungere il punto di pareggio. (Opzionale) Analisi Grafica: Genera un grafico che visualizzi: Costi fissi totali. Costi variabili totali (in funzione delle unità prodotte). Costi totali (costi fissi + costi variabili). Ricavi totali (in funzione delle unità vendute). Evidenzia il punto di pareggio (intersezione tra costi totali e ricavi totali). Considera un intervallo di produzione/vendita da 0 a 5.000 unità. Librerie Python:
Utilizza numpy per la creazione di array di dati e matplotlib.pyplot per la creazione del grafico.
Output Atteso:
Istruzioni:
Esegui un codice per effettuare i calcoli indicati Rispondi solo in base al risultato dell’esecuzione del codice Fornisci il valore del punto di pareggio in unità. Fornisci il valore del punto di pareggio in euro. Fornisci il grafico con la visualizzazione dell’analisi. Fornisci un paragrafo descrittivo dei risultati ottenuti ed eventuali consigli strategici
Query
Risolvi il quesito utilizzando l’interprete di codice Python per calcolare e analizzare il punto di pareggio (Break-Even Point) per questa nuova linea di prodotto.
Output del processo di analisi
Punto di pareggio in unità: 3.000 Punto di pareggio in valore (fatturato): 12.0000 €

- Punto di pareggio in unità: 3.000 unità
- Punto di pareggio in valore: 12.0000 €
- Grafico: Il grafico allegato visualizza i costi fissi, i costi variabili, i costi totali e i ricavi totali in funzione delle unità prodotte/vendute. Il punto di pareggio è evidenziato all’intersezione tra le curve dei costi totali e dei ricavi totali.
Analisi e Consigli Strategici:
L’analisi del punto di pareggio indica che l’azienda deve vendere 3.000 unità del nuovo prodotto per coprire tutti i costi e non realizzare né profitto né perdita. Il fatturato necessario per raggiungere questo obiettivo è di 12.0000 €.
Consigli Strategici:
- Monitoraggio delle Vendite: È fondamentale monitorare attentamente le vendite iniziali per verificare se si sta raggiungendo il punto di pareggio previsto.
- Ottimizzazione dei Costi: Esplorare opportunità per ridurre i costi variabili (ad esempio, negoziare prezzi migliori con i fornitori) o i costi fissi (ad esempio, ottimizzare l’utilizzo delle risorse) può ridurre il punto di pareggio e aumentare la redditività.
- Strategie di Prezzo: Valutare la possibilità di aggiustare il prezzo di vendita. Un aumento del prezzo (se il mercato lo consente) può ridurre il punto di pareggio.
- Marketing e Promozione: Investire in attività di marketing e promozione per aumentare la domanda del prodotto e accelerare il raggiungimento del punto di pareggio.
- Analisi di Sensibilità: Eseguire un’analisi di sensibilità per valutare come le variazioni nei costi o nel prezzo di vendita influenzano il punto di pareggio. Questo aiuta a identificare i fattori critici per il successo del prodotto.
- Considerare il Flusso di Cassa: Anche se il punto di pareggio viene raggiunto, è importante gestire attentamente il flusso di cassa. Potrebbero esserci ritardi nei pagamenti dei clienti, quindi è necessario avere riserve di liquidità sufficienti.
Codice del modello di analisi
Lo stesso del Caso d’uso 1
# @title Risolvere un quesito azinedale con Code Execution
import ipywidgets as widgets
from IPython.display import display, Markdown, HTML
from IPython.display import display
from google.genai import types
import time
# Import Output from ipywidgets
from ipywidgets import Output # Importing Output class from ipywidgets
# --- Funzioni ---
def salva_quesito(b):
global quesito
quesito = textarea.value
with output_caricamento: # Redirect output to output_caricamento
display(HTML('<p style="font-size:16px;">Quesito salvato.</p>')) # Display as HTML
def visualizza_domanda(b):
display(Markdown(quesito))
# --- Funzioni aggiuntive ---
output_caricamento = Output() # Crea un'istanza di Output
def mostra_caricamento():
"""Visualizza il messaggio di caricamento."""
with output_caricamento: # Usa output_caricamento come contesto
display(HTML('<p style="font-size:16px;">Elaborazione in corso, attendere prego...</p>'))
output_caricamento.clear_output(wait=True) # Cancella l'output precedente
def nascondi_caricamento():
"""Nasconde il messaggio di caricamento e mostra messaggio di completamento."""
with output_caricamento:
output_caricamento.clear_output(wait=True)
display(HTML('<p style="font-size:16px;">Elaborazione completata.</p>'))
# --- Modifica della funzione invia_quesito ---
def invia_quesito(b):
global quesito
mostra_caricamento() # Mostra il messaggio di caricamento
prompt = f"\"{quesito}.\n Generate ed eseguite il codice per il calcolo e assicuratevi di ottenere tutti i risutltati richiesti. Restituisci la risposta in lingia italiana\"\"\""
try:
response = client.models.generate_content(
model=MODEL_ID,
contents=prompt,
config=types.GenerateContentConfig(
tools=[types.Tool(code_execution=types.ToolCodeExecution)]
)
)
display_code_execution_result(response)
finally: # Assicurati che il messaggio venga nascosto anche in caso di errore
nascondi_caricamento() # Nascondi il messaggio di caricamento e mostra messaggio di completamento
# Stampa informazioni sui token utilizzati
print("\n-------------------- Utilizzo dei Token --------------------")
print(f"Token prompt: {response.usage_metadata.prompt_token_count}")
print(f"Token risposta: {response.usage_metadata.candidates_token_count}")
print(f"Token totali: {response.usage_metadata.prompt_token_count + response.usage_metadata.candidates_token_count}")
# --- Widget ---
# Variabile per memorizzare il quesito
quesito = ""
# Titolo
titolo = widgets.HTML(value='<h2 style="float: left;">Descrizione del quesito da risolvere</h2>')
# Textarea per il quesito
textarea = widgets.Textarea(
placeholder='Inserisci il tuo quesito qui...',
layout=widgets.Layout(width='100%', height='400px')
)
# Pulsante Salva
salva_button = widgets.Button(description='Salva')
salva_button.on_click(salva_quesito)
# Pulsante Visualizza domanda
visualizza_domanda_button = widgets.Button(description='Visualizza domanda')
visualizza_domanda_button.on_click(visualizza_domanda)
# Pulsante Invia a Gemini
invia_button = widgets.Button(description='Invia a Gemini')
invia_button.on_click(invia_quesito)
# --- Visualizzazione ---
display(titolo)
display(textarea)
display(salva_button)
display(visualizza_domanda_button)
display(invia_button)
display(output_caricamento)
Output:




Caso d’uso 3: Ottimizzare la distribuzione di merci
In questo caso d’uso si impiega l’AI come uno strumento di ottimizzazione logistica. Si richiede all’intelligenza artificiale di tradurre i vincoli aziendali (capacità, domanda) e l’obiettivo (minimizzare i costi) in un modello matematico.
L’AI deve quindi scrivere ed eseguire codice Python, usando librerie scientifiche (SciPy, Matplotlib), per calcolare la soluzione ottimale. L’output non è solo un numero, ma un’analisi completa che include calcolo, programmazione e interpretazione visiva della soluzione.
Quesito di analisi
Ottimizzazione della Distribuzione con Visualizzazione grafica UTILIZZA L’INTERPRETE DI CODICE PYTHON E MOSTRA IL GRAFICO
Scenario:
Un’azienda di logistica deve pianificare la distribuzione giornaliera di merci da un magazzino centrale a due destinazioni (Cliente 1 e Cliente 2). Sono noti i seguenti dati:
- Capacità Totale Distribuibile: Massimo 300 unità di merce.
- Domanda Minima dei Clienti:
- Cliente 1: Almeno 100 unità
- Cliente 2: Almeno 50 unità
- Costo di Trasporto per Unità di Merce dal Magazzino a Ciascun Cliente:
- Al Cliente 1: 0.6 €/unità
- Al Cliente 2: 0.4 €/unità
Obiettivo:
Determinare la quantità di merce da spedire dal magazzino a ciascun cliente per minimizzare il costo totale di trasporto, soddisfacendo la domanda minima e rispettando la capacità totale. Visualizzare graficamente la regione ammissibile e la linea della funzione obiettivo ottima in un formato concettualmente simile all’esempio fornito.
Istruzioni:
Elabora il quesito Esegui un codice per effettuare i calcoli indicati Genera SEMPRE il GRAFICO Rispondi solo in base al risultato dell’esecuzione del codice
Consigli:
- Risolve il problema utilizzando scipy.optimize.linprog.
- Genera un GRAFICO matplotlib con che visualizza:
- Le rette che rappresentano i confini dei vincoli nel piano (x1, x2).
- La regione ammissibile (l’area che soddisfa tutti i vincoli di colore celeste chiaro).
- Almeno una linea della funzione obiettivo (idealmente quella ottima).
- Il punto che rappresenta la soluzione ottima.
- Etichette e chiare per gli assi, le rette e la soluzione.
- Legenda completa con tutti gli elementi
Richiesta:
Elabora il quesito, visualizza il grafico descrivi il risultato dell’esecuzione in modo strategico.
Output del processo di analisi
Quantità ottima da spedire al Cliente 1: 100 Quantità ottima da spedire al Cliente 2: 50 Costo totale minimo: 80

L’azienda di logistica dovrebbe spedire 100 unità di merce al Cliente 1 e 50 unità di merce al Cliente 2 per minimizzare il costo totale di trasporto. Il costo totale minimo è di 80 €. Il grafico mostra la regione ammissibile delimitata dai vincoli di capacità e domanda minima. La linea arancione rappresenta la funzione obiettivo ottima e il punto nero indica la soluzione ottima (100, 50).
Codice del modello di analisi
Lo stesso del Caso d’uso 1
# @title Risolvere un quesito azinedale con Code Execution
import ipywidgets as widgets
from IPython.display import display, Markdown, HTML
from IPython.display import display
from google.genai import types
import time
# Import Output from ipywidgets
from ipywidgets import Output # Importing Output class from ipywidgets
# --- Funzioni ---
def salva_quesito(b):
global quesito
quesito = textarea.value
with output_caricamento: # Redirect output to output_caricamento
display(HTML('<p style="font-size:16px;">Quesito salvato.</p>')) # Display as HTML
def visualizza_domanda(b):
display(Markdown(quesito))
# --- Funzioni aggiuntive ---
output_caricamento = Output() # Crea un'istanza di Output
def mostra_caricamento():
"""Visualizza il messaggio di caricamento."""
with output_caricamento: # Usa output_caricamento come contesto
display(HTML('<p style="font-size:16px;">Elaborazione in corso, attendere prego...</p>'))
output_caricamento.clear_output(wait=True) # Cancella l'output precedente
def nascondi_caricamento():
"""Nasconde il messaggio di caricamento e mostra messaggio di completamento."""
with output_caricamento:
output_caricamento.clear_output(wait=True)
display(HTML('<p style="font-size:16px;">Elaborazione completata.</p>'))
# --- Modifica della funzione invia_quesito ---
def invia_quesito(b):
global quesito
mostra_caricamento() # Mostra il messaggio di caricamento
prompt = f"\"{quesito}.\n Generate ed eseguite il codice per il calcolo e assicuratevi di ottenere tutti i risutltati richiesti. Restituisci la risposta in lingia italiana\"\"\""
try:
response = client.models.generate_content(
model=MODEL_ID,
contents=prompt,
config=types.GenerateContentConfig(
tools=[types.Tool(code_execution=types.ToolCodeExecution)]
)
)
display_code_execution_result(response)
finally: # Assicurati che il messaggio venga nascosto anche in caso di errore
nascondi_caricamento() # Nascondi il messaggio di caricamento e mostra messaggio di completamento
# Stampa informazioni sui token utilizzati
print("\n-------------------- Utilizzo dei Token --------------------")
print(f"Token prompt: {response.usage_metadata.prompt_token_count}")
print(f"Token risposta: {response.usage_metadata.candidates_token_count}")
print(f"Token totali: {response.usage_metadata.prompt_token_count + response.usage_metadata.candidates_token_count}")
# --- Widget ---
# Variabile per memorizzare il quesito
quesito = ""
# Titolo
titolo = widgets.HTML(value='<h2 style="float: left;">Descrizione del quesito da risolvere</h2>')
# Textarea per il quesito
textarea = widgets.Textarea(
placeholder='Inserisci il tuo quesito qui...',
layout=widgets.Layout(width='100%', height='400px')
)
# Pulsante Salva
salva_button = widgets.Button(description='Salva')
salva_button.on_click(salva_quesito)
# Pulsante Visualizza domanda
visualizza_domanda_button = widgets.Button(description='Visualizza domanda')
visualizza_domanda_button.on_click(visualizza_domanda)
# Pulsante Invia a Gemini
invia_button = widgets.Button(description='Invia a Gemini')
invia_button.on_click(invia_quesito)
# --- Visualizzazione ---
display(titolo)
display(textarea)
display(salva_button)
display(visualizza_domanda_button)
display(invia_button)
display(output_caricamento)






Caso d’uso 4: Ottimizzare la gestione dell’inventario
Questo caso d’uso impiega l’AI come analista della supply chain per ottimizzare la gestione dell’inventario in condizioni di incertezza e stagionalità.
Si chiede al modello LLM di modellare un sistema di scorte complesso, bilanciando costi, vincoli (spazio, budget) e il rischio di rottura di stock. Eseguendo codice Python con librerie statistiche (SciPy), l’AI applica modelli gestionali avanzati (EOQ, Punto di Riordino) per calcolare i livelli di scorta ottimali.
La soluzione richiesta è una policy di riordino dinamica, supportata da un’analisi dei costi e da una simulazione grafica dell’andamento delle scorte nel tempo. L’AI, non solo calcola, ma simula e definisce una strategia per la gestione dell’inventario.
Quesito di analisi
Quesito: Ottimizzazione gestione inventario con stagionalità
Scenario: MediFarm S.p.A., distributore farmaceutico, deve ottimizzare la gestione dell’inventario per due farmaci essenziali: “AntiFlu” e “CardioActive”. L’azienda deve bilanciare costi di mantenimento, costi di ordinazione e rischio di stock-out considerando la domanda stagionale.
Dati Operativi:
| Prodotto | Domanda Media Mensile | Costo Unitario (€) | Prezzo Vendita (€) | Costo Mantenimento (%/anno) |
|---|---|---|---|---|
| AntiFlu | 2.400 unità | 12 | 25 | 15% |
| CardioActive | 1.800 unità | 35 | 60 | 12% |
Vincoli Operativi:
- Spazio magazzino: ≤ 8.000 unità totali
- Budget ordinazioni mensili: ≤ 120.000 €
- Livello servizio minimo: 95% (max 5% di stock-out)
- Lead time fornitori: 15 giorni
- Variabilità domanda: ±20% (distribuzione normale)
Richiesta:
- Calcola il punto di riordino (ROP) ottimale per entrambi i prodotti
- Determina la quantità economica di ordinazione (EOQ)
- Analizza i costi totali di inventario annuali
- Visualizza graficamente l’evoluzione delle scorte nel tempo (6 mesi)
- Fornisci raccomandazioni strategiche per la gestione
Suggerimenti:
- Utilizza le formule EOQ classiche e i modelli di sicurezza stock
- Considera la stagionalità con coefficienti di variazione
- Usa matplotlib per visualizzare i livelli di stock nel tempo
- Applica scipy.stats per l’analisi probabilistica dello stock-out
Output del processo di analisi

Risultati e Raccomandazioni:
1. Punto di Riordino (ROP) Ottimale:
- AntiFlu: 1.758 unità
- CardioActive: 1.319 unità
2. Quantità Economica di Ordinazione (EOQ):
- AntiFlu: 1.265 unità
- CardioActive: 717 unità
3. Costi Totali di Inventario Annuali:
- AntiFlu: 34.8882 €
- CardioActive: 76.0771 €
4. Evoluzione delle Scorte nel Tempo (6 mesi):
- Le simulazioni mostrano le fluttuazioni dei livelli di inventario nel tempo, con ordini effettuati quando l’inventario raggiunge il ROP. I grafici visualizzano l’andamento e permettono di valutare la gestione. Si può vedere che il livello di CardioActive scende sotto lo stock di sicurezza, il che suggerisce che i parametri potrebbero necessitare di una messa a punto.
5. Raccomandazioni Strategiche per la Gestione dell’Inventario:
- Monitoraggio Continuo: Implementare un sistema di monitoraggio continuo dell’inventario per rilevare tempestivamente variazioni nella domanda e possibili stock-out.
- Revisione Periodica dei Parametri: Rivisitare periodicamente i parametri di EOQ e ROP (almeno trimestralmente) per adattarsi ai cambiamenti stagionali e alle fluttuazioni della domanda.
- Gestione della Variabilità: Analizzare più a fondo la variabilità della domanda. Se la variabilità stagionale è prevedibile, utilizzare modelli previsionali più sofisticati per anticipare i picchi di domanda.
- Ottimizzazione del Lead Time: Negoziare con i fornitori per ridurre il lead time, diminuendo così la necessità di scorte di sicurezza elevate.
- Analisi ABC: Eseguire un’analisi ABC per classificare i prodotti in base al valore e concentrare gli sforzi di gestione dell’inventario sui prodotti più importanti.
- Considerazione dei Vincoli: Tenere conto dei vincoli di spazio magazzino e budget. Se necessario, riconsiderare le quantità di ordinazione per rispettare tali vincoli, anche se ciò significa discostarsi leggermente dall’EOQ ideale. La quantità totale da tenere a magazzino, considerando che EOQ e safety stock è di circa 3.000 unita di AntiFlu e 1.100 di CardioActive. Quindi non c’è problema di spazio. Il costo totale di mantenimento delle scorte, che comprende anche il costo di ordinazione, è di circa 34.000 euro per AntiFlu e 22.000 euro per CardioActive, che è ben al di sotto del budget.
- Migliorare la previsione della domanda: Utilizzare tecniche di previsione della domanda più avanzate, come modelli di serie temporali o machine learning, per prevedere la domanda futura in modo più accurato. Ciò può aiutare a ridurre la necessità di scorte di sicurezza elevate e a migliorare il livello di servizio.
- Valutare l’implementazione di un sistema ERP: Un sistema ERP (Enterprise Resource Planning) può aiutare a automatizzare la gestione dell’inventario, migliorare la visibilità dell’inventario e supportare il processo decisionale.
Considerazioni aggiuntive:
- Stagionalità: La domanda stagionale è un fattore chiave. Sarebbe utile raccogliere dati storici sulla domanda mensile per entrambi i prodotti al fine di identificare modelli stagionali specifici. Questi modelli possono quindi essere incorporati nei calcoli di EOQ e ROP, utilizzando coefficienti di variazione stagionali.
- Stock-out: Il livello di servizio minimo del 95% implica che l’azienda è disposta ad accettare un rischio di stock-out del 5%. È importante monitorare attentamente il numero di stock-out e valutare se il livello di servizio attuale è adeguato. Se gli stock-out sono frequenti, potrebbe essere necessario aumentare le scorte di sicurezza.
Codice del modello di analisi
Lo stesso del Caso d’uso 1
# @title Risolvere un quesito azinedale con Code Execution
import ipywidgets as widgets
from IPython.display import display, Markdown, HTML
from IPython.display import display
from google.genai import types
import time
# Import Output from ipywidgets
from ipywidgets import Output # Importing Output class from ipywidgets
# --- Funzioni ---
def salva_quesito(b):
global quesito
quesito = textarea.value
with output_caricamento: # Redirect output to output_caricamento
display(HTML('<p style="font-size:16px;">Quesito salvato.</p>')) # Display as HTML
def visualizza_domanda(b):
display(Markdown(quesito))
# --- Funzioni aggiuntive ---
output_caricamento = Output() # Crea un'istanza di Output
def mostra_caricamento():
"""Visualizza il messaggio di caricamento."""
with output_caricamento: # Usa output_caricamento come contesto
display(HTML('<p style="font-size:16px;">Elaborazione in corso, attendere prego...</p>'))
output_caricamento.clear_output(wait=True) # Cancella l'output precedente
def nascondi_caricamento():
"""Nasconde il messaggio di caricamento e mostra messaggio di completamento."""
with output_caricamento:
output_caricamento.clear_output(wait=True)
display(HTML('<p style="font-size:16px;">Elaborazione completata.</p>'))
# --- Modifica della funzione invia_quesito ---
def invia_quesito(b):
global quesito
mostra_caricamento() # Mostra il messaggio di caricamento
prompt = f"\"{quesito}.\n Generate ed eseguite il codice per il calcolo e assicuratevi di ottenere tutti i risutltati richiesti. Restituisci la risposta in lingia italiana\"\"\""
try:
response = client.models.generate_content(
model=MODEL_ID,
contents=prompt,
config=types.GenerateContentConfig(
tools=[types.Tool(code_execution=types.ToolCodeExecution)]
)
)
display_code_execution_result(response)
finally: # Assicurati che il messaggio venga nascosto anche in caso di errore
nascondi_caricamento() # Nascondi il messaggio di caricamento e mostra messaggio di completamento
# Stampa informazioni sui token utilizzati
print("\n-------------------- Utilizzo dei Token --------------------")
print(f"Token prompt: {response.usage_metadata.prompt_token_count}")
print(f"Token risposta: {response.usage_metadata.candidates_token_count}")
print(f"Token totali: {response.usage_metadata.prompt_token_count + response.usage_metadata.candidates_token_count}")
# --- Widget ---
# Variabile per memorizzare il quesito
quesito = ""
# Titolo
titolo = widgets.HTML(value='<h2 style="float: left;">Descrizione del quesito da risolvere</h2>')
# Textarea per il quesito
textarea = widgets.Textarea(
placeholder='Inserisci il tuo quesito qui...',
layout=widgets.Layout(width='100%', height='400px')
)
# Pulsante Salva
salva_button = widgets.Button(description='Salva')
salva_button.on_click(salva_quesito)
# Pulsante Visualizza domanda
visualizza_domanda_button = widgets.Button(description='Visualizza domanda')
visualizza_domanda_button.on_click(visualizza_domanda)
# Pulsante Invia a Gemini
invia_button = widgets.Button(description='Invia a Gemini')
invia_button.on_click(invia_quesito)
# --- Visualizzazione ---
display(titolo)
display(textarea)
display(salva_button)
display(visualizza_domanda_button)
display(invia_button)
display(output_caricamento)








