I modelli di intelligenza artificiale generativa non sono strumenti magici, ma acceleratori. La loro efficacia dipende interamente dalla precisione con cui formuliamo le nostre aspettative. In assenza di requisiti chiari e ben definiti, questi strumenti non fanno altro che portare rapidamente a un cattivo risultato. Per questo motivo, l’uso dell’AI nella fase di estrazione dei requisiti richiede una comprensione raffinata degli obiettivi progettuali. È un processo che deve essere strutturato, validato e continuamente iterato.
L’approccio adottato qui si basa sull’utilizzo di strumenti generativi – in particolare ChatGPT e Gemini – per trasformare un documento di progettazione in un insieme strutturato di requisiti funzionali. Sebbene l’obiettivo sia semplice, la sua attuazione richiede rigore metodologico. Un prompt efficace è il primo passo: deve delimitare chiaramente il campo di analisi, richiedere un output strutturato e sollecitare l’identificazione dei possibili errori o insidie.
Il processo può essere sintetizzato in tre fasi: individuazione dei requisiti principali, conversione in user stories, e infine creazione degli stub corrispondenti. Nella prima fase, ChatGPT si dimostra efficace, soprattutto quando il documento di progettazione è complesso e richiede un’analisi veloce ma accurata. Il modello ha visto decine di migliaia di documenti simili e può riconoscere pattern ricorrenti, suggerire requisiti impliciti e individuare omissioni.
Nel caso specifico, ChatGPT ha prodotto un output strutturato e articolato in sei sezioni principali: database delle domande, modulo di selezione casuale, interfaccia utente, componente di valutazione, considerazioni future e requisiti generali. Ogni sezione è ulteriormente suddivisa in requisiti numerati, con un livello di dettaglio sufficiente a permettere l’assegnazione dei compiti. Ad esempio, viene richiesto lo sviluppo di un database SQL o NoSQL con campi specifici, un algoritmo per garantire la casualità nella selezione delle domande, e un’interfaccia utente accessibile e intuitiva.
Questa capacità di strutturazione non è banale. Richiede che il modello comprenda non solo il lessico tecnico, ma anche le implicazioni funzionali di ciascun elemento. Tuttavia, il rischio di allucinazioni – ovvero, l’invenzione di requisiti plausibili ma non necessari – rimane sempre presente. Per questo motivo, ogni output va sottoposto a una validazione da parte degli stakeholder o esperti di dominio. È una misura di sicurezza indispensabile. Anche quando il risultato sembra ottimo, è essenziale ottenere una seconda opinione.
In parallelo, è stata condotta un’analisi con Gemini, utilizzando lo stesso prompt. Il risultato, sebbene simile nei contenuti, presenta variazioni significative nella struttura e nella sintesi. Questo è un aspetto fondamentale da comprendere: modelli diversi generano risposte diverse, anche quando il punto di partenza è identico. Ciò dipende non solo dai dati su cui sono stati addestrati, ma anche dal modo in cui interpretano e priorizzano l’informazione. Alcuni modelli tendono alla concisione, altri offrono maggiore granularità. Né l’uno né l’altro è intrinsecamente migliore: entrambi offrono prospettive utili, ma incomplete.
Non bisogna lasciarsi ingannare dalla somiglia
Come Scegliere Domande Casuali per un Test: Un'Approccio con Flask e SQLite
Quando si sviluppa un'applicazione web che interagisce con un database, come nel caso di un quiz o di un test, è fondamentale comprendere come estrarre e visualizzare i dati in modo efficiente e flessibile. In questo contesto, una delle sfide più comuni è quella di selezionare un numero casuale di domande da un database, garantendo che siano uniche e che rappresentino una selezione casuale autentica.
In un'applicazione realizzata con Flask e SQLite, la gestione della connessione al database e l'estrazione dei dati avvengono attraverso un approccio modulare, dove ogni parte del processo è ben separata e riutilizzabile. In questo scenario, l'applicazione recupera delle domande memorizzate in un database SQLite e le visualizza dinamicamente all'utente. La struttura di base del codice include la connessione al database, l'estrazione dei dati tramite una classe di gestione delle domande, e la visualizzazione tramite un template HTML.
Il codice di base per la gestione della connessione al database si presenta come segue:
In questo esempio, il file App.py avvia un'app Flask con un'unica route (/) che gestisce la visualizzazione delle domande. Il percorso del database (db_path) è definito come 'data/questions.db'. La connessione al database avviene utilizzando la classe DatabaseConnection, che gestisce la connessione tramite un contesto di tipo with, garantendo che la connessione venga chiusa correttamente dopo l'uso. Le domande vengono quindi recuperate dalla classe Questions, che si occupa di estrarre i dati attraverso il metodo fetch_data(). Infine, i dati vengono passati al template HTML index.html, che visualizzerà le domande recuperate.
Questo approccio, sebbene semplice, fornisce una base solida per costruire un'applicazione che possa essere facilmente estesa e testata. L'uso di classi e metodi per separare le preoccupazioni, come la gestione della connessione al database e la logica di recupero dei dati, rende il codice più manutenibile e riutilizzabile.
Tuttavia, la visualizzazione di tutte le domande in modo statico non è sufficiente per simulare un'esperienza di test interattiva. L'obiettivo successivo è quello di estrarre le domande in modo casuale, una alla volta, simulando un'esperienza di esame. La sfida qui è estrarre un numero specifico di domande in modo che siano uniche e casuali, per esempio 35 domande da un set di domande più ampio.
Per ottenere questo, possiamo definire una nuova funzione nella classe Questions che seleziona un sottoinsieme casuale di domande dal database. La funzione può essere progettata in questo modo:
Questa funzione esegue il compito di selezionare 35 domande casuali. Inizialmente, controlla che ci siano abbastanza domande nel database. Se il numero di domande è inferiore a 35, restituisce un messaggio di errore. Altrimenti, seleziona in modo casuale gli ID delle domande e li aggiunge a un set, che garantisce l'unicità delle domande. Una volta che il set contiene 35 domande, queste vengono restituite come una lista.
L'implementazione di questa funzione richiede l'aggiunta di un metodo get_all_questions() che recupera tutte le domande dal database. Il metodo get_all_questions() può essere definito come segue:
In questo caso, il metodo esegue una query SQL per selezionare tutte le domande dalla tabella questions. Il risultato viene restituito come una lista di tuple, ciascuna rappresentante una domanda.
Una volta che la funzione get_question_set() è pronta, è possibile modificarla nel file run.py in modo che l'applicazione utilizzi i 35 ID delle domande casuali anziché tutte le domande:
In questo modo, l'applicazione estrae una selezione casuale di domande, che può essere utilizzata per generare una simulazione di test.
Questa metodologia offre vari vantaggi. Permette di personalizzare facilmente il numero di domande, di aggiungere logiche più sofisticate per la selezione delle domande (ad esempio, basate su categorie o difficoltà), e di separare la logica di selezione delle domande dalla logica di presentazione. Inoltre, l'uso di un set per garantire l'unicità delle domande è particolarmente utile per evitare duplicazioni durante la selezione casuale.
Un aspetto importante da considerare è la gestione della risposta dell'utente. In un'applicazione di test, l'utente interagirà con le domande, selezionando le risposte. Sebbene la selezione delle domande sia una parte cruciale, è altrettanto importante sviluppare una logica che permetta di memorizzare le risposte fornite e di calcolare il punteggio in base alle risposte corrette. Questo richiede l'integrazione di un sistema di gestione delle sessioni o di una struttura che memorizzi le risposte e confronti quelle selezionate dall'utente con quelle corrette presenti nel database.
In sintesi, la gestione efficiente della selezione casuale delle domande è una parte fondamentale della progettazione di un'applicazione di test. L'approccio descritto offre una soluzione scalabile e flessibile, che può essere facilmente estesa con ulteriori funzionalità, come il tracciamento delle risposte degli utenti e la generazione di report sui risultati del test.
Come creare un pulsante per eliminare il cookie e ricaricare la pagina in modo semplice con JavaScript
Nel contesto della gestione delle sessioni web, può capitare che si desideri offrire agli utenti la possibilità di cancellare rapidamente i cookie e ricaricare la pagina per testare o iniziare un nuovo ciclo di interazione. Creare un pulsante che esegua questa funzione è relativamente semplice e può essere realizzato con poche righe di codice JavaScript. Questa soluzione si integra facilmente in una pagina HTML, senza la necessità di librerie esterne o framework complessi.
Per iniziare, bisogna scrivere un codice HTML che includa un pulsante. Il codice del pulsante è il seguente:
L'elemento HTML <button> è associato a una funzione JavaScript tramite l'attributo onclick. Quando l'utente clicca sul pulsante, la funzione deleteCookieAndRefresh() verrà eseguita.
Ora, per quanto riguarda il codice JavaScript che deve essere eseguito quando il pulsante viene cliccato, esso deve eliminare il cookie e ricaricare la pagina. Qui viene utilizzato un semplice metodo per farlo:
La funzione deleteCookieAndRefresh() esegue due operazioni principali:
-
Eliminazione del cookie: Utilizza
document.cookieper modificare il valore del cookie, impostando una data di scadenza nel passato. In questo modo, il browser riconosce che il cookie deve essere eliminato. In questo esempio, il cookie che stiamo cercando di eliminare è chiamatosession_id, ma potrebbe essere qualsiasi cookie definito precedentemente. La parte del codice che imposta l'espirazione del cookie è fondamentale per garantirne l'eliminazione. -
Ricarica della pagina: Dopo aver eliminato il cookie, la funzione chiama
window.location.reload(), che forza il browser a ricaricare la pagina attuale. Questo è utile quando si desidera resettare lo stato della pagina, in modo che eventuali modifiche derivanti dalla presenza del cookie vengano azzerate.
Questa soluzione è semplice ma efficace, e può essere facilmente adattata ad altri casi d'uso. È possibile personalizzare il nome del cookie, il percorso, o altre opzioni di configurazione a seconda delle esigenze specifiche del progetto.
Un aspetto importante da considerare è che questo metodo funziona solo per i cookie che sono stati impostati dallo stesso dominio. Se il cookie è stato impostato su un dominio diverso o con attributi di sicurezza come HttpOnly, potrebbe essere necessario un approccio differente. Inoltre, è sempre buona prassi testare il comportamento in vari browser per garantire la compatibilità.
In alcuni casi, potrebbe essere utile anche aggiungere una conferma all'utente prima di eseguire l'eliminazione del cookie, in modo da evitare cancellazioni accidentali. Tuttavia, in scenari di test o applicazioni con flussi di lavoro veloci, la soluzione proposta è pratica e diretta.
Anche se l'eliminazione dei cookie non è una pratica invasiva, è sempre consigliato fornire agli utenti una chiara informazione su cosa stia accadendo, soprattutto in contesti dove i dati personali o le preferenze degli utenti sono coinvolti. Una trasparenza maggiore sulle operazioni che si stanno eseguendo contribuisce a migliorare la fiducia e la comprensione da parte degli utenti.
Come Funziona l'Intelligenza Artificiale Generativa nel Codice?
Nel mondo della musica, i musicisti raramente lavorano isolati. Come fanno a sapere se stanno eseguendo correttamente un brano? La risposta risiede nel feedback: condividono la loro esecuzione con altri, cercando di ottenere una valutazione. Se l'insegnante annuisce, significa che stanno suonando correttamente. Se il pubblico applaude, il musicista sa che la performance è riuscita. Ma se il pubblico lancia pomodori, allora è chiaro che qualcosa è andato storto e necessita di correzione. Questo processo di valutazione e feedback è fondamentale per la crescita continua.
Il funzionamento dell'intelligenza artificiale generativa nel coding segue una logica simile. Un modello di AI analizza centinaia di migliaia, se non milioni, di righe di codice. Esamina il codice e cerca dei pattern che possano essere utilizzati per creare software funzionante. Dopo una formazione adeguata, il modello sviluppa una sorta di comprensione di come dovrebbe apparire il codice: una visione di ciò che è un software corretto. Inizialmente, si parte da dati di addestramento creati attraverso il codice sorgente esistente in vari linguaggi, che vengono alimentati nel modello. Questo modello viene valutato e strutturato in vari strati che cercano specifici parametri. Un primo strato verifica la sintassi, un altro cerca parole chiave e come vengono usate, e infine uno strato finale determina se "questo è probabilmente un codice corretto e funzionante".
Esistono numerosi algoritmi di machine learning che utilizzano questo modello per passare attraverso questi strati e giungere a delle conclusioni. Il risultato che l'AI genera è una previsione di come dovrebbe apparire il nuovo software. Il modello fornisce un output che rappresenta la previsione più probabile per il codice che si sta cercando. Il programmatore, a questo punto, entra nel processo di valutazione. Se accetta il suggerimento, il feedback ritorna al modello (in molti casi, ma non sempre) come previsione corretta. Se invece lo rifiuta, anche questo viene tracciato. Grazie a questo continuo scambio di feedback, lo strumento impara come dovrebbe apparire un buon codice.
L'interazione tra sviluppatore e AI crea un potente ciclo di miglioramento continuo. Questo processo è simile a un loop di feedback che, anziché essere statico, cresce dinamicamente con l'esperienza. Si parte da un input da parte dello sviluppatore—che può essere codice sorgente, commenti o requisiti in linguaggio naturale—per poi passare all'analisi del contesto, la previsione del codice, e infine al feedback da parte dello sviluppatore, che può accettare, modificare o rifiutare i suggerimenti generati. Questo sistema di adattamento del modello porta ad un miglioramento costante delle future proposte di codice.
Il concetto di AI generativa si fonda sul tentativo di prevedere ciò che è più probabile che sia una corretta esecuzione di qualcosa di nuovo, sulla base dei dati su cui è stato addestrato. Questo rende i modelli probabilistici, a differenza di quelli deterministici. Un sistema deterministico, infatti, restituirà sempre lo stesso risultato se fornito lo stesso input, come ad esempio una calcolatrice tradizionale che darà sempre 4 per l'operazione 2 + 2. Al contrario, i modelli di AI generativa non sono deterministici per progettazione. Il loro obiettivo è creare qualcosa di nuovo piuttosto che riprodurre qualcosa che è già stato scritto. Ciò significa che, quando si utilizza un sistema di AI generativa, è possibile ottenere risposte differenti anche con lo stesso input, e questo è fatto deliberatamente per stimolare la creatività nell'output.
L'intelligenza artificiale generativa, quindi, non si limita a riprodurre codici esistenti, ma cerca di innovare, generando nuove soluzioni a problemi complessi, spesso introducendo approcci che un programmatore umano potrebbe non aver preso in considerazione. Questo processo di "creatività assistita" ha il potenziale di velocizzare significativamente lo sviluppo software, esponendo lo sviluppatore a nuovi modelli e tecniche che potrebbero arricchire il suo repertorio.
Un altro aspetto fondamentale di questi sistemi è il cosiddetto "large language model" (LLM), che rappresenta la base delle tecnologie più avanzate di AI generativa. Un LLM è un tipo di rete neurale che è in grado di elaborare e generare testo in modo simile agli esseri umani, grazie a un addestramento su enormi dataset di testo. Questo gli permette di apprendere i modelli linguistici umani e di tradurre, scrivere o rispondere a domande con un testo che sembri naturale. Gli LLM si basano sul modello Transformer, che ha superato i limiti delle reti neurali ricorrenti (RNN) e delle reti LSTM, permettendo un'elaborazione parallela e una scalabilità che ha aperto la strada a applicazioni come chatbot, traduzione automatica e generazione di contenuti. La chiave del Transformer è la capacità di analizzare le relazioni tra le parole, non solo nel loro ordine, ma anche nel contesto in cui appaiono, grazie a meccanismi di autoattenzione che migliorano l'efficienza dell'addestramento.
I modelli Transformer elaborano i dati in sequenza, considerando ogni parola come un’entità separata che viene trasformata in numeri, i quali vengono successivamente analizzati per determinare le relazioni tra le parole stesse. Questo processo aiuta il modello a comprendere meglio il significato globale della frase o del testo, migliorando la capacità di tradurre, generare o classificare il contenuto.
La combinazione di questi avanzamenti tecnologici nel campo dell'AI generativa e degli LLM ha reso possibile la creazione di strumenti di coding che possono non solo velocizzare il processo di sviluppo, ma anche suggerire soluzioni nuove, stimolando la creatività degli sviluppatori e aprendoli a nuove modalità di pensiero.
Come funziona un certificato TLS e perché è cruciale per il tuo sito web
Gli effetti dell'adsorbimento molecolare sugli eccitoni nei nanotubi di carbonio sospesi nell'aria
Come funzionano i nanotubi di carbonio e il loro impiego nelle applicazioni ad alte prestazioni

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский