Converted to use json for rules instead of yaml
[eliza.git] / eliza.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 51,
6 "metadata": {},
7 "outputs": [],
8 "source": [
9 "# import yaml\n",
10 "import json\n",
11 "import collections\n",
12 "import random"
13 ]
14 },
15 {
16 "cell_type": "code",
17 "execution_count": 52,
18 "metadata": {},
19 "outputs": [],
20 "source": [
21 "Match = collections.namedtuple('Match', 'text, rule, bindings')"
22 ]
23 },
24 {
25 "cell_type": "code",
26 "execution_count": 53,
27 "metadata": {},
28 "outputs": [],
29 "source": [
30 "# def read_rules_y(rules_file):\n",
31 "# with open(rules_file) as f:\n",
32 "# rules = [{'pattern': r['pattern'].split(),\n",
33 "# 'responses': [t.split() for t in r['responses']]}\n",
34 "# for r in yaml.safe_load(f)]\n",
35 "# return rules\n",
36 "\n",
37 "# all_rules_y = read_rules_y('rules.yaml')\n",
38 "# all_rules_y"
39 ]
40 },
41 {
42 "cell_type": "code",
43 "execution_count": 54,
44 "metadata": {},
45 "outputs": [
46 {
47 "data": {
48 "text/plain": [
49 "[{'pattern': ['?X', 'hello', '?Y'],\n",
50 " 'responses': [['how',\n",
51 " 'do',\n",
52 " 'you',\n",
53 " 'do.',\n",
54 " 'please',\n",
55 " 'state',\n",
56 " 'your',\n",
57 " 'problem']]},\n",
58 " {'pattern': ['?X', 'computer', '?Y'],\n",
59 " 'responses': [['do', 'computers', 'worry', 'you'],\n",
60 " ['what', 'do', 'you', 'think', 'about', 'machines'],\n",
61 " ['why', 'do', 'you', 'mention', 'computers'],\n",
62 " ['what',\n",
63 " 'do',\n",
64 " 'you',\n",
65 " 'think',\n",
66 " 'machines',\n",
67 " 'have',\n",
68 " 'to',\n",
69 " 'do',\n",
70 " 'with',\n",
71 " 'your',\n",
72 " 'problem']]},\n",
73 " {'pattern': ['?X', 'name', '?Y'],\n",
74 " 'responses': [['i', 'am', 'not', 'interested', 'in', 'names']]},\n",
75 " {'pattern': ['?X', 'sorry', '?Y'],\n",
76 " 'responses': [['please', \"don't\", 'apologize'],\n",
77 " ['apologies', 'are', 'not', 'necessary'],\n",
78 " ['what', 'feelings', 'do', 'you', 'have', 'when', 'you', 'apologize']]},\n",
79 " {'pattern': ['?X', 'i', 'remember', '?Y'],\n",
80 " 'responses': [['do', 'you', 'often', 'think', 'of', '?Y'],\n",
81 " ['does', 'thinking', 'of', '?Y', 'bring', 'anything', 'else', 'to', 'mind'],\n",
82 " ['what', 'else', 'do', 'you', 'remember?'],\n",
83 " ['why', 'do', 'you', 'recall', '?Y', 'right', 'now'],\n",
84 " ['what',\n",
85 " 'in',\n",
86 " 'this',\n",
87 " 'present',\n",
88 " 'situation',\n",
89 " 'reminds',\n",
90 " 'you',\n",
91 " 'of',\n",
92 " '?Y'],\n",
93 " ['what', 'is', 'the', 'connection', 'between', 'me', 'and', '?Y']]},\n",
94 " {'pattern': ['?X', 'do', 'you', 'remember', '?Y'],\n",
95 " 'responses': [['did', 'you', 'think', 'i', 'would', 'forget', '?Y'],\n",
96 " ['why', 'do', 'you', 'think', 'i', 'should', 'recall', '?Y'],\n",
97 " ['what', 'about', '?Y'],\n",
98 " ['you', 'mentioned', '?Y']]},\n",
99 " {'pattern': ['?X', 'if', '?Y'],\n",
100 " 'responses': [['do',\n",
101 " 'you',\n",
102 " 'really',\n",
103 " 'think',\n",
104 " 'it',\n",
105 " 'is',\n",
106 " 'likely',\n",
107 " 'that',\n",
108 " '?Y'],\n",
109 " ['do', 'you', 'wish', 'that', '?Y'],\n",
110 " ['what', 'do', 'you', 'think', 'about', '?Y'],\n",
111 " ['really', '--', 'if', '?Y']]},\n",
112 " {'pattern': ['?X', 'i', 'dreamt', '?Y'],\n",
113 " 'responses': [['really', '--', '?Y'],\n",
114 " ['have',\n",
115 " 'you',\n",
116 " 'ever',\n",
117 " 'fantasized',\n",
118 " '?Y',\n",
119 " 'while',\n",
120 " 'you',\n",
121 " 'were',\n",
122 " 'awake'],\n",
123 " ['have', 'you', 'dreamt', '?Y', 'before']]},\n",
124 " {'pattern': ['?X', 'i', 'dreamed', '?Y'],\n",
125 " 'responses': [['really', '--', '?Y'],\n",
126 " ['have',\n",
127 " 'you',\n",
128 " 'ever',\n",
129 " 'fantasized',\n",
130 " '?Y',\n",
131 " 'while',\n",
132 " 'you',\n",
133 " 'were',\n",
134 " 'awake'],\n",
135 " ['have', 'you', 'dreamed', '?Y', 'before']]},\n",
136 " {'pattern': ['?X', 'dream', '?Y'],\n",
137 " 'responses': [['what', 'does', 'this', 'dream', 'suggest', 'to', 'you'],\n",
138 " ['do', 'you', 'dream', 'often'],\n",
139 " ['what', 'persons', 'appear', 'in', 'your', 'dreams'],\n",
140 " [\"don't\",\n",
141 " 'you',\n",
142 " 'believe',\n",
143 " 'that',\n",
144 " 'dream',\n",
145 " 'has',\n",
146 " 'to',\n",
147 " 'do',\n",
148 " 'with',\n",
149 " 'your',\n",
150 " 'problem']]},\n",
151 " {'pattern': ['?X', 'my', 'mother', '?Y'],\n",
152 " 'responses': [['who', 'else', 'is', 'in', 'your', 'family', '?Y'],\n",
153 " ['tell', 'me', 'more', 'about', 'your', 'family']]},\n",
154 " {'pattern': ['?X', 'my', 'father', '?Y'],\n",
155 " 'responses': [['your', 'father'],\n",
156 " ['does', 'he', 'influence', 'you', 'strongly'],\n",
157 " ['what',\n",
158 " 'else',\n",
159 " 'comes',\n",
160 " 'to',\n",
161 " 'mind',\n",
162 " 'when',\n",
163 " 'you',\n",
164 " 'think',\n",
165 " 'of',\n",
166 " 'your',\n",
167 " 'father']]},\n",
168 " {'pattern': ['?X', 'i', 'want', '?Y'],\n",
169 " 'responses': [['what', 'would', 'it', 'mean', 'if', 'you', 'got', '?Y'],\n",
170 " ['why', 'do', 'you', 'want', '?Y'],\n",
171 " ['suppose', 'you', 'got', '?Y', 'soon']]},\n",
172 " {'pattern': ['?X', 'i', 'am', 'glad', '?Y'],\n",
173 " 'responses': [['how', 'have', 'i', 'helped', 'you', 'to', 'be', '?Y'],\n",
174 " ['what', 'makes', 'you', 'happy', 'just', 'now'],\n",
175 " ['can', 'you', 'explain', 'why', 'you', 'are', 'suddenly', '?Y']]},\n",
176 " {'pattern': ['?X', 'i', 'am', 'happy', '?Y'],\n",
177 " 'responses': [['how', 'have', 'i', 'helped', 'you', 'to', 'be', '?Y'],\n",
178 " ['what', 'makes', 'you', 'glad', 'just', 'now'],\n",
179 " ['can', 'you', 'explain', 'why', 'you', 'are', 'suddenly', '?Y']]},\n",
180 " {'pattern': ['?X', 'i', 'am', 'sad', '?Y'],\n",
181 " 'responses': [['i', 'am', 'sorry', 'to', 'hear', 'you', 'are', 'depressed'],\n",
182 " [\"i'm\", 'sure', \"it's\", 'not', 'pleasant', 'to', 'be', 'sad']]},\n",
183 " {'pattern': ['?X', 'i', 'am', 'unhappy', '?Y'],\n",
184 " 'responses': [['i', 'am', 'sorry', 'to', 'hear', 'you', 'are', 'depressed'],\n",
185 " [\"i'm\", 'sure', \"it's\", 'not', 'pleasant', 'to', 'be', 'unhappy']]},\n",
186 " {'pattern': ['?X', 'are', 'like', '?Y'],\n",
187 " 'responses': [['what',\n",
188 " 'resemblance',\n",
189 " 'do',\n",
190 " 'you',\n",
191 " 'see',\n",
192 " 'between',\n",
193 " '?X',\n",
194 " 'and',\n",
195 " '?Y']]},\n",
196 " {'pattern': ['?X', 'is', 'like', '?Y'],\n",
197 " 'responses': [['in',\n",
198 " 'what',\n",
199 " 'way',\n",
200 " 'is',\n",
201 " 'it',\n",
202 " 'that',\n",
203 " '?X',\n",
204 " 'is',\n",
205 " 'like',\n",
206 " '?Y'],\n",
207 " ['what', 'resemblence', 'do', 'you', 'see'],\n",
208 " ['could', 'there', 'really', 'be', 'some', 'connection'],\n",
209 " ['how']]},\n",
210 " {'pattern': ['?X', 'alike', '?Y'],\n",
211 " 'responses': [['in', 'what', 'way'],\n",
212 " ['what', 'similarities', 'are', 'there']]},\n",
213 " {'pattern': ['?X', 'same', '?Y'],\n",
214 " 'responses': [['what', 'other', 'connections', 'do', 'you', 'see']]},\n",
215 " {'pattern': ['?X', 'i', 'was', '?Y'],\n",
216 " 'responses': [['were', 'you', 'really'],\n",
217 " ['perhaps', 'i', 'already', 'knew', 'you', 'were', '?Y'],\n",
218 " ['why', 'do', 'you', 'tell', 'me', 'you', 'were', '?Y', 'now']]},\n",
219 " {'pattern': ['?X', 'was', 'i', '?Y'],\n",
220 " 'responses': [['what', 'if', 'you', 'were', '?Y'],\n",
221 " ['do', 'you', 'think', 'you', 'were', '?Y'],\n",
222 " ['what', 'would', 'it', 'mean', 'if', 'you', 'were', '?Y']]},\n",
223 " {'pattern': ['?X', 'i', 'am', '?Y'],\n",
224 " 'responses': [['in', 'what', 'way', 'are', 'you', '?Y'],\n",
225 " ['do', 'you', 'want', 'to', 'be', '?Y']]},\n",
226 " {'pattern': ['?X', 'am', 'i', '?Y'],\n",
227 " 'responses': [['do', 'you', 'believe', 'you', 'are', '?Y'],\n",
228 " ['would', 'you', 'want', 'to', 'be', '?Y'],\n",
229 " ['you', 'wish', 'i', 'would', 'tell', 'you', 'you', 'are', '?Y'],\n",
230 " ['what', 'would', 'it', 'mean', 'if', 'you', 'were', '?Y']]},\n",
231 " {'pattern': ['?X', 'am', '?Y'],\n",
232 " 'responses': [['why', 'do', 'you', 'say', '\"am\"'],\n",
233 " ['i', \"don't\", 'understand', 'that']]},\n",
234 " {'pattern': ['?X', 'are', 'you', '?Y'],\n",
235 " 'responses': [['why',\n",
236 " 'are',\n",
237 " 'you',\n",
238 " 'interested',\n",
239 " 'in',\n",
240 " 'whether',\n",
241 " 'i',\n",
242 " 'am',\n",
243 " '?Y',\n",
244 " 'or',\n",
245 " 'not'],\n",
246 " ['would', 'you', 'prefer', 'it', 'if', 'i', \"weren't\", '?Y'],\n",
247 " ['perhaps', 'i', 'am', '?Y', 'in', 'your', 'fantasies']]},\n",
248 " {'pattern': ['?X', 'you', 'are', '?Y'],\n",
249 " 'responses': [['what', 'makes', 'you', 'think', 'i', 'am', '?Y']]},\n",
250 " {'pattern': ['?X', 'because', '?Y'],\n",
251 " 'responses': [['is', 'that', 'the', 'real', 'reason'],\n",
252 " ['what', 'other', 'reason', 'might', 'there', 'be'],\n",
253 " ['does', 'that', 'reason', 'seem', 'to', 'explain', 'anything', 'else']]},\n",
254 " {'pattern': ['?X', 'were', 'you', '?Y'],\n",
255 " 'responses': [['perhaps', 'i', 'was', '?Y'],\n",
256 " ['what', 'do', 'you', 'think'],\n",
257 " ['what', 'if', 'i', 'had', 'been', '?Y']]},\n",
258 " {'pattern': ['?X', 'i', \"can't\", '?Y'],\n",
259 " 'responses': [['maybe', 'you', 'could', '?Y', 'now'],\n",
260 " ['what', 'if', 'you', 'could', '?Y']]},\n",
261 " {'pattern': ['?X', 'i', 'feel', '?Y'],\n",
262 " 'responses': [['do', 'you', 'often', 'feel', '?Y']]},\n",
263 " {'pattern': ['?X', 'i', 'felt', '?Y'],\n",
264 " 'responses': [['what', 'other', 'feelings', 'do', 'you', 'have']]},\n",
265 " {'pattern': ['?X', 'i', '?Y', 'you', '?Z'],\n",
266 " 'responses': [['perhaps',\n",
267 " 'in',\n",
268 " 'your',\n",
269 " 'fantasies',\n",
270 " 'we',\n",
271 " '?Y',\n",
272 " 'each',\n",
273 " 'other']]},\n",
274 " {'pattern': ['?X', 'why', \"don't\", 'you', '?Y'],\n",
275 " 'responses': [['should', 'you', '?Y', 'yourself'],\n",
276 " ['do', 'you', 'believe', 'i', \"don't\", '?Y'],\n",
277 " ['perhaps', 'i', 'will', '?Y', 'in', 'good', 'time']]},\n",
278 " {'pattern': ['?X', 'yes', '?Y'],\n",
279 " 'responses': [['you', 'seem', 'quite', 'positive'],\n",
280 " ['you', 'are', 'sure'],\n",
281 " ['i', 'understand']]},\n",
282 " {'pattern': ['?X', 'no', '?Y'],\n",
283 " 'responses': [['why', 'not'],\n",
284 " ['you', 'are', 'being', 'a', 'bit', 'negative'],\n",
285 " ['are', 'you', 'saying', '\"no\"', 'just', 'to', 'be', 'negative']]},\n",
286 " {'pattern': ['?X', 'someone', '?Y'],\n",
287 " 'responses': [['can', 'you', 'be', 'more', 'specific']]},\n",
288 " {'pattern': ['?X', 'everyone', '?Y'],\n",
289 " 'responses': [['surely', 'not', 'everyone'],\n",
290 " ['can', 'you', 'think', 'of', 'anyone', 'in', 'particular'],\n",
291 " ['who', 'for', 'example'],\n",
292 " ['you', 'are', 'thinking', 'of', 'a', 'special', 'person']]},\n",
293 " {'pattern': ['?X', 'always', '?Y'],\n",
294 " 'responses': [['can', 'you', 'think', 'of', 'a', 'specific', 'example'],\n",
295 " ['when'],\n",
296 " ['what', 'incident', 'are', 'you', 'thinking', 'of'],\n",
297 " ['really', '--', 'always']]},\n",
298 " {'pattern': ['?X', 'what', '?Y'],\n",
299 " 'responses': [['why', 'do', 'you', 'ask'],\n",
300 " ['does', 'that', 'question', 'interest', 'you'],\n",
301 " ['what', 'is', 'it', 'you', 'really', 'want', 'to', 'know'],\n",
302 " ['what', 'do', 'you', 'think'],\n",
303 " ['what', 'comes', 'to', 'your', 'mind', 'when', 'you', 'ask', 'that']]},\n",
304 " {'pattern': ['?X', 'perhaps', '?Y'],\n",
305 " 'responses': [['you', 'do', 'not', 'seem', 'quite', 'certain']]},\n",
306 " {'pattern': ['?X', 'are', '?Y'],\n",
307 " 'responses': [['do', 'you', 'think', 'they', 'might', 'not', 'be', '?Y'],\n",
308 " ['possibly', 'they', 'are', '?Y']]},\n",
309 " {'pattern': ['?X'],\n",
310 " 'responses': [['very', 'interesting'],\n",
311 " ['i', 'am', 'not', 'sure', 'i', 'understand', 'you', 'fully'],\n",
312 " ['what', 'does', 'that', 'suggest', 'to', 'you'],\n",
313 " ['please', 'continue'],\n",
314 " ['go', 'on'],\n",
315 " ['do',\n",
316 " 'you',\n",
317 " 'feel',\n",
318 " 'strongly',\n",
319 " 'about',\n",
320 " 'discussing',\n",
321 " 'such',\n",
322 " 'things']]}]"
323 ]
324 },
325 "execution_count": 54,
326 "metadata": {},
327 "output_type": "execute_result"
328 }
329 ],
330 "source": [
331 "def read_rules(rules_file):\n",
332 " with open(rules_file) as f:\n",
333 " rules = [{'pattern': r['pattern'].split(),\n",
334 " 'responses': [t.split() for t in r['responses']]}\n",
335 " for r in json.load(f)]\n",
336 " return rules\n",
337 "\n",
338 "all_rules = read_rules('rules.json')\n",
339 "all_rules"
340 ]
341 },
342 {
343 "cell_type": "code",
344 "execution_count": 55,
345 "metadata": {},
346 "outputs": [
347 {
348 "name": "stdout",
349 "output_type": "stream",
350 "text": [
351 "> hello there\n"
352 ]
353 },
354 {
355 "data": {
356 "text/plain": [
357 "['hello', 'there']"
358 ]
359 },
360 "execution_count": 55,
361 "metadata": {},
362 "output_type": "execute_result"
363 }
364 ],
365 "source": [
366 "i = input(\"> \")\n",
367 "i.split()"
368 ]
369 },
370 {
371 "cell_type": "code",
372 "execution_count": 56,
373 "metadata": {},
374 "outputs": [],
375 "source": [
376 "def match(text, rule):\n",
377 " return all_matches([Match(text, rule, {})])"
378 ]
379 },
380 {
381 "cell_type": "code",
382 "execution_count": 57,
383 "metadata": {},
384 "outputs": [],
385 "source": [
386 "def all_matches(matches):\n",
387 " successes = []\n",
388 " while matches:\n",
389 " # print(matches, successes)\n",
390 " current = matches[0]\n",
391 " new_matches = []\n",
392 " if successful_match(current):\n",
393 " successes += [current.bindings]\n",
394 " elif current.rule:\n",
395 " new_matches = match_item(current.text, current.rule, current.bindings)\n",
396 " matches = matches[1:] + new_matches\n",
397 " return successes"
398 ]
399 },
400 {
401 "cell_type": "code",
402 "execution_count": 58,
403 "metadata": {},
404 "outputs": [],
405 "source": [
406 "def is_var(word):\n",
407 " return word[0] == '?'"
408 ]
409 },
410 {
411 "cell_type": "code",
412 "execution_count": 59,
413 "metadata": {},
414 "outputs": [],
415 "source": [
416 "def successful_match(match):\n",
417 " return match.text == [] and match.rule == []"
418 ]
419 },
420 {
421 "cell_type": "code",
422 "execution_count": 60,
423 "metadata": {},
424 "outputs": [],
425 "source": [
426 "def splits(item):\n",
427 " return [(item[:i], item[i:]) for i in range(len(item)+1)]"
428 ]
429 },
430 {
431 "cell_type": "code",
432 "execution_count": 61,
433 "metadata": {},
434 "outputs": [
435 {
436 "data": {
437 "text/plain": [
438 "[('', 'harry'),\n",
439 " ('h', 'arry'),\n",
440 " ('ha', 'rry'),\n",
441 " ('har', 'ry'),\n",
442 " ('harr', 'y'),\n",
443 " ('harry', '')]"
444 ]
445 },
446 "execution_count": 61,
447 "metadata": {},
448 "output_type": "execute_result"
449 }
450 ],
451 "source": [
452 "splits(\"harry\")"
453 ]
454 },
455 {
456 "cell_type": "code",
457 "execution_count": 62,
458 "metadata": {},
459 "outputs": [],
460 "source": [
461 "def match_item(text, rule, bindings):\n",
462 " r0 = rule[0]\n",
463 " if is_var(r0):\n",
464 " if r0 in bindings:\n",
465 " # already seen this variable\n",
466 " if text[:len(bindings[r0])] == bindings[r0]:\n",
467 " return [Match(text[(len(bindings[r0])):], rule[1:], bindings)]\n",
468 " else:\n",
469 " return []\n",
470 " else:\n",
471 " # not seen this variable yet\n",
472 " matches = []\n",
473 " for pre, suf in splits(text):\n",
474 " new_bindings = bindings.copy()\n",
475 " new_bindings[r0] = pre\n",
476 " matches += [Match(suf, rule[1:], new_bindings)]\n",
477 " return matches\n",
478 " elif text and text[0] == r0:\n",
479 " return [Match(text[1:], rule[1:], bindings)]\n",
480 " else:\n",
481 " return []\n"
482 ]
483 },
484 {
485 "cell_type": "code",
486 "execution_count": 63,
487 "metadata": {},
488 "outputs": [
489 {
490 "data": {
491 "text/plain": [
492 "[{'?X': ['fred'], '?Y': ['jane']}]"
493 ]
494 },
495 "execution_count": 63,
496 "metadata": {},
497 "output_type": "execute_result"
498 }
499 ],
500 "source": [
501 "match('fred hello jane'.split(), '?X hello ?Y'.split())"
502 ]
503 },
504 {
505 "cell_type": "code",
506 "execution_count": 64,
507 "metadata": {},
508 "outputs": [
509 {
510 "data": {
511 "text/plain": [
512 "[{'?X': [], '?Y': ['jane']}]"
513 ]
514 },
515 "execution_count": 64,
516 "metadata": {},
517 "output_type": "execute_result"
518 }
519 ],
520 "source": [
521 "match('hello jane'.split(), '?X hello ?Y'.split())"
522 ]
523 },
524 {
525 "cell_type": "code",
526 "execution_count": 65,
527 "metadata": {},
528 "outputs": [
529 {
530 "data": {
531 "text/plain": [
532 "[{'?X': ['fred'], '?Y': []}]"
533 ]
534 },
535 "execution_count": 65,
536 "metadata": {},
537 "output_type": "execute_result"
538 }
539 ],
540 "source": [
541 "match('fred hello'.split(), '?X hello ?Y'.split())"
542 ]
543 },
544 {
545 "cell_type": "code",
546 "execution_count": 66,
547 "metadata": {},
548 "outputs": [
549 {
550 "data": {
551 "text/plain": [
552 "[{'?X': [], '?Y': []}]"
553 ]
554 },
555 "execution_count": 66,
556 "metadata": {},
557 "output_type": "execute_result"
558 }
559 ],
560 "source": [
561 "match('hello'.split(), '?X hello ?Y'.split())"
562 ]
563 },
564 {
565 "cell_type": "code",
566 "execution_count": 67,
567 "metadata": {},
568 "outputs": [
569 {
570 "data": {
571 "text/plain": [
572 "[]"
573 ]
574 },
575 "execution_count": 67,
576 "metadata": {},
577 "output_type": "execute_result"
578 }
579 ],
580 "source": [
581 "match('fred jane'.split(), '?X hello ?Y'.split())"
582 ]
583 },
584 {
585 "cell_type": "code",
586 "execution_count": 68,
587 "metadata": {},
588 "outputs": [
589 {
590 "data": {
591 "text/plain": [
592 "[{'?X': ['fred']}]"
593 ]
594 },
595 "execution_count": 68,
596 "metadata": {},
597 "output_type": "execute_result"
598 }
599 ],
600 "source": [
601 "match('fred hello'.split(), '?X hello'.split())"
602 ]
603 },
604 {
605 "cell_type": "code",
606 "execution_count": 69,
607 "metadata": {},
608 "outputs": [
609 {
610 "data": {
611 "text/plain": [
612 "[]"
613 ]
614 },
615 "execution_count": 69,
616 "metadata": {},
617 "output_type": "execute_result"
618 }
619 ],
620 "source": [
621 "match('hello fred'.split(), '?X hello'.split())"
622 ]
623 },
624 {
625 "cell_type": "code",
626 "execution_count": 70,
627 "metadata": {},
628 "outputs": [
629 {
630 "data": {
631 "text/plain": [
632 "[{'?X': ['yes'], '?Y': ['rain']}]"
633 ]
634 },
635 "execution_count": 70,
636 "metadata": {},
637 "output_type": "execute_result"
638 }
639 ],
640 "source": [
641 "match('yes i remember rain'.split(), '?X i remember ?Y'.split())"
642 ]
643 },
644 {
645 "cell_type": "code",
646 "execution_count": 71,
647 "metadata": {},
648 "outputs": [
649 {
650 "data": {
651 "text/plain": [
652 "[{'?X': ['no'], '?Y': ['rain']}]"
653 ]
654 },
655 "execution_count": 71,
656 "metadata": {},
657 "output_type": "execute_result"
658 }
659 ],
660 "source": [
661 "match('no i remember rain'.split(), '?X i remember ?Y'.split())"
662 ]
663 },
664 {
665 "cell_type": "code",
666 "execution_count": 72,
667 "metadata": {},
668 "outputs": [
669 {
670 "data": {
671 "text/plain": [
672 "[]"
673 ]
674 },
675 "execution_count": 72,
676 "metadata": {},
677 "output_type": "execute_result"
678 }
679 ],
680 "source": [
681 "match(\"no remember rain\".split(), '?X i remember ?Y'.split())"
682 ]
683 },
684 {
685 "cell_type": "code",
686 "execution_count": 73,
687 "metadata": {},
688 "outputs": [
689 {
690 "data": {
691 "text/plain": [
692 "[{'?X': [], '?Y': ['rain']}]"
693 ]
694 },
695 "execution_count": 73,
696 "metadata": {},
697 "output_type": "execute_result"
698 }
699 ],
700 "source": [
701 "match(\"i remember rain\".split(), '?X i remember ?Y'.split())"
702 ]
703 },
704 {
705 "cell_type": "code",
706 "execution_count": 74,
707 "metadata": {
708 "scrolled": true
709 },
710 "outputs": [
711 {
712 "data": {
713 "text/plain": [
714 "[{'?X': [], '?Y': ['hello', 'there', 'hello']},\n",
715 " {'?X': ['hello'], '?Y': ['there']}]"
716 ]
717 },
718 "execution_count": 74,
719 "metadata": {},
720 "output_type": "execute_result"
721 }
722 ],
723 "source": [
724 "match(\"hello there hello\".split(), '?X ?Y ?X'.split())"
725 ]
726 },
727 {
728 "cell_type": "code",
729 "execution_count": 75,
730 "metadata": {
731 "scrolled": true
732 },
733 "outputs": [
734 {
735 "data": {
736 "text/plain": [
737 "[{'?X': ['hello']}]"
738 ]
739 },
740 "execution_count": 75,
741 "metadata": {},
742 "output_type": "execute_result"
743 }
744 ],
745 "source": [
746 "match(\"hello there hello\".split(), '?X there ?X'.split())"
747 ]
748 },
749 {
750 "cell_type": "code",
751 "execution_count": 76,
752 "metadata": {},
753 "outputs": [
754 {
755 "data": {
756 "text/plain": [
757 "[{'?X': [], '?Y': ['hello', 'hello', 'hello']},\n",
758 " {'?X': ['hello'], '?Y': ['hello', 'hello']},\n",
759 " {'?X': ['hello', 'hello'], '?Y': ['hello']},\n",
760 " {'?X': ['hello', 'hello', 'hello'], '?Y': []}]"
761 ]
762 },
763 "execution_count": 76,
764 "metadata": {},
765 "output_type": "execute_result"
766 }
767 ],
768 "source": [
769 "match(\"hello hello hello\".split(), '?X ?Y'.split())"
770 ]
771 },
772 {
773 "cell_type": "code",
774 "execution_count": 77,
775 "metadata": {},
776 "outputs": [
777 {
778 "data": {
779 "text/plain": [
780 "[{'?X': [], '?Y': ['hello', 'hello', 'hello']},\n",
781 " {'?X': ['hello'], '?Y': ['hello']}]"
782 ]
783 },
784 "execution_count": 77,
785 "metadata": {},
786 "output_type": "execute_result"
787 }
788 ],
789 "source": [
790 "match(\"hello hello hello\".split(), '?X ?Y ?X'.split())"
791 ]
792 },
793 {
794 "cell_type": "code",
795 "execution_count": 78,
796 "metadata": {},
797 "outputs": [],
798 "source": [
799 "def candidate_rules(rules, comment):\n",
800 " return [(rule, bindings) \n",
801 " for rule in rules \n",
802 " for bindings in match(comment, rule['pattern'])]"
803 ]
804 },
805 {
806 "cell_type": "code",
807 "execution_count": 79,
808 "metadata": {
809 "scrolled": true
810 },
811 "outputs": [
812 {
813 "data": {
814 "text/plain": [
815 "[({'pattern': ['?X', 'i', 'remember', '?Y'],\n",
816 " 'responses': [['do', 'you', 'often', 'think', 'of', '?Y'],\n",
817 " ['does',\n",
818 " 'thinking',\n",
819 " 'of',\n",
820 " '?Y',\n",
821 " 'bring',\n",
822 " 'anything',\n",
823 " 'else',\n",
824 " 'to',\n",
825 " 'mind'],\n",
826 " ['what', 'else', 'do', 'you', 'remember?'],\n",
827 " ['why', 'do', 'you', 'recall', '?Y', 'right', 'now'],\n",
828 " ['what',\n",
829 " 'in',\n",
830 " 'this',\n",
831 " 'present',\n",
832 " 'situation',\n",
833 " 'reminds',\n",
834 " 'you',\n",
835 " 'of',\n",
836 " '?Y'],\n",
837 " ['what', 'is', 'the', 'connection', 'between', 'me', 'and', '?Y']]},\n",
838 " {'?X': [], '?Y': ['rain']}),\n",
839 " ({'pattern': ['?X'],\n",
840 " 'responses': [['very', 'interesting'],\n",
841 " ['i', 'am', 'not', 'sure', 'i', 'understand', 'you', 'fully'],\n",
842 " ['what', 'does', 'that', 'suggest', 'to', 'you'],\n",
843 " ['please', 'continue'],\n",
844 " ['go', 'on'],\n",
845 " ['do',\n",
846 " 'you',\n",
847 " 'feel',\n",
848 " 'strongly',\n",
849 " 'about',\n",
850 " 'discussing',\n",
851 " 'such',\n",
852 " 'things']]},\n",
853 " {'?X': ['i', 'remember', 'rain']})]"
854 ]
855 },
856 "execution_count": 79,
857 "metadata": {},
858 "output_type": "execute_result"
859 }
860 ],
861 "source": [
862 "candidate_rules(all_rules, \"i remember rain\".split())"
863 ]
864 },
865 {
866 "cell_type": "code",
867 "execution_count": 80,
868 "metadata": {},
869 "outputs": [],
870 "source": [
871 "def fill(response, bindings):\n",
872 " filled_response = []\n",
873 " for w in response:\n",
874 " if is_var(w):\n",
875 " if w in bindings:\n",
876 " filled_response += bindings[w]\n",
877 " else:\n",
878 " filled_response += ['MISSING']\n",
879 " else:\n",
880 " filled_response += [w]\n",
881 " return filled_response"
882 ]
883 },
884 {
885 "cell_type": "code",
886 "execution_count": 81,
887 "metadata": {},
888 "outputs": [
889 {
890 "data": {
891 "text/plain": [
892 "'do you often think of rain'"
893 ]
894 },
895 "execution_count": 81,
896 "metadata": {},
897 "output_type": "execute_result"
898 }
899 ],
900 "source": [
901 "bs = match('yes i remember rain'.split(), '?X i remember ?Y'.split())[0]\n",
902 "fr = fill(['do', 'you', 'often', 'think', 'of', '?Y'], bs)\n",
903 "' '.join(fr)"
904 ]
905 },
906 {
907 "cell_type": "code",
908 "execution_count": 82,
909 "metadata": {},
910 "outputs": [],
911 "source": [
912 "pronoun_swaps = {\n",
913 " 'i': 'you',\n",
914 " 'me': 'you',\n",
915 " 'my': 'your',\n",
916 " 'mine': 'yours',\n",
917 " 'am': 'are'\n",
918 "}\n",
919 "\n",
920 "def pronoun_person_swap(bindings):\n",
921 " def swapped(words):\n",
922 " sw = []\n",
923 " for w in words:\n",
924 " if w in pronoun_swaps:\n",
925 " sw += [pronoun_swaps[w]]\n",
926 " else:\n",
927 " sw += [w]\n",
928 " return sw\n",
929 " \n",
930 " return {var: swapped(bindings[var]) for var in bindings}"
931 ]
932 },
933 {
934 "cell_type": "code",
935 "execution_count": 83,
936 "metadata": {},
937 "outputs": [
938 {
939 "data": {
940 "text/plain": [
941 "{'?X': ['your', 'father'], '?Y': ['you', 'are', 'your', 'brother', 'keeper']}"
942 ]
943 },
944 "execution_count": 83,
945 "metadata": {},
946 "output_type": "execute_result"
947 }
948 ],
949 "source": [
950 "pronoun_person_swap({'?X': ['my', 'father'], '?Y': 'i am my brother keeper'.split()})"
951 ]
952 },
953 {
954 "cell_type": "code",
955 "execution_count": 84,
956 "metadata": {},
957 "outputs": [],
958 "source": [
959 "def respond(rule, bindings):\n",
960 " return fill(random.choice(rule['responses']), bindings)"
961 ]
962 },
963 {
964 "cell_type": "code",
965 "execution_count": 85,
966 "metadata": {},
967 "outputs": [
968 {
969 "data": {
970 "text/plain": [
971 "['what', 'is', 'the', 'connection', 'between', 'me', 'and', 'rain']"
972 ]
973 },
974 "execution_count": 85,
975 "metadata": {},
976 "output_type": "execute_result"
977 }
978 ],
979 "source": [
980 "r0, b0 = candidate_rules(all_rules, \"i remember rain\".split())[0]\n",
981 "respond(r0, b0)"
982 ]
983 },
984 {
985 "cell_type": "code",
986 "execution_count": 86,
987 "metadata": {},
988 "outputs": [],
989 "source": [
990 "def eliza_loop():\n",
991 " print(\"Hello. I'm Eliza. What seems to be the problem?\")\n",
992 " while True:\n",
993 " c = input(\"> \")\n",
994 " if c.strip() in 'quit halt exit stop'.split(): break\n",
995 " comment = c.split()\n",
996 " rule, bindings = candidate_rules(all_rules, comment)[0]\n",
997 " swapped_bindings = pronoun_person_swap(bindings)\n",
998 " print(' '.join(respond(rule, swapped_bindings)))"
999 ]
1000 },
1001 {
1002 "cell_type": "code",
1003 "execution_count": 87,
1004 "metadata": {
1005 "scrolled": true
1006 },
1007 "outputs": [
1008 {
1009 "name": "stdout",
1010 "output_type": "stream",
1011 "text": [
1012 "Hello. I'm Eliza. What seems to be the problem?\n",
1013 "> hello\n",
1014 "how do you do. please state your problem\n",
1015 "> i am sad about life\n",
1016 "i'm sure it's not pleasant to be sad\n",
1017 "> it isn't\n",
1018 "very interesting\n",
1019 "> are you happy\n",
1020 "perhaps i am happy in your fantasies\n",
1021 "> quit\n"
1022 ]
1023 }
1024 ],
1025 "source": [
1026 "eliza_loop()"
1027 ]
1028 },
1029 {
1030 "cell_type": "code",
1031 "execution_count": null,
1032 "metadata": {},
1033 "outputs": [],
1034 "source": []
1035 }
1036 ],
1037 "metadata": {
1038 "kernelspec": {
1039 "display_name": "Python 3",
1040 "language": "python",
1041 "name": "python3"
1042 },
1043 "language_info": {
1044 "codemirror_mode": {
1045 "name": "ipython",
1046 "version": 3
1047 },
1048 "file_extension": ".py",
1049 "mimetype": "text/x-python",
1050 "name": "python",
1051 "nbconvert_exporter": "python",
1052 "pygments_lexer": "ipython3",
1053 "version": "3.7.4"
1054 }
1055 },
1056 "nbformat": 4,
1057 "nbformat_minor": 1
1058 }