Le evoluzioni dell’intelligenza artificiale prodotta da OpenAI, un confronto fra GPT-4 e GPT-3.5

3

Negli ultimi mesi, precisamente dalla sua presentazione nel novembre 2022, abbiamo parlato spesso di ChatGPT, il chatbot prodotto da OpenAI che risponde a domande e risolve problemi utilizzando l’intelligenza artificiale. Questa intelligenza artificiale è prodotta dall’utilizzo di un Large Language Model o LLM, che consente di generare testo perché poggia su una rete neurale con la quale interagisce mediante centinaia di miliardi di parametri.

Se quindi ChatGPT è lo strumento, GPT è il cervello, il backend, ciò che fa funzionare tutto il sistema e, come tutti i programmi (poiché è di questo che si tratta), anche GPT ha delle versioni.

Tutti i GPT disponibili

Al momento esistono GPT-3, 3.5 e 4, ed i più tecnici di voi si staranno sicuramente chiedendo quali differenze vi siano nel loro funzionamento. Tenteremo di fare luce su questo aspetto, nonostante tutto ciò sia in costante evoluzione e, ricordiamo, sia soltanto l’anteprima di ciò che queste tecnologie diventeranno nei prossimi anni.

Per fruire dell’ultimo modello, ovvero GPT-4, al momento in cui scriviamo vi sono due strade:

  • Usare ChatGPT Plus, a pagamento (attualmente 24 dollari al mese)
  • Usare Bing Chat (gratuito, ma funziona solo da browser Edge).

La situazione, come intuibile, è probabile che vari nei prossimi mesi, quindi vi invitiamo a verificare direttamente nel momento in cui leggete.

Cosa c’è di nuovo? Per una discussione puramente tecnica vi rimandiamo alle abbondanti news in giro sul web in questi giorni e, vi anticipiamo, non vedrete molto poiché questi strumenti, ahimè, sono open solo di nome ma non di fatto.

Tutto ciò, infatti, non è open-source ma, anzi, codice proprietario che rappresenta la nuova corsa all’oro nonché ciò che sembra il più grande evento dopo la nascita di Internet.

Ciò che faremo oggi sarà, invece, mettere alla prova ancora una volta i due modelli per mostrarvi la situazione attuale di ciò che potete aspettarvi. Un avvertimento: saremo tecnici, ma molti di voi sicuramente usano questi tool già per lavoro, quindi simuleremo delle richieste che potrebbero riflettere tale utilizzo.

Il test pratico

Partiamo con una richiesta che, per un algoritmo (ma anche per molti di voi), dovrebbe essere semplice:

Scrivi uno script bash che crei una rete podman con un nome a caso e che supporti due subnet, ipv4 e ipv6, e imposti le relative subnet mask per contenere al massimo 1022 host

Ecco cosa ci hanno risposto.

ChatGPT-3.5:

#!/bin/bash

# Genera un nome casuale per la rete
net_name=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)

# Crea la rete con il nome generato
podman network create $net_name

# Imposta le subnet IPv4 e IPv6 con una maschera di rete di /22 (che contiene fino a 1022 host)
podman network set $net_name --subnet=10.0.0.0/22
podman network set $net_name --ipv6 --subnet=fd00::/22

# Avvia il contenitore di prova nella rete appena creata
podman run -d --name test-container --network $net_name nginx

echo "La rete $net_name è stata creata con successo con subnet IPv4 e IPv6 contenenti al massimo 1022 host."

Non male, forse esagerata la randomizzazione letterale dei nomi delle reti (avevamo chiesto un nome a caso, anche ‘paperino’ andava bene), ma abbiamo problemi più grossi: il dimensionamento della rete ipv6 è errato (doveva essere una /118) e il comando podman run non l’avevamo richiesto, anche se risulta corretto.

Abbiamo provato a chiedere lumi sulla dimensione scelta per la subnet ipv6 ma le informazioni restituiteci continuavano a essere errate.

Proviamo con ChatGPT-4:

#!/bin/bash

# Genera un nome casuale per la rete
NETWORK_NAME="podman_network_$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1)"

# Imposta i valori delle subnet IPv4 e IPv6
IPV4_SUBNET="10.0.0.0"
IPV6_SUBNET="fd00::"

# Calcola la subnet mask per consentire al massimo 1022 host (subnet /22 per IPv4 e subnet /118 per IPv6)
IPV4_SUBNET_MASK="/22"
IPV6_SUBNET_MASK="/118"

# Crea una rete Podman con le subnet e le maschere di sottorete specificate
podman network create "$NETWORK_NAME" --subnet="$IPV4_SUBNET$IPV4_SUBNET_MASK" --subnet="$IPV6_SUBNET$IPV6_SUBNET_MASK"

echo "La rete $NETWORK_NAME è stata creata con successo:"
echo "Subnet IPv4: $IPV4_SUBNET$IPV4_SUBNET_MASK"
echo "Subnet IPv6: $IPV6_SUBNET$IPV6_SUBNET_MASK"

Lo script ci piace, usa variabili e funziona. La subnet mask è corretta e lo è anche il prefisso ipv6, che è /118 come ci aspettavamo.

Proviamo ora la terza opzione, Bing Chat che, ricordiamo, usa anch’esso ChatGPT 4.0 di OpenAI e, a differenza di esso, non è limitato dalla sua ignoranza sugli eventi successivi al 2021. Esso ci ha risposto in modo discorsivo nonostante la richiesta di uno script, ma la risposta è stata comunque soddisfacente:

Per creare una rete podman con un nome a caso, puoi usare il comando podman network create senza specificare il nome. Podman assegnerà una subnet libera e un nome per la rete. Per esempio:

$ podman network create
/etc/cni/net.d/podman-cni-20211019155759.conflist
$ podman network ls
NAME                      VERSION   PLUGINS
podman                    0.4.0     bridge,portmap,firewall,tuning,dnsname
podman-cni-20211019155759 0.4.0     bridge,portmap,firewall,tuning,dnsname
Per supportare due subnet, ipv4 e ipv6, puoi usare le opzioni --subnet e --ipv62. Devi specificare una subnet valida per ogni protocollo. Per esempio:

$ podman network create --subnet 192.168.100.0/24 --ipv6 --subnet fd00:100::/64 mynet
/etc/cni/net.d/mynet.conflist
Per impostare le subnet mask per contenere al massimo 1022 host, devi usare una maschera di 22 bit per ipv4 e una maschera di 118 bit per ipv63. Per esempio:

$ podman network create --subnet 192.168.0.0/22 --ipv6 --subnet fd00::/118 mynet2
/etc/cni/net.d/mynet2.conflist

Le subnet sono corrette, così come lo sono le informazioni fornite, e l’ultimo comando listato funziona come atteso.

Vogliamo provare a cambiare argomento?

Round 2:

Scrivi uno script bash che crei un filesystem ext2 su un logical volume chiamato ‘mylv’ di 500GB spannato su due drive (vdc e vdd) montandolo su /lv al boot in modo persistente con l’opzione noatime.

/lv deve avere una dimensione dei physical extent di 16MiB

ChatGPT-3.5:

#!/bin/bash

# Creazione del logical volume mylv di 500GB, spannato su due drive (vdc e vdd)
sudo pvcreate /dev/vdc /dev/vdd
sudo vgcreate myvg /dev/vdc /dev/vdd
sudo lvcreate --name mylv --size 500G myvg

# Creazione del filesystem ext2 sul logical volume mylv
sudo mkfs.ext2 /dev/myvg/mylv

# Creazione della directory /lv e montaggio del logical volume
sudo mkdir /lv
echo "/dev/myvg/mylv /lv ext2 defaults,noatime 0 0" | sudo tee -a /etc/fstab
sudo mount -a

# Impostazione della dimensione dei physical extent a 16MiB
sudo lvconvert --extentsize 16M /dev/myvg/mylv

# Verifica delle impostazioni
sudo lvdisplay /dev/myvg/mylv
sudo mount | grep /lv

Nonostante ‘spannato’ sia un inglesismo, il significato è stato compreso e lo script, tecnicamente, risulta corretto, anche se l’opzione --extentsize del comando lvconvert è decisamente un’allucinazione poiché, provandola, non risulta un’opzione valida. Uno dei nostri requisiti, quindi, non è stato implementato.

ChatGPT-4:

#!/bin/bash

# Crea i Physical Volumes
sudo pvcreate /dev/vdc /dev/vdd

# Crea un Volume Group chiamato 'vg' usando i due Physical Volumes
sudo vgcreate vg --physicalextentsize 32M /dev/vdc /dev/vdd

# Crea un Logical Volume chiamato 'lv' all'interno del Volume Group 'vg'
sudo lvcreate -l 100%FREE -n lv vg

# Crea un filesystem ext2 sul Logical Volume
sudo mkfs.ext2 /dev/vg/lv

# Crea una directory per montare il filesystem
sudo mkdir /lv

# Modifica /etc/fstab per montare il filesystem in modo persistente
echo "/dev/vg/lv /lv ext2 defaults,noatime 0 0" | sudo tee -a /etc/fstab

# Monta il filesystem
sudo mount -a

Niente male!

Bing Chat (ChatGPT-4):

# Creare un volume group chiamato 'myvg' che includa i due drive vdc e vdd
vgcreate -s 16M myvg /dev/vdc /dev/vdd

# Creare un logical volume chiamato 'mylv' di 500GB all'interno del volume group 'myvg'
lvcreate -L 500G -n mylv myvg

# Creare un filesystem ext2 sul logical volume 'mylv'
mkfs.ext2 /dev/myvg/mylv

# Ottenere l'UUID del filesystem ext2 appena creato
UUID=$(blkid /dev/myvg/mylv | cut -d '"' -f 2)

# Creare un punto di mount per il filesystem ext2
mkdir /lv

# Modificare il file /etc/fstab per montare il filesystem ext2 sul punto di mount /lv al boot in modo persistente con l'opzione noatime
echo "UUID=$UUID /lv ext2 defaults,noatime 0 0" >> /etc/fstab

# Montare il filesystem ext2 manualmente
mount -a

Anche qui, ottimo risultato.

Vogliamo fare anche un round 3?

Crea uno script bash che, su un sistema Linux, crei 3 utenti:

  • u1
  • u2
  • u3

Tutti devono avere una password già scaduta e che venga cambiata al massimo ogni 10 giorni ma non più presto di 2.
Il terzo non deve essere in grado di loggarsi da ssh.

GPT-3.5:

#!/bin/bash

# Crea gli utenti u1, u2, u3 con password scaduta
useradd -m -p $(openssl passwd -1 -salt salt u1password) -e $(date +%Y-%m-%d -d "10 days ago") u1
useradd -m -p $(openssl passwd -1 -salt salt u2password) -e $(date +%Y-%m-%d -d "10 days ago") u2
useradd -m -p $(openssl passwd -1 -salt salt u3password) -e $(date +%Y-%m-%d -d "10 days ago") u3

# Imposta le politiche di scadenza password per gli utenti
chage -M 10 -m 2 -I 1 u1
chage -M 10 -m 2 -I 1 u2
chage -M 10 -m 2 -I 1 u3

# Imposta la configurazione ssh per l'utente u3
echo "DenyUsers u3" >> /etc/ssh/sshd_config
systemctl restart sshd

Non male anche per GPT-3.5, anche se ci aspettavamo un ciclo o qualcosa per ottimizzare i task ripetitivi. L’utilizzo di openssl per settare le password temporanee già hashate è, forse, un pò esagerato, ma decisamente corretto.

GPT-4:

#!/bin/bash

# Crea gli utenti u1, u2 e u3 con password scadute
for user in u1 u2 u3; do
    sudo useradd -m $user
    sudo passwd -e $user
done

# Imposta la politica di cambio password (massimo 10 giorni, minimo 2 giorni)
for user in u1 u2 u3; do
    sudo chage -M 10 -m 2 $user
done

# Disabilita l'accesso SSH per l'utente u3
sudo sh -c "echo 'DenyUsers u3' >> /etc/ssh/sshd_config"
sudo systemctl restart sshd

echo "Utenti creati e configurati."

Corretto anche qui ma la qualità della risposta si è alzata, poichè abbiamo i cicli che cercavamo.

Bing Chat (GPT-4):

#!/bin/bash

# Creare 3 utenti u1, u2 e u3
useradd u1
useradd u2
useradd u3

# Impostare una password scaduta per tutti e 3 gli utenti
passwd -e u1
passwd -e u2
passwd -e u3

# Impostare la politica di scadenza della password a 10 giorni massimi e 2 giorni minimi per tutti e 3 gli utenti
chage -M 10 -m 2 u1
chage -M 10 -m 2 u2
chage -M 10 -m 2 u3

# Disabilitare l'accesso ssh per l'utente u3 modificando il file /etc/ssh/sshd_config e aggiungendo la riga seguente:
echo "DenyUsers u3" >> /etc/ssh/sshd_config

# Riavviare il servizio sshd per rendere effettive le modifiche
systemctl restart sshd.service

Per qualche ragione, in questa risposta di Bing Chat non abbiamo cicli e l’implementazione è banale, ma vogliamo mostrarvi che succede se rigeneriamo la risposta da capo:

#!/bin/bash
# Creare gli utenti
useradd u1
useradd u2
useradd u3

# Impostare le password (scegliere password sicure)
echo "sifs4you1" | passwd u1 --stdin
echo "sifs4you2" | passwd u2 --stdin
echo "sifs4you3" | passwd u3 --stdin

# Forzare il cambio di password al primo login
chage -d 0 u1
chage -d 0 u2
chage -d 0 u3

# Impostare la politica di scadenza della password ogni 10 giorni ma non prima di 2 giorni[^2^][2]
chage -M 10 -m 2 u1
chage -M 10 -m 2 u2
chage -M 10 -m 2 u3

# Disabilitare il login ssh per l'utente u3[^3^][3]
usermod -s /sbin/nologin u3

Come si nota, la risposta è comunque valida, a tratti migliorata (la password non è richiesta a noi in modo interattivo ma settata direttamente), a tratti leggermente cambiata (impostando la shell a /sbin/nologin, si ottiene un risultato nella pratica uguale a quanto abbiamo chiesto, tuttavia esso non è una regola ssh e influisce anche sui login locali).

Riguardo i cicli che non ci sono, si può rimediare se chiediamo espressamente di ottimizzare lo script, anche se non sono l’unica cosa a cambiare. Ad esempio, stavolta si è deciso di usare chpasswd e, per qualche ragione, tutti gli utenti sono blacklistati da ssh e non solo il terzo, come da noi richiesto:

#!/bin/bash
# Creare 10 utenti con il prefisso user e il suffisso da 1 a 10

# Usare un ciclo for per iterare sui numeri da 1 a 10
for i in {1..10}; do
  # Creare il nome utente concatenando il prefisso e il suffisso
  username="user$i"
  
  # Creare l'utente con il comando useradd
  useradd $username -d /home/$username -m
  
  # Assegnare la password con il comando chpasswd
  echo "$username:password$i" | chpasswd
  
  # Impostare la scadenza della password con il comando chage
  chage -d 0 -m 2 -M 10 $username # la password è scaduta e deve essere cambiata tra 2 e 10 giorni
  
done

# Disabilitare l'accesso ssh per tutti gli utenti creati modificando il file /etc/ssh/sshd_config
echo "DenyUsers user*" >> /etc/ssh/sshd_config # aggiungere la riga DenyUsers user* alla fine del file

# Riavviare il servizio ssh per rendere effettive le modifiche
service ssh restart # riavviare il servizio ssh 

In questo caso, quindi, qualcosa si è perso per strada, anche se si può, come al solito, rettificare facendolo presente (queste chat permettono, infatti, di fare ulteriori domande e rettifiche o chiedere di ottenere la stessa risposta in un altro liguaggio).

Aggiungiamo che nessuna delle risposte precedenti ha voluto considerare il fatto che il servizio ssh potrebbe, a seconda della distribuzione Linux su cui ci si trova, chiamarsi ssh o sshd, nonostante anche GPT3.5 sia a conoscenza del fatto (abbiamo provato a chiederlo in un prompt dedicato e la risposta è stata corretta) e che in quest’ultima iterazione della risposta non si è usato systemd per riavviare il servizio ma un comando decisamente arcaico e non più valido, anche se non si può negare che la qualità e l’utilità di questi strumenti stia raggiungendo livelli soddisfacenti.

Le conclusioni

E’ ancora una volta presto per trarle, tuttavia il trend è chiaro e, se vi stavate chiedendo il perché della recente popolarità di questi strumenti, visto di cosa sono già capaci (al netto della loro imperfezione), la risposta è presto data.

Vi invitiamo a provare voi stessi ma, come avete notato, le risposte variano anche di parecchio di volta in volta. Ogni iterazione che farete rimane, in fondo, coerente con il task alla mano, ma può produrre script del tutto diversi, alcuni con variabili altri meno, alcuni ottimizzati e altri banali o persino inserire delle condizioni o degli abbellimenti da voi non richiesti, quindi è utile essere più specifici possibile nelle richieste e aggiungere precisazioni a seguito della prima risposta ottenuta.

Come anche indicato nei disclaimer di questi tool, le risposte possono contenere delle inesattezze e può capitare che un comando abbia dei parametri che nella realtà non esistono o che fanno qualcosa di completamente diverso da ciò che ci si aspetta, quindi è sempre bene verificare le relative manpages per utilizzi importanti. Del resto, non è poi così dissimile dall’eseguire codice scritto da altri. Non vi sognereste mai di farlo alla cieca, vero?

In ogni caso, nonostante i pochi esempi e il fatto che entrambi i modelli hanno ancora delle visibili imperfezioni, il nuovo GPT-4 (sia con Microsoft Bing, sia direttamente usato dal sito di OpenAI) sembra decisamente più sul pezzo di GPT-3.5, migliorandone la comprensione e riducendo il tasso di errori.

La scena AI, come visto, sta diventando decisamente interessante e ciò sta avvenendo molto in fretta.

Su come fruire GPT4 o sulla scelta di usarlo o meno, a voi la scelta, ricordandovi che, ancora una volta, lo strumento diventa tanto più efficace quanto lo è l’utente che lo usa.

Appassionato di Linux e della cultura open-source da vent’anni, continuo a fare del mio meglio per diffondere tale filosofia e soprattutto condividere la conoscenza.

C’è sempre qualcuno da qualche parte nel mondo che sta avendo un problema che tu hai già risolto e, condividendo la soluzione, puoi fare la differenza.

Se quel qualcuno sei tu, chiedi pure alla community. La trovi ovunque, ad esempio su reddit.com/r/italyinformatica, reddit.com/r/fedora, reddit.com/r/debian, reddit.com/r/ubuntu, reddit.com/r/archlinux, reddit.com/r/linux, sui forum specifici delle distro oppure sulle loro wiki.

Perchè nessun problema andrebbe risolto più di una volta.

[https://it.linkedin.com/in/john-toscano]