Anti-pattern FinOps: cosa (non) fare per avere più budget per innovare
22 Ottobre 2025 - 9 min. read
Andrea Pusineri
& Nicola Ferrari
& Nicola Ferrari
Con il crescente impiego dell’intelligenza artificiale e con l’avvento di nuove interfacce uomo-macchina, diventa sempre più importante esplorare le nuove tecnologie ed impiegarle al meglio per trarne la massima utilità ed il massimo valore.Uno degli impieghi dell’intelligenza artificiale e del deep learning più orientato all’utente finale è certamente la realizzazione di nuovi tipi di interfacce uomo-macchina basate sul riconoscimento degli intenti, sia su messaggi di testo sia da interazioni vocali.Per avere alcuni esempi di questa tipologia di applicazioni basta pensare agli assistenti vocali sugli smartphone, a quelli domestici come ad esempio Amazon Alexa e a tutti i servizi con cui è possibile interagire via chat.In questo articolo vi mostreremo come realizzare uno Slack bot usando Amazon Lex.In ambito informatico, riconoscimento vocale e comprensione del linguaggio naturale sono tra i problemi più complessi affrontati, tanto da necessitare algoritmi di deep learning molto complessi. Tali algoritmi richiedono enormi quantità di dati per essere addestrati efficacemente, oltre ad apposite infrastrutture di calcolo dai costi particolarmente elevati. Amazon Lex rende queste tecnologie accessibili a tutti aprendo la strada verso una categoria completamente nuova di prodotti.Amazon Lex è un servizio per la creazione di interfacce di comunicazione tramite voce e testo realizzato per essere sufficientemente generico da essere impiegato in qualsiasi applicazione. Offre funzionalità avanzate di apprendimento per il riconoscimento vocale e la dettatura, nonché per il riconoscimento del linguaggio naturale e per la comprensione di testi, consentendo la creazione di applicazioni con una user-experience coinvolgente, basata su conversazioni realistiche. Con Amazon Lex, le stesse tecnologie di apprendimento approfondito su cui si basa Amazon Alexa sono a disposizione di tutti gli sviluppatori, consentendo così la creazione di bot di conversazione (“chatbot”) sofisticati e naturali in modo semplice, veloce e a basso effort.Lex consente una facile integrazione con Facebook Messenger, Slack e Twilio SMS. Attualmente, Lex supporta solamente la lingua Inglese, ma è possibile realizzare bot in altre lingue costruendo una soluzione ad-hoc che sfrutti Amazon Translate.Prima di entrare nei dettagli di implementazione occorre definire il gergo ed i concetti fondamentali di Lex.Un bot realizzato mediante Lex si compone sostanzialmente di 3 parti:
L’infrastruttura è molto semplice e si compone di soli servizi gestiti.Il trigger tra Lex e Lambda è completamente gestito da AWS; per configurarlo basta indicare l’arn della funzione nel modello del bot, ed abbinarlo all’intento desiderato.Anche i canali supportati non richiedono il provisioning di risorse all’interno dell’account AWS. La gestione di eventuali endpoint o canali di comunicazioni con servizi esterni sono gestiti automaticamente da Lex.{ "metadata": { "schemaVersion": "1.0", "importType": "LEX", "importFormat": "JSON" }, "resource": { "name": "TestBot", "version": "1", "intents": [ { "name": "greetings", "version": "2", "fulfillmentActivity": { "type": "ReturnIntent" }, "sampleUtterances": [ "greet me", "please greet me", "greetings", "make the greetings for me", "would you greet me please", "would you greet me" ], "slots": [], "conclusionStatement": { "messages": [ { "groupNumber": 1, "contentType": "PlainText", "content": "Hello" }, { "groupNumber": 1, "contentType": "PlainText", "content": "Greetings" }, { "groupNumber": 1, "contentType": "PlainText", "content": "Hi :-)" } ] } } ], "voiceId": "Salli", "childDirected": false, "locale": "en-US", "idleSessionTTLInSeconds": 300, "clarificationPrompt": { "messages": [ { "contentType": "PlainText", "content": "Sorry, can you please repeat that?" } ], "maxAttempts": 5 }, "abortStatement": { "messages": [ { "contentType": "PlainText", "content": "Sorry, I could not understand. Goodbye." } ] } } }A questo punto, basta configurare un canale, ad esempio Slack, per poi pubblicare e testare il bot.Per maggiori informazioni su come configurare un canale qui è disponibile una guida passo a passo.Che ci crediate o no, questo modello è del tutto sufficiente a produrre un bot funzionante :)
{ "metadata": { "schemaVersion": "1.0", "importType": "LEX", "importFormat": "JSON" }, "resource": { "name": "TestBot", "version": "2", "intents": [ { "name": "factorial", "version": "4", "fulfillmentActivity": { "codeHook": { "uri": "arn:aws:lambda:eu-west-1:XXXXXXXXXXXX:function:besharp-testbot", "messageVersion": "1.0" }, "type": "CodeHook" }, "sampleUtterances": [ "{n} factorial", "compute {n} factorial", "please calc {n} factorial", "factorial of {n}", "what is the factorial of {n}", "what is {n}" ], "slots": [ { "sampleUtterances": [], "slotType": "AMAZON.NUMBER", "slotConstraint": "Required", "valueElicitationPrompt": { "messages": [ { "contentType": "PlainText", "content": "What is the input number?" } ], "maxAttempts": 2 }, "priority": 1, "name": "n" } ] }, { "name": "greetings", "version": "3", "fulfillmentActivity": { "type": "ReturnIntent" }, "sampleUtterances": [ "greet me", "please greet me", "greetings", "make the greetings for me", "would you greet me please", "would you greet me", "hello", "hi" ], "slots": [], "followUpPrompt": { "prompt": { "messages": [ { "groupNumber": 1, "contentType": "PlainText", "content": "Hello" }, { "groupNumber": 1, "contentType": "PlainText", "content": "Greetings" }, { "groupNumber": 1, "contentType": "PlainText", "content": "Hi :-)" } ], "maxAttempts": 3 }, "rejectionStatement": { "messages": [ { "groupNumber": 1, "contentType": "PlainText", "content": "Yes, yes, whatever" } ] } } } ], "voiceId": "Salli", "childDirected": false, "locale": "en-US", "idleSessionTTLInSeconds": 300, "clarificationPrompt": { "messages": [ { "contentType": "PlainText", "content": "Sorry, can you please repeat that?" } ], "maxAttempts": 5 }, "abortStatement": { "messages": [ { "contentType": "PlainText", "content": "Sorry, I could not understand. Goodbye." } ] } } }
import json import datetime import time import os import dateutil.parser import logging logger = logging.getLogger() logger.setLevel(logging.DEBUG) # --- Helpers that build all of the responses --- def elicit_slot(session_attributes, intent_name, slots, slot_to_elicit, message): return { 'sessionAttributes': session_attributes, 'dialogAction': { 'type': 'ElicitSlot', 'intentName': intent_name, 'slots': slots, 'slotToElicit': slot_to_elicit, 'message': message } } def confirm_intent(session_attributes, intent_name, slots, message): return { 'sessionAttributes': session_attributes, 'dialogAction': { 'type': 'ConfirmIntent', 'intentName': intent_name, 'slots': slots, 'message': message } } def close(session_attributes, fulfillment_state, message): response = { 'sessionAttributes': session_attributes, 'dialogAction': { 'type': 'Close', 'fulfillmentState': fulfillment_state, 'message': message } } return response def delegate(session_attributes, slots): return { 'sessionAttributes': session_attributes, 'dialogAction': { 'type': 'Delegate', 'slots': slots } } # --- Helper Functions --- def safe_int(n): """ Safely convert n value to int. """ if n is not None: return int(n) return n def try_ex(func): """ Call passed in function in try block. If KeyError is encountered return None. This function is intended to be used to safely access dictionary. Note that this function would have negative impact on performance. """ try: return func() except KeyError: return None """ --- Functions that control the bot's behavior --- """ def factorial(intent_request): n = safe_int(try_ex(lambda: intent_request['currentIntent']['slots']['n'])) return close( {}, 'Fulfilled', { 'contentType': 'PlainText', 'content': 'The result is ' + str(fatt(n)) } ) def fatt(n): r = 1 for i in range(1, n + 1): r = r * i return r # --- Intents --- def dispatch(intent_request): """ Called when the user specifies an intent for this bot. """ logger.debug('dispatch userId={}, intentName={}'.format(intent_request['userId'], intent_request['currentIntent']['name'])) intent_name = intent_request['currentIntent']['name'] # Dispatch to your bot's intent handlers if intent_name == 'factorial': return factorial(intent_request) raise Exception('Intent with name ' + intent_name + ' not supported') # --- Main handler --- def lambda_handler(event, context): """ Route the incoming request based on intent. The JSON body of the request is provided in the event slot. """ # By default, treat the user request as coming from the America/New_York time zone. os.environ['TZ'] = 'America/New_York' time.tzset() logger.debug('event.bot.name={}'.format(event['bot']['name'])) return dispatch(event)Anche in questo caso basta pubblicare la lambda e poi aggiornare il modello del bot precedente per poter subito utilizzare le nuove capacità del bot.Come potete notare, una volta appresi i concetti chiave, la realizzazione di un bot è piuttosto semplice ed assistita dai servizi di Amazon ed AWS.Un esempio di conversazione:
In questo articolo abbiamo trattato i concetti fondamentali che stanno alla base del funzionamento di Lex. Abbiamo poi analizzato l’anatomia di un bot semplice e funzionante, il primo passo per la realizzazione di bot più complessi.Restate sintonizzati per altri articoli su Lex e per tutte le ultime novità!