5. Risolvere i tre problemi con ChatGPT
5.1. Introduzione
Ecco una prima schermata di una sessione di ChatGPT:
![]() ![]() |
- In [1-3], i tre problemi sottoposti a ChatGPT;
- In [4], l'URL di ChatGPT;
- In [5], la versione di ChatGPT utilizzata;
ChatGPT è un prodotto di OpenAI disponibile all'URL [https://chatgpt.com/]. Per visualizzare una cronologia delle sessioni di domande e risposte come quella sopra riportata, è necessario creare un account. Inoltre, come tutte le altre IA testate, ChatGPT limita il numero di domande che è possibile porre e il numero di file che è possibile caricare. Quando si raggiunge questo limite, la sessione termina e viene offerta la possibilità di continuare in un secondo momento. I limiti imposti da ChatGPT vengono raggiunti molto rapidamente. Per creare questo tutorial, ho dovuto acquistare un abbonamento a pagamento di un mese.
L'interfaccia di ChatGPT è la seguente:
![]() |
- In [1], per allegare file alla domanda posta;
- Al punto [2], la domanda posta;
- Al punto [3], per eseguire l'IA;
5.2. Problema 1
La domanda per ChatGPT:
![]() |
ChatGPT risponde correttamente.
5.3. Problema 2
Si tratta di calcolare l'imposta utilizzando il PDF. A dire il vero, useremo il PDF generato da Gemini, che corregge gli errori presenti nel PDF originale.
![]() |
- In [1] abbiamo fornito il PDF generato da Gemini;
- In [2], abbiamo aggiunto il test unitario attraverso il quale Gemini ha dimostrato la sua superiorità:
Eseguiamo ChatGPT. Ci vogliono circa 3 minuti per generare la risposta. A differenza di Gemini, fornisce un link funzionante per recuperare lo script generato. Lo carichiamo in PyCharm:
![]() |
Lo script [chatGPT1] funziona al primo tentativo. Non c'è storia: su questo problema, ChatGPT ha superato Gemini.
Lo script [chatGPT1] fornito da ChatGPT è il seguente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | |
5.4. Problema 3
Ora chiediamo a ChatGPT di cercare su Internet le regole di calcolo delle imposte:
![]() |
Questa volta non forniamo il PDF contenente le regole di calcolo da seguire. Forniamo solo le nostre istruzioni nel file di testo. Si noti che questo file di testo ora contiene 12 test unitari dopo aver aggiunto, agli 11 test iniziali, quello utilizzato da Gemini per dimostrare che il mio PDF iniziale era errato.
ChatGPT risponde in 8 minuti, fornendo un link per scaricare lo script generato. Una volta caricato in PyCharm, questo script supera tutti e 12 i test. Quindi, per entrambi i problemi posti, ChatGPT ha dato le risposte giuste al primo tentativo, superando così Gemini.
ChatGPT fornisce le sue fonti nella risposta:
![]() |
Non c'è altro da dire: è un lavoro ben fatto.
Ora possiamo chiedergli, proprio come abbiamo fatto con Gemini, di generare un PDF per gli studenti.
![]() |
La risposta di ChatGPT è arrivata dopo diversi scambi perché il PDF generato utilizzava un font che sostituiva i caratteri con dei quadrati. Ma alla fine ha generato il PDF. Lo condivido perché presenta regole diverse rispetto al PDF di Gemini e mi chiedevo quale fosse quello corretto. Analizziamolo.
![]() |
![]() |
![]() | ![]() |
![]() |
La differenza rispetto al PDF di Gemini sta nel modo in cui viene calcolato lo sconto. Le due IA adottano approcci diversi. Gemini aveva scritto:
![]() |
![]() |
![]() |
Le due IA hanno due approcci diversi. Qual è quello giusto?
5.5. Problema 4
Chiederemo a ChatGPT di utilizzare il suo PDF per calcolare l'imposta:
![]() | ![]() |
Come nei casi precedenti, genera uno script Python che funziona al primo tentativo. Avevamo aggiunto un test aggiuntivo alle istruzioni:
Tutti i 13 test sono stati superati con successo.
5.6. Torna a Gemini
Torniamo ora a Gemini, al quale presenteremo il PDF di ChatGPT. Poiché le regole implementate in questo PDF differiscono da quelle del PDF di Gemini, ci chiediamo cosa succederà:
![]() |
Gemini ha prima generato uno script Python che non ha superato alcuni test. Gli abbiamo presentato i log:
Domanda 2
![]() |
Domanda 3
Ci sono ancora degli errori. Continuiamo.
![]() |
Domanda 4
Si verificano ancora errori durante l'esecuzione:
![]() |
Questa volta è corretto.
Ci incuriosisce ancora il fatto che, anche con PDF che hanno regole di calcolo piuttosto diverse, entrambe le IA generino risultati corretti.
Poniamo a Gemini la seguente domanda:
![]() |
La domanda completa è la seguente:
La risposta di Gemini è inequivocabile:
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
5.7. Cosa ne pensa ChatGPT?
Poniamo a ChatGPT la stessa domanda che abbiamo posto a Gemini.
![]() |
La risposta di ChatGPT è la seguente:
![]() |
![]() |
Quindi, ChatGPT suggerisce un test unitario per scegliere tra i due metodi. Duplichiamo:
- Lo script [gemini3] generato da Gemini utilizzando il suo PDF [Il problema secondo Gemini] come fonte viene duplicato nello script [gemini4];
- Lo script [chatGPT3] generato da ChatGPT utilizzando il proprio PDF [Il problema secondo ChatGPT] come fonte viene duplicato nello script [chatGPT4];
![]() | ![]() |
Inoltre, aggiungiamo il test unitario proposto da ChatGPT a ciascuno degli script [gemini4, chatGPT4] per distinguere tra le due IA.
L'esecuzione di [gemini4] produce i seguenti risultati:
C:\Data\st-2025\dev\python\code\python-flask-2025-cours\.venv\Scripts\python.exe "C:/Program Files/JetBrains/PyCharm 2025.2.1.1/plugins/python-ce/helpers/pycharm/_jb_unittest_runner.py" --path "C:\Data\st-2025\dev\python\code\python-flask-2025-cours\outils ia\gemini\gemini4.py"
Testing started at 17:45 ...
Launching unittests with arguments python -m unittest C:\Data\st-2025\dev\python\code\python-flask-2025-cours\outils ia\gemini\gemini4.py in C:\Data\st-2025\dev\python\code\python-flask-2025-cours
SubTest failure: Traceback (most recent call last):
File "C:\Program Files\Python313\Lib\unittest\case.py", line 58, in testPartExecutor
yield
File "C:\Program Files\Python313\Lib\unittest\case.py", line 556, in subTest
yield
File "C:\Data\st-2025\dev\python\code\python-flask-2025-cours\outils ia\gemini\gemini4.py", line 234, in test_cas_verifies_simulateur_officiel
self.assertAlmostEqual(calcul_impot, attendu_impot, delta=1, msg="Échec sur le montant de l'impôt")
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 2669 != 2270 within 1 delta (399 difference) : Échec sur le montant de l'impôt
Ran 1 test in 0.010s
FAILED (failures=1)
One or more subtests failed
Failed subtests list: [Test 'test12' avec entrée (2, 0, 43333)]
Process finished with exit code 1
Quindi Gemini non supera il test aggiunto da ChatGPT.
L'esecuzione di [chatGPT4] produce i seguenti risultati:
C:\Data\st-2025\dev\python\code\python-flask-2025-cours\.venv\Scripts\python.exe "C:\Data\st-2025\dev\python\code\python-flask-2025-cours\outils ia\chatGPT\chatGPT4.py"
Test (2, 2, 55555) -> obtenu (impôt=2814, décote=0, réduction=0) | attendu (2815, 0, 0) | OK
Test (2, 2, 50000) -> obtenu (impôt=1384, décote=384, réduction=347) | attendu (1385, 384, 346) | OK
Test (2, 3, 50000) -> obtenu (impôt=0, décote=721, réduction=0) | attendu (0, 720, 0) | OK
Test (1, 2, 100000) -> obtenu (impôt=19884, décote=0, réduction=0) | attendu (19884, 0, 0) | OK
Test (1, 3, 100000) -> obtenu (impôt=16782, décote=0, réduction=0) | attendu (16782, 0, 0) | OK
Test (2, 3, 100000) -> obtenu (impôt=9200, décote=0, réduction=0) | attendu (9200, 0, 0) | OK
Test (2, 5, 100000) -> obtenu (impôt=4230, décote=0, réduction=0) | attendu (4230, 0, 0) | OK
Test (1, 0, 100000) -> obtenu (impôt=22986, décote=0, réduction=0) | attendu (22986, 0, 0) | OK
Test (2, 2, 30000) -> obtenu (impôt=0, décote=0, réduction=0) | attendu (0, 0, 0) | OK
Test (1, 0, 200000) -> obtenu (impôt=64210, décote=0, réduction=0) | attendu (64211, 0, 0) | OK
Test (2, 3, 200000) -> obtenu (impôt=42842, décote=0, réduction=0) | attendu (42843, 0, 0) | OK
Test (2, 2, 49500) -> obtenu (impôt=1296, décote=431, réduction=325) | attendu (1297, 431, 324) | OK
Test (1, 0, 18535) -> obtenu (impôt=359, décote=491, réduction=90) | attendu (359, 491, 90) | OK
Test (2, 0, 43333) -> obtenu (impôt=2268, décote=0, réduction=401) | attendu (2270, 0, 400) | ECHEC
Détails tolérance ±1€ : impôt ok? False, décote ok? True, réduction ok? True
Résultat global : AU MOINS UN TEST ÉCHOUE ❌
Process finished with exit code 0
Anche ChatGPT fallisce il test aggiunto, ma non per gli stessi motivi di Gemini. ChatGPT ha trovato i risultati corretti, ma con uno scarto di 2 euro invece dell'1 euro richiesto.
Quindi, d'ora in poi, useremo il PDF generato da ChatGPT con le seguenti IA. Vale la pena notare che è proprio a causa della mancanza di test unitari nelle mie istruzioni che entrambe le IA hanno superato i primi test. Da qui, in questo specifico esempio, l'importanza di includere test unitari per i casi limite nel calcolo delle imposte. Dato che è piuttosto difficile ideare questi test da soli, chiederemo alle IA di aggiungerli autonomamente.
5.8. Problema 3 con i test unitari generati dalle IA
I risultati ottenuti con Gemini e ChatGPT lasciano spazio a dubbi. Le IA hanno trovato una soluzione generale che supera ogni test immaginabile, o hanno trovato una soluzione che supera solo i test richiesti? Ricominceremo da capo con una soluzione senza PDF per costringere le IA a collegarsi a Internet e cercare le informazioni di cui hanno bisogno. E modificheremo le nostre istruzioni come segue:
![]() |
Il file di testo [instructionsSansPDF4.txt] contiene già 14 test richiesti. A questi test aggiungiamo le seguenti istruzioni:
7 - tu ajouteras autant de tests unitaires que nécessaires pour vérifier les cas limites du calcul de l'impôt.
Pour le code tu complèteras le script suivant auquel tu auras rajouté tes propres tests.
# =========================
# Tests unitaires (tolérance de ±1 €)
# =========================
TESTS = [
# (adultes, enfants, revenus) -> (impot, decote, reduction)
((2, 2, 55555), (2815, 0, 0)),
((2, 2, 50000), (1385, 384, 346)),
((2, 3, 50000), (0, 720, 0)),
((1, 2, 100000), (19884, 0, 0)),
((1, 3, 100000), (16782, 0, 0)),
((2, 3, 100000), (9200, 0, 0)),
((2, 5, 100000), (4230, 0, 0)),
((1, 0, 100000), (22986, 0, 0)),
((2, 2, 30000), (0, 0, 0)),
((1, 0, 200000), (64211, 0, 0)),
((2, 3, 200000), (42843, 0, 0)),
((2, 2, 49500), (1297, 431, 324)),
((1, 0, 18535), (359, 491, 90)),
((2, 0, 43333), (2270, 0, 400)),
]
def _ok(a, b, tol=1):
return abs(a - b) <= tol
def run_tests(verbose: bool = True) -> bool:
all_ok = True
for (params, expected) in TESTS:
a, e, r = params
exp_impot, exp_decote, exp_reduc = expected
res = calcul_impot_2019(a, e, r)
ok_impot = _ok(res.impot, exp_impot)
ok_decote = _ok(res.decote, exp_decote)
ok_reduc = _ok(res.reduction, exp_reduc)
test_ok = ok_impot and ok_decote and ok_reduc
if verbose:
print(
f"Test {params} -> obtenu (impôt={res.impot}, décote={res.decote}, réduction={res.reduction}) | attendu {expected} | {'OK' if test_ok else 'ECHEC'}")
if not test_ok:
print(
f" Détails tolérance ±1€ : impôt ok? {ok_impot}, décote ok? {ok_decote}, réduction ok? {ok_reduc}")
all_ok &= test_ok
if verbose:
print("\nRésultat global :", "TOUS LES TESTS PASSENT ✅" if all_ok else "AU MOINS UN TEST ÉCHOUE ❌")
return all_ok
if __name__ == "__main__":
run_tests()
- Righe 11–24: i 14 test richiesti;
- Righe 5-55: questo codice proviene dallo script generato da ChatGPT. Chiederemo a Gemini di utilizzare questo codice per facilitare il confronto tra i due script generati.
Inizieremo con ChatGPT:
![]() |
La sua prima risposta è errata. Glielo faccio notare fornendo i log di esecuzione:
![]() | ![]() |
La sua seconda risposta è corretta. ChatGPT ha aggiunto i seguenti 11 test ai 14 test richiesti:
Ora ci sono 25 test unitari. Ho verificato manualmente gli 11 nuovi test utilizzando il simulatore DGIP ufficiale e sono stati superati.
Ora passiamo a Gemini. Sarà molto più complicato. Riuscirà a generare uno script che superi tutti i 25 test di ChatGPT, ma solo dopo un lungo processo di debug.
![]() |
Di seguito è riportato il log di debug:
![]() |
Stranamente, la maggior parte dei test ha dato esito negativo, anche tra i 14 richiesti, mentre in passato Gemini aveva generato un codice che li superava tutti.
La seguente risposta di Gemini è ancora errata:
![]() |
E nemmeno la seguente risposta:
![]() |
E nemmeno la seguente risposta. Quindi sto cambiando approccio. Gli sto chiedendo di superare i 25 test che ChatGPT ha superato, allegando i log di ChatGPT:
![]() |
Gemini fallisce. Ha aggiunto i test di ChatGPT. Allego i log della sua esecuzione:
![]() |
Ancora no:
![]() |
Ancora no:
![]() |
Ancora no:
![]() |
Ancora no, ma va meglio:
![]() |
Gemini sta commettendo nuovi errori:
![]() |
La situazione sta migliorando di nuovo:
![]() |
Questa volta è corretto:
![]() |
Indubbiamente, in questo specifico esempio di calcolo delle imposte del 2019 con i vincoli specificati nel file di istruzioni, ChatGPT è stato più accurato di Gemini. Ma questo è solo un esempio.
Possiamo andare oltre. Possiamo chiedere a Gemini di rigenerare un PDF basato sulle regole di calcolo che ha utilizzato per superare i 25 test. Vogliamo vedere se ha modificato il suo ragionamento iniziale riguardo ai calcoli per lo sconto e la riduzione del 20%:
![]() | ![]() |
Questa volta, Gemini ha generato un file Markdown che ho poi convertito in PDF [Il problema secondo Gemini Versione 2]. E Gemini ha effettivamente cambiato il suo ragionamento:
![]() |
![]() |
Possiamo notare che il calcolo specifico dello sconto e la regola del riporto non sono più presenti. Gemini ha ora adottato il ragionamento di ChatGPT.






















































