Sapeva 22.000 sentenze, ma non un numero di atto

13/09/20267 min read
Sapeva 22.000 sentenze, ma non un numero di atto

Risposta diretta: più un sistema è sofisticato su una dimensione, più è facile che il caso banale accanto non sia mai stato testato. Il mio motore giuridico indicizzava oltre 22.000 pronunce della Corte Costituzionale dal 1956, sentenze europee, Cassazione e migliaia di collegamenti fra norme — e non sapeva trovare un disegno di legge cercato per numero, perché la ricerca funzionava solo sulle parole del titolo. Nessuno l'aveva provato: sembrava troppo ovvio per essere rotto.

TL;DR

  • Domanda: «Atto Senato n. 1627». Risposta: «non sono riuscito a recuperare informazioni verificate».
  • Lo stesso sistema rispondeva senza problemi a domande molto più difficili sulla giurisprudenza costituzionale.
  • Causa: la ricerca degli atti faceva solo matching testuale sul titolo. L'identificativo numerico non era un criterio di ricerca.
  • Nessun test lo copriva, perché cercare per numero sembra la funzione più elementare che esista — quindi si dà per fatta.
  • Pattern generale: si testa ciò che si costruisce con fatica, non ciò che si dà per scontato.
  • Nota a margine ricorsiva: quella feature l'ho costruita con un piccolo team di agenti AI in parallelo. Il prodotto finale è un agente, costruito da agenti.

Il momento in cui te ne accorgi

Il sistema è un assistente che risponde su leggi e dati pubblici italiani. Ha dentro, indicizzata e interrogabile, la giurisprudenza della Corte Costituzionale dal 1956: oltre ventiduemila pronunce. Più sentenze europee, Cassazione, e migliaia di collegamenti espliciti fra norme e decisioni.

Gli ho chiesto una cosa semplice: informazioni sull'Atto Senato n. 1627.

«Non sono riuscito a recuperare informazioni verificate.»

Non un errore, non un timeout: un fallimento educato, del tipo che il sistema produce quando davvero non trova niente. Su un identificativo esatto. Di un atto che esiste.

La causa, imbarazzante quanto basta

La ricerca degli atti parlamentari era implementata come ricerca testuale sul titolo. Cercavi «antisemitismo» e trovavi i disegni di legge che avevano quella parola nel titolo. Funzionava benissimo per quello.

L'identificativo numerico — che è il modo in cui chiunque lavori davvero con gli atti parlamentari li chiama — non era previsto come criterio di ricerca. Cercando «1627» il motore cercava atti con «1627» nel titolo. Non ce ne sono.

Non era un bug di implementazione. Era una funzionalità mai scritta, che sembrava esserci perché era troppo ovvia per essere assente.

Perché nessuno l'aveva testato

Questa è la parte che vale la pena generalizzare, perché non riguarda il mio codice.

Quando costruisci la parte difficile di un sistema — l'ingestione di ventiduemila sentenze, la costruzione del grafo, la disambiguazione delle entità — la tua attenzione sta tutta lì. È lì che ti aspetti i problemi, ed è lì che scrivi i test, perché è lì che hai visto le cose rompersi.

Il caso banale accanto non entra nel campo visivo, per tre motivi:

  • Non sembra una funzionalità. «Cercare per numero» non è un elemento di un piano di lavoro: è quello che il sistema ovviamente fa.
  • Non è mai stato dichiarato. Se nessuno l'ha scritto in un requisito, nessun test lo copre.
  • Chi costruisce non lo prova mai. Io, in mesi di lavoro, non ho mai avuto bisogno di cercare un atto per numero: cercavo per tema, perché stavo costruendo il tema.

Il risultato è un'asimmetria specifica: il sistema è robustissimo dove hai sudato e fragile dove hai dato per scontato. E la parte data per scontata è, quasi sempre, quella che l'utente prova per prima.

Il test che non scrivi mai

Dopo questo caso ho aggiunto una voce fissa alla mia checklist, e la chiamo il test da profano:

Prima del rilascio, fai al sistema le tre domande più stupide che un nuovo utente farebbe nei primi due minuti.

Non le domande difficili — quelle le hai già coperte. Le domande che dai per scontate:

Tipo di sistema La domanda stupida che non hai testato
Motore di ricerca documentale Cercare un documento con il suo codice identificativo
Gestionale clienti Cercare un cliente per partita IVA invece che per nome
Assistente su un catalogo Chiedere un articolo per codice prodotto
Sistema di prenotazioni Cercare una prenotazione con il numero di conferma

Tutte queste hanno la stessa forma: l'identificativo esatto invece della descrizione. È il caso che gli sviluppatori usano meno e gli utenti usano di più, perché l'utente quel codice ce l'ha davanti, stampato su un documento.

È lo stesso motivo per cui un bug che rompe la vista sopravvive per mesi: la persona che potrebbe accorgersene non attraversa mai quel percorso.

Nota a margine: un team di agenti per costruire un agente

Una cosa ricorsiva che vale la pena raccontare, perché dice qualcosa su come si lavora oggi.

Per ripartire dopo questo problema ho diviso il lavoro in tre filoni indipendenti — recupero della fonte dati, correzione del bug di ricerca, dossier giuridico di riferimento — e li ho affidati a tre agenti AI in parallelo, invece di farli io in sequenza.

Il prodotto finale è un agente che risponde su leggi. Costruito, in buona parte, da un piccolo team di agenti.

Non lo racconto per la simmetria carina, ma per una conseguenza pratica: dividere il lavoro in filoni con confini netti di proprietà — questo tocca solo questi file, quello solo quegli altri — è ciò che rende il parallelismo possibile senza che il risultato sia un pasticcio da ricucire. È la stessa disciplina che serve fra persone, solo resa obbligatoria: un agente non negozia i confini, li rispetta o li sfonda. E se li sfonda te ne accorgi subito, il che è più di quanto si possa dire di molti processi umani. Ne ho scritto in dettaglio ragionando su cosa cambia quando si costruisce a velocità AI.

FAQ

Perché un sistema complesso può fallire su una ricerca elementare?

Perché l'attenzione — e quindi i test — si concentra dove il lavoro è stato difficile. Le funzioni elementari non vengono dichiarate come requisiti, non entrano nei test e non vengono mai provate da chi costruisce, che interroga il sistema con le domande del proprio lavoro, non con quelle di un nuovo utente.

Cos'è il «test da profano»?

È una verifica di rilascio in cui poni al sistema le domande più ovvie che farebbe un utente nei primi due minuti — tipicamente ricerche per identificativo esatto invece che per descrizione. Sono le domande che gli sviluppatori usano meno e gli utenti usano di più.

Come si evita questa classe di problema in modo sistematico?

Scrivendo i requisiti anche per l'ovvio e includendo nella suite di test almeno un caso per ogni modo in cui un utente reale può nominare un'entità: per nome, per identificativo, per codice, per riferimento esterno. Se un identificativo compare su un documento che l'utente ha in mano, deve essere un criterio di ricerca.

Dividere il lavoro fra più agenti AI conviene davvero?

Conviene quando i filoni hanno confini di proprietà netti sui file e sulle responsabilità. Senza quei confini il parallelismo produce conflitti che costano più del tempo risparmiato; con quei confini, è il modo più efficace di non fare le cose in sequenza.


Se hai un sistema che funziona benissimo sulle domande difficili e ti sorprende su quelle facili, di solito il problema è nella copertura dei requisiti impliciti, non nel codice. Parliamone.

AIBehind the scenesLegal Tech

Scritto da Giulio Garofalo