forked from amirharati/neo4j_protobot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBotMemory.py
125 lines (109 loc) · 4.89 KB
/
BotMemory.py
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""
A wrapper class to interface with neo4j graph database.
The interface is acting as "memory".
"""
from neo4jrestclient.client import GraphDatabase
from neo4jrestclient import client
from random import randrange
class BotMemory:
"""
Simple wrapper class.
allows to add to memory.
perform simple inference.
"""
def __init__(self, db_user, db_pass, host="http://localhost:7474"):
# connect to the database.
self.db = GraphDatabase(host,
username=db_user,
password=db_pass)
def memorize_restaurant_facts(self, name, cuisine=None, location=None):
"""
A method to memorize facts related to restaurants
"""
n = self._add_node(name, "restaurant_name")
if cuisine is not None:
c = self._add_node(cuisine, "cuisine")
n.relationships.create("is_a", c)
if location is not None:
l = self._add_node(location, "location")
n.relationships.create("located", l)
def memorize_user_facts(self, name, cuisine=None, location=None):
"""
A method to memorize facts about user.
"""
n = self._add_node(name, "user_name")
if cuisine is not None:
c = self._add_node(cuisine, "cuisine")
n.relationships.create("likes", c)
if location is not None:
l = self._add_node(location, "location")
n.relationships.create("located", l)
def clear_memory(self):
"""
forget everything.
"""
q = "MATCH (n:user_name) DETACH DELETE n"
results = self.db.query(q, returns=(client.Node, str, client.Node))
q = "MATCH (n:restaurant_name) DETACH DELETE n"
results = self.db.query(q, returns=(client.Node, str, client.Node))
q = "MATCH (n:cuisine) DETACH DELETE n"
results = self.db.query(q, returns=(client.Node, str, client.Node))
q = "MATCH (n:location) DETACH DELETE n"
results = self.db.query(q, returns=(client.Node, str, client.Node))
def _add_node(self, node_name, node_type):
"""
add a node if not existed.
and return the node.
"""
q = 'MATCH (r:' + node_type + ') WHERE r.name="' \
+ node_name + '" RETURN r'
results = self.db.query(q, returns=(client.Node, str, client.Node))
res = self.db.labels.create(node_type)
if (len(results) == 0):
r = self.db.nodes.create(name=node_name)
res.add(r)
else:
r = results[0][0]
return r
def get_user_location(self, u):
loc = None
q = 'MATCH p=(u:user_name {name:"' + u + '"})-[:located]->(ul:location) RETURN ul'
results = self.db.query(q, data_contents=True)
if len(results) > 0:
loc = results.rows[0][0]["name"]
return loc
def find_restaurant(self, u, c):
"""
find a good choice!
Should handle when there is no result or
when user location is not specified.
If cuisine c specified apply it.
"""
r_name = None
r_location = None
r_cuisine = None
u_name = u
if c is not None:
q0 = 'MATCH p=(rl:location)<-[:located]-(res:restaurant_name)-[r:is_a]->(c:cuisine {name:"' + c + '"})<-[:likes]-(u:user_name {name:"' + u + '"})-[:located]->(ul:location) where ul=rl RETURN res, c, u, rl LIMIT 25'
results = self.db.query(q0, data_contents=True)
if (len(results) > 0):
random_index = randrange(0, len(results))
r_name = results.rows[random_index][0]["name"]
r_location = results.rows[random_index][3]["name"]
r_cuisine = results.rows[random_index][1]["name"]
return (u_name, r_name, r_location, r_cuisine)
q1 = 'MATCH p=(rl:location)<-[:located]-(res:restaurant_name)-[r:is_a]->(c:cuisine)<-[:likes]-(u:user_name {name:"' + u + '"})-[:located]->(ul:location) where ul=rl RETURN res, c, u, rl LIMIT 25'
results = self.db.query(q1, data_contents=True)
if (len(results) > 0):
random_index = randrange(0, len(results))
r_name = results.rows[random_index][0]["name"]
r_location = results.rows[random_index][3]["name"]
r_cuisine = results.rows[random_index][1]["name"]
return (u_name, r_name, r_location, r_cuisine)
q2 = 'MATCH p=(u:user_name {name:"' + u + '"})-[:located]->(ul:location)<-[:located]-(res:restaurant_name) RETURN res, u, ul LIMIT 25'
results = self.db.query(q2, data_contents=True)
if (len(results) > 0):
random_index = randrange(0, len(results))
r_name = results.rows[random_index][0]["name"]
r_location = results.rows[random_index][2]["name"]
return (u_name, r_name, r_location, r_cuisine)