eliza in js following charles hayden's classic java implementation
commit
d1d5eca12e
@ -0,0 +1,360 @@
|
||||
initial: How do you do. Please tell me your problem.
|
||||
final: Goodbye. Thank you for talking to me.
|
||||
quit: bye
|
||||
quit: goodbye
|
||||
quit: quit
|
||||
pre: dont don't
|
||||
pre: cant can't
|
||||
pre: wont won't
|
||||
pre: recollect remember
|
||||
pre: dreamt dreamed
|
||||
pre: dreams dream
|
||||
pre: maybe perhaps
|
||||
pre: how what
|
||||
pre: when what
|
||||
pre: certainly yes
|
||||
pre: machine computer
|
||||
pre: computers computer
|
||||
pre: were was
|
||||
pre: you're you are
|
||||
pre: i'm i am
|
||||
pre: same alike
|
||||
post: am are
|
||||
post: your my
|
||||
post: me you
|
||||
post: myself yourself
|
||||
post: yourself myself
|
||||
post: i you
|
||||
post: you I
|
||||
post: my your
|
||||
post: i'm you are
|
||||
synon: belief feel think believe wish
|
||||
synon: family mother mom father dad sister brother wife children child
|
||||
synon: desire want need
|
||||
synon: sad unhappy depressed sick
|
||||
synon: happy elated glad better
|
||||
synon: cannot can't
|
||||
synon: everyone everybody nobody noone
|
||||
synon: be am is are was
|
||||
key: xnone
|
||||
decomp: *
|
||||
reasmb: I'm not sure I understand you fully.
|
||||
reasmb: Please go on.
|
||||
reasmb: What does that suggest to you ?
|
||||
reasmb: Do you feel strongly about discussing such things ?
|
||||
key: sorry
|
||||
decomp: *
|
||||
reasmb: Please don't apologise.
|
||||
reasmb: Apologies are not necessary.
|
||||
reasmb: I've told you that apologies are not required.
|
||||
key: apologise
|
||||
decomp: *
|
||||
reasmb: goto sorry
|
||||
key: remember 5
|
||||
decomp: * i remember *
|
||||
reasmb: Do you often think of (2) ?
|
||||
reasmb: Does thinking of (2) bring anything else to mind ?
|
||||
reasmb: What else do you recollect ?
|
||||
reasmb: Why do you recollect (2) just now ?
|
||||
reasmb: What in the present situation reminds you of (2) ?
|
||||
reasmb: What is the connection between me and (2) ?
|
||||
decomp: * do you remember *
|
||||
reasmb: Did you think I would forget (2) ?
|
||||
reasmb: Why do you think I should recall (2) now ?
|
||||
reasmb: What about (2) ?
|
||||
reasmb: goto what
|
||||
reasmb: You mentioned (2) ?
|
||||
key: if 3
|
||||
decomp: * if *
|
||||
reasmb: Do you think its likely that (2) ?
|
||||
reasmb: Do you wish that (2) ?
|
||||
reasmb: What do you know about (2) ?
|
||||
reasmb: Really, if (2) ?
|
||||
key: dreamed 4
|
||||
decomp: * i dreamed *
|
||||
reasmb: Really, (2) ?
|
||||
reasmb: Have you ever fantasized (2) while you were awake ?
|
||||
reasmb: Have you ever dreamed (2) before ?
|
||||
reasmb: goto dream
|
||||
key: dream 3
|
||||
decomp: *
|
||||
reasmb: What does that dream suggest to you ?
|
||||
reasmb: Do you dream often ?
|
||||
reasmb: What persons appear in your dreams ?
|
||||
reasmb: Do you believe that dreams have something to do with your problems ?
|
||||
key: perhaps
|
||||
decomp: *
|
||||
reasmb: You don't seem quite certain.
|
||||
reasmb: Why the uncertain tone ?
|
||||
reasmb: Can't you be more positive ?
|
||||
reasmb: You aren't sure ?
|
||||
reasmb: Don't you know ?
|
||||
key: name 15
|
||||
decomp: *
|
||||
reasmb: I am not interested in names.
|
||||
reasmb: I've told you before, I don't care about names -- please continue.
|
||||
key: deutsch
|
||||
decomp: *
|
||||
reasmb: goto xforeign
|
||||
reasmb: I told you before, I don't understand German.
|
||||
key: francais
|
||||
decomp: *
|
||||
reasmb: goto xforeign
|
||||
reasmb: I told you before, I don't understand French.
|
||||
key: italiano
|
||||
decomp: *
|
||||
reasmb: goto xforeign
|
||||
reasmb: I told you before, I don't understand Italian.
|
||||
key: espanol
|
||||
decomp: *
|
||||
reasmb: goto xforeign
|
||||
reasmb: I told you before, I don't understand Spanish.
|
||||
key: xforeign
|
||||
decomp: *
|
||||
reasmb: I speak only English.
|
||||
key: hello
|
||||
decomp: *
|
||||
reasmb: How do you do. Please state your problem.
|
||||
reasmb: Hi. What seems to be your problem ?
|
||||
key: computer 50
|
||||
decomp: *
|
||||
reasmb: Do computers worry you ?
|
||||
reasmb: Why do you mention computers ?
|
||||
reasmb: What do you think machines have to do with your problem ?
|
||||
reasmb: Don't you think computers can help people ?
|
||||
reasmb: What about machines worrys you ?
|
||||
reasmb: What do you think about machines ?
|
||||
key: am
|
||||
decomp: * am i *
|
||||
reasmb: Do you believe you are (2) ?
|
||||
reasmb: Would you want to be (2) ?
|
||||
reasmb: Do you wish I would tell you you are (2) ?
|
||||
reasmb: What would it mean if you were (2) ?
|
||||
reasmb: goto what
|
||||
decomp: *
|
||||
reasmb: Why do you say 'am' ?
|
||||
reasmb: I don't understand that.
|
||||
key: are
|
||||
decomp: * are you *
|
||||
reasmb: Why are you interested in whether I am (2) or not ?
|
||||
reasmb: Would you prefer if I weren't (2) ?
|
||||
reasmb: Perhaps I am (2) in your fantasies.
|
||||
reasmb: Do you sometimes think I am (2) ?
|
||||
reasmb: goto what
|
||||
decomp: * are *
|
||||
reasmb: Did you think they might not be (2) ?
|
||||
reasmb: Would you like it if they were not (2) ?
|
||||
reasmb: What if they were not (2) ?
|
||||
reasmb: Possibly they are (2).
|
||||
key: your
|
||||
decomp: * your *
|
||||
reasmb: Why are you concerned over my (2) ?
|
||||
reasmb: What about your own (2) ?
|
||||
reasmb: Are you worried about someone else's (2) ?
|
||||
reasmb: Really, my (2) ?
|
||||
key: was 2
|
||||
decomp: * was i *
|
||||
reasmb: What if you were (2) ?
|
||||
reasmb: Do you think you were (2) ?
|
||||
reasmb: Were you (2) ?
|
||||
reasmb: What would it mean if you were (2) ?
|
||||
reasmb: What does (2) suggest to you ?
|
||||
reasmb: goto what
|
||||
decomp: * i was *
|
||||
reasmb: Were you really ?
|
||||
reasmb: Why do you tell me you were (2) now ?
|
||||
reasmb: Perhaps I already know you were (2).
|
||||
decomp: * was you *
|
||||
reasmb: Would you like to believe I was (2) ?
|
||||
reasmb: What suggests that I was (2) ?
|
||||
reasmb: What do you think ?
|
||||
reasmb: Perhaps I was (2).
|
||||
reasmb: What if I had been (2) ?
|
||||
key: i
|
||||
decomp: * i @desire *
|
||||
reasmb: What would it mean to you if you got (3) ?
|
||||
reasmb: Why do you want (3) ?
|
||||
reasmb: Suppose you got (3) soon ?
|
||||
reasmb: What if you never got (3) ?
|
||||
reasmb: What would getting (3) mean to you ?
|
||||
reasmb: What does wanting (3) have to do with this discussion ?
|
||||
decomp: * i am* @sad *
|
||||
reasmb: I am sorry to hear that you are (3).
|
||||
reasmb: Do you think that coming here will help you not to be (3) ?
|
||||
reasmb: I'm sure it's not pleasant to be (3).
|
||||
reasmb: Can you explain what made you (3) ?
|
||||
decomp: * i am* @happy *
|
||||
reasmb: How have I helped you to be (3) ?
|
||||
reasmb: Has your treatment made you (3) ?
|
||||
reasmb: What makes you (3) just now ?
|
||||
reasmb: Can you explan why you are suddenly (3) ?
|
||||
decomp: * i was *
|
||||
reasmb: goto was
|
||||
decomp: * i @belief * i *
|
||||
reasmb: Do you really think so ?
|
||||
reasmb: But you are not sure you (3).
|
||||
reasmb: Do you really doubt you (3) ?
|
||||
decomp: * i* @belief *you *
|
||||
reasmb: goto you
|
||||
decomp: * i am *
|
||||
reasmb: Is it because you are (2) that you came to me ?
|
||||
reasmb: How long have you been (2) ?
|
||||
reasmb: Do you believe it is normal to be (2) ?
|
||||
reasmb: Do you enjoy being (2) ?
|
||||
decomp: * i @cannot *
|
||||
reasmb: How do you think that you can't (3) ?
|
||||
reasmb: Have you tried ?
|
||||
reasmb: Perhaps you could (3) now.
|
||||
reasmb: Do you really want to be able to (3) ?
|
||||
decomp: * i don't *
|
||||
reasmb: Don't you really (2) ?
|
||||
reasmb: Why don't you (2) ?
|
||||
reasmb: Do you wish to be able to (2) ?
|
||||
reasmb: Does that trouble you ?
|
||||
decomp: * do i feel *
|
||||
reasmb: Tell me more about such feelings.
|
||||
reasmb: Do you often feel (2) ?
|
||||
reasmb: Do you enjoy feeling (2) ?
|
||||
reasmb: Of what does feeling (2) remind you ?
|
||||
decomp: * i * you *
|
||||
reasmb: Perhaps in your fantasies we (2) each other.
|
||||
reasmb: Do you wish to (2) me ?
|
||||
reasmb: You seem to need to (2) me.
|
||||
reasmb: Do you (2) anyone else ?
|
||||
decomp: *
|
||||
reasmb: You say (1) ?
|
||||
reasmb: Can you elaborate on that ?
|
||||
reasmb: Do you say (1) for some special reason ?
|
||||
reasmb: That's quite interesting.
|
||||
key: you
|
||||
decomp: * you remind me of *
|
||||
reasmb: goto alike
|
||||
decomp: * you are *
|
||||
reasmb: What makes you think I am (2) ?
|
||||
reasmb: Does it please you to believe I am (2) ?
|
||||
reasmb: Do you sometimes wish you were (2) ?
|
||||
reasmb: Perhaps you would like to be (2).
|
||||
decomp: * you* me *
|
||||
reasmb: Why do you think I (2) you ?
|
||||
reasmb: You like to think I (2) you -- don't you ?
|
||||
reasmb: What makes you think I (2) you ?
|
||||
reasmb: Really, I (2) you ?
|
||||
reasmb: Do you wish to believe I (2) you ?
|
||||
reasmb: Suppose I did (2) you -- what would that mean ?
|
||||
reasmb: Does someone else believe I (2) you ?
|
||||
decomp: * you *
|
||||
reasmb: We were discussing you -- not me.
|
||||
reasmb: Oh, I (2) ?
|
||||
reasmb: You're not really talking about me -- are you ?
|
||||
reasmb: What are your feelings now ?
|
||||
key: yes
|
||||
decomp: *
|
||||
reasmb: You seem to be quite positive.
|
||||
reasmb: You are sure.
|
||||
reasmb: I see.
|
||||
reasmb: I understand.
|
||||
key: no
|
||||
decomp: *
|
||||
reasmb: Are you saying no just to be negative?
|
||||
reasmb: You are being a bit negative.
|
||||
reasmb: Why not ?
|
||||
reasmb: Why 'no' ?
|
||||
key: my 2
|
||||
decomp: $ * my *
|
||||
reasmb: Lets discuss further why your (2).
|
||||
reasmb: Earlier you said your (2).
|
||||
reasmb: But your (2).
|
||||
reasmb: Does that have anything to do with the fact that your (2) ?
|
||||
decomp: * my* @family *
|
||||
reasmb: Tell me more about your family.
|
||||
reasmb: Who else in your family (4) ?
|
||||
reasmb: Your (3) ?
|
||||
reasmb: What else comes to mind when you think of your (3) ?
|
||||
decomp: * my *
|
||||
reasmb: Your (2) ?
|
||||
reasmb: Why do you say your (2) ?
|
||||
reasmb: Does that suggest anything else which belongs to you ?
|
||||
reasmb: Is it important that your (2) ?
|
||||
key: can
|
||||
decomp: * can you *
|
||||
reasmb: You believe I can (2) don't you ?
|
||||
reasmb: goto what
|
||||
reasmb: You want me to be able to (2).
|
||||
reasmb: Perhaps you would like to be able to (2) yourself.
|
||||
decomp: * can i *
|
||||
reasmb: Whether or not you can (2) depends on you more than me.
|
||||
reasmb: Do you want to be able to (2) ?
|
||||
reasmb: Perhaps you don't want to (2).
|
||||
reasmb: goto what
|
||||
key: what
|
||||
decomp: *
|
||||
reasmb: Why do you ask ?
|
||||
reasmb: Does that question interest you ?
|
||||
reasmb: What is it you really wanted to know ?
|
||||
reasmb: Are such questions much on your mind ?
|
||||
reasmb: What answer would please you most ?
|
||||
reasmb: What do you think ?
|
||||
reasmb: What comes to mind when you ask that ?
|
||||
reasmb: Have you asked such questions before ?
|
||||
reasmb: Have you asked anyone else ?
|
||||
key: because
|
||||
decomp: *
|
||||
reasmb: Is that the real reason ?
|
||||
reasmb: Don't any other reasons come to mind ?
|
||||
reasmb: Does that reason seem to explain anything else ?
|
||||
reasmb: What other reasons might there be ?
|
||||
key: why
|
||||
decomp: * why don't you *
|
||||
reasmb: Do you believe I don't (2) ?
|
||||
reasmb: Perhaps I will (2) in good time.
|
||||
reasmb: Should you (2) yourself ?
|
||||
reasmb: You want me to (2) ?
|
||||
reasmb: goto what
|
||||
decomp: * why can't i *
|
||||
reasmb: Do you think you should be able to (2) ?
|
||||
reasmb: Do you want to be able to (2) ?
|
||||
reasmb: Do you believe this will help you to (2) ?
|
||||
reasmb: Have you any idea why you can't (2) ?
|
||||
reasmb: goto what
|
||||
decomp: *
|
||||
reasmb: goto what
|
||||
key: everyone 2
|
||||
decomp: * @everyone *
|
||||
reasmb: Realy, (2) ?
|
||||
reasmb: Surely not (2).
|
||||
reasmb: Can you think of anyone in particular ?
|
||||
reasmb: Who, for example?
|
||||
reasmb: Are you thinking of a very special person ?
|
||||
reasmb: Who, may I ask ?
|
||||
reasmb: Someone special perhaps ?
|
||||
reasmb: You have a particular person in mind, don't you ?
|
||||
reasmb: Who do you think you're talking about ?
|
||||
key: everybody 2
|
||||
decomp: *
|
||||
reasmb: goto everyone
|
||||
key: nobody 2
|
||||
decomp: *
|
||||
reasmb: goto everyone
|
||||
key: noone 2
|
||||
decomp: *
|
||||
reasmb: goto everyone
|
||||
key: always 1
|
||||
decomp: *
|
||||
reasmb: Can you think of a specific example ?
|
||||
reasmb: When ?
|
||||
reasmb: What incident are you thinking of ?
|
||||
reasmb: Really, always ?
|
||||
key: alike 10
|
||||
decomp: *
|
||||
reasmb: In what way ?
|
||||
reasmb: What resemblence do you see ?
|
||||
reasmb: What does that similarity suggest to you ?
|
||||
reasmb: What other connections do you see ?
|
||||
reasmb: What do you suppose that resemblence means ?
|
||||
reasmb: What is the connection, do you suppose ?
|
||||
reasmb: Could here really be some connection ?
|
||||
reasmb: How ?
|
||||
key: like 10
|
||||
decomp: * @be *like *
|
||||
reasmb: goto alike
|
||||
|
@ -0,0 +1,191 @@
|
||||
function chatbot (rules, textarea, display, debug) {
|
||||
function process_rules (rules) {
|
||||
function looping_iterator (l) {
|
||||
var next = function () {
|
||||
var ret = l[next.i];
|
||||
if (++next.i >= l.length) { next.i = 0 };
|
||||
return ret;
|
||||
};
|
||||
next.length = l.length;
|
||||
next.i = 0;
|
||||
next.items = l;
|
||||
return next;
|
||||
}
|
||||
// index pre + post and tokenize results
|
||||
function _index (name) {
|
||||
var new_value = {};
|
||||
rules[name].forEach(function (x) {
|
||||
var words = tokenize(x),
|
||||
word = words.shift();
|
||||
new_value[word] = words;
|
||||
})
|
||||
rules[name] = new_value;
|
||||
}
|
||||
_index("pre");
|
||||
_index("post");
|
||||
// index synonmys by first word
|
||||
var new_synon = {};
|
||||
rules.synon.forEach(function (x) {
|
||||
var words = tokenize(x);
|
||||
new_synon[words[0]] = words;
|
||||
})
|
||||
rules.synon = new_synon;
|
||||
// index keywords by name
|
||||
rules.keywords_by_token = {};
|
||||
rules.keywords.forEach(function (x) {
|
||||
// console.log("token", x.token);
|
||||
rules.keywords_by_token[x.token] = x;
|
||||
// wrap the rules
|
||||
x.rules.forEach(function (r) {
|
||||
// ensure list
|
||||
if (!Array.isArray(r.reasmb)) { r.reasmb = [r.reasmb]; }
|
||||
// wrap the reasmb list in a looping iterator that perserves its state
|
||||
r.reasmb = looping_iterator(r.reasmb);
|
||||
});
|
||||
});
|
||||
// console.log("keywords_by_token", rules.keywords_by_token)
|
||||
}
|
||||
// function trim (text) { return text.replace(/\s+$/, "").replace(/\s+/, ""); }
|
||||
function trimword (text) {
|
||||
return text
|
||||
.replace(/[^a-zA-Zéèàöùç]+$/, "")
|
||||
.replace(/^[^a-zA-Zéèàöùç]+/, "");
|
||||
}
|
||||
|
||||
function tokenize (text) {
|
||||
return (trimword(text).split(/\s+/).map(trimword));
|
||||
}
|
||||
|
||||
function sub (tokens, subst) {
|
||||
for (var i=0, l=tokens.length; i<l; i++) {
|
||||
var sub = subst[tokens[i].toLowerCase()];
|
||||
if (sub) {
|
||||
if (Array.isArray(sub)) {
|
||||
Array.prototype.splice.apply(tokens, [i, 1].concat(sub));
|
||||
i += (sub.length - 1);
|
||||
} else {
|
||||
tokens[i] = sub;
|
||||
}
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
function select_keywords (tokens) {
|
||||
var ret = [];
|
||||
for (var i=0, l=tokens.length; i<l; i++) {
|
||||
var w = tokens[i].toLowerCase(),
|
||||
rule = rules.keywords_by_token[w];
|
||||
if (rule) { ret.push(rule); }
|
||||
}
|
||||
if (rules.keywords_by_token.xnone && rules.keywords_by_token.xnone.weight != 0) {
|
||||
// append xnone rule pre-sort
|
||||
ret.push(rules.keywords_by_token.xnone);
|
||||
}
|
||||
ret.sort(function (a, b) { return b.weight - a.weight });
|
||||
if (rules.keywords_by_token.xnone && rules.keywords_by_token.xnone.weight == 0) {
|
||||
// append xnone rule post-sort (ensuring it's last)
|
||||
ret.push(rules.keywords_by_token.xnone);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
function compile_pattern (pattern) {
|
||||
// compile a decomposition pattern
|
||||
// * i @cannot * ==> i(cannot|cant|...)(.+)
|
||||
// * i* @belief *you * ==> (belief|feel|think|believe|wish)
|
||||
// * i @belief i *
|
||||
var ret = pattern
|
||||
.replace(/ *\* */g, "*") // compact spaces around stars
|
||||
.replace(/\*/g, "(.*?)")
|
||||
.replace(/@(\w+)/, function (match, word) {
|
||||
var syn = rules.synon[word.toLowerCase()];
|
||||
if (syn) {
|
||||
return "("+syn.join("|")+")";
|
||||
} else {
|
||||
console.log("Missing @synonym", word);
|
||||
return match;
|
||||
}
|
||||
});
|
||||
return "^"+ret+"$";
|
||||
}
|
||||
function match_decomp (pattern, tokens) {
|
||||
var ppat = compile_pattern(pattern);
|
||||
// console.log("compile_pattern.in", pattern);
|
||||
// console.log("compile_pattern.out", ppat);
|
||||
var ppat = new RegExp(ppat, "i");
|
||||
return ppat.exec(tokens.join(" "));
|
||||
}
|
||||
function do_post (txt) {
|
||||
var tokens = tokenize(txt);
|
||||
tokens = sub(tokens, rules.post);
|
||||
return tokens.join(" ");
|
||||
}
|
||||
function do_reasmb (reasmb, match, tokens) {
|
||||
if (Array.isArray(match)) {
|
||||
return reasmb.replace(/\((\d+)\)/, function (m, n) {
|
||||
// console.log("replace", m, n);
|
||||
var ret = match[parseInt(n)];
|
||||
return do_post(ret); // apply POST substitutions here to matching input
|
||||
});
|
||||
} else {
|
||||
return reasmb;
|
||||
}
|
||||
}
|
||||
function apply_keywords (keywords, tokens) {
|
||||
for (var i=0, l=keywords.length; i<l; i++) {
|
||||
var keyword = keywords[i];
|
||||
while (true) {
|
||||
console.log("trying keyword", keyword.token);
|
||||
for (var ri=0, rl = keyword.rules.length; ri<rl; ri++) {
|
||||
var rule = keyword.rules[ri];
|
||||
console.log("trying rule", rule.decomp, "("+(ri+1)+"/"+rl+")");
|
||||
var match = match_decomp(rule.decomp, tokens);
|
||||
if (match) {
|
||||
var ra = rule.reasmb();
|
||||
if (ra.indexOf("goto ") == 0) {
|
||||
var goto_name = ra.substr(5);
|
||||
console.log("goto", goto_name);
|
||||
keyword = rules.keywords_by_token[goto_name]
|
||||
} else {
|
||||
console.log("match", match, ra);
|
||||
return do_reasmb(ra, match, tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function log (msg, kls) {
|
||||
var d = document.createElement("div");
|
||||
d.setAttribute("class", kls);
|
||||
d.innerHTML = msg;
|
||||
display.appendChild(d);
|
||||
}
|
||||
function say (msg) {
|
||||
log(msg, "bot");
|
||||
}
|
||||
|
||||
function process (text) {
|
||||
if (debug) { console.log("input", text); }
|
||||
var tokens = tokenize(text);
|
||||
if (debug) { console.log("tokens", tokens); }
|
||||
tokens = sub(tokens, rules.pre);
|
||||
if (debug) { console.log("pre", tokens); }
|
||||
var keywords = select_keywords(tokens);
|
||||
if (debug) { console.log("keywords", keywords.map(function (x) { return x.token })); }
|
||||
var output = apply_keywords(keywords, tokens);
|
||||
if (debug) { console.log("output", output); }
|
||||
say(output);
|
||||
}
|
||||
|
||||
process_rules(rules);
|
||||
textarea.addEventListener("keypress", function (event) {
|
||||
if (event.keyCode == 13) {
|
||||
var text = textarea.value;
|
||||
log(text, "user");
|
||||
process(text);
|
||||
textarea.value = "";
|
||||
textarea.focus();
|
||||
}
|
||||
});
|
||||
say(rules.initial);
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
"""
|
||||
key: remember 5
|
||||
decomp: * i remember *
|
||||
reasmb: Do you often think of (2) ?
|
||||
reasmb: Does thinking of (2) bring anything else to mind ?
|
||||
reasmb: What else do you recollect ?
|
||||
reasmb: Why do you remember (2) just now ?
|
||||
reasmb: What in the present situation reminds you of (2) ?
|
||||
reasmb: What is the connection between me and (2) ?
|
||||
reasmb: What else does (2) remind you of ?
|
||||
"""
|
||||
import sys
|
||||
|
||||
output = {}
|
||||
output['pre'] = pre = []
|
||||
output['post'] = post = []
|
||||
output['synon'] = synon = []
|
||||
output['quit'] = quit = []
|
||||
output['keywords'] = keys = []
|
||||
for line in sys.stdin:
|
||||
line = line.strip()
|
||||
if line.startswith("#") or not line:
|
||||
continue
|
||||
cmd, rest = line.split(" ", 1)
|
||||
cmd = cmd.strip()
|
||||
rest = rest.strip()
|
||||
if cmd == "initial:":
|
||||
output['initial'] = rest
|
||||
elif cmd == "final:":
|
||||
output['final'] = rest
|
||||
elif cmd == "pre:":
|
||||
pre.append(rest)
|
||||
elif cmd == "post:":
|
||||
post.append(rest)
|
||||
elif cmd == "synon:":
|
||||
synon.append(rest)
|
||||
elif cmd == "key:":
|
||||
try:
|
||||
token, weight = rest.split()
|
||||
except ValueError:
|
||||
token = rest.strip()
|
||||
weight = 0
|
||||
print ("key", token, int(weight), file=sys.stderr)
|
||||
keys.append({"token": token.strip(), "weight": int(weight), "rules": []})
|
||||
elif line.startswith("decomp:"):
|
||||
_, pattern = line.split(" ", 1)
|
||||
print ("decomp", pattern, file=sys.stderr)
|
||||
keys[-1]['rules'].append({"decomp": pattern.strip(), "reasmb": []})
|
||||
elif line.startswith("reasmb:"):
|
||||
_, pattern = line.split(" ", 1)
|
||||
print ("reasmb", pattern, file=sys.stderr)
|
||||
keys[-1]['rules'][-1]['reasmb'].append(pattern.strip())
|
||||
# out = {}
|
||||
# keywords = out['keywords'] = {}
|
||||
# for obj in keys:
|
||||
# keyname = obj.get("token")
|
||||
# del obj['token']
|
||||
# keywords[keyname] = obj
|
||||
import json
|
||||
print (json.dumps(output, indent=2))
|
@ -0,0 +1,64 @@
|
||||
How Eliza Works
|
||||
|
||||
All the behavior of Eliza is controlled by a script file.
|
||||
The standard script is attached to the end of this explanation.
|
||||
|
||||
Eliza starts by reading the script file. Because of Java security, it
|
||||
must be on the same server as the class files. Eliza then reads a line at
|
||||
a time from the user, processes it, and formulates a reply.
|
||||
|
||||
Processing consists of the following steps.
|
||||
First the sentence broken down into words, separated by spaces. All further
|
||||
processing takes place on these words as a whole, not on the individual
|
||||
characters in them.
|
||||
Second, a set of pre-substitutions takes place.
|
||||
Third, Eliza takes all the words in the sentence and makes a list of all
|
||||
keywords it finds. It sorts this keyword list in descending weight. It
|
||||
process these keywords until it produces an output.
|
||||
Fourth, for the given keyword, a list of decomposition patterns is searched.
|
||||
The first one that matches is selected. If no match is found, the next keyword
|
||||
is selected instead.
|
||||
Fifth, for the matching decomposition pattern, a reassembly pattern is
|
||||
selected. There may be several reassembly patterns, but only one is used
|
||||
for a given sentence. If a subsequent sentence selects the same decomposition
|
||||
pattern, the next reassembly pattern in sequence is used, until they have all
|
||||
been used, at which point Eliza starts over with the first reassembly pattern.
|
||||
Sixth, a set of post-substitutions takes place.
|
||||
Finally, the resulting sentence is displayed as output.
|
||||
|
||||
The script is used to construct the pre and post substitution lists, the
|
||||
keyword lists, and the decomposition and reassembly patterns.
|
||||
In addition, there is a synonym matching facility, which is explained below.
|
||||
|
||||
Every line of script is prefaced by a tag that tells what list it is
|
||||
part of. Here is an explanation of the tags.
|
||||
|
||||
initial: Eliza says this when it starts.
|
||||
final: Eliza says this when it quits.
|
||||
quit: If the input is this, then Eliza quits. Any number permitted.
|
||||
pre: Part of the pre-substitution list. If the first word appears in
|
||||
the sentence, it is replaced by the rest of the words.
|
||||
post: Part of the post-subsititution list. If the first word appears
|
||||
in the sentence, it is replaced by the rest of the words.
|
||||
key: A keyword. Keywords with greater weight are selected in
|
||||
preference to ones with lesser weight.
|
||||
If no weight is given, it is assumed to be 1.
|
||||
decomp: A decomposition pattern. The character * stands for any
|
||||
sequence of words.
|
||||
reasmb: A reassembly pattern. A set of words matched by * in
|
||||
the decomposition pattern can be used as part of the reassembly.
|
||||
For instance, (2) inserts the words matched by the second *
|
||||
in the decomposition pattern.
|
||||
synon: A list of synonyms. In a decomposition rule, for instance, @be
|
||||
matches any of the words "be am is are was" because of the line:
|
||||
"synon: be am is are was". The match @be also counts as a *
|
||||
in numbering the matches for use by reassembly rules.
|
||||
|
||||
Other Special Rules
|
||||
If a $ appears first in a decomposition rule, then the output is formed as
|
||||
normal, but is saved and Eliza goes on to the next keyword. If no keywords
|
||||
match, and there are saved sentences, one of them is picked at random and
|
||||
used as the output, then it is discarded.
|
||||
If there are no saved sentences, and no keywords match, then it uses the
|
||||
keyword "xnone".
|
||||
|
@ -0,0 +1,13 @@
|
||||
from __future__ import print_function
|
||||
import json, sys, argparse
|
||||
|
||||
ap = argparse.ArgumentParser("wrap JSON in either a variable declaration (hardcode) or a callback (JSONP).")
|
||||
ap.add_argument("--variable", default="weft", help="define a variable")
|
||||
ap.add_argument("--callback", help="use a named callback (JSONP) -- overrides --variable")
|
||||
args = ap.parse_args()
|
||||
|
||||
d = json.load(sys.stdin)
|
||||
if args.callback:
|
||||
print ("{0}({1});".format(args.callback, json.dumps(d)))
|
||||
else:
|
||||
print ("{0} = {1};".format(args.variable, json.dumps(d)))
|
Loading…
Reference in New Issue