Gary Larson has this famous cartoon:
It might as well be labelled, 'What
chatbots hear'.
I type something profound to the chatbot, and this is what the program gets:
"I *!@ +^% £")# owl +=&£."
Plainly no amount of
inference is going to reconstruct
that. However, a gossipy chatbot has only to keep the conversation going .. .
An Eliza-type program uses
patterns such as:
"I tokens* owl tokens*" => "How interested are you in owls?"
where the response is bland enough to match most owl-related utterances.
If the chatbot can recognise a little more, perhaps put some syntactic structure to it, then we could do a semantically-informed best match to the noisy user input using a metric over the space of semantic structures (I'm thinking something like
situation semantics, or more likely an extensible, data-populated semantic net).
It might be tempting to map everything into a vector space but that's way too much gratuitous (and irrelevant) structure: like doing logic programming using arithmetic over
Gödel numbering. To save us from that was why God invented compilers.
---
I'd like to play with some of these ideas, restart my stalled chatbot programme. But I'm lazy, I don't want to do low-level coding, I want a really high-level language which lets me get straight into the problem space. And this brings me - via consideration of
Lisp and
Haskell - back to Prolog.
As I
wrote a couple of years ago,
"First, Prolog. Its supporters always touted it as a higher-level language than Lisp - though I always found Lisp more congenial, I like to set up data structures and manipulate them explicitly. With Prolog you define relationships between things and the miraculous powers of unification and depth-first search with backtracking pull magical rabbits out of hats. The Eliza program in Prolog can be read in its entirety on one screen, ditto for the blocks world planning system.
This procedural power is the result of enormously complex recursive structures built at execution time by the Prolog system. It frequently defies one's powers of abstraction, short-term memory and inference to visualise what's actually going on. I know you're meant to read and understand the programs declaratively, but in reality you don't get too far without a consideration of what actually happens at run-time.
Still, the power to write ridiculously-powerful programs in just a few lines of code is addictive. It reminds me of the first time I fired the General-Purpose Machine Gun (GPMG). I was good with the Lee-Enfield rifle and prided myself on my accuracy; the GPMG just bounced around and hosed the target. So much power and so little control!"
---
Oh, and here's
Eliza in Prolog (as modified to represent our deceased pet, Shadow) from the Sterling and Shapiro book, '
The Art of Prolog', (chapter 14):
shadow :-
write('Hello, I am Shadow. Miaow!'),
nl,write('Please type your thoughts and press return.'),
nl,write('To finish type bye'),nl,
read_word_list(Input),shadow(Input),!.
shadow([bye]) :- reply(['Goodbye, miaow!']).
shadow(Input) :-
pattern(Stimulus,Response),
match(Stimulus,Dictionary,Input),
match(Response,Dictionary,Output),
reply(Output),
read_word_list(Input1),
!,shadow(Input1).
match([Word|Pattern],Dictionary,[Word|Target]) :-
atom(Word),
match(Pattern,Dictionary,Target).
match([N|Pattern],Dictionary,Target) :-
integer(N),
append(LeftTarget,RightTarget,Target),
lookup(N,Dictionary,LeftTarget),
match(Pattern,Dictionary,RightTarget).
match([],_,[]).
reply([Head|Tail]) :- write(Head), write(' '),reply(Tail).
reply([]) :- nl.
lookup(Key,[(Key,Value)|_],Value).
lookup(Key,[(Key1,_)|Dict],Value) :-
Key \= Key1,lookup(Key,Dict,Value).
There are some lower-level functions (and the relevant patterns) defined elsewhere, but this is the gist of it.
Pretty clear, wouldn't you say?
I used to think it was just me, but I read somewhere of the despair of computer science students at Edinburgh university at the sheer intellectual difficulty of writing (and even understanding) non-trivial programs in Prolog. It would seem there's a high IQ-cutoff just to use the language at all.
This reminds me of
Marain, the language of the Culture, where those dialects used by the Minds were simply beyond the intellectual capacities of humans. And while we're on
that case, let me remind you of a real-world counterpart:
Malbolge.
"... invented by Ben Olmstead in 1998 and named after the eighth circle of hell in Dante's Inferno.
"Malbolge was specifically designed to be almost impossible to use, via a counter-intuitive 'crazy operation', base-three arithmetic, and self-altering code." *
In fact the author of Malbolge was unable himself to write a program in it.
In the end it required an AI system to write the first program, using a form of 'best-first' search in the space of all possible programs.
Here is the "Hello World!" program in Malbolge.
(=<`#9]~6ZY32Vx/4Rs+0No-&Jk)"Fh}|Bcy?`=*z]Kw%oG4UUS0/@-ejc(:'8dc
---
* Malbolge design trivia.
After each instruction is executed, the guilty instruction gets encrypted so that it won't do the same thing next time, unless a jump just happened. Right after a jump, Malbolge will encrypt the innocent instruction just prior to the one it jumped to instead."
Of course, with artificial neural networks and deep learning, we're already
away with the fairies as far as esoteric programming is concerned.
As for me, I've re-installed
SWI-Prolog. Time to get up to speed with
programming in logic again -
so hard to think with, yet so much more compact than Lisp.