Il ritorno del linguaggio naturale: Inform

Summary: natural language processing is coming back, as seen in free-format input in popular web apps, in the Inform programming language, or in the Ruby on Rails framework

Il linguaggio naturale per l’input è un trend che si comincia a notare: le applicazioni web più cool accettano input in formato naturale. Google Calendar accetta “15:00 dentista” senza bisogno di un box separato per l’ora e uno per il nome dell’evento. Basecamp va oltre (http://backpackit.com/calendar):

Type like you think:
“6pm Dinner” or “Doctor Wednesday 3pm” or “Call Jim tomorrow”.

L’ultima revisione di Inform, il linguaggio per avventure testuali, è radicalmente innovativo rispetto alle versioni precedenti, e anche rispetto a tutti gli altri sistemi analoghi.

Enfasi data al test: molti autori di narrativa interattiva iniziano a lavorare da uno scritto di interazione, da una lista di comandi e risposte che il gioco dovrebbe produrre una volta funzionante. Inform 7 conserva queste tracce di interazione, e permette di rilevare automaticamente quando il programma da noi realizzato riesce finalmente a rispondere all’interazione nella maniera desiderata. Questo riecheggia meravigliosamente con Kent Beck: prima scrivi l’output atteso, poi modifica il programma fino a che l’output del programma non sia uguale a quello atteso.

L’uso del linguaggio naturale per l’input. Lo so che questo chiama alla mente obbrobri di linguaggi di programmazione cammuffati da linguaggio naturale, come AppleScript o Cobol. Ma Inform 7 è un po’ più raffinato di così. Consideriamo questo frammento da The Reliques of Tolti-Aph di G. Nelson:

Chapter 1 – Fundamentals

Section 1(a) – Substance

A material is a kind of value. The materials are stone, wood, paper, magic-imbued wood, metal, clay, flesh, sustenance and air. A thing has a material. Things are usually stone. People are usually flesh.

Questo è il vero e proprio codice sorgente di un gioco. E a leggerlo sembra un moderno De Rerum Natura. “Things are usually stone. People are usually flesh.” è poesia.

L’adozione di uno stile di programmazione “per relazioni” piuttosto che ad oggetti. Da anni tenevo la mia copia del Clocksin & Mellish in cantina e sono andato a riprenderla. Mi sono ritrovato a pensare al tema del mio esame di Prolog di tanti anni fa. Siamo abituati a pensare ad oggetti da tanto tempo che ci sembra l’unica maniera naturale di programmare. Mi è tornato in mente che la programmazione logica alla Prolog permette di scrivere certi tipi di programmi in maniera estremamente concisa. E la concisione è potere.

Giocare con I7 mi ha riportato alle radici della fantascienza che amavo da bambino. Un programma che capisce le mie istruzioni in inglese! E chi se ne importa se “capisce” solo un epsilon della complessità del linguaggio naturale. E’ più sofisticato di qualsiasi altro sistema abbia mai usato. E’ sufficiente per scrivere programmi. Scusate se è poco.

I7 è un domain-specific language per realizzare narrativa interattiva. Il problema di “comprendere il linguaggio naturale”, che è di una complessità tale da sfuggire di gran lunga alle nostre capacità di programmazione, diventa gestibile quando la comprensione viene limitata a un dominio specifico, quale nel nostro caso è la scrittura di avventure testuali.

Mi sono divertito a scrivere codice Inform 7 che fa semplici ragionamenti geometrici

A geometric shape is a kind of thing.

A triangle is a kind of geometric shape. It has a number called side A. It has a number called side B. It has a number called side C. After printing the name of a triangle: say “, with sides ([side A],[side B],[side C])”.

To decide whether (x – a number) equals (y – a number) and (z – a number):
if x is y and y is z, decide yes;
otherwise decide no.

Definition: A triangle is equilateral if its side A equals its side B and its side C.

The blue triangle is a triangle with side A 10, side B 10, and side C 10.

The green triangle is a triangle with side A 5, side B 5, and side C 10.

The pink triangle is a triangle with side A 3, side B 4, and side C 5.

The Geometry lab is a room. “You are in a weird lab.” The green triangle, the pink triangle and the blue triangle are in the lab.

A tester is a kind of container. They are always fixed in place.

The equilateral box is a tester. It is in the lab. “A large box is here; gold letters on it say ‘drop equilateral triangles here.'”

Instead of inserting something (called the supposed equilateral) into the equilateral box:
if the supposed equilateral is not an equilateral triangle, say “My, my. Read again the definition of ‘equilateral.'” instead;
Increase the score by one;
move the supposed equilateral to the equilateral box.

To decide whether (x – a number) equals (y – a number):
if x is y, decide yes;
decide no.

Definition: A triangle is isosceles if its side A equals its side B, or its side B equals its side C, or its side C equals its side A.

The isosceles box is a tester. It is in the lab. “A small box is here; silver letters on it say ‘drop isosceles triangles here.'”

Instead of inserting something (called the object) into the isosceles box:
if the object is not an isosceles triangle, say “A mysterious force prevents you from doing that.” instead;
Increase the score by one;
Move the object to the isosceles box.

Instead of taking something which is in a tester, say “You can’t reach inside the box.”.

Test remove with “put green into isosceles box / get green / get pink”

To decide what number is the square of (x – a number): decide on x times x.

To decide what number is the lesser of (x – a number) and (y – a number):
if x is greater than y, decide on y;
decide on x.

To decide what number is the greater of (x – a number) and (y – a number):
if x is less than y, decide on y;
decide on x.

To decide what number is the lesser of (x – a number) and (y – a number) and (z – a number):
let a be the lesser of x and y;
decide on the lesser of a and z.

To decide what number is the greater of (x – a number) and (y – a number) and (z – a number):
let a be the greater of x and y;
decide on the greater of a and z.

To decide what number is the middle value of (x – a number) and (y – a number) and (z – a number):
let a be the lesser of x and y;
let b be the lesser of y and z;
let c be the lesser of x and z;
decide on the greater of a and b and c.

To decide whether (x – a number) forms a pythagorean triple with (y – a number) and (z – a number):
let a be the lesser of x and y and z;
let b be the middle value of x and y and z;
let c be the greater of x and y and z;
if the square of a plus the square of b is the square of c, decide yes;
decide no.

Definition: a triangle is rectangle if its side A forms a pythagorean triple with its side B and its side C.

Mi riesco facilmente a immaginare come la concisione di Inform potrebbe essere catturata in un sistema per la realizzazione di applicazioni gestionali.

Un impiegato è una persona. Un impiegato ha una data di nascita, un nome, un cognome, e un numero chiamato salario…

Un utente appartiene a molti gruppi. Un gruppo contiene molti utenti. Un gruppo ha un insieme di diritti di accesso…

Tutti questi esperimenti con la generazione di applicazioni, e la comprensione del linguaggio naturale, sono stati fatti e abbandonati negli anni 80-90. Andavano sotto il nome di “linguaggi di quarta generazione”. Perché fallirono negli anni 90? Perché potrebbero avere successo oggi? Non c’è una singola ragione precisa. La ragione c’è, e dipende da come vengono fatte le cose. Prima di tutto, potremmo osservare che ci sono centinaia di framework per realizzare applicazioni web, ma solo una manciata sono di qualità paragonabile a Rails.

Rails mi ha subito colpito per l’attenzione che dava alla gestione del linguaggio naturale, sia nel presentare output all’utente (niente “0 file(s) copied”!) sia in come appare il sorgente al programmatore.

class User < ActiveRecord::base
  validates_presence_of :name, :address
  validates_uniqueness_of :nickname, :email

  has_many :posts
  has_and_belongs_to_many: groups
end

Definire "has_many :posts" aggiunge alla classe User una serie di metodi: ad esempio "user.posts" che restituisce gli oggetti "post" associati all'utente. Questo implica che Rails deve sapere che il singolare di "posts" è "post", così che venga usata la classe Post. Rails è preconfigurato con le regole più comuni della lingua inglese, ma posso benissimo estenderlo con regole aggiuntive. Per esempio, recentemente ho dovuto scrivere questo, per permettere a Rails di lavorare con un database legacy con i nomi delle tabelle in italiano:

Inflector.inflections do |inflect|
  inflect.irregular 'campagna',   'campagne'
  inflect.irregular 'promotore',  'promotori'
  inflect.irregular 'provincia',  'province'
  inflect.irregular 'regione',    'regioni'
  inflect.irregular 'trattativa', 'trattative'
end

E' stato sufficiente dare a Rails questa lezioncina di italiano per integrare i nomi di tabelle italiani nell'applicazione. Questo ti dà il senso che programmare bene significa definire un linguaggio. O meglio insegnare alla macchina un linguaggio, che ne estende le capacità.

4 Responses to “Il ritorno del linguaggio naturale: Inform”

  1. Enri Says:

    Molto interessante Matteo.

    Le avventure testuali mi sono sempre piaciute, ma non le avevo mai viste sotto quest’ottica, soprattutto perchè ero troppo piccolo quando ci giocavo.

    Programmazione logica e programmazione ad oggetti. Il confronto fa riflettere, anche e soprattutto alla luce di Ruby.

    Domanda: è più semplice (e mantenibile) implementare/creare un linguaggio (DSL) come quello che hai incollato sopra, utilizzando il paradigma ad oggetti (es Ruby) magari con qualche costrutto tirato dentro dal paradigma logico (vedi chiusure), o utilizzando un linguaggio alla Prolog?

  2. Enri Says:

    Aggiungo che FIT e Fitnesse mi stimolano molto soprattutto per questo motivo: non conosco nessun altro framework che mi permetta di esprimere proprietà in un linguaggio così vicino al linguaggio naturale.

  3. matteo Says:

    Credo che Ruby sia particolarmente adatto alla creazione di DSL. Non sono molto fluente con Prolog, ma credo che il suo target sia molto più circoscritto, ovvero i problemi che coinvolgono ricerca di alternative (alfa-beta, problemi combinatori, ricerca su alberi, ecc.)

  4. Andrea Garbagnoli Says:

    Penso che la possibilità di fare query complesse in linguaggio naturale su database relazionali sarebbe molto gradita; a che punto è la ricerca per questo genere di applicazioni?

Leave a Reply