La macchina di Pavlov

18 giugno, 2017 | 15 commenti

Humanity is doomed once the media is run by artificial intelligence. (J. Assange)

Per combattere il pensiero mainstream occorre conoscerlo. A questo scopo un gruppo di ricercatori pedanti ne ha riprodotto gli algoritmi in un simulatore. La macchina di Pavlov è un esperimento di intelligenza artificiale elementare, come lo è il fenomeno riprodotto.

Risponditore moderato

Il pubblico moderato reagisce a un set limitato di stimoli semantici, qui esemplificati nelle radici {"russia", "sovran", "nazion", "lira", "putin"}. Digita una frase nel campo (o seleziona una frase di default premendo le frecce su/giù) e premi invio. Premi ripetutamente invio per ottenere risposte diverse.

Sticazzi.

Risponditore AntiFa

Più lineare è la versione AntiFa dell'esperimento. Qui è sufficiente non parlare di fascismo, cioè non includere la radice {"fasci"} nell'input, per innescare il riflesso.

Ben detto.

Codici

La community ha rielaborato in diversi linguaggi informatici il codice dei risponditori utilizzati nell'esperimento, nell'intento di fornire a storici, ricercatori e psichiatri una base di sviluppo per approfondire l'analisi.

Bash (Tonno nella Tonnara):

#!/bin/bash 
# Generatore di risposte moderate
echo "Inserisci una frase: "
read input
phrase=$(echo "$input" | tr '[:upper:]' '[:lower:]')
x=$(echo $phrase | grep -E "russia|sovran|nazion|lira|putin")
RANDOM=$$

if [ -n "$x" ]
then
  reply=$((RANDOM%5))
case $reply in
    0) echo "Fascionazzionalistabrutto!"
       echo ""; echo ""
       ;;
    1) echo "Lei e' un populista. Mi fa ovvove."
       echo ""; echo ""
       ;;
    2) echo "Ah, ho capito. Il solito neurino."
       echo ""; echo ""
       ;;
    3) echo "E il debito pubblico? Eh? Eh?"
       echo ""; echo ""
       ;;
    4) echo "Vedi come e' finita l'Argentina..."
       echo ""; echo ""
       ;;
    *) 
  esac
  
else
  echo "Esticazzi...";
  echo ""; echo ""
fi

C++ 11 (Tiziano Diamanti):

#include <iostream>
#include <string>
#include <vector>
#include <random>
#include <omp.h>
#include <mutex>

using namespace std;

int main(int argc, char **argv)
{
  string phrase, reply;
  vector<string> bads = { "russia", "sovran", "nazion", "lira", "putin" };
  vector<string> replies = { "Fascionazzzionalistabrutto!", "Lei e' un populista. Mi fa ovvove", 
  "Ah, ho capito. Il solito neurino.", "E il debito pubblico? Eh? Eh?", "Vedi come e' finita l'Argentina..." };
  random_device rd; 
  mt19937 gen(rd());
  uniform_int_distribution<> dis(0, replies.size() - 1);
  cout << "Inserisci una frase" << endl;
  getline (cin, phrase);
  
  static mutex mutex;
  #pragma omp parallel for
  for (string bad : bads)
  {
    if (phrase.find(bad) != string::npos)
    {
      lock_guard<std::mutex> lock(mutex);
      reply = replies.at(dis(gen));
      break;
    }
  }
  
  !reply.empty() ? cout << reply : cout << "Sticazzi";
  cout << endl;
  
  return 0;
}</std::mutex></string></string></mutex></omp.h></random></vector></string></iostream>

Free Basic (Marco Caporaletti):

REM *** Free Basic Online *** 
REM *** edito at: https://www.tutorialspoint.com/compile_freebasic_online.php

Dim phrase  as String
Dim lphrase as String
Dim n as Integer
Dim f as Integer
Dim bads(1 to 5) as String = {"russia","sovran","nazion","lira","putin"} 
Dim replies(1 to 5) as String = {"Fascionazzionalistabrutto!","Lei è un populista. Mi fa ovvove.","Ah, ho capito. Il solito neurino.","E il debito pubblico? Eh? Eh?","Vedi come è finita l'Argentina..."}

Line Input "Inserisci una frase"; phrase
lphrase = Lcase(phrase)

f=0
For n=1 to 5
    If (InStr(lphrase, bads(n)) > 0) then
        f=1
        Exit For
    End If
next

if f > 0 then
    print replies(Rnd*5)
else
    print "Sticazzi!"
end if

Javascript/Jquery (vers. estesa che gira su questa pagina) (Il Pedante):

var generatore = {

  response: function(id, phrase) {

    this.fillReply(id, this.responder[id](phrase));
  
  },

  responder: {

    antifa: function(phrase) {
      return (phrase.toLowerCase().indexOf('fasci') == -1) ? generatore.replies.antifa[Math.floor(Math.random()*generatore.replies.antifa.length)] : 'Ben detto!';
    },

    moderati: function(phrase) {

      var reply = 'Sticazzi.';
      var replies = generatore.replies.moderati;
      var bads = generatore.bads.moderati;

      for (var i = bads.length - 1; i >= 0; i--) {
        if (phrase.toLowerCase().indexOf(bads[i]) > -1) {
          reply = replies[Math.floor(Math.random()*replies.length)];
        }
      };

      return reply;

    }
  },

  fillDefault: function(id, charCode) {

    var defaults = this.defaults[id];
    
    if (charCode == 38) { // Su
      this.defaultIndex[id] = (this.defaultIndex[id] == 0) ? defaults.length-1 : this.defaultIndex[id] - 1;
    } else { // Giù
      this.defaultIndex[id] = (this.defaultIndex[id] == defaults.length-1) ? 0 : this.defaultIndex[id] + 1;
    }

    $('input.frase#'+id).val(defaults[this.defaultIndex[id]]);

  },

  fillReply: function(id, phrase) {

    $('p#'+id).text(phrase);
  
  },

  defaultIndex: { antifa: 0, moderati: 0 },

  defaults: {
    antifa: [
      'Mi scusi, sa che ore sono?', 'Buongiorno a Lei!', 'Mi sa che pomeriggio viene a piovere.', 'Vedo fascisti che escono dalle fottute pareti.'
    ],
    moderati: [
      'La sovranità appartiene al popolo, che la esercita...', 'Mio figlio suona l\'inno nazionale con l\'ocarina.', 'In Grecia non ci sono più farmaci.', 'Putin ha dichiarato che...', 'Il lavoro è sempre più precarizzato: ce lo chiede Leuropa.', 'Suono la lira in un coro di voci bianche.'
    ]
  },

  replies: {
    antifa: [
      'Fassista!', 'Ecco un altro fascistello da ricacciare nelle fogne.', 'Per quelli come te ci vuole Piazzale Loreto, ci vuole.', 'Gratta gratta, salta fuori il rossobruno.', 'Classico ragionamento da fascio.', 'Ti puoi nascondere finché vuoi, ma io i fasci li riconosco dal fetore.', 
    ],
    moderati: [
      'Fascionazzionalistabrutto!', 'Lei è un populista. Mi fa ovvove.', 'Ah, ho capito. Il solito neurino.', 'E il debito pubblico? Eh? Eh?', 'Vedi come è finita l\'Argentina...'
    ]
  },

  bads: { 
    moderati: [
      'russi', 'sovran', 'nazion', 'lira', 'putin'
    ]
  }
}

Lua (Il Pedante):

print( "Inserisci una frase:" )

phrase = io.read()

bads = { "russ", "sovran", "nazion", "lira", "putin" }
replies = { "fascionazzionalistabrutto!", "Lei è un populista. Mi fa ovvove.", "Ah, ho capito. Il solito neurino.", "E il debito pubblico? Eh? Eh?", "Vedi come è finita l'Argentina..." }
reply = "Sticazzi"

for i, bad in ipairs( bads ) do
  if phrase:lower():find( bad ) then
    reply = replies[ math.random( #replies ) ];
    break
  end
end

print( reply )

MatLab (Antonio Stanziola):

phrase = lower(input('Inserisci una frase:\n','s'));

bads = {'russia', 'sovran', 'nazion', 'lira', 'putin'};
replies = {'Fascionazzionalistabrutto!',...
    'Lei è un populista. Mi fa ovvove.',...
    'Ah, ho capito. Il solito neurino.',...
    'E il debito pubblico? Eh ? Eh?', ...
    "Vedi come è finita l'Argentina"};

for b = bads
    if strfind(phrase,b{1})
        reply = replies{randi(length(replies))}; break
    end
end

if exist('reply','var'); fprintf(strcat(reply, '\n')); else
    fprintf('Sticazzi\n'); end

Perl6 (Vittore Scolari)

#!perl6

my @tokens = qw|russia sovran nazion lira putin|;

my @aggressivity = q:to/⬅ 完/.split("\n", :skip-empty);
    Fascionazzionalistabrutto!
    Lei e' un populista. Mi fa ovvove.
    Ah, ho capito. Il solito neurino.
    E il debito pubblico? Eh? Eh?
    Vedi come e' finita l'Argentina...
    ⬅ 完

my @defaults = q:to/⬅ 完/.split("\n", :skip-empty);
    Esticazzi...
    ⬅ 完

my $input = prompt "Inserisci una frase: ";

my $phrase= $input.lc;

if $phrase.match: any(@tokens) {
    say @aggressivity.pick; say ""; say "";
} else {
    say @defaults.pick; say ""; say "";
}

PHP (Il Pedante):

echo "\nInserisci una frase:\n";

$phrase = fgets(STDIN);
$bads = array('russia', 'sovran', 'nazion', 'lira', 'putin');
$replies = ('Fascionazzionalistabrutto!', 'Lei è un populista. Mi fa ovvove.', 'Ah, ho capito. Il solito neurino.', 'E il debito pubblico? Eh? Eh?', 'Vedi come è finita l\'Argentina...');

foreach ($bads as $bad) {
  if(strpos(strtolower($phrase), $bad) !== false) {
    $reply = $replies[array_rand($replies)];
    break;
  }
}

echo (isset($reply)) ? $reply : "Sticazzi.";
echo "\n\n";

PHP vers. AntiFa (Il Pedante):

echo "\nInserisci una frase:\n";

$phrase = fgets(STDIN);

echo (strpos(strtolower($phrase), 'fasc')) ? 'Ben detto.' : 'Fascista!';
echo "\n\n";

Python 2.7 (TonnoNellaTonnara):

#!/usr/bin/python

# Generatore di risposte moderate

import sys
import random

print "Inserisci una frase: "

phrase = sys.stdin.readline()

bads = ["russia",
        "sovran",
        "nazion",
        "lira",
        "putin"]

replies = ["Fascionazzionalistabrutto!",
           "Lei e' un populista. Mi fa ovvove.",
           "Ah, ho capito. Il solito neurino.",
           "E il debito pubblico? Eh? Eh?",
           "Vedi come e' finita l'Argentina..."]

random.seed()
k = random.randint(0,len(bads)-1)

for bad in bads:
  if (bad in phrase.lower()):
    reply = replies[k] 

try:
  reply
except NameError:
  print "Sticazzi\n\n"
else:
  print reply, "\n\n"

Ruby (Flavio):

loop do

print "Inserisci una frase: "
phrase = STDIN.readline.chomp

answer = 'Sticazzi'

answer = [
"Fascionazzionalistabrutto!",
"Lei e' un populista. Mi fa ovvove.",
"Ah, ho capito. Il solito neurino.",
"E il debito pubblico? Eh? Eh?",
"Vedi come e' finita l'Argentina..."
].sample if phrase =~ /(russia|sovran|nazion|lira|putin)/

puts answer
end

Rust (Marc0gr):

extern crate rand;

use std::io;
use rand::Rng;

// Generatore di risposte moderate /©IlPedante
fn main() {
    let bads = ["russia", "sovran", "nazion", "lira", "putin"];
    let replies = [
        "Fascionazzionalistabrutto!", 
        "Lei è un populista. Mi fa ovvove.",
        "Ah, ho capito. Il solito neurino.",
        "E il debito pubblico? Eh? Eh?",
        "Vedi com'è finita l'Argentina..."
    ];
    println!("Inserisci una frase:");
    let mut phrase = String::new();
    io::stdin()
        .read_line(&mut phrase)
        .expect("Impossibile leggere da stdin");
    let phrase = phrase.to_lowercase();
    if bads.iter().any(|bad| phrase.contains(bad)) {
        println!("{}", rand::thread_rng().choose(&replies).unwrap());        
    } else {
        println!("Sticazzi");
    }
}

Scratch (Stefano Longagnani): v. https://scratch.mit.edu/projects/165284396.

Scratch vers. AntiFa (Stefano Longagnani): v. https://scratch.mit.edu/projects/166494272.

Tcl/Tk (Marco Caporaletti):

# TCL/TK ActiveState ActiveTcl 8.5.17.0.298612 Nov 09, 2014

# init variables and arrays
set phrase ""
set reply "Sticazzi!"
set bads [split "russia+sovran+nazion+lira+putin"]                       
set replies [split "Fascionazzionalistabrutto!+Lei è un populista. Mi fa ovvove.+Ah, ho capito. Il solito neurino.+E il debito pubblico? Eh? Eh?+Vedi come è finita l'Argentina..." +]    

# mainloop
while {$phrase != "end"} {
    
    # get input
    puts "Inserisci una frase o 'end'"
    set phrase [string tolower [gets stdin]]

    # words compare
    foreach bad $bads {
        if {[string first $bad $phrase] >= 0} {
            set reply [lindex $replies [expr {int(rand()*[llength $replies])}]]
            break
        } 
    }    
    puts "$reply\n\n"
}

...


Lascia un commento

Invia

Flavio 26 dicembre, 2017 15:03

Versione Ruby

===========

loop do

print "Inserisci una frase: "

phrase = STDIN.readline.chomp

answer = 'Sticazzi'

answer = [

"Fascionazzionalistabrutto!",

"Lei e' un populista. Mi fa ovvove.",

"Ah, ho capito. Il solito neurino.",

"E il debito pubblico? Eh? Eh?",

"Vedi come e' finita l'Argentina..."

].sample if phrase =~ /(russia|sovran|nazion|lira|putin)/

puts answer

end

Rispondi

massimo 02 luglio, 2017 22:13

non ho capito niente -

Rispondi

Maurizio Moretti 21 giugno, 2017 19:37

Bell'idea

Gli algoritmi potrebbero venir estesi scansionando piu' a fondo l'input in modo da discriminare fra domande e affermazioni, doppi negativi, numero di aggettivi, ecc.

Per le risposte suggerirei un semplice file di testo dove i paragrafi (CR LF) segnano i confini dei record. In questo modo il database di risposte si potrebbe estendere a piacimento.

Ottima anche l'idea di rete neurale.

E introducendo un feedback finale (risposta gradita, sgradita, a vanvera) l'algoritmo potrebbe cominciare a "imparare" sul serio.

Rispondi

Di Cuius 23 giugno, 2017 09:28

Gentile @Maurizio Moretti,

il risponditore moderato reagisce in modo pavloviano a semplici stimoli; la sua idea è molto interessante (seppur più complicata di quello che può apparire), ma renderebbe il risponditore più intelligente rispetto a quello che realmente è, cioè rispetto alla realtà “moderata” che simula.

Rispondi

NicolaTE 20 giugno, 2017 20:17

Caro IlPedante,

pure il programmatore sai fare?

Io di computer ci capisco un'acca, quindi per me questa è magia. Magia molto divertente.

Mi permetto però di segnalare che mancano riferimenti alla Cina e soprattutto al fatto che l'immigrazione è necessaria, visto che noi italiani facciamo schifo, e che tutto ciò è ineluttabile.

Saluti,

Nicola

Rispondi

petrux 20 giugno, 2017 14:11

Sarebbe possibile trovare abbastanza materiale per addestrare una rete neural (o anche un modello linguistico più semplice)?

Rispondi

Fartzilla 20 giugno, 2017 12:58

AH AH AH!

L'unico problema (forse) è che se do del fascista all'Antifa, egli risponde: "Ben detto!", credendo ce l'abbia con un altro...

Rispondi

Stefano Longagnani 21 giugno, 2017 14:11

Gentile @Fartzilla,

lo abbiamo notato probabilmente in molti, e abbiamo sorriso piacevolmente del deprecabile (?) "errore"... ;-)

Rispondi

Davide Piva 20 giugno, 2017 09:53

Bellissima idea.

Vorrei dare due suggerimenti "evergreen" per il risponditore moderato:

1) i debiti si pagano (soprattutto in riferimento alla tragica situazione greca).

2) abbiamo vissuto al di sopra delle nostre possibilità (sta bene con tutto).

3) il debito pubblico ci toglie credibilità.

Rispondi

Take Zoo 19 giugno, 2017 20:43

La versione C++11 contiene l'effetto di qualche postprocessamento che ha interpretato gli include come tag HTML/XML ed è andato a chiuderli in automatico. (Poi come C++11 è quasi-antidiomatico, ma questa è più un'opinione personale. Credo.)

La versione bash a occhio può essere tranquillamente sh e usa i soliti onnipresenti strumenti esterni (grep…)…

Rispondi

Bombadillo 19 giugno, 2017 18:29

Carissimi,

io ci aggiungerei:

Però l'Europa ci ha dato la pace (al moderato);

Stai zitto tu, fascista (all'antifa).

Tom

Rispondi

Yari 18 giugno, 2017 07:43

Uno strumento di vitale importanza, che potrà finalmente svelare il segreto dei segreti.

Un ringraziamento pedante a tutti i ricercatori coinvolti. L'umanità ne aveva bisogno.

Dobbiamo comprendere per correggere.

Rispondi

Stefano Longagnani 18 giugno, 2017 02:39

Peccato non essere stato degno di citazione. Ma vedo che ne mancano parecchi altri. Il mIO amor proprio sopporterà stoicamente. :-)

Rispondi

Il Pedante 18 giugno, 2017 10:30

È in progress. Ho problemi di codifiche dei caratteri sul server che mi rallentano.

Rispondi

Stefano Longagnani 18 giugno, 2017 23:29

Gentile @Il Pedante,

mi scuso per la poca pazienza dimostrata. A mia parziale giustificazione il fatto che non mi ero reso conto che il post fosse in progress.

Segnalo, se può essere utile al pubblico e ad altri ricercatori pedanti che volessere approfondire il modello di "intelligenza" (con le virgolette) qui riprodotto, che è possibile includere il software funzionante direttamente in altri siti web tramite il seguente codice (che si può scaricare pure dal sito del MIT facendo click sul pulsante "Includi"):

<iframe allowtransparency="true" width="485" height="402" src="/scratch.mit.edu/projects/embed/165284396/?autostart=false" frameborder="0" allowfullscreen></iframe>

L'unica scomodità è che per il funzionamento del programma di chi volesse guardarlo o analizzarne il codice il computer deve essere dotato di Flash (e questo purtroppo taglia fuori moltissimi dispositivi mobili). Un click su un pulsante con una caption abbastanza inquietante ("Guarda dentro") consente di analizzare il codice.

Con stima e cordialità (e un grazie per questo lavoro che ha risvegliato molte mie sinapsi da tempo dormienti).

P.S. mi permetto di suggerire un ulteriore indirizzo di ricerca pedante: anche un traduttore simultaneo per quando si interloquisce personalmente con un piddino potrebbe diventare a breve uno strumento indispensabile (cfr. /p/dizionario.html )

P.P.S. Per farmi perdonare l'impazienza ho scritto pure la versione ANTIFA. La trova qui: https://scratch.mit.edu/projects/166494272/

Rispondi