-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlambda_function.py
More file actions
103 lines (86 loc) · 2.7 KB
/
lambda_function.py
File metadata and controls
103 lines (86 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import boto3
import json
import random
import re
from boto3.dynamodb.conditions import Key
class Robot:
DEFAULT_ARGS = {
"user_input": None,
"dry_run": False,
}
def __init__(self):
self._table = None
@property
def table(self):
if self._table is None:
self._table = self._init_table()
return self._table
def _init_table(self):
dyn_resource = boto3.resource("dynamodb")
table = dyn_resource.Table("Niall2")
table.load()
return table
def __call__(self, event, context):
args = self.DEFAULT_ARGS.copy()
args.update(json.loads(event["body"]))
user_input = args["user_input"]
dry_run = args["dry_run"]
# Analyse user input.
if user_input:
tokens = self.tokenize(user_input)
if tokens and not dry_run:
self.store(tokens)
# Generate Niall's response.
niall_output = " ".join(self.generate())
if dry_run:
niall_output = "[dry] " + niall_output
response = {"niall_output": niall_output}
return {
"statusCode": 200,
"headers": {
"Access-Control-Allow-Origin": "*",
},
"body": json.dumps(response),
}
def tokenize(self, s):
"""Sanitize user input, then split into tokens.
:param s: What the user is saying to Niall.
:returns: A sequence of tokens (i.e. words).
"""
s = s.strip()
s = re.sub(r"[^\w\s']", "", s)
s = s.lower()
return s.split()
def store(self, tokens):
"""Store a sequence of tokens in the database.
:param tokens: A sequence of tokens.
"""
tokens = list(tokens)
for this, next in zip(["_"] + tokens, tokens + ["_"]):
self.table.update_item(
Key={
"From": this,
"To": next,
},
UpdateExpression="ADD Weight :one",
ExpressionAttributeValues={
":one": 1,
}
)
def generate(self):
"""Generate a sequence of tokens.
:returns tokens: A sequence of tokens.
"""
word = "_"
while True:
response = self.table.query(
KeyConditionExpression=Key("From").eq(word)
)
next_words = sum([[item["To"]] * int(item["Weight"])
for item in response["Items"]],
start=[])
word = random.choice(next_words)
if word == "_":
break
yield word
lambda_handler = Robot()