Tuesday, May 09, 2023

Io, ChatGPT e julia

Riassunto della puntata precedente che trovate nel post "Io, ChatGPT e Lorenza": stimolato da qualche domanda, chiedo a ChatGPT di risolvere un esercizio semplice da compito. Il celebre programma di Intelligenza Artificiale lo risolve in un attimo, spiegando pure i passaggi con sicumera, ma è tutto sbagliato e ChatGPT non si ravvede nemmeno quando provo ad aiutarlo... bocciato senza appello!

Non so nulla di julia, un linguaggio di programmazione che ha il nome della mia criminologa preferita e di cui sento dire meraviglie, con tanto di commenti sul web e discorsi di amici che si spingono a dire che sarebbe ottimo anche per scrivere modelli ad agenti. Eppure, vista la desolante performance di un tentativo di ChatGPT di risolvere l'equazione x^3+x+1=0, una roba standard e fattibile che uso in ogni compito tanto per scaldare i muscoli ai miei studenti, decido di partire da zero: ce la faccio con julia a trovare la soluzione, anche se non so nulla e non ho nemmeno il programma?

Sono le 13.26 e attacco con zio google per trovare l'installer, individuo subito vari siti molto ben fatti con quanto serve e parecchia documentazione. Scarico, doppio click e vedo sul terminal lo splash screen di benvenuto, a metà fra la preistoria dell'interfaccia testuale (che sempre sia lodata, per altro!) e la scelta accattivante dei colori. Due secondi e due righe dopo ho definito la mia funzione e tanto per gradire provo a vedere se tutto funziona con f(1), che produce 3, e f(-0.62)=0.141672, non lontano da zero. Chi ben comincia è già a metà dell'opera.

Altro giro per digitare la stringa di ricerca "solving equation julia" e "solving equation julia one variable", imbattendomi in una bella lista di pagine che spesso mi suggeriscono di utilizzare NLsolve o nlsolve. A dir la verità, leggendo due righe di esempio alla massima velocità, vedo che lo usano per risolvere sistemi di equazioni, anche troppa grazia visti che a me servirebbe qualcosa di più semplice, nella sola variabile x. Pesto sulla tastiera:

julia> using NLsolve
 │ Attempted to find missing packages in package registries but no registries are installed.
 └ Use package mode to install a registry. `pkg> registry add` will install the default registries.

ERROR: ArgumentError: Package NLsolve not found in current path.
- Run `import Pkg; Pkg.add("NLsolve")` to install the NLsolve package.
Stacktrace:
 [1] macro expansion
   @ ./loading.jl:1163 [inlined]
 [2] macro expansion
   @ ./lock.jl:223 [inlined]
 [3] require(into::Module, mod::Symbol)
   @ Base ./loading.jl:1144

julia> nlsolve(f,[-2,-1])
ERROR: UndefVarError: nlsolve not defined
Stacktrace:
 [1] top-level scope
 Mi rendo conto che devo installare qualcosa di aggiuntivo, NLsolve
 e poi potrò riprovare. Va bene, vai con import Pkg; Pkg.add("NLsolve"), non perdete nulla se scorrete velocemente il lungo elenco di passaggi seguenti, è solo per dare l'idea che julia ci mette impegno:
julia> import Pkg; Pkg.add("NLsolve")
  Installing known registries into `~/.julia`
    Updating registry at `~/.julia/registries/General.toml`
   Resolving package versions...
   Installed IrrationalConstants ── v0.2.2
   Installed DiffRules ──────────── v1.13.0
   Installed DiffResults ────────── v1.1.0
   Installed Adapt ──────────────── v3.6.1
   Installed Setfield ───────────── v1.1.1
   Installed NLsolve ────────────── v4.5.1
   Installed SpecialFunctions ───── v2.2.0
   Installed Preferences ────────── v1.4.0
   Installed NaNMath ────────────── v1.0.2
   Installed StaticArrays ───────── v1.5.24
   Installed StaticArraysCore ───── v1.4.0
   Installed OrderedCollections ─── v1.6.0
   Installed ConstructionBase ───── v1.5.2
   Installed SnoopPrecompile ────── v1.0.3
   Installed JLLWrappers ────────── v1.4.1
   Installed ChainRulesCore ─────── v1.15.7
   Installed NLSolversBase ──────── v7.8.3
   Installed Reexport ───────────── v1.2.2
   Installed Requires ───────────── v1.3.0
   Installed LogExpFunctions ────── v0.3.23
   Installed ArrayInterface ─────── v7.4.3
   Installed LineSearches ───────── v7.2.0
   Installed ForwardDiff ────────── v0.10.35
   Installed CommonSubexpressions ─ v0.3.0
   Installed MacroTools ─────────── v0.5.10
   Installed OpenSpecFun_jll ────── v0.5.5+0
   Installed StatsAPI ───────────── v1.6.0
   Installed UnPack ─────────────── v1.0.2
   Installed InverseFunctions ───── v0.1.9
   Installed Compat ─────────────── v4.6.1
   Installed Parameters ─────────── v0.12.3
   Installed Distances ──────────── v0.10.8
   Installed ChangesOfVariables ─── v0.1.7
   Installed FiniteDiff ─────────── v2.20.0
   Installed DocStringExtensions ── v0.9.3
  Downloaded artifact: OpenSpecFun
    Updating `~/.julia/environments/v1.8/Project.toml`
  [2774e3e8] + NLsolve v4.5.1
    Updating `~/.julia/environments/v1.8/Manifest.toml`
  [79e6a3ab] + Adapt v3.6.1
  [4fba245c] + ArrayInterface v7.4.3
  [d360d2e6] + ChainRulesCore v1.15.7
  [9e997f8a] + ChangesOfVariables v0.1.7
  [bbf7d656] + CommonSubexpressions v0.3.0
  [34da2185] + Compat v4.6.1
  [187b0558] + ConstructionBase v1.5.2
  [163ba53b] + DiffResults v1.1.0
  [b552c78f] + DiffRules v1.13.0
  [b4f34e82] + Distances v0.10.8
  [ffbed154] + DocStringExtensions v0.9.3
  [6a86dc24] + FiniteDiff v2.20.0
  [f6369f11] + ForwardDiff v0.10.35
  [3587e190] + InverseFunctions v0.1.9
  [92d709cd] + IrrationalConstants v0.2.2
  [692b3bcd] + JLLWrappers v1.4.1
  [d3d80556] + LineSearches v7.2.0
  [2ab3a3ac] + LogExpFunctions v0.3.23
  [1914dd2f] + MacroTools v0.5.10
  [d41bc354] + NLSolversBase v7.8.3
  [2774e3e8] + NLsolve v4.5.1
  [77ba4419] + NaNMath v1.0.2
  [bac558e1] + OrderedCollections v1.6.0
  [d96e819e] + Parameters v0.12.3
  [21216c6a] + Preferences v1.4.0
  [189a3867] + Reexport v1.2.2
  [ae029012] + Requires v1.3.0
  [efcf1570] + Setfield v1.1.1
  [66db9d55] + SnoopPrecompile v1.0.3
  [276daf66] + SpecialFunctions v2.2.0
  [90137ffa] + StaticArrays v1.5.24
  [1e83bf80] + StaticArraysCore v1.4.0
  [82ae8749] + StatsAPI v1.6.0
  [3a884ed6] + UnPack v1.0.2
  [efe28fd5] + OpenSpecFun_jll v0.5.5+0
  [0dad84c5] + ArgTools v1.1.1
  [56f22d72] + Artifacts
  [2a0f44e3] + Base64
  [ade2ca70] + Dates
  [8ba89e20] + Distributed
  [f43a241f] + Downloads v1.6.0
  [7b1f6079] + FileWatching
  [9fa8497b] + Future
  [b77e0a4c] + InteractiveUtils
  [b27032c2] + LibCURL v0.6.3
  [76f85450] + LibGit2
  [8f399da3] + Libdl
  [37e2e46d] + LinearAlgebra
  [56ddb016] + Logging
  [d6f4376e] + Markdown
  [ca575930] + NetworkOptions v1.2.0
  [44cfe95a] + Pkg v1.8.0
  [de0858da] + Printf
  [3fa0cd96] + REPL
  [9a3f8284] + Random
  [ea8e919c] + SHA v0.7.0
  [9e88b42a] + Serialization
  [6462fe0b] + Sockets
  [2f01184e] + SparseArrays
  [10745b16] + Statistics
  [4607b0f0] + SuiteSparse
  [fa267f1f] + TOML v1.0.0
  [a4e569a6] + Tar v1.10.1
  [8dfed614] + Test
  [cf7118a7] + UUIDs
  [4ec0a83e] + Unicode
  [e66e0078] + CompilerSupportLibraries_jll v1.0.1+0
  [deac9b47] + LibCURL_jll v7.84.0+0
  [29816b5a] + LibSSH2_jll v1.10.2+0
  [c8ffd9c3] + MbedTLS_jll v2.28.0+0
  [14a3606d] + MozillaCACerts_jll v2022.2.1
  [4536629a] + OpenBLAS_jll v0.3.20+0
  [05823500] + OpenLibm_jll v0.8.1+0
  [83775a58] + Zlib_jll v1.2.12+3
  [8e850b90] + libblastrampoline_jll v5.1.1+0
  [8e850ede] + nghttp2_jll v1.48.0+0
  [3f19e933] + p7zip_jll v17.4.0+0
Precompiling project...
  42 dependencies successfully precompiled in 42 seconds
Sembra aramaico ma julia, tutta da sola e senza errori, installa 42 pacchetti in 42 secondi, facendomi vedere con grazia lo stato di avanzamento a terminale. Adesso nlsolve ce l'ho e ci riprovo, ottenendo quel che vedete in figura. Non ci siamo ancora e la cosa ha molto senso, sto digitando cose a caso e già avevo capito che, probabilmente, stavo usando un macchinario enorme per risolvere una cosa semplice, proprio come quando ti metti in testa di usare la mitragliatrice contro le formiche.


Altro giro sui motori ma ormai sento il sapore del sangue, leggo in questa pagina che "NLsolve only solve vector problem AFAIK, but you can define a problem of size 1", c'è un esempio e capisco forte e chiaro come smanettarlo! 


Lo ammetto, non so (ancora) bene che cosa ho scritto e non capisco bene perché servano i due argomenti F e x ma si vede bene la sostanza: x^3+x+1

julia> function fun!(F, x)
                  F[1] = x[1]^3+x[1]+1
              end
fun! (generic function with 1 method)

Adesso non mi resta che dare il comando nlsolve(fun!, [0.1]), significa "risolvi", e si ottiene la soluzione -0.6823278047019576 che vedete in figura. Ci siamo, è la cosa giusta e sono le 13.41, da zero alla soluzione in 15 minuti (senza capire nulla seriamente, installando un po' a caso julia e i suoi pacchetti, senza alcun intoppo, ravanando un po' fino a quando ho trovato un esempio che potevo modificare). 15 minuti...

Questo episodio mi ha spinto a decidere di insegnare julia ai miei studenti l'anno prossimo, è ora di cambiare e di innovare rispetto a R, che è ed è stato un software meraviglioso. Ma il corso ha questa forma da una dozzina d'anni, a quel tempo R era la frontiera ed è ora di rimettersi in marcia. Lo devo ai miei neuroni in via d'invecchiamento, lo devo ai miei studenti che si possono mettere alla prova con quello che servirà nel prossimo decennio (e non col vecchiume di matlab, python and so on).

In fondo, la spinta me l'ha data ChatGPT e il suo clamoroso fiasco: tutti ne parlano ma l'intelligenza artificiale non è in grado di risolvere un problemino che si risolve in due righe di R e che io ho risolto in 15 minuti con uno strumento sconosciuto. Per qualche motivo questa esperienza (e lo scambio con Lorenza) mi hanno dato la carica. Sarà anche necessario capire la potenza e i difetti di un fenomeno come ChatGPT ma lo è di più vedere che altre cose sono affidabili, divertenti e formative, vai con julia!

Ma non è finita così. Una volta deciso di inserire in programma julia, di cui al momento non so una mazza, mi sono reso conto che mi devo documentare e cosa c'è di meglio che chiedere a ChatGPT? Specchio delle mie brame, puoi fornirmi le referenze più belle del reame?


ChatGPT, servizievolissimo, mi suggerisce tre referenze per imparare julia e i link ai pdf. Cappero, è proprio bravo, no?




È una figata e m'ingolosisco, clicco sul primo indirizzo, ma il link è broken e non c'è nessun file. Poi clicco sul secondo link, broken pure lui... Indovinate cosa è successo quando ho provato a raggiungere il terzo link? Sì, ci avete beccato! Broken, page not found anche la terza volta! Tre su tre, mi hai preso per mona? Non è la prima volta che lo becco a dare referenze fantasiose, scritte secondo lui da gente che  sembra sensata, con titolo accattivante e tanto di indirizzo. Ma è tutto inventato o forse, decidete voi, completamente tarocco pur nella somiglianza superficiale con qualcosa che pare rilevante.

Ecco, ChatGPT è un portento ma non mettetevi nelle sue mani perché tutto quel che dice, quando si tratta di informazioni fattuali e non di discorsi vaghi, va verificato a sangue perché spesso fornisce informazioni del tutto inaffidabili. Per ora. Uomo avvisato mezzo salvato!


ps. I link su julia erano broken e "sbagliati" ma non sono stati del tutto inutili. Con un po' di pazienza, sono risalito a titolo e autore dei libri e ho anche ritrovato altrove alcuni dei file cui ChatGPT mi aveva indirizzato. A saperle usare anche informazioni imprecise possono essere utili, sono stati punti di partenza per il segugio  che è in me (è un altra versione di quanto dicevo prima: non sempre servono livelli di precisione atroce, spesso va bene un su-e-zo!).

ps2. Per chi ne vuol sapere di più (sono le stesse cose che sto leggendo o leggerò io):

julia> using Roots

 │ Package Roots not found, but a package named Roots is available from a

 │ registry. 

 │ Install package?

 │   (@v1.8) pkg> add Roots 

 └ (y/n/o) [y]: y

   Resolving package versions...

   Installed Roots ─────── v2.0.14

   Installed CommonSolve ─ v0.2.3

    Updating `~/.julia/environments/v1.8/Project.toml`

  [f2b01f46] + Roots v2.0.14

    Updating `~/.julia/environments/v1.8/Manifest.toml`

  [38540f10] + CommonSolve v0.2.3

  [f2b01f46] + Roots v2.0.14

Precompiling project...

  2 dependencies successfully precompiled in 8 seconds. 42 already precompiled.


julia> find_zero(f,0)

-0.6823278038280193


julia> f(x) = x^3+x+1

f (generic function with 1 method)


julia> find_zero(f,0)

-0.6823278038280193


julia> 


No comments: